跳至主要內容
高級

Mining RPC

了解 Bitcoin Core 提供的挖礦相關 RPC 命令,包括區塊模板和區塊提交。

10 分鐘

Bitcoin Core 提供了多個 RPC 命令用於挖礦操作,從獲取區塊模板到提交新區塊。 這些接口主要供礦池和獨立礦工使用。

getblocktemplate

獲取區塊模板,包含待打包的交易和區塊頭信息。

# 獲取區塊模板
bitcoin-cli getblocktemplate '{"rules": ["segwit"]}'

{
  "capabilities": ["proposal"],
  "version": 536870912,
  "rules": ["csv", "segwit", "taproot"],
  "vbavailable": {},
  "vbrequired": 0,
  "previousblockhash": "000000000000000000...",
  "transactions": [
    {
      "data": "02000000...",
      "txid": "abc123...",
      "hash": "def456...",      // wtxid
      "depends": [],
      "fee": 12500,             // satoshis
      "sigops": 4,
      "weight": 561
    },
    ...
  ],
  "coinbaseaux": {},
  "coinbasevalue": 625012500,   // 獎勵 + 手續費
  "longpollid": "000000000000000000...123",
  "target": "0000000000000000000a1b2c3d...",
  "mintime": 1700000000,
  "mutable": ["time", "transactions", "prevblock"],
  "noncerange": "00000000ffffffff",
  "sigoplimit": 80000,
  "sizelimit": 4000000,
  "weightlimit": 4000000,
  "curtime": 1700000100,
  "bits": "1703c8f9",
  "height": 840001,
  "default_witness_commitment": "6a24aa21a9ed..."
}

submitblock

提交新挖到的區塊到網路。

# 提交區塊
bitcoin-cli submitblock "0200000000000000000..."

# 返回值:
# null - 成功
# "duplicate" - 區塊已存在
# "duplicate-invalid" - 區塊已知無效
# "inconclusive" - 驗證未完成
# "rejected" - 區塊被拒絕

# 提交區塊並獲取詳細結果
bitcoin-cli submitblock "0200000..." '{"dummy": true}'

getmininginfo

獲取當前挖礦狀態信息。

bitcoin-cli getmininginfo

{
  "blocks": 840000,
  "currentblockweight": 3998456,
  "currentblocktx": 2345,
  "difficulty": 72006146478567.06,
  "networkhashps": 5.234e+20,
  "pooledtx": 45678,
  "chain": "main",
  "warnings": ""
}

getnetworkhashps

估算網路的總算力。

# 使用最近 120 個區塊估算
bitcoin-cli getnetworkhashps

# 指定區塊數量和結束高度
bitcoin-cli getnetworkhashps 2016 840000

# 返回: 5.234567890123456e+20 (哈希/秒)

prioritisetransaction

調整交易在區塊模板中的優先級。

# 增加交易優先級(增加虛擬費用)
bitcoin-cli prioritisetransaction <txid> 0 10000

# 參數:
# 1. txid - 交易 ID
# 2. dummy - 已棄用,填 0
# 3. fee_delta - 調整量(satoshis)

# 降低優先級
bitcoin-cli prioritisetransaction <txid> 0 -5000

# 用途:
# - 礦池優先打包自己的交易
# - 加速重要交易
# - 測試目的

generateblock (Regtest)

在 regtest 模式下立即生成區塊。

# 生成包含指定交易的區塊
bitcoin-cli -regtest generateblock <address> '["<txid1>", "<txid2>"]'

# 返回
{
  "hash": "abc123..."
}

# 生成空區塊
bitcoin-cli -regtest generateblock <address> '[]'

generatetoaddress (Regtest)

生成多個區塊並將獎勵發送到指定地址。

# 生成 100 個區塊
bitcoin-cli -regtest generatetoaddress 100 <address>

# 返回區塊雜湊列表
[
  "block_hash_1",
  "block_hash_2",
  ...
]

# 指定最大嘗試次數
bitcoin-cli -regtest generatetoaddress 1 <address> 1000000

generatetodescriptor (Regtest)

生成區塊並使用描述符指定輸出。

# 使用描述符生成區塊
bitcoin-cli -regtest generatetodescriptor 10 "wpkh([...]/0/*)"

# 支持複雜描述符
bitcoin-cli -regtest generatetodescriptor 1 \
  "wsh(multi(2,[...]/0/*,[...]/0/*))"

挖礦工作流程

import hashlib
import struct
import json
import requests

def mine_block():
    # 1. 獲取區塊模板
    template = rpc_call("getblocktemplate", [{"rules": ["segwit"]}])

    # 2. 構建 coinbase 交易
    coinbase = build_coinbase(
        height=template["height"],
        reward=template["coinbasevalue"],
        witness_commitment=template["default_witness_commitment"]
    )

    # 3. 構建交易列表
    txids = [coinbase.txid()] + [tx["txid"] for tx in template["transactions"]]

    # 4. 計算 Merkle Root
    merkle_root = compute_merkle_root(txids)

    # 5. 構建區塊頭
    header = struct.pack("<I", template["version"])
    header += bytes.fromhex(template["previousblockhash"])[::-1]
    header += merkle_root[::-1]
    header += struct.pack("<I", template["curtime"])
    header += bytes.fromhex(template["bits"])[::-1]

    # 6. 挖礦(找 nonce)
    target = int(template["target"], 16)
    for nonce in range(0xffffffff):
        candidate = header + struct.pack("<I", nonce)
        hash_result = hashlib.sha256(hashlib.sha256(candidate).digest()).digest()
        if int.from_bytes(hash_result, 'little') < target:
            # 找到有效區塊!
            block = serialize_block(header + struct.pack("<I", nonce), txs)
            return rpc_call("submitblock", [block.hex()])

    return None  # 需要更新模板重試

Long Polling

# 使用 longpollid 等待新工作
bitcoin-cli getblocktemplate '{
  "rules": ["segwit"],
  "longpollid": "000000000000000000...123"
}'

# 當以下情況發生時返回:
# - 新區塊到達
# - mempool 顯著變化
# - 超時(約 5 分鐘)

# 這允許礦工及時獲取新工作
# 而不需要持續輪詢

區塊模板模式

# 標準模式(獲取模板)
bitcoin-cli getblocktemplate '{"rules": ["segwit"]}'

# 提案模式(驗證區塊)
bitcoin-cli getblocktemplate '{
  "mode": "proposal",
  "data": "02000000..."
}'

# 返回:
# null - 區塊有效
# "rejected" - 區塊無效
# "inconclusive" - 需要更多檢查

安全注意事項

  • RPC 安全:挖礦 RPC 應該只在安全網路中暴露
  • 區塊模板緩存:不要過度緩存,區塊鏈狀態會變化
  • 時間戳:使用合理的時間戳,過大會被拒絕
  • 交易選擇:確保選擇的交易有效且無衝突
  • Witness Commitment:SegWit 區塊必須包含正確的 commitment

相關 RPC 命令

命令 用途
getblocktemplate 獲取區塊模板
submitblock 提交新區塊
submitheader 提交區塊頭
getmininginfo 挖礦狀態
getnetworkhashps 網路算力
prioritisetransaction 調整交易優先級
getblockstats 區塊統計
已複製連結
已複製到剪貼簿