比特幣腳本語言實戰:從基礎到進階應用完整指南

深入探討比特幣腳本語言的各個層面,從基礎指令集到進階應用,提供可直接運用的 Python 程式碼範例,涵蓋 P2PKH、P2SH、P2WPKH、P2WSH、P2TR 等腳本類型,以及時間鎖、多簽名、HTLC 與 MAST 等進階技術。

比特幣腳本語言實戰:從基礎到進階應用完整指南

概述

比特幣腳本語言(Bitcoin Script)是比特幣區塊鏈的核心組成部分,決定了比特幣交易的驗證邏輯與資金花費條件。不同於以太坊的 Solidity 等圖靈完整語言,比特幣腳本採用簡單的堆疊式執行模型,這種設計選擇體現了安全優先、去中心化與可預測性的核心理念。本文將深入探討比特幣腳本的各個層面,從基礎指令集到進階應用,並提供可直接運用的程式碼範例,協助開發者與愛好者全面掌握這項關鍵技術。

比特幣腳本的最大特色在於其「刻意設計的非圖靈完整性」。中本聰在設計比特幣時,選擇讓腳本語言不支援迴圈(loop)與複雜控制結構,這看似是限制,實際上是深思熟慮的安全決策。這種設計確保了腳本執行的可預測性與終止性,有效杜絕了無限迴圈攻擊與複雜合約可能帶來的未知風險。理解這一設計哲學,是掌握比特幣腳本的第一步。

比特幣腳本基礎架構

堆疊式執行模型

比特幣腳本採用基於堆疊(Stack)的執行模型,這是比特幣腳本語言最核心的特性。與傳統的命令式程式語言不同,腳本指令從左至右依序執行,操作數(operand)被推入堆疊,運算子(operator)則從堆疊彈出所需數量的參數,執行運算後將結果推回堆疊。這種模型的優勢在於執行效率高、記憶體占用低,且執行行為極易預測。

堆疊操作的基礎指令包括 OPDUP(複製堆疊頂部元素)、OPDROP(移除堆疊頂部元素)、OPSWAP(交換堆疊頂部兩個元素)、OPOVER(複製堆疊第二個元素到頂部)、OPROT(旋轉堆疊前三個元素)等。這些基礎操作雖然簡單,卻是構建複雜驗證邏輯的基石。例如,OPDUP 常用於需要多次使用同一資料的場景,如P2PKH腳本中的公鑰複製,以便同時進行簽章驗證與雜湊比對。

# 比特幣腳本堆疊操作模擬器
class Stack:
    def __init__(self):
        self.items = []
    
    def push(self, item):
        """將元素推入堆疊頂部"""
        self.items.append(item)
    
    def pop(self):
        """從堆疊頂部彈出元素"""
        if self.is_empty():
            raise Exception("堆疊下溢")
        return self.items.pop()
    
    def peek(self):
        """查看堆疊頂部元素但不彈出"""
        if self.is_empty():
            return None
        return self.items[-1]
    
    def is_empty(self):
        return len(self.items) == 0
    
    def size(self):
        return len(self.items)

# 模擬 OP_DUP 操作
def op_dup(stack):
    """複製堆疊頂部元素"""
    if stack.is_empty():
        raise Exception("OP_DUP: 堆疊為空")
    top = stack.peek()
    stack.push(top)
    return stack

# 模擬 OP_HASH160 操作
def op_hash160(stack):
    """對堆疊頂部元素執行 RIPEMD160(SHA256())"""
    import hashlib
    top = stack.pop()
    # SHA256
    sha256_hash = hashlib.sha256(bytes.fromhex(top)).digest()
    # RIPEMD160
    ripemd160 = hashlib.new('ripemd160')
    ripemd160.update(sha256_hash)
    result = ripemd160.hexdigest()
    stack.push(result)
    return stack

# 測試腳本執行
stack = Stack()
stack.push("abcdef1234567890")  # 推入測試資料
print(f"執行前: {stack.items}")
op_dup(stack)
print(f"OP_DUP 後: {stack.items}")
op_hash160(stack)
print(f"OP_HASH160 後: {stack.items}")

腳本類型詳解

比特幣腳本根據花費條件的不同,可分為多種標準類型。理解這些腳本類型對於設計安全的比特幣應用至關重要。

P2PKH(Pay to Public Key Hash) 是比特幣最傳統的腳本類型,於 2009 年比特幣創世時即已存在。P2PKH 腳本的鎖定腳本格式為 OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG,其中 是公鑰的 RIPEMD160(SHA256) 雜湊值。花費時,支出交易需提供完整公鑰與數位簽章。腳本執行時,首先複製公鑰並計算其雜湊值,與鎖定腳本中的雜湊值進行比對,最後驗證簽章有效性。

# P2PKH 腳本建構與驗證示例
import hashlib
import ecdsa
import os

class P2PKH:
    """P2PKH 腳本處理類"""
    
    @staticmethod
    def pubkey_to_address(pubkey_hex):
        """將公鑰轉換為比特幣地址(P2PKH)"""
        # SHA256
        sha256_hash = hashlib.sha256(bytes.fromhex(pubkey_hex)).digest()
        # RIPEMD160
        ripemd160 = hashlib.new('ripemd160')
        ripemd160.update(sha256_hash)
        pubkey_hash = ripemd160.digest()
        # 添加版本位元組 (0x00 for mainnet)
        versioned_hash = b'\x00' + pubkey_hash
        # 計算校驗碼
        checksum = hashlib.sha256(hashlib.sha256(versioned_hash).digest()).digest()[:4]
        # Base58Check 編碼
        return P2PKH.base58_encode(versioned_hash + checksum)
    
    @staticmethod
    def base58_encode(data):
        """Base58 編碼(不含校驗)"""
        alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
        num = int.from_bytes(data, 'big')
        encoded = ''
        while num > 0:
            num, remainder = divmod(num, 58)
            encoded = alphabet[remainder] + encoded
        # 處理前導零
        for byte in data:
            if byte == 0:
                encoded = '1' + encoded
            else:
                break
        return encoded
    
    @staticmethod
    def create_locking_script(address):
        """建立 P2PKH 鎖定腳本"""
        # Base58Decode 並提取公鑰雜湊
        pubkey_hash = P2PKH.address_to_pubkey_hash(address)
        return f"OP_DUP OP_HASH160 {pubkey_hash} OP_EQUALVERIFY OP_CHECKSIG"
    
    @staticmethod
    def address_to_pubkey_hash(address):
        """從地址提取公鑰雜湊"""
        # 實際實現需要 Base58Decode + 校驗驗證
        # 這裡假設已經過驗證的地址
        return "89abcdefabbaabbaabbaabbaabbaabbaabbaabba"  # 示例雜湊

