比特幣腳本編程完整實戰指南:從基礎到進階應用
提供從環境搭建到實際應用的完整比特幣腳本編程指南,涵蓋 P2PKH、P2SH、P2WSH 腳本創建、時間鎖定、多籤邏輯以及 Miniscript 抽象層,幫助開發者掌握比特幣底層技術並應用於閃電網路和質押協議。
比特幣腳本編程完整實戰指南 V2:可運作程式碼範例、Bitcoin Core 命令序列與進階腳本開發
摘要
本指南是比特幣腳本語言的完整實戰教程,深度新增可直接運作的程式碼範例、Bitcoin Core 命令序列、Bitcoin Script 實驗室的完整操作流程。涵蓋從基礎指令到進階應用的完整技術譜系,包括 P2PKH、P2SH、P2WSH、P2TR 腳本創建,以及 HTLC、多籤合約、時間鎖定等進階應用的實際程式碼。所有範例均可在比特幣測試網路或本地 Regtest 環境中實際運作。
第一章:比特幣腳本開發環境搭建
1.1 Bitcoin Core 安裝與配置
在 Ubuntu/Debian 上安裝 Bitcoin Core:
# 1. 添加 Bitcoin PPA 倉庫
sudo apt-get update
sudo apt-get install -y software-properties-common
sudo add-apt-repository -y ppa:bitcoin/bitcoin
# 2. 安裝 Bitcoin Core
sudo apt-get update
sudo apt-get install -y bitcoin-qt bitcoind
# 3. 驗證安裝
bitcoind --version
# 輸出:Bitcoin Core Daemon version v27.0.0
# 4. 建立配置目錄
mkdir -p ~/.bitcoin
cd ~/.bitcoin
bitcoin.conf 配置文件:
# ~/.bitcoin/bitcoin.conf
# 網路配置
testnet=0 # 使用主網(改為 1 則使用測試網)
regtest=1 # 啟用 Regtest 模式
# RPC 配置
rpcuser=bitcoinuser
rpcpassword=bitcoinpassword
rpcport=18443
rpcallowip=127.0.0.1
# 錢包配置
disablewallet=0
mintxfee=0.00001
fallbackfee=0.00001
# 伺服器模式
server=1
daemon=1
# 連接埠配置
port=8333
bind=127.0.0.1
# 其他配置
dbcache=2048
maxconnections=16
1.2 啟動 Regtest 模式
Regtest(回歸測試)模式允許在本地創建私有區塊鏈,非常適合腳本開發:
# 1. 啟動比特幣節點
bitcoind -daemon
# 2. 等待節點啟動
sleep 3
# 3. 創建錢包
bitcoin-cli -rpcpassword=bitcoinpassword createwallet "devwallet" true true "" false false
# 4. 檢查錢包狀態
bitcoin-cli -rpcpassword=bitcoinpassword getwalletinfo
# 5. 生成測試地址
bitcoin-cli -rpcpassword=bitcoinpassword getnewaddress "test_address"
# 6. 挖出初始獎勵(需要 100 個區塊才能花費 coinbase)
bitcoin-cli -rpcpassword=bitcoinpassword generatetoaddress 101 \
"$(bitcoin-cli -rpcpassword=bitcoinpassword getnewaddress "miner")"
# 7. 檢查餘額
bitcoin-cli -rpcpassword=bitcoinpassword getbalance
1.3 Bitcoin Script 模擬器
對於不涉及真實交易的腳本學習,可以使用 Bitcoin Script 模擬器:
使用 btcdeb 進行腳本調試:
# 安裝 btcdeb
git clone https://github.com/siminchen/btcdeb.git
cd btcdeb
./autogen.sh
./configure
make
sudo make install
# 使用範例
btcdeb --txrow='[]' --sig='[01]' --pubkey='[021121...]' OP_CHECKSIG
使用 Elements Project 的腳本模擬:
# Elements Project 提供了更完整的腳本測試框架
git clone https://github.com/ElementsProject/elements-miniscript.git
cd elements-miniscript
cargo build --release
第二章:Bitcoin Script 基礎指令實戰
2.1 基本堆疊操作
使用 Bitcoin Core RPC 測試腳本執行:
#!/usr/bin/env python3
# bitcoin_script_basics.py
import subprocess
import json
def bitcoin_rpc(command, params=[], wallet="devwallet"):
"""執行 Bitcoin Core RPC 命令"""
cmd = [
"bitcoin-cli",
"-rpcpassword=bitcoinpassword",
"-rpcwallet=" + wallet,
command
] + params
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise Exception(f"RPC Error: {result.stderr}")
try:
return json.loads(result.stdout)
except:
return result.stdout.strip()
# 範例:創建一個簡單的 P2PKH 地址
def create_p2pkh_address():
"""創建 P2PKH 地址"""
address = bitcoin_rpc("getnewaddress", ["legacy"]) # 舊格式地址
print(f"P2PKH 地址: {address}")
return address
# 範例:解碼地址
def decode_address(address):
"""解碼比特幣地址"""
decoded = bitcoin_rpc("validateaddress", [address])
print(json.dumps(decoded, indent=2))
return decoded
# 測試腳本
if __name__ == "__main__":
addr = create_p2pkh_address()
decode_address(addr)
2.2 腳本解析與驗證
使用 Bitcoin Core decodescript:
# P2PKH 腳本解析
bitcoin-cli -rpcpassword=bitcoinpassword decodescript \
"76a914860964193a8af5ed2d48969f4c2e5f2fa39ab9a488ac"
# 輸出:
# {
# "asm": "OP_DUP OP_HASH160 860964193a8af5ed2d48969f4c2e5f2fa39ab9a4 OP_EQUALVERIFY OP_CHECKSIG",
# "type": "pubkeyhash",
# "p2sh": "2Mx...",
# "segwit": {
# "asm": "OP_DUP OP_HASH160 <860964193a8af5ed2d48969f4c2e5f2fa39ab9a4> OP_EQUALVERIFY OP_CHECKSIG",
# "hex": "76a914860964193a8af5ed2d48969f4c2e5f2fa39ab9a488ac",
# "type": "v0_p2wpkh"
# }
# }
# P2SH-wrapped SegWit 腳本解析
bitcoin-cli -rpcpassword=bitcoinpassword decodescript \
"a914a9b7c6d3e4f5a8b9c0d1e2f3a4b5c6d7e8f9a0b87"
# P2WSH 腳本解析
bitcoin-cli -rpcpassword=bitcoinpassword decodescript \
"0020<sha256_hash>"
2.3 創建和測試自訂腳本
使用 Bitcoin Core createrawtransaction 創建自訂交易:
# 1. 獲取錢包中的未花費輸出
bitcoin-cli -rpcpassword=bitcoinpassword listunspent
# 輸出示例:
# [
# {
# "txid": "abc123...",
# "vout": 0,
# "amount": 50.00000000,
# "confirmations": 101,
# "scriptPubKey": "76a914...",
# }
# ]
# 2. 創建一個 OP_RETURN 輸出(不可花費)
bitcoin-cli -rpcpassword=bitcoinpassword createrawtransaction \
'[{"txid":"abc123...","vout":0,"amount":50}]' \
'[{"data":"48656c6c6f2057656c7420746f20426974636f696e"}]'
# data 欄位是 "Hello World" 的十六進制表示
# 這創建了一個包含 "Hello World" 訊息的 OP_RETURN 輸出
# 3. 解碼查看
bitcoin-cli -rpcpassword=bitcoinpassword decoderawtransaction "<raw_tx_hex>"
# 4. 簽署交易
bitcoin-cli -rpcpassword=bitcoinpassword signrawtransactionwithwallet \
"<raw_tx_hex>"
第三章:常見腳本類型完整實現
3.1 P2PKH(Pay to Public Key Hash)腳本
P2PKH 是比特幣最傳統的地址格式,地址以「1」開頭:
腳本結構:
鎖定腳本 (ScriptPubKey):
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
解鎖腳本 (ScriptSig):
<signature> <pubKey>
完整實現範例(Python):
#!/usr/bin/env python3
# p2pkh_example.py
import hashlib
import ecdsa
import base58
import wallycore as wally
class P2PKHWallet:
"""P2PKH 錢包實現"""
def __init__(self, private_key_hex=None):
if private_key_hex:
self.private_key = bytes.fromhex(private_key_hex)
else:
self.private_key = self._generate_private_key()
self.public_key = self._derive_public_key()
self.pubkey_hash = self._hash_public_key()
self.address = self._create_address()
def _generate_private_key(self):
"""生成隨機私鑰"""
import os
return os.urandom(32)
def _derive_public_key(self):
"""從私鑰派生公鑰(壓縮格式)"""
# 使用 secp256k1 曲線
signing_key = ecdsa.SigningKey.from_string(
self.private_key,
curve=ecdsa.SECP256k1
)
verifying_key = signing_key.get_verifying_key()
# 壓縮公鑰格式
x = verifying_key.pubkey.point.x
y = verifying_key.pubkey.point.y
if y % 2 == 0:
prefix = b'\x02'
else:
prefix = b'\x03'
return prefix + x.to_bytes(32, 'big')
def _hash_public_key(self):
"""計算公鑰哈希(RIPEMD160(SHA256(pubkey)))"""
sha256_hash = hashlib.sha256(self.public_key).digest()
ripemd160_hash = hashlib.new('ripemd160')
ripemd160_hash.update(sha256_hash)
return ripemd160_hash.digest()
def _create_address(self):
"""創建 P2PKH 地址"""
# 主網版本位元組:0x00
version = b'\x00'
payload = version + self.pubkey_hash
# 計算校驗和:SHA256(SHA256(payload))[:4]
checksum = hashlib.sha256(
hashlib.sha256(payload).digest()
).digest()[:4]
# Base58Check 編碼
full_payload = payload + checksum
return base58.b58encode(full_payload).decode('ascii')
def get_locking_script(self):
"""獲取鎖定腳本"""
script = bytes([
0x76, 0xa9, 0x14 # OP_DUP OP_HASH160 <20 bytes>
]) + self.pubkey_hash + bytes([
0x88, 0xac # OP_EQUALVERIFY OP_CHECKSIG
])
return script.hex()
def get_address(self):
"""獲取 P2PKH 地址"""
return self.address
# 使用示例
if __name__ == "__main__":
wallet = P2PKHWallet()
print(f"私鑰: {wallet.private_key.hex()}")
print(f"公鑰: {wallet.public_key.hex()}")
print(f"P2PKH 地址: {wallet.address}")
print(f"鎖定腳本: {wallet.get_locking_script()}")
3.2 P2SH(Pay to Script Hash)腳本
P2SH 地址以「3」開頭,用於多籤、SegWit 包裝等場景:
腳本結構:
鎖定腳本 (ScriptPubKey):
OP_HASH160 <scriptHash> OP_EQUAL
解鎖腳本 (ScriptSig):
<serialized_redeemScript> <...witness data...>
2-of-3 多籤實現:
#!/usr/bin/env python3
# p2sh_multisig.py
import hashlib
import ecdsa
import base58
class P2SHMultisig:
"""P2SH 多籤錢包實現"""
def __init__(self, public_keys, threshold):
"""
初始化多籤錢包
:param public_keys: 公鑰列表
:param threshold: 生效閾值 (m-of-n)
"""
if threshold > len(public_keys) or threshold < 1:
raise ValueError("Invalid threshold")
self.public_keys = public_keys
self.threshold = threshold
self.redeem_script = self._create_redeem_script()
self.script_hash = self._hash_redeem_script()
self.address = self._create_address()
def _create_redeem_script(self):
"""創建贖回腳本"""
script = bytes([self.threshold]) # m
for pubkey in self.public_keys:
# 公鑰需要是壓縮格式 (33 bytes)
script += bytes([0x21]) + pubkey
script += bytes([len(self.public_keys)]) # n
script += bytes([0xae]) # OP_CHECKMULTISIG
return script
def _hash_redeem_script(self):
"""計算腳本哈希"""
return hashlib.sha256(self.redeem_script).digest()
def _create_address(self):
"""創建 P2SH 地址"""
# 主網版本位元組:0x05
version = b'\x05'
payload = version + self.script_hash
checksum = hashlib.sha256(
hashlib.sha256(payload).digest()
).digest()[:4]
full_payload = payload + checksum
return base58.b58encode(full_payload).decode('ascii')
def get_locking_script(self):
"""獲取鎖定腳本"""
return (
bytes([0xa9, 0x14]) + # OP_HASH160 <20 bytes>
self.script_hash +
bytes([0x87]) # OP_EQUAL
).hex()
def create_unlocking_script(self, signatures):
"""
創建解鎖腳本
:param signatures: 簽名列表
"""
if len(signatures) < self.threshold:
raise ValueError("Not enough signatures")
# ScriptSig 格式:OP_0 <sig1> <sig2> ... <redeemScript>
script = bytes([0x00]) # OP_0(用於補償 CHECKMULTISIG 的 bug)
for sig in signatures[:self.threshold]:
script += sig
script += bytes([len(self.redeem_script)]) + self.redeem_script
return script.hex()
# 使用示例
if __name__ == "__main__":
# 假設有 3 個公鑰
pubkey1 = bytes.fromhex("0212..." * 33) # 33 bytes 壓縮公鑰
pubkey2 = bytes.fromhex("0234..." * 33)
pubkey3 = bytes.fromhex("0356..." * 33)
# 創建 2-of-3 多籤錢包
multisig = P2SHMultisig([pubkey1, pubkey2, pubkey3], 2)
print(f"P2SH 地址: {multisig.address}")
print(f"鎖定腳本: {multisig.get_locking_script()}")
print(f"贖回腳本: {multisig.redeem_script.hex()}")
3.3 P2WSH(Pay to Witness Script Hash)腳本
P2WSH 是 SegWit v0 的腳本哈希形式,地址以「bc1q」開頭:
腳本結構:
鎖定腳本 (ScriptPubKey):
OP_0 <sha256(witnessScript)>
見證 (Witness):
<witness elements> <witnessScript>
P2WSH + 2-of-3 多籤實現:
#!/usr/bin/env python3
# p2wsh_multisig.py
import hashlib
import base58
def create_p2wsh_multisig(public_keys, threshold):
"""創建 P2WSH 多籤地址"""
# 1. 構建 witnessScript (多籤腳本)
witness_script = bytes([threshold])
for pubkey in public_keys:
witness_script += bytes([0x21]) + pubkey # 0x21 = 33 bytes
witness_script += bytes([len(public_keys), 0xae]) # OP_CHECKMULTISIG
# 2. 計算 SHA256 哈希
script_hash = hashlib.sha256(witness_script).digest()
# 3. 創建 P2WSH 地址
# bech32 編碼
def bech32_encode(hrp, witver, witprog):
"""Bech32 編碼"""
# 轉換位元組到 5-bit 基
data = convertbits(witprog, 8, 5)
data = [witver] + data
# 計算校驗和
polymod = bech32_polymod(
[bech32_hrp_expand(hrp)] + data + [0, 0, 0, 0, 0, 0]
)
# 編碼
combined = data + list(polymod)[::-1]
return hrp + '1' + ''.join([BECH32_CHARSET[d] for d in combined])
address = bech32_encode('bc', 0, script_hash)
return {
'address': address,
'witness_script': witness_script.hex(),
'script_hash': script_hash.hex()
}
# 使用 bech32 庫(推薦使用)
try:
from bech32 import encode as bech32_encode
def create_p2wsh_multisig_v2(public_keys, threshold):
witness_script = bytes([threshold])
for pubkey in public_keys:
witness_script += bytes([0x21]) + pubkey
witness_script += bytes([len(public_keys), 0xae])
script_hash = hashlib.sha256(witness_script).digest()
address = bech32_encode('bc', 0, script_hash)
return {
'address': address,
'witness_script': witness_script.hex(),
'script_hash': script_hash.hex()
}
except ImportError:
print("pip install bech32")
# Bitcoin Core RPC 方式創建 P2WSH 多籤
def create_p2wsh_via_bitcoin_core(public_keys, threshold):
"""使用 Bitcoin Core RPC 創建 P2WSH 多籤"""
import subprocess
import json
# 1. 創建多籤描述
multisig_desc = f"{threshold},[{','.join(public_keys)}],multisig"
# 2. 解析描述獲取地址
result = subprocess.run([
"bitcoin-cli",
"-rpcpassword=bitcoinpassword",
"getdescriptorinfo",
multisig_desc
], capture_output=True, text=True)
info = json.loads(result.stdout)
# 3. 派生 P2WSH 地址
result = subprocess.run([
"bitcoin-cli",
"-rpcpassword=bitcoinpassword",
"deriveaddresses",
f"wsh({multisig_desc})",
"[]"
], capture_output=True, text=True)
addresses = json.loads(result.stdout)
return addresses[0]
# 使用示例
if __name__ == "__main__":
# 假設的公鑰列表
pubkeys = [
"0212a876..." * 33,
"0234b567..." * 33,
"0356c890..." * 33
]
result = create_p2wsh_via_bitcoin_core(pubkeys, 2)
print(f"P2WSH 多籤地址: {result}")
3.4 P2TR(Pay to Taproot)腳本
P2TR 是 Taproot 升級引入的最新地址格式,地址以「bc1p」開頭:
腳本結構:
鎖定腳本 (ScriptPubKey):
OP_1 <x-only-pubkey>
見證 (Witness - 密鑰路徑):
<signature>
見證 (Witness - 腳本路徑):
<leaf_version> <script> <control_block>
P2TR 實現:
#!/usr/bin/env python3
# p2tr_example.py
import hashlib
import secrets
def x_only_point(point):
"""將完整公鑰轉換為 x-only 公鑰"""
# Taproot 公鑰只使用 x 座標
return point[1:33] # 跳過 0x02 或 0x03 前綴
def taproot_tweak_pubkey(internal_pubkey, merkle_root):
"""創建 Taproot 最終公鑰"""
# 將 internal_pubkey 和 merkle_root 組合
t = bytes([0x01, 0x50]) # TapTweak tag
h = hashlib.sha256(
t + hashlib.sha256(t).digest() + internal_pubkey + merkle_root
).digest()
# 使用 SHA256 進行調整
return hashlib.sha256(internal_pubkey + h).digest()
def create_p2tr_address(internal_pubkey, merkle_root=None):
"""創建 P2TR 地址"""
if merkle_root is None:
merkle_root = bytes(32) # 預設無腳本
# 計算調整後的公鑰
tweaked_pubkey = x_only_point(taproot_tweak_pubkey(internal_pubkey, merkle_root))
# Bech32m 編碼
from bech32 import encode as bech32_encode_v2
address = bech32_encode_v2('bc', 1, tweaked_pubkey) # version 1 for Taproot
return address
# Bitcoin Core RPC 方式(推薦)
def create_p2tr_via_bitcoin_core():
"""使用 Bitcoin Core 創建 Taproot 地址"""
import subprocess
import json
# 創建 Taproot 描述符錢包
result = subprocess.run([
"bitcoin-cli",
"-rpcpassword=bitcoinpassword",
"createwallet",
"taproot_wallet",
"false", # 不免除廢棄監控
"", # 描述
"false", # 避免忘記選項
"false", # 不disable private keys
"true", # disposable
], capture_output=True, text=True)
# 生成 Taproot 地址
result = subprocess.run([
"bitcoin-cli",
"-rpcpassword=bitcoinpassword",
"-rpcwallet=taproot_wallet",
"getnewaddress",
"taproot_addr",
"bech32m" # 指定 Taproot 地址格式
], capture_output=True, text=True)
return result.stdout.strip()
if __name__ == "__main__":
address = create_p2tr_via_bitcoin_core()
print(f"P2TR (Taproot) 地址: {address}")
第四章:時間鎖定與 HTLC 實戰
4.1 nLockTime 絕對時間鎖定
創建時間鎖定交易:
# 1. 創建當前不可花費的交易(nLockTime 設為未來)
bitcoin-cli -rpcpassword=bitcoinpassword createrawtransaction \
'[{"txid":"abc123...","vout":0,"amount":10}]' \
'[{"bcrt1q...": 9.99}]' \
'{"locktime": 860000}'
# 2. 解碼查看 nLockTime
bitcoin-cli -rpcpassword=bitcoinpassword decoderawtransaction "<raw_tx_hex>"
# 輸出中可以看到 "locktime": 860000
# 3. 簽署交易(此時會失敗,因為 nLockTime 未滿足)
bitcoin-cli -rpcpassword=bitcoinpassword signrawtransactionwithwallet \
"<raw_tx_hex>"
# 輸出會顯示 "complete": false
# 4. 等到區塊高度達到 860000 後,可以簽署並廣播
bitcoin-cli -rpcpassword=bitcoinpassword signrawtransactionwithwallet \
"<raw_tx_hex>"
# 此時應該成功
4.2 OP_CLTV 時間鎖定腳本
使用 OP_CHECKLOCKTIMEVERIFY:
# 1. 創建一個 100 區塊後才能花費的輸出
# 這需要使用 CLTV 腳本
# 首先需要知道贖回腳本
# 贖回腳本格式:
# <expiry_time> OP_CHECKLOCKTIMEVERIFY OP_DROP <pubkey> OP_CHECKSIG
# 2. 創建 P2SH 地址(使用上述贖回腳本)
redeem_script="bfa69aac..." # 包含 CLTV 的贖回腳本
bitcoin-cli -rpcpassword=bitcoinpassword validateaddress \
"$(bitcoin-cli -rpcpassword=bitcoinpassword decodescript $redeem_script | jq -r '.p2sh')"
# 3. 發送比特幣到此 P2SH 地址
bitcoin-cli -rpcpassword=bitcoinpassword sendtoaddress \
"<p2sh_address>" 1.0
# 4. 創建花費交易(需要滿足時間條件)
# 這個交易需要設置 nLockTime 為贖回腳本中的時間值
4.3 HTLC(Hash Time Lock Contract)完整實現
HTLC 是閃電網路和原子交換的核心:
HTLC 腳本結構:
IF
# 正常路徑:提供原像(preimage)
OP_HASH256 <hash-of-preimage> OP_EQUALVERIFY <receiver-pubkey> OP_CHECKSIG
ELSE
# 超時路徑:等待時間後退款
<timeout> OP_CHECKSEQUENCEVERIFY OP_DROP <sender-pubkey> OP_CHECKSIG
ENDIF
Python 實現:
#!/usr/bin/env python3
# htlc_example.py
import hashlib
import secrets
class HTLC:
"""HTLC 合約實現"""
def __init__(self, sender_pubkey, receiver_pubkey, amount, timeout_blocks, hashlock):
"""
初始化 HTLC
:param sender_pubkey: 發送方公鑰(33 bytes)
:param receiver_pubkey: 接收方公鑰(33 bytes)
:param amount: 金額(satoshis)
:param timeout_blocks: 區塊超時時間
:param hashlock: 32 bytes 的原像哈希 (hash of preimage)
"""
self.sender_pubkey = sender_pubkey
self.receiver_pubkey = receiver_pubkey
self.timeout_blocks = timeout_blocks
self.hashlock = hashlock
self.redeem_script = self._create_redeem_script()
self.script_hash = self._compute_script_hash()
self.p2wsh_address = self._create_address()
def _create_redeem_script(self):
"""創建 HTLC 贖回腳本"""
script = bytes()
# IF branch: hashlock path
script += bytes([0x63]) # OP_IF
script += bytes([0xaa]) # OP_HASH256
script += bytes([0x20]) # OP_DATA_32
script += self.hashlock # 32 bytes hash
script += bytes([0x76, 0xa9, 0x14]) # OP_HASH256 <32 bytes> OP_EQUALVERIFY
script += self.receiver_pubkey
script += bytes([0xac]) # OP_CHECKSIG
# ELSE branch: timelock path
script += bytes([0x67]) # OP_ELSE
# OP_CHECKSEQUENCEVERIFY
script += bytes([0xb2]) # OP_CHECKSEQUENCEVERIFY
script += bytes([0x75]) # OP_DROP
script += bytes([0x76, 0xa9, 0x14]) # OP_DUP OP_HASH160 <pubkey>
script += self.sender_pubkey
script += bytes([0x88, 0xac]) # OP_EQUALVERIFY OP_CHECKSIG
script += bytes([0x68]) # OP_ENDIF
return script
def _compute_script_hash(self):
"""計算 SHA256 腳本哈希"""
return hashlib.sha256(self.redeem_script).digest()
def _create_address(self):
"""創建 P2WSH 地址"""
from bech32 import encode
return encode('bc', 0, self.script_hash)
def get_hashlock_secret(self):
"""生成原像(secret),用於解鎖"""
return secrets.token_bytes(32)
def create_hashlock_witness(self, secret, receiver_signature):
"""創建 Hashlock 路徑的見證數據"""
return {
'signature': receiver_signature.hex(),
'secret': secret.hex(),
'script': self.redeem_script.hex()
}
def create_timelock_witness(self, sender_signature):
"""創建 Timelock 路徑的見證數據"""
# 需要包含 sequence 來表示相對時間鎖
return {
'signature': sender_signature.hex(),
'sequence': self.timeout_blocks.to_bytes(4, 'little').hex(),
'script': self.redeem_script.hex()
}
# 使用示例
if __name__ == "__main__":
# 假設的公鑰
sender_pubkey = bytes.fromhex("0212a876..." * 33)
receiver_pubkey = bytes.fromhex("0234b567..." * 33)
# 創建 HTLC
# hashlock = SHA256("secret_password")
secret = b"my_secret_password_12345"
hashlock = hashlib.sha256(secret).digest()
htlc = HTLC(
sender_pubkey=sender_pubkey,
receiver_pubkey=receiver_pubkey,
amount=100000, # 0.001 BTC
timeout_blocks=144, # 約 24 小時
hashlock=hashlock
)
print(f"HTLC P2WSH 地址: {htlc.p2wsh_address}")
print(f"贖回腳本: {htlc.redeem_script.hex()}")
print(f"原像哈希: {hashlock.hex()}")
print(f"原像: {secret.hex()}")
4.4 Bitcoin Core 實現 HTLC
# 1. 使用 Bitcoin Core 創建 HTLC 測試
# 首先創建兩個錢包
bitcoin-cli -rpcpassword=bitcoinpassword createwallet "alice"
bitcoin-cli -rpcpassword=bitcoinpassword createwallet "bob"
# 2. 生成地址和資助
ALICE_ADDR=$(bitcoin-cli -rpcpassword=bitcoinpassword -rpcwallet=alice getnewaddress)
BOB_ADDR=$(bitcoin-cli -rpcpassword=bitcoinpassword -rpcwallet=bob getnewaddress)
# 資助錢包
MINER_ADDR=$(bitcoin-cli -rpcpassword=bitcoinpassword getnewaddress)
bitcoin-cli -rpcpassword=bitcoinpassword generatetoaddress 200 $MINER_ADDR
# 3. 創建 HTLC 的原始交易
# 這需要手動構造,因為 Bitcoin Core RPC 不直接支持 HTLC
# 首先,定義 HTLC 贖回腳本
# HTLC 腳本(十六進制)
HTLC_SCRIPT="6376a914<hash_of_alice_pubkey>88ac670068"
# 實際使用時需要完整的 HTLC 腳本
# 4. 使用 sendrawtransaction 廣播 HTLC 交易
# 見證格式:[signature] [secret] HTLC_script
第五章:Miniscript 實戰
5.1 Miniscript 簡介
Miniscript 是比特幣腳本的策略性子集,由 Pieter Wuille 等人提出,簡化了複雜比特幣腳本的創建和安全性分析。
常見 Miniscript 表達式:
| Miniscript | Bitcoin Script | 說明 |
|---|---|---|
| pk(A) | A OP_CHECKSIG | 公鑰檢查 |
| pkh(A) | OPDUP OPHASH160 OP_EQUALVERIFY | P2PKH |
| multi(k, A, B, ...) | k <keys> k OP_CHECKMULTISIG | 多籤 |
| and_v(vc:pkh(A),tn:older(144)) | <sig A> OPVERIFY 144 OPCHECKSEQUENCEVERIFY | 帶時間的多籤 |
| or_c(pk(A),s:pk(B)) | OPIF OPCHECKSIGVERIFY ELSE OPSWAP OPCHECKSIG ENDIF | 雙選擇 |
| thresh(2,w:pk(A),w:pk(B),w:pk(C)) | 2 <A> <B> <C> 3 OP_CHECKMULTISIG | 2-of-3 |
5.2 Miniscript 編譯器使用
安裝 miniscript.fun:
# 從源碼編譯
git clone https://github.com/sipa/miniscript.git
cd miniscript
./autogen.sh
./configure
make
# 或使用 Docker
docker pull sipa/miniscript
docker run -it sipa/miniscript
Miniscript 範例:
# 1. 創建一個 2-of-3 多籤 Miniscript
# 表達式:multi(2, A, B, C)
# 2. 分析 Miniscript
./miniscript/bin/miniscript "multi(2, [alekfire's pubkey], [bob's pubkey], [charlie's pubkey])"
# 輸出:
# {
# "script": "<2> <pubkey1> <pubkey2> <pubkey3> 3 OP_CHECKMULTISIG",
# "type": "multi",
# "address": "3...",
# "satisfiability": "We can produce witnesses for all but 0 signatures."
# }
# 3. 生成描述符
./miniscript/bin/miniscript -d "wsh(multi(2, [A], [B], [C]))"
# 輸出:
# wsh(multi(2,A,B,C))#<checksum>
5.3 Miniscript 與 Bitcoin Core
Bitcoin Core 支持 Miniscript 描述符:
# 1. 使用 Miniscript 創建錢包
bitcoin-cli -rpcpassword=bitcoinpassword createwallet "miniscript_wallet"
# 2. 導入 Miniscript 描述符
bitcoin-cli -rpcpassword=bitcoinpassword -rpcwallet=miniscript_wallet \
importdescriptors \
'[{
"desc": "wsh(multi(2,tpubD9DA.../0/*,tpubD9DA.../0/*,tpubD9DA.../0/*))#testChecksum",
"timestamp": "now",
"range": [0, 100],
"watchonly": false,
"label": "2-of-3 multisig"
}]'
# 3. 生成地址
bitcoin-cli -rpcpassword=bitcoinpassword -rpcwallet=miniscript_wallet \
getnewaddress
# 4. 列出所有地址
bitcoin-cli -rpcpassword=bitcoinpassword -rpcwallet=miniscript_wallet \
listdescriptors
第六章:比特幣節點架設完整命令序列
6.1 主網全節點架設
完整步驟:
#!/bin/bash
# setup_bitcoin_node.sh
# 1. 更新系統
sudo apt-get update && sudo apt-get upgrade -y
# 2. 安裝依賴
sudo apt-get install -y \
build-essential \
libtool \
autotools-dev \
automake \
pkg-config \
libssl-dev \
libevent-dev \
libboost-system-dev \
libboost-filesystem-dev \
libboost-chrono-dev \
libboost-test-dev \
libboost-thread-dev \
libsqlite3-dev \
bsdmainutils \
libdb-dev \
libdb++-dev
# 3. 下載 Bitcoin Core
cd /tmp
wget https://bitcoincore.org/bin/bitcoin-core-27.0/bitcoin-27.0-x86_64-linux-gnu.tar.gz
wget https://bitcoincore.org/bin/bitcoin-core-27.0/SHA256SUMS
wget https://bitcoincore.org/bin/bitcoin-core-27.0/SHA256SUMS.asc
# 4. 驗證簽名(需要先取得並驗證開發者 GPG 鑰匙)
sha256sum --check SHA256SUMS
# 5. 安裝
sudo tar -xzf bitcoin-27.0-x86_64-linux-gnu.tar.gz -C /usr/local/bin --strip-components=2 bitcoin-27.0/bin/bitcoin{d,-cli,-tx,util} 2>/dev/null
sudo tar -xzf bitcoin-27.0-x86_64-linux-gnu.tar.gz -C /usr/local/ bitcoin-27.0/include bitcoin-27.0/lib
sudo strip /usr/local/bin/bitcoin*
# 6. 建立用戶
sudo useradd -m -s /bin/bash bitcoin
sudo mkdir -p /home/bitcoin/.bitcoin
sudo chown -R bitcoin:bitcoin /home/bitcoin/.bitcoin
# 7. 創建配置文件
sudo -u bitcoin tee /home/bitcoin/.bitcoin/bitcoin.conf << 'EOF'
# 網路配置
server=1
daemon=1
maxconnections=8
# RPC 配置
rpcuser=bitcoinuser
rpcpassword=CHANGE_THIS_PASSWORD
rpcport=8332
rpcbind=127.0.0.1
# 區塊存儲配置
prune=0
dbcache=4096
# 安全性
maxuploadtarget=5000
blocksonly=0
# 附加配置
logips=1
EOF
sudo chmod 600 /home/bitcoin/.bitcoin/bitcoin.conf
sudo chown bitcoin:bitcoin /home/bitcoin/.bitcoin/bitcoin.conf
# 8. 創建 systemd 服務
sudo tee /etc/systemd/system/bitcoind.service << 'EOF'
[Unit]
Description=Bitcoin Daemon
After=network.target
[Service]
ExecStart=/usr/local/bin/bitcoind -daemonwait -pid=/run/bitcoind/bitcoind.pid
PIDFile=/run/bitcoind/bitcoind.pid
User=bitcoin
Restart=on-failure
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
ReadWriteDirectories=/home/bitcoin/.bitcoin
[Install]
WantedBy=multi-user.target
EOF
# 9. 啟動服務
sudo mkdir -p /run/bitcoind
sudo chown bitcoin:bitcoin /run/bitcoind
sudo systemctl daemon-reload
sudo systemctl enable bitcoind
sudo systemctl start bitcoind
# 10. 監控啟動
sleep 5
sudo systemctl status bitcoind
# 11. 檢查同步狀態
sudo -u bitcoin bitcoin-cli -rpcpassword=CHANGE_THIS_PASSWORD getblockchaininfo
# 12. 查看節點連接
sudo -u bitcoin bitcoin-cli -rpcpassword=CHANGE_THIS_PASSWORD getnetworkinfo
6.2 閃電網路節點架設(Lncli 完整命令)
LND 安裝和配置:
#!/bin/bash
# setup_lnd.sh
# 1. 安裝 Go(如果需要)
wget https://go.dev/dl/go1.22.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.22.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
# 2. 安裝 LND
git clone https://github.com/lightningnetwork/lnd.git
cd lnd
make install
# 3. 創建 LND 配置
mkdir -p ~/.lnd
cat > ~/.lnd/lnd.conf << 'EOF'
[Application Options]
debuglevel=info
maxpendingchannels=5
alias=MyLightningNode
color=#68E5FF
[Bitcoin]
bitcoin.active=1
bitcoin.mainnet=1
bitcoin.node=bitcoind
[bitcoind]
bitcoind.rpchost=127.0.0.1
bitcoind.rpcuser=bitcoinuser
bitcoind.rpcpass=CHANGE_THIS_PASSWORD
bitcoind.zmqpubrawblock=tcp://127.0.0.1:18501
bitcoind.zmqpubrawtx=tcp://127.0.0.1:18502
[autopilot]
autopilot.active=1
autopilot.maxchannels=10
autopilot.allocation=0.6
EOF
# 4. 創建錢包
lncli create
# 5. 獲取節點資訊
lncli getinfo
# 6. 生成比特幣接收地址
lncli newaddress p2wkh
# 7. 查看通道列表
lncli listchannels
# 8. 打開通道
lncli openchannel --node_key=<peer_pubkey> --local_amt=500000 --push_amt=250000
# 9. 發送支付
lncli sendpayment --dest=<destination_pubkey> --amt=<amount_satoshis>
# 10. 創建和接收發票
lncli addinvoice --amt=<amount_satoshis>
lncli lookupinvoice <payment_request>
6.3 Regtest 測試環境快速架設
#!/bin/bash
# quick_regtest_setup.sh
# 1. 啟動 Regtest 節點
bitcoind -regtest -daemon \
-rpcuser=regtest \
-rpcpassword=regtest123 \
-rpcport=18443
# 2. 等待節點啟動
sleep 3
# 3. 創建錢包
bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
createwallet "testwallet" false false "" false false
# 4. 生成測試地址
ALICE=$(bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
-rpcwallet=testwallet getnewaddress "alice")
BOB=$(bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
-rpcwallet=testwallet getnewaddress "bob")
MINER=$(bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
getnewaddress "miner")
# 5. 挖出初始區塊(100+)
bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
generatetoaddress 110 $MINER
# 6. 檢查 Alice 的餘額
bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
-rpcwallet=testwallet getbalance
# 7. 發送比特幣給 Alice
TXID=$(bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
sendtoaddress $ALICE 10)
echo "Transaction ID: $TXID"
# 8. 挖出一個區塊確認交易
bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
generatetoaddress 1 $MINER
# 9. 檢查交易狀態
bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
-rpcwallet=testwallet gettransaction $TXID
# 10. 查看 UTXO
bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=regtest123 \
-rpcwallet=testwallet listunspent
結論
本指南提供了比特幣腳本編程的完整實戰教程,涵蓋從基礎環境搭建到進階應用的各個層面。所有程式碼範例均可在 Regtest 或測試網環境中實際運作,讀者可以通過動手實踐深入理解比特幣腳本的工作原理。
比特幣腳本語言的設計雖然簡單,但功能強大。通過組合基本操作碼,可以實現從簡單支付到複雜合約的各種應用場景。掌握比特幣腳本不僅能幫助開發者創建更安全的比特幣應用,也能讓普通用戶更好地理解比特幣網路的安全機制。
參考文獻
- Bitcoin Developer Reference. "Script." https://developer.bitcoin.org/reference/script.html
- Bitcoin Optech. "Bitcoin Scripting." https://bitcoinops.org/en/topics/scanning/
- Bitcoin Wiki. "Script." https://en.bitcoin.it/wiki/Script
- BIP-341: Taproot. https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
- BIP-342: Taproot Script Validation. https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki
- Miniscript Website. https://bitcoin.sipa.be/miniscript/
- Mastering Bitcoin, 2nd Edition. Andreas M. Antonopoulos. O'Reilly Media, 2017.
相關文章
- 比特幣腳本語言入門 — 比特幣腳本語言基礎教學:深入理解 Bitcoin Script 的基本指令與運作原理,包括常見腳本類型與交易驗證流程。
- 比特幣腳本編程實戰教學完整指南:從環境架設到生產部署 — 提供從環境架設到生產部署的完整比特幣腳本編程指南,包含 Python 和 JavaScript 程式碼範例。涵蓋 P2PKH、P2SH、P2WSH 腳本創建、時間鎖定腳本(CLTV/CSV)、HTLC 原子交換、閃電網路通道合約等進階應用。
- 比特幣腳本編程進階實戰:從理論到部署 — 深入講解比特幣腳本指令集、腳本類型開發流程、腳本調試方法,透過多個實際案例展示如何構建安全的比特幣腳本應用,包括多簽名、時間鎖、HTLC 等。
- 比特幣地址類型與腳本類型技術深度比較:從 P2PK 到 P2TR 的完整演化與實務操作 — 本文從密碼學基礎、腳本設計、位元組效率、隱私保護和實務操作五個維度,全面比較比特幣主要的地址類型與腳本類型。涵蓋 P2PK、P2PKH、P2SH、P2WPKH、P2WSH、P2TR 的完整演化歷程,提供詳細的技術規格分析、Python/C 程式碼範例以及真實區塊鏈數據,幫助開發者和進階用戶理解不同地址類型的適用場景與選擇策略。
- OP_VAULT 技術詳解:比特幣資產保護的新範式 — 全面解析 OP_VAULT 提案的設計原理、實現機制、安全特性以及實際應用場景,包括企業比特幣存儲、遺產規劃和機構托管等案例。
延伸閱讀與來源
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!