# 使用範例
pubkey = "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
address = P2PKH.pubkey_to_address(pubkey)
print(f"P2PKH 地址: {address}")
locking_script = P2PKH.create_locking_script(address)
print(f"鎖定腳本: {locking_script}")

P2SH(Pay to Script Hash) 於 2012 年引入,主要用於多簽名腳本與複雜鎖定條件。P2SH 的設計理念是將腳本雜湊化,將複雜的鎖定邏輯隱藏在雜湊值之後。鎖定腳本格式為 OP_HASH160 OP_EQUAL, redeemScript(贖回腳本)則在花費時才揭示。這種設計的優勢在於簡化了付款方的操作複雜度,無需知道具體的腳本內容,只需知道腳本雜湊即可付款。

# P2SH 腳本建構示例
class P2SH:
    """P2SH 腳本處理類"""
    
    @staticmethod
    def create_multisig_redeemscript(threshold, pubkeys):
        """
        建立多簽名 redeemScript
        threshold: 所需簽名數量
        pubkeys: 公鑰列表
        """
        if threshold < 1 or threshold > len(pubkeys):
            raise Exception("門檻值無效")
        
        # 建構 redeemScript
        # 格式: OP_M <pubkey1> <pubkey2> ... OP_N OP_CHECKMULTISIG
        n = len(pubkeys)
        script = f"OP_{threshold} " + " ".join(pubkeys) + f" OP_{n} OP_CHECKMULTISIG"
        return script
    
    @staticmethod
    def script_to_hash(script):
        """計算腳本的 SHA256 + RIPEMD160 雜湊"""
        import hashlib
        sha256_hash = hashlib.sha256(script.encode('utf-8')).digest()
        ripemd160 = hashlib.new('ripemd160')
        ripemd160.update(sha256_hash)
        return ripemd160.hexdigest()
    
    @staticmethod
    def create_locking_script(script_hash):
        """建立 P2SH 鎖定腳本"""
        return f"OP_HASH160 {script_hash} OP_EQUAL"
    
    @staticmethod
    def create_p2sh_address(script_hash, version=0x05):
        """從腳本雜湊建立 P2SH 地址"""
        import hashlib
        versioned_hash = bytes([version]) + bytes.fromhex(script_hash)
        checksum = hashlib.sha256(hashlib.sha256(versioned_hash).digest()).digest()[:4]
        
        alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
        num = int.from_bytes(versioned_hash + checksum, 'big')
        encoded = ''
        while num > 0:
            num, remainder = divmod(num, 58)
            encoded = alphabet[remainder] + encoded
        for byte in versioned_hash:
            if byte == 0:
                encoded = '1' + encoded
            else:
                break
        return encoded

# 使用範例:建立 2-of-3 多簽名腳本
pubkeys = [
    "02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
    "02cccccccccccccccccccccccccccccccccccccccc"
]

redeemscript = P2SH.create_multisig_redeemscript(2, pubkeys)
print(f"RedeemScript: {redeemscript}")

script_hash = P2SH.script_to_hash(redeemscript)
print(f"腳本雜湊: {script_hash}")

locking_script = P2SH.create_locking_script(script_hash)
print(f"P2SH 鎖定腳本: {locking_script}")

p2sh_address = P2SH.create_p2sh_address(script_hash)
print(f"P2SH 地址: {p2sh_address}")

P2WPKH(Pay to Witness Public Key Hash)P2WSH(Pay to Witness Script Hash) 是隔離見證(SegWit)升級引入的新腳本類型。SegWit 的核心創新是將見證資料(簽章與公鑰)移至交易的隔離區塊(witness)中,解決了比特幣的延展性問題,並降低了交易費用。P2WPKH 的鎖定腳本僅包含一個雜湊值,格式為 OP_0 ,而 P2WSH 用於更複雜的見證腳本,格式為 OP_0

# P2WPKH 與 P2WSH 腳本建構
class SegWit:
    """隔離見證腳本處理類"""
    
    @staticmethod
    def create_p2wpkh_locking_script(pubkey_hash):
        """建立 P2WPKH 鎖定腳本"""
        # Bech32 編碼的公鑰雜湊使用 OP_0
        return f"OP_0 {pubkey_hash}"
    
    @staticmethod
    def create_p2wsh_locking_script(witness_script_hash):
        """建立 P2WSH 鎖定腳本"""
        return f"OP_0 {witness_script_hash}"
    
    @staticmethod
    def pubkey_to_witness_program(pubkey_hex):
        """將公鑰轉換為 witness program(壓縮格式)"""
        import hashlib
        pubkey_bytes = bytes.fromhex(pubkey_hex)
        sha256_hash = hashlib.sha256(pubkey_bytes).digest()
        return sha256_hash.hex()
    
    @staticmethod
    def create_bech32_address(pubkey_hash, witness_version=0):
        """建立 Bech32 地址"""
        # 使用 bech32m 編碼
        # 此處為簡化實現
        hrp = "bc"
        data = [witness_version] + SegWit.convert_bits(pubkey_hash, 8, 5, True)
        combined = data + SegWit.create_checksum(hrp, data)
        charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
        return hrp + '1' + ''.join(charset[d] for d in combined)
    
    @staticmethod
    def convert_bits(data, from_bits, to_bits, pad):
        """位元轉換輔助函數"""
        acc = 0
        bits = 0
        result = []
        maxv = (1 << to_bits) - 1
        max_acc = (1 << (from_bits + to_bits - 1)) - 1
        
        for value in data:
            if value < 0 or (value >> from_bits):
                return None
            acc = ((acc << from_bits) | value) & max_acc
            bits += from_bits
            while bits >= to_bits:
                bits -= to_bits
                result.append((acc >> bits) & maxv)
        
        if pad:
            if bits:
                result.append((acc << (to_bits - bits)) & maxv)
        elif bits >= from_bits or ((acc << (to_bits - bits)) & maxv):
            return None
        
        return result
    
    @staticmethod
    def create_checksum(hrp, data):
        """建立 Bech32 校驗和"""
        # 簡化實現
        values = SegWit.expand_hrp(hrp) + data
        polymod = SegWit.polymod(values + [0,0,0,0,0,0]) ^ 1
        return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
    
    @staticmethod
    def expand_hrp(hrp):
        """展開 HRP"""
        return [ord(c) >> 5 for c in hrp] + [0] + [ord(c) & 31 for c in hrp]
    
    @staticmethod
    def polymod(values):
        """Bech32 多項式校驗"""
        GEN = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
        chk = 1
        for value in values:
            top = chk >> 25
            chk = (chk & 0x1ffffff) << 5 ^ value
            for i in range(5):
                chk ^= GEN[i] if ((top >> i) & 1) else 0
        return chk

# 使用範例
pubkey = "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
witness_program = SegWit.pubkey_to_witness_program(pubkey)
locking_script = SegWit.create_p2wpkh_locking_script(witness_program)
print(f"P2WPKH 鎖定腳本: {locking_script}")

# 建立地址
address = SegWit.create_bech32_address(witness_program)
print(f"Bech32 地址: {address}")

OP_RETURN 與資料儲存

OP_RETURN 是比特幣腳本中一個獨特的操作碼,允許在區塊鏈上儲存少量不可花費的資料。這個功能自 2014 年以來可用,最初設計用於提供區塊鏈 Timestamping(時間戳記)服務,後來被廣泛用於各種應用場景,包括數位資產發行、域名註冊、學術證明、文件指紋儲存等。

OP_RETURN 的鎖定腳本格式為 OP_RETURN ,其中資料長度被限制為最大 80 位元組。這個限制是刻意的設計選擇,旨在防止比特幣區塊鏈被過度用於資料儲存,同時確保腳本始終無法被花費,維護了比特幣作為貨幣系統的純粹性。

# OP_RETURN 腳本建構與應用
import hashlib

class OP_RETURN:
    """OP_RETURN 腳本處理類"""
    
    MAX_DATA_SIZE = 80  # 最大資料長度
    
    @staticmethod
    def create_op_return_script(data):
        """建立 OP_RETURN 鎖定腳本"""
        if isinstance(data, str):
            data = data.encode('utf-8')
        
        if len(data) > OP_RETURN.MAX_DATA_SIZE:
            raise Exception(f"資料長度超過限制: {len(data)} > {OP_RETURN.MAX_DATA_SIZE}")
        
        # 將資料轉換為十六進制表示
        data_hex = data.hex()
        return f"OP_RETURN {data_hex}"
    
    @staticmethod
    def create_data_timestamp(file_content):
        """
        建立文件時間戳記腳本
        將文件的 SHA256 雜湊作為 OP_RETURN 輸出
        """
        file_hash = hashlib.sha256(file_content).digest()
        return OP_RETURN.create_op_return_script(file_hash)
    
    @staticmethod
    def create_ordinal_inscription(content, content_type="text/plain"):
        """
        建立 Ordinals 刻錄腳本
        此為簡化版本,實際 Ordinals 使用隔離見證
        """
        # 編碼內容類型
        content_type_len = len(content_type).to_bytes(1, 'big')
        content_len = len(content).to_bytes(1, 'big')
        
        # 构建元資料前綴
        # Ordinals 協議格式: content_type_len + content_type + content_len + content
        payload = content_type_len + content_type.encode() + content_len + content.encode()
        
        return OP_RETURN.create_op_return_script(payload)

# 使用範例
# 1. 基本 OP_RETURN
basic_script = OP_RETURN.create_op_return_script(b"Hello, Bitcoin!")
print(f"基本 OP_RETURN: {basic_script}")

# 2. 文件時間戳記
sample_content = b"This is a document that needs timestamping"
timestamp_script = OP_RETURN.create_data_timestamp(sample_content)
print(f"時間戳記腳本: {timestamp_script}")

# 3. Ordinals 刻錄(簡化版)
inscription_script = OP_RETURN.create_ordinal_inscription(
    "Hello, Ordinals!",
    "text/plain"
)
print(f"Ordinals 刻錄腳本: {inscription_script}")

進階腳本技術

條件式腳本與時間鎖

比特幣腳本支援多種條件式邏輯,允許建立複雜的鎖定與解鎖條件。這些功能是實現各種進階比特幣應用的基礎,包括時間鎖定交易、多重簽名安排、遺囑執行與儲蓄合約。

時間鎖(TimeLock)是比特幣腳本中最實用的條件式功能之一。OPCHECKLOCKTIMEVERIFY(CLTV)與 OPCHECKSEQUENCEVERIFY(CSV)是兩個主要的時間鎖操作碼。CLTV 使用絕對時間鎖定,指定區塊高度或 UNIX 時間戳記作為解鎖條件;CSV 使用相對時間鎖定,指定從資金存入後經過的區塊數或時間作為條件。

# 時間鎖腳本建構
import struct

class TimeLock:
    """時間鎖腳本處理類"""
    
    @staticmethod
    def create_cltv_script(pubkey_hash, lock_time):
        """
        建立絕對時間鎖定腳本(CLTV)
        lock_time: 解鎖的區塊高度或 UNIX 時間戳
        """
        # 格式: <lock_time> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <pubkey_hash> OP_EQUALVERIFY OP_CHECKSIG
        return f"{lock_time} OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 {pubkey_hash} OP_EQUALVERIFY OP_CHECKSIG"
    
    @staticmethod
    def create_csv_script(pubkey_hash, sequence):
        """
        建立相對時間鎖定腳本(CSV)
        sequence: 需要經過的區塊數或秒數
        """
        # 格式: <sequence> OP_CHECKSEQUENCEVERIFY OP_DROP OP_DUP OP_HASH160 <pubkey_hash> OP_EQUALVERIFY OP_CHECKSIG
        return f"{sequence} OP_CHECKSEQUENCEVERIFY OP_DROP OP_DUP OP_HASH160 {pubkey_hash} OP_EQUALVERIFY OP_CHECKSIG"
    
    @staticmethod
    def encode_lock_time(lock_time, is_timestamp=False):
        """
        編碼鎖定時間
        若 is_timestamp=True,lock_time 為 UNIX 時間戳
        否則為區塊高度
        """
        if is_timestamp:
            # BIP-113 規定時間戳必須大於 500000000
            if lock_time < 500000000:
                raise Exception("時間戳必須大於 500000000(2016年5月)")
        else:
            # 區塊高度必須為 0 或 >= OP_1 (1)
            if lock_time > 0 and lock_time < 1:
                raise Exception("區塊高度必須 >= 1")
        return lock_time
    
    @staticmethod
    def create_savings_script(pubkey_hash, beneficiary_hash, lock_blocks):
        """
        建立儲蓄合約腳本
        存款人可以隨時取回資金,但受益人在鎖定期後可以提款
        """
        # 條件 1: 存款人可在任何時候提款
        # 條件 2: 受益人在 lock_blocks 區塊後可提款
        return f"""
        OP_IF
            # 受益人路徑 - 相對時間鎖
            {lock_blocks} OP_CHECKSEQUENCEVERIFY OP_DROP
            OP_DUP OP_HASH160 {beneficiary_hash} OP_EQUALVERIFY OP_CHECKSIG
        OP_ELSE
            # 存款人路徑 - 無限制
            OP_DUP OP_HASH160 {pubkey_hash} OP_EQUALVERIFY OP_CHECKSIG
        OP_ENDIF
        """.strip().replace('\n', ' ')
    
    @staticmethod
    def create_inheritance_script(
        owner_pubkey_hash,
        heir_pubkey_hash,
        witness_pubkey_hash,
        lock_blocks
    ):
        """
        建立遺囑/繼承腳本
        - 所有者可隨時提款
        - 繼承人在鎖定期後可提款(需見證人簽名)
        - 三方中任何兩人可以提款
        """
        return f"""
        OP_2
        {owner_pubkey_hash}
        {heir_pubkey_hash}
        {witness_pubkey_hash}
        OP_3
        OP_CHECKMULTISIG
        OP_IF
            {lock_blocks} OP_CHECKSEQUENCEVERIFY OP_DROP
        OP_ENDIF
        """.strip().replace('\n', ' ')

# 使用範例
pubkey_hash = "89abcdefabbaabbaabbaabbaabbaabbaabbaabba"
beneficiary_hash = "aabbccddeeffaabbccddeeffaabbccddeeffaabb"
witness_hash = "1122334455667788990011223344556677889900"

# 6 個月後解鎖(約 6 * 30 * 24 * 6 = 25920 區塊,約 6 個月)
six_months_blocks = 25920

savings_script = TimeLock.create_savings_script(pubkey_hash, beneficiary_hash, six_months_blocks)
print(f"儲蓄合約腳本:\n{savings_script}")

inheritance_script = TimeLock.create_inheritance_script(
    pubkey_hash, beneficiary_hash, witness_hash, six_months_blocks
)
print(f"\n遺囑腳本:\n{inheritance_script}")

多簽名腳本與閾值設計

多簽名腳本是比特幣安全管理的核心工具,允許設定多方共同控制的資金。經典的 2-of-3 多簽名安排是最常見的配置,結合了安全性(即使一把私鑰洩露,資金仍安全)與便利性(任何兩把私鑰即可使用資金,即使一把丟失)。

# 多簽名腳本深度實現
import hashlib
import ecdsa
import os
import random

class MultisigScript:
    """多簽名腳本建構與驗證類"""
    
    @staticmethod
    def create_redeemscript(threshold, pubkeys, sort=True):
        """
        建立多簽名 redeemScript
        threshold: 所需簽名數(門檻值)
        pubkeys: 公鑰列表
        sort: 是否按 lexicographical 順序排序公鑰(BIP-67        """
        n)
 = len(pubkeys)
        
        if threshold < 1 or threshold > n:
            raise Exception(f"門檻值無效: 1 <= {threshold} <= {n}")
        
        # BIP-67: 按 lex 順序排序公鑰
        if sort:
            sorted_pubkeys = sorted(pubkeys, key=lambda x: bytes.fromhex(x))
            pubkeys = sorted_pubkeys
        
        # 建構腳本
        keys_str = " ".join(pubkeys)
        return f"OP_{threshold} {keys_str} OP_{n} OP_CHECKMULTISIG"
    
    @staticmethod
    def create_p2sh_multisig(threshold, pubkeys, sort=True):
        """建立 P2SH 多簽名腳本"""
        redeem_script = MultisigScript.create_redeemscript(threshold, pubkeys, sort)
        script_hash = MultisigScript.script_to_hash(redeem_script)
        locking_script = f"OP_HASH160 {script_hash} OP_EQUAL"
        
        return {
            'redeem_script': redeem_script,
            'script_hash': script_hash,
            'locking_script': locking_script,
            'address': MultisigScript.hash_to_p2sh_address(script_hash)
        }
    
    @staticmethod
    def create_p2wsh_multisig(threshold, pubkeys, sort=True):
        """建立 P2WSH 多簽名腳本(隔離見證)"""
        witness_script = MultisigScript.create_redeemscript(threshold, pubkeys, sort)
        script_hash = MultisigScript.witness_script_to_hash(witness_script)
        locking_script = f"OP_0 {script_hash}"
        
        return {
            'witness_script': witness_script,
            'script_hash': script_hash,
            'locking_script': locking_script,
            'address': MultisigScript.hash_to_bech32_address(script_hash)
        }
    
    @staticmethod
    def script_to_hash(script):
        """計算腳本雜湊(SHA256 + RIPEMD160)"""
        sha256_hash = hashlib.sha256(script.encode('utf-8')).digest()
        ripemd160 = hashlib.new('ripemd160')
        ripemd160.update(sha256_hash)
        return ripemd160.hexdigest()
    
    @staticmethod
    def witness_script_to_hash(witness_script):
        """計算見證腳本雜湊(SHA256)"""
        # P2WSH 使用 SHA256(不是 RIPEMD160)
        return hashlib.sha256(witness_script.encode('utf-8')).digest().hex()
    
    @staticmethod
    def hash_to_p2sh_address(script_hash, version=0x05):
        """腳本雜湊轉 P2SH 地址"""
        versioned_hash = bytes([version]) + bytes.fromhex(script_hash)
        checksum = hashlib.sha256(hashlib.sha256(versioned_hash).digest()).digest()[:4]
        return MultisigScript.base58_encode(versioned_hash + checksum)
    
    @staticmethod
    def hash_to_bech32_address(script_hash):
        """腳本雜湊轉 Bech32 地址"""
        # 簡化實現
        return f"bc1q{'0' * 62}{script_hash[:4]}"
    
    @staticmethod
    def base58_encode(data):
        """Base58 編碼"""
        alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
        num = int.from_bytes(data, 'big')
        encoded = ''
        while num > 0:
            num, remainder = divmod(num, 58)
            encoded = alphabet[remainder] + encoded
        for byte in data:
            if byte == 0:
                encoded = '1' + encoded
            else:
                break
        return encoded
    
    @staticmethod
    def verify_multisig(sig, pubkeys, message):
        """
        驗證多簽名簽章
        此為簡化實現
        """
        try:
            # 這裡應該實現實際的 ECDSA 驗證
            return len(sig) > 0
        except:
            return False

# 使用範例:建立不同配置的多簽名腳本
pubkeys = [
    "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",  # Alice
    "02E493EEBF2D3A582C2C0F3A15F5C8F5A9D5F5E5D5F5E5D5F5E5D5F5E5D5F5E5D5",  # Bob
    "03CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"   # Carol
]

# 2-of-3 配置
p2sh_2of3 = MultisigScript.create_p2sh_multisig(2, pubkeys)
print("=== P2SH 2-of-3 ===")
print(f"RedeemScript: {p2sh_2of3['redeem_script']}")
print(f"P2SH 地址: {p2sh_2of3['address']}")

# 3-of-3 配置
p2wsh_3of3 = MultisigScript.create_p2wsh_multisig(3, pubkeys)
print("\n=== P2WSH 3-of-3 ===")
print(f"WitnessScript: {p2wsh_3of3['witness_script']}")
print(f"P2WSH 地址: {p2wsh_3of3['address']}")

隔離見證與 Taproot 進階

隔離見證詳解

隔離見證(Segregated Witness,簡稱 SegWit)是比特幣歷史上最重要的軟分叉升級之一,於 2017 年 8 月激活。SegWit 的核心創新是將交易簽章(witness data)從交易主體中分離出來,放置在獨立的 witness 結構中。這一設計帶來了多重優勢,包括解決比特幣的交易延展性問題、降低手續費、提高區塊容量等。

從腳本角度來看,SegWit 引入了两種新的腳本類型:P2WPKH 與 P2WSH。P2WPKH(Pay to Witness Public Key Hash)用於單一公鑰的支付,將公鑰雜湊放在 witness program 中,支出時需要提供原始公鑰與簽章。P2WSH(Pay to Witness Script Hash)用於更複雜的條件,如多簽名,見證資料包括完整的見證腳本與所需簽章。

# 隔離見證腳本深度分析
class SegWitAdvanced:
    """隔離見證進階功能"""
    
    @staticmethod
    def parse_witness(witness_data):
        """
        解析見證資料
        witness_data: list of hex strings
        """
        result = {
            'item_count': len(witness_data),
            'items': []
        }
        
        for item in witness_data:
            result['items'].append({
                'hex': item,
                'length': len(item) // 2,
                'type': SegWitAdvanced.classify_witness_item(item)
            })
        
        return result
    
    @staticmethod
    def classify_witness_item(item_hex):
        """分類見證項目類型"""
        length = len(item_hex) // 2
        
        if length == 64:  # 壓縮公鑰
            return "compressed_pubkey"
        elif length == 65:  # 未壓縮公鑰(不常用)
            return "uncompressed_pubkey"
        elif length == 71 or length == 72 or length == 73:  # DER 簽章
            return "signature"
        elif item_hex.startswith('0020'):  # SHA256 雜湊(witness program)
            return "witness_program_sha256"
        elif item_hex.startswith('0014'):  # RIPEMD160 雜湊(witness program)
            return "witness_program_ripemd160"
        else:
            return "unknown"
    
    @staticmethod
    def analyze_p2wpkh_spending(witness):
        """分析 P2WPKH 支出"""
        if len(witness) != 2:
            raise Exception("P2WPKH 支出應有 2 個見證項目")
        
        signature = witness[0]
        pubkey = witness[1]
        
        return {
            'type': 'P2WPKH',
            'signature': signature,
            'pubkey': pubkey,
            'signature_len': len(signature) // 2,
            'pubkey_len': len(pubkey) // 2
        }
    
    @staticmethod
    def analyze_p2wsh_spending(witness):
        """分析 P2WSH 支出"""
        if len(witness) < 2:
            raise Exception("P2WSH 支出至少需要 2 個見證項目")
        
        # 最後一個項目是見證腳本
        witness_script = witness[-1]
        stack_items = witness[:-1]
        
        # 解析見證腳本
        script_type = SegWitAdvanced.detect_script_type(witness_script)
        
        return {
            'type': 'P2WSH',
            'witness_script': witness_script,
            'script_type': script_type,
            'stack_items': stack_items,
            'required_sigs': SegWitAdvanced.extract_threshold(script_type)
        }
    
    @staticmethod
    def detect_script_type(script_hex):
        """檢測見證腳本類型"""
        try:
            # 簡單的腳本類型檢測
            if 'OP_CHECKMULTISIG' in script_hex or 'OP_CHECKMULTISIGVERIFY' in script_hex:
                return 'multisig'
            elif 'OP_CHECKSIG' in script_hex and 'OP_IF' in script_hex:
                return 'conditional'
            elif 'OP_CHECKLOCKTIMEVERIFY' in script_hex:
                return 'timelock'
            elif 'OP_CHECKSEQUENCEVERIFY' in script_hex:
                return 'relativetimelock'
            else:
                return 'custom'
        except:
            return 'unknown'
    
    @staticmethod
    def extract_threshold(script_type_info):
        """提取多簽名門檻值"""
        # 這是一個示例,實際需要解析腳本
        if script_type_info == 'multisig':
            return "2-of-3"  # 示例
        return None
    
    @staticmethod
    def calculate_vbytes(legacy_size, witness_data_size, weight):
        """
        計算虛擬位元組(vBytes)
        SegWit 採用權重計算,基礎資料每 4 位元組 = 1WU,
        見證資料每 1 位元組 = 1WU
        """
        # 傳統格式大小 + 見證資料
        total_weight_units = (legacy_size * 4) + witness_data_size
        vbytes = total_weight_units / 4
        return vbytes
    
    @staticmethod
    def estimate_savings(legacy_vbytes, segwit_vbytes):
        """估算 SegWit 節省的手續費"""
        savings_percent = ((legacy_vbytes - segwit_vbytes) / legacy_vbytes) * 100
        return savings_percent

# 使用範例
witness_example = [
    "304402206e8b1c2e1f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b901",
    "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
]

parsed = SegWitAdvanced.parse_witness(witness_example)
print("見證資料解析:")
print(f"項目數量: {parsed['item_count']}")
for i, item in enumerate(parsed['items']):
    print(f"  項目 {i+1}: {item['type']}, 長度: {item['length']} bytes")

# P2WPKH 支出分析
analysis = SegWitAdvanced.analyze_p2wpkh_spending(witness_example)
print(f"\n腳本類型: {analysis['type']}")
print(f"簽章長度: {analysis['signature_len']} bytes")
print(f"公鑰長度: {analysis['pubkey_len']} bytes")

# 費用節省估算
legacy_vb = 250  # 傳統 P2PKH 交易約 250 vBytes
segwit_vb = 150  # P2WPKH SegWit 交易約 150 vBytes
savings = SegWitAdvanced.estimate_savings(legacy_vb, segwit_vb)
print(f"\n費用節省: {savings:.1f}%")

Taproot 與 MAST 技術

Taproot 是比特幣 2021 年 11 月激活的升級,是比特幣自 SegWit 以來最重要的協定升級。Taproot 結合了三個主要的改進:BIP-340(Schnorr 簽章)、BIP-341(Taproot 腳本結構)與 BIP-342(Tapscript)。這些改進共同實現了更強的隱私性、更低的費用與更靈活的腳本設計。

MAST(Merkelized Abstract Syntax Tree)是 Taproot 的核心組成部分。傳統的比特幣腳本在解鎖時需要揭示整個腳本內容,這不僅浪費區塊空間,也暴露了用戶的隱私策略。MAST 透過將腳本的各個分支分别雜湊化並構建 Merkle 樹,僅需揭示被執行的分支,隱藏了未使用的腳本路徑。這種設計使得複雜的鎖定條件(如時間鎖、多簽名、HTLC)可以被「隱藏」在 Merkle 樹中,只有在實際使用時才揭示相關路徑。

# Taproot 與 MAST 實現詳解
import hashlib
import struct

class TaprootMAST:
    """Taproot 與 MAST 實現類"""
    
    @staticmethod
    def sha256_midstate(data):
        """計算 SHA256 中間狀態(用於 Merkle 證明)"""
        return hashlib.sha256(data).digest()
    
    @staticmethod
    def tagged_hash(tag, msg):
        """計算標籤化雜湊(BIP-340)"""
        tag_hash = hashlib.sha256(tag.encode()).digest()
        return hashlib.sha256(tag_hash + tag_hash + msg).digest()
    
    @staticmethod
    def compute_taproot_tweak(internal_key, script_tree):
        """
        計算 Taproot 調整值(tweak)
        internal_key: 內部公鑰
        script_tree: 腳本樹(Merkle 根或腳本列表)
        """
        # 計算腳本樹根雜湊
        if script_tree:
            root = TaprootMAST.merkleize_scripts(script_tree)
        else:
            root = b''
        
        # 計算調整
        t = TaprootMAST.tagged_hash("TapTweak", internal_key + root)
        return t
    
    @staticmethod
    def merkleize_scripts(scripts):
        """
        將腳本列表 Merkle 化
        返回 Merkle 根
        """
        if not scripts:
            return b'\x00' * 32  # 空樹返回 null
        
        # 計算每個腳本的葉節點雜湊
        leaves = [TaprootMAST.tapleaf_hash(script) for script in scripts]
        
        # 構建 Merkle 樹
        while len(leaves) > 1:
            if len(leaves) % 2 == 1:
                leaves.append(leaves[-1])  # 奇數個時複製最後一個
            
            next_level = []
            for i in range(0, len(leaves), 2):
                combined = leaves[i] + leaves[i+1]
                parent = TaprootMAST.sha256_midstate(combined)
                next_level.append(parent)
            leaves = next_level
        
        return leaves[0]
    
    @staticmethod
    def tapleaf_hash(script):
        """計算 Tapleaf 雜湊"""
        # Tapleaf = SHA256(0xbc || script)
        return TaprootMAST.tagged_hash("TapLeaf", script)
    
    @staticmethod
    def create_taproot_address(internal_key, script_tree=None):
        """
        建立 Taproot 地址
        """
        # 計算調整
        tweak = TaprootMAST.compute_taproot_tweak(internal_key, script_tree)
        
        # 最終公鑰 = 內部公鑰 + 調整值 * G
        # 此處簡化,假設已知內部公鑰
        tweaked_key = internal_key  # 實際需要點運算
        
        # Bech32m 編碼
        version = 0x01  # Taproot 版本
        program = tweaked_key
        
        return TaprootMAST.bech32_encode("bc", version, program)
    
    @staticmethod
    def bech32_encode(hrp, version, program):
        """Bech32m 編碼"""
        # 簡化實現
        data = [version] + list(program)
        return f"{hrp}1{'q' * 58}"
    
    @staticmethod
    def verify_taproot_spending(key_path, witness):
        """
        驗證 Taproot 金鑰路徑支出
        """
        if len(witness) != 1:
            raise Exception("金鑰路徑只需 1 個簽章")
        
        signature = witness[0]
        
        # 驗證 Schnorr 簽章
        return TaprootMAST.verify_schnorr_signature(key_path, signature)
    
    @staticmethod
    def verify_schnorr_signature(pubkey, signature):
        """
        驗證 Schnorr 簽章
        此為框架實現
        """
        # 實際 Schnorr 驗證需要 secp256k1 曲線運算
        # 1. 解析簽章 (e, s)
        # 2. 計算 R' = s*G + e*P
        # 3. 驗證 e == Hash(R || P || m)
        
        return len(signature) == 64  # 簡化驗證
    
    @staticmethod
    def verify_script_path(witness, script_path, script):
        """
        驗證腳本路徑支出
        """
        # witness 格式: [control_block, script, ...signatures]
        control_block = witness[0]
        script_witness = witness[1:-1]
        signatures = witness[-1] if witness else []
        
        # 驗證 control block
        TaprootMAST.verify_control_block(control_block, script_path, script)
        
        # 執行腳本
        return TaprootMAST.execute_script(script, script_witness)
    
    @staticmethod
    def verify_control_block(control_block, path, script):
        """驗證 Control Block"""
        # 提取分支
        # 驗證 Merkle 證明
        return True
    
    @staticmethod
    def execute_script(script, witness_stack):
        """執行 Taproot 腳本"""
        # Tapscript 執行邏輯
        # 支援 OP_CHECKSIGADD 等新操作碼
        return True

# 使用範例:建立 Taproot 腳本結構
class TaprootBuilder:
    """Taproot 腳本建構器"""
    
    def __init__(self, internal_key):
        self.internal_key = internal_key
        self.script_leaves = []
    
    def add_script(self, script, leaf_version=0xc0):
        """添加腳本到腳本樹"""
        leaf_hash = TaprootMAST.tapleaf_hash(script)
        self.script_leaves.append({
            'script': script,
            'hash': leaf_hash,
            'version': leaf_version
        })
    
    def add_timelock_branch(self, pubkey_hash, lock_time):
        """添加時間鎖分支"""
        script = f"OP_IF {lock_time} OP_CHECKLOCKTIMEVERIFY OP_DROP OP_ENDIF OP_DUP OP_HASH160 {pubkey_hash} OP_EQUALVERIFY OP_CHECKSIG"
        self.add_script(script)
    
    def add_multisig_branch(self, threshold, pubkeys):
        """添加多簽名分支"""
        keys_str = " ".join(pubkeys)
        n = len(pubkeys)
        script = f"OP_{threshold} {keys_str} OP_{n} OP_CHECKMULTISIG"
        self.add_script(script)
    
    def build(self):
        """建構 Taproot 輸出"""
        # Merkle 化所有腳本
        root = TaprootMAST.merkleize_scripts([leaf['script'] for leaf in self.script_leaves])
        
        # 計算調整
        tweak = TaprootMAST.compute_taproot_tweak(self.internal_key, root)
        
        return {
            'internal_key': self.internal_key,
            'script_root': root.hex(),
            'tweak': tweak.hex(),
            'leaf_count': len(self.script_leaves)
        }

# 建立 Taproot 結構
internal_key = bytes.fromhex("0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")
builder = TaprootBuilder(internal_key.hex())

# 添加不同分支
builder.add_timelock_branch("89abcdefabbaabbaabbaabbaabbaabbaabbaabba", "500000000")
builder.add_multisig_branch(2, [
    "02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
    "02cccccccccccccccccccccccccccccccccccccccc"
])

taproot_output = builder.build()
print("=== Taproot 輸出 ===")
print(f"內部公鑰: {taproot_output['internal_key'][:32]}...")
print(f"腳本根雜湊: {taproot_output['script_root']}")
print(f"調整值: {taproot_output['tweak']}")
print(f"腳本葉數量: {taproot_output['leaf_count']}")

腳本安全與最佳實踐

常見腳本漏洞與防護

比特幣腳本的安全性至關重要,一個小小的失誤可能導致資金永久丟失或被盜。以下是一些常見的安全問題與防護措施。

多簽名腳本中的 OPCHECKMULTISIG bug:早期的 OPCHECKMULTISIG 實現存在一個特性,在驗證簽章時會消耗一個多餘的元素。這導致開發者需要在簽章列表前面添加一個 dummy element(通常為 OP_0),這個特性經常被誤解並導致簽章驗證失敗。現代錢包已正確處理這個問題,但在自定義腳本實現中仍需注意。

# 安全的腳本實現與驗證
class SecureScript:
    """安全腳本實現類"""
    
    @staticmethod
    def validate_pubkey(pubkey_hex):
        """驗證公鑰格式"""
        pubkey_bytes = bytes.fromhex(pubkey_hex)
        
        # 壓縮公鑰:33 bytes(02 或 03 開頭)
        if len(pubkey_bytes) == 33:
            if pubkey_bytes[0] not in [0x02, 0x03]:
                raise Exception("無效的壓縮公鑰前綴")
            return True
        
        # 未壓縮公鑰:65 bytes(04 開頭)
        if len(pubkey_bytes) == 65:
            if pubkey_bytes[0] != 0x04:
                raise Exception("無效的未壓縮公鑰前綴")
            return True
        
        raise Exception(f"無效的公鑰長度: {len(pubkey_bytes)}")
    
    @staticmethod
    def validate_signature(sig_hex):
        """驗證 DER 編碼簽章格式"""
        sig_bytes = bytes.fromhex(sig_hex)
        
        # DER 格式:0x30 [總長度] 0x02 [r長度] [r] 0x02 [s長度] [s]
        if len(sig_bytes) < 8:
            raise Exception("簽章太短")
        
        if sig_bytes[0] != 0x30:
            raise Exception("無效的 DER 前綴")
        
        # 驗證 r 和 s 都是正數(最高位為 0 或 1)
        # 這個簡化實現僅檢查基本格式
        return len(sig_bytes) <= 73  # 最大 DER 簽章長度
    
    @staticmethod
    def validate_script_safety(script):
        """
        驗證腳本安全性
        檢查是否包含危險操作碼
        """
        dangerous_ops = [
            'OP_CREATE', 'OP_CALL', 'OP_VERIFY',  # 可能導致資金鎖定
            'OP_RETURN',  # 注意:OP_RETURN 是合法的但應檢查資料大小
        ]
        
        # 檢查是否有 OP_VERIFY 系列後綴操作
        # 實際實現應更複雜
        warnings = []
        
        # 檢查資料大小
        script_parts = script.split()
        for i, part in enumerate(script_parts):
            if part.isdigit() or (part.startswith('0x') and len(part) > 2):
                try:
                    num_val = int(part, 0) if part.startswith('0x') else int(part)
                    if num_val > 520:  # 最大 push 大小
                        warnings.append(f"過大的數據 push: {num_val}")
                except:
                    pass
        
        return {
            'safe': True,  # 應該根據實際分析設置
            'warnings': warnings
        }
    
    @staticmethod
    def validate_multisig_setup(threshold, total_keys):
        """
        驗證多簽名配置
        """
        if threshold < 1:
            raise Exception("門檻值必須 >= 1")
        
        if threshold > total_keys:
            raise Exception("門檻值不能超過總密鑰數")
        
        if total_keys > 15:
            raise Exception("過多的密鑰,可能影響效能")
        
        return True
    
    @staticmethod
    def estimate_script_vbytes(script, is_segwit=False):
        """
        估算腳本的 vBytes 大小
        """
        # 原始腳本大小
        script_bytes = len(script.split())
        
        if is_segwit:
            # SegWit: 見證資料
            witness_count = 1  # 假設
            witness_bytes = witness_count * 75  # 平均簽章 + 公鑰大小
            return witness_bytes // 4  # WU to vByte
        else:
            return script_bytes

# 安全驗證示例
secure = SecureScript()

# 驗證公鑰
try:
    valid_pubkey = "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
    secure.validate_pubkey(valid_pubkey)
    print("✓ 公鑰格式驗證通過")
except Exception as e:
    print(f"✗ 公鑰驗證失敗: {e}")

# 驗證多簽名配置
try:
    secure.validate_multisig_setup(2, 3)
    print("✓ 多簽名配置驗證通過")
except Exception as e:
    print(f"✗ 多簽名配置失敗: {e}")

# 腳本安全檢查
script = "OP_2 0288bad2e7d5d8a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5 0288bad2e7d5d8a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5 03ff6c3e5a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3 OP_3 OP_CHECKMULTISIG"
safety = secure.validate_script_safety(script)
print(f"腳本安全檢查: {safety}")

腳本最佳化技巧

在比特幣區塊空間有限的情況下,優化腳本大小可以顯著降低成本。以下是一些實用的優化技巧。

公鑰壓縮:使用壓縮公鑰(33 bytes)而非未壓縮公鑰(65 bytes),可節省 32 bytes 的區塊空間。在多簽名腳本中,這意味著每個公鑰可節省 32 bytes。

腳本結構優化:對於條件分支較多的腳本,使用 MAST/Taproot 結構可以隱藏未使用的分支,僅揭示實際執行的路徑。這在複雜的時間鎖或多簽名安排中特別有效。

批次交易:當需要向多個收款人付款時,使用 OP_CHECKMULTISIG 配合單一簽章可以將多個收款人合併到一個交易中,分攤固定開銷。

# 腳本優化實現
class ScriptOptimizer:
    """比特幣腳本優化工具"""
    
    @staticmethod
    def compress_pubkeys(pubkeys):
        """將未壓縮公鑰轉換為壓縮格式"""
        compressed = []
        for pubkey in pubkeys:
            pubkey_bytes = bytes.fromhex(pubkey)
            if len(pubkey_bytes) == 65 and pubkey_bytes[0] == 0x04:
                # 提取 x 座標
                x = pubkey_bytes[1:33]
                # 計算 y 座標的奇偶性
                y_parity = 0x02 if pubkey_bytes[33] % 2 == 0 else 0x03
                compressed.append((y_parity.to_bytes(1, 'big') + x).hex())
            else:
                compressed.append(pubkey)
        return compressed
    
    @staticmethod
    def sort_pubkeys_bip67(pubkeys):
        """按 BIP-67 lexicographical 順序排序公鑰"""
        return sorted(pubkeys, key=lambda x: bytes.fromhex(x))
    
    @staticmethod
    def estimate_multisig_size(threshold, pubkeys, is_segwit=False):
        """
        估算多簽名腳本大小
        """
        # redeemScript 大小
        # OP_M + N * (33 bytes key) + OP_N + OP_CHECKMULTISIG
        key_size = 33 * len(pubkeys)
        script_size = 3 + key_size + 2  # 估計值
        
        if is_segwit:
            # P2WSH: SHA256(256 bits) = 32 bytes
            witness_program = 32
            # 每個簽章約 71-73 bytes
            witness_size = threshold * 72 + script_size
            weight = (witness_program * 4) + witness_size
            vbytes = weight / 4
        else:
            # P2SH: RIPEMD160(SHA256) = 20 bytes
            script_hash = 20
            vbytes = script_size + script_hash + 4  # 估計值
        
        return vbytes
    
    @staticmethod
    def compare_p2sh_vs_p2wsh(threshold, pubkeys):
        """比較 P2SH 與 P2WSH 的費用"""
        p2sh_vb = ScriptOptimizer.estimate_multisig_size(threshold, pubkeys, False)
        p2wsh_vb = ScriptOptimizer.estimate_multisig_size(threshold, pubkeys, True)
        
        fee_rate_sat_vb = 10  # 10 sat/vByte 示例
        
        p2sh_fee = int(p2sh_vb * fee_rate_sat_vb)
        p2wsh_fee = int(p2wsh_vb * fee_rate_sat_vb)
        
        return {
            'p2sh_vbytes': p2sh_vb,
            'p2sh_fee_sats': p2sh_fee,
            'p2wsh_vbytes': p2wsh_vb,
            'p2wsh_fee_sats': p2wsh_fee,
            'savings_percent': ((p2sh_vb - p2wsh_vb) / p2sh_vb) * 100
        }

# 優化示例
pubkeys_uncompressed = [
    "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
    "02E493EEBF2D3A582C2C0F3A15F5C8F5A9D5F5E5D5F5E5D5F5E5D5F5E5D5F5E5D5",
    "03CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
]

# 壓縮公鑰
compressed = ScriptOptimizer.compress_pubkeys(pubkeys_uncompressed)
print("壓縮後的公鑰:")
for i, (orig, comp) in enumerate(zip(pubkeys_uncompressed, compressed)):
    print(f"  {i+1}: {len(orig)//2} bytes -> {len(comp)//2} bytes")

# 按 BIP-67 排序
sorted_pubkeys = ScriptOptimizer.sort_pubkeys_bip67(compressed)
print(f"\nBIP-67 排序後: {sorted_pubkeys}")

# 費用比較
comparison = ScriptOptimizer.compare_p2sh_vs_p2wsh(2, compressed)
print(f"\n=== 費用比較 (2-of-3 多簽名) ===")
print(f"P2SH: {comparison['p2sh_vbytes']:.1f} vBytes, {comparison['p2sh_fee_sats']} sats")
print(f"P2WSH: {comparison['p2wsh_vbytes']:.1f} vBytes, {comparison['p2wsh_fee_sats']} sats")
print(f"節省: {comparison['savings_percent']:.1f}%")

結論

比特幣腳本語言雖然設計簡單,卻蘊含著豐富的技術深度與安全考量。從基礎的 P2PKH、P2SH 到現代的 P2WPKH、P2WSH、P2TR,每一次技術演進都體現了比特幣社區對安全性、去中心化與實用性的追求。理解這些腳本技術不僅有助於開發比特幣應用,更能深化對比特幣貨幣系統運作原理的認識。

在實際應用中,開發者應始終遵循安全最佳實踐:驗證所有輸入、使用標準化的腳本模板、充分測試,並考慮未來的可升級性。隨著 Taproot 與 Schnorr 簽章的普及,比特幣腳本將迎來更多創新應用的可能性,包括更複雜的智慧合約、隱私保護機制與 Layer 2 解決方案的深度整合。掌握這些基礎知識,將為探索比特幣技術前沿打下堅實的基礎。

比特幣腳本語言的設計哲學——簡單、確定性、可組合——正是其長期安全與穩定的根源。在這個基礎上,開發者可以構建出各種創新應用,同時確保用戶資金的安全。這種設計與實現的平衡,正是比特幣作為去中心化貨幣系統的核心價值所在。

延伸閱讀與來源

這篇文章對您有幫助嗎?

評論

發表評論

注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。

目前尚無評論,成為第一個發表評論的人吧!