比特币交易脚本详解,解锁数字资产的密码锁
摘要:比特币作为点对点的电子现金系统,其核心在于安全、透明且无需中央机构验证的交易,而这一切的背后,都离不开一个至关重要的组件——交易脚本(TransactionScript),它像是每一笔比特币交易的“...
比特币作为点对点的电子现金系统,其核心在于安全、透明且无需中央机构验证的交易,而这一切的背后,都离不开一个至关重要的组件——交易脚本(Transaction Script),它像是每一笔比特币交易的“密码锁”和“解锁规则”,定义了谁有权花费这笔比特币,以及如何花费,本文将详细解析比特币交易脚本的原理、类型、组成及其在比特币网络中的作用。
什么是比特币交易脚本?
比特币交易脚本是一种基于堆栈(Stack)的、用于执行交易验证的小型编程语言,它并非图灵完备的,即没有循环或复杂跳转,从而保证了脚本执行的确定性和安全性,每一笔比特币交易都包含两个主要脚本:
- 锁定脚本(Locking Script / ScriptSig):也称为“见证脚本”(Witness Script)在隔离见证中,它附加在交易的输入(Input)中,定义了花费该笔UTXO(Unspent Transaction Output,未花费交易输出)所需的条件,可以把它想象成锁在箱子上的锁,规定了打开锁的规则。
- 解锁脚本(Unlocking Script / ScriptPubKey):也称为“公钥脚本”(Public Key Script),它附加在交易的输出(Output)中,包含了满足锁定脚本条件所需的数据或签名,可以把它想象成打开锁的钥匙。
当一笔交易被广播到比特币网络时,网络中的节点会执行输入中的解锁脚本和输出中的锁定脚本,验证解锁脚本提供的“钥匙”是否能满足锁定脚本设定的“规则”,如果验证通过,交易有效;否则,交易将被拒绝。
脚本语言基础:操作码与堆栈
比特币脚本语言由一系列操作码(OpCodes)和数据(Data)组成,操作码是执行特定指令的命令,而数据则是操作码处理的对象(如公钥、签名、哈希值等)。
脚本的执行过程是在一个堆栈上进行的,堆栈是一种“后进先出”(LIFO)的数据结构。
- 数据推送:当脚本遇到数据时(如公钥、签名),它们会被推入堆栈。
- 操作码执行:当脚本遇到操作码时,操作码会从堆栈顶部弹出所需数量的操作数(如果需要),执行相应操作,然后将结果(如果有的话)推回堆栈。
- 最终验证:脚本执行完毕后,堆栈顶部必须留下一个
TRUE(在比特币中,通常是非零数值,如1)表示验证通过,如果堆栈为空或顶部为FALSE(零),则验证失败。
简单示例:一个最简单的脚本验证过程
- 解锁脚本(ScriptSig):
<签名> <公钥> - 锁定脚本(ScriptPubKey):
OP_DUP OP_HASH160 <公钥哈希> OP_EQUALVERIFY OP_CHECKSIG
执行流程:
- 解锁脚本
<签名> <公钥>推入堆栈:堆栈底部到顶部为<公钥>,<签名>。 - 执行锁定脚本
OP_DUP:复制堆栈顶部的<签名>?不,OP_DUP复制堆栈顶部的元素,此时堆栈顶部是<签名>?不对,解锁脚本先执行,堆栈是<公钥>,<签名>,然后执行锁定脚本:OP_DUP:复制堆栈顶部元素<公钥>,堆栈变为<公钥>,<签名>,<公钥>。OP_HASH160:对顶部<公钥>进行SHA256哈希后再RIPEMD160哈希,得到<公钥哈希>,堆栈变为<公钥>,<签名>,<公钥哈希>。<公钥哈希>(数据):将锁定脚本中的<公钥哈希>推入堆栈,堆栈变为<公钥>,<签名>,<公钥哈希>,<公钥哈希>。OP_EQUALVERIFY:弹出顶部两个<公钥哈希>进行比较,如果相等则继续,否则失败,然后验证堆栈下一个元素(<签名>)?不,OP_EQUALVERIFY比较两个值,如果相等,继续执行下一个操作码,否则将FALSE留在堆栈上,假设相等,堆栈此时为<公钥>,<签名>。OP_CHECKSIG:弹出<签名>和<公钥>,验证签名是否是对<公钥>对应地址的解锁签名(实际上是验证签名对交易特定哈希的有效性),如果验证通过,将TRUE(1)推入堆栈;否则,FALSE(0)。
- 最终堆栈顶部为
1,验证通过。
常见的脚本类型
比特币脚本系统非常灵活,支持多种复杂的脚本类型,以实现不同的功能和安全性需求,以下是一些最常见和重要的脚本类型:
P2PKH (Pay-to-Public-Key-Hash) - 最常见的脚本类型
这是比特币最广泛使用的脚本类型,我们日常的比特币地址大多都是P2PKH地址。
- 锁定脚本(ScriptPubKey):
OP_DUP OP_HASH160 <公钥哈希> OP_EQUALVERIFY OP_CHECKSIG - 解锁脚本(ScriptSig):
<签名> <公钥> - 含义:允许拥有对应公钥私钥的人通过提供正确的签名和公钥来花费UTXO,这是标准比特币地址的基础。
P2SH (Pay-to-Script-Hash) - 更复杂的脚本封装
P2SH允许用户将复杂的脚本逻辑“封装”起来,接收方只需要提供一个满足该复杂脚本的“签名集”,而无需关心脚本的具体内容,从而简化了交易并节省了区块空间。
- 锁定脚本(ScriptPubKey):
OP_HASH160 <脚本哈希> OP_EQUAL - 解锁脚本(ScriptSig):
<满足封装脚本的数据> <封装的脚本> - 含义:发送方将一个脚本的哈希值作为锁定条件,接收方在花费时,必须提供完整的原始脚本以及能够满足该脚本的数据,并且原始脚本的哈希值必须与锁定脚本中的哈希值匹配,常见的P2SH脚本包括多签地址(P2SH多签)。
P2WPKH (Pay-to-Witness-Public-Key-Hash) - 隔离见证下的P2PKH
随着隔离见证(SegWit)的引入,P2WPKH成为了一种更高效、更节省费用的脚本类型。
- 锁定脚本(ScriptPubKey,见证版本0):
OP_0 <公钥的哈希> - 解锁脚本(ScriptWitness,见证数据):
<签名> <公钥> - 含义:与P2PKH类似,但签名和公钥作为见证数据存储在单独的见证区域,而不是交易本身,这带来了更高的可扩展性(见证数据不占用区块大小限制,只占用权重)和更强的隐私性(签名与交易输入的关联性降低)。
P2WSH (Pay-to-Witness-Script-Hash) - 隔离见证下的P2SH
P2WSH是P2SH在隔离见证下的对应版本,允许用户将任意复杂的脚本作为见证数据。
- 锁定脚本(ScriptPubKey,见证版本0):
OP_0 <脚本的哈希> - 解锁脚本(ScriptWitness,见证数据):
<满足脚本的数据> <脚本> - 含义:提供了与P2SH类似的脚本封装功能,但利用了隔离见证的优势,支持更复杂的脚本逻辑(如时间锁、多签等),并且效率更高。
多签脚本 (Multi-signature Script)
要求多个私钥共同签名才能花费UTXO,常用于增强安全性或实现组织共同控制。
- 标准P2SH多签锁定脚本(ScriptPubKey):
OP_M <公钥1> <公钥2> ... <公钥N> OP_N OP_CHECKMULTISIGOP_M:需要的签名数量(M ≤ N)。OP_N:公钥总数。
- 解锁脚本(ScriptSig):通常需要提供N个签名(即使其中一些是无效的,由于历史原因,需要占位符),但实际有效的签名数量必须≥M。
<签名1> <签名2> <...> <签名N>(对于OP_2_OF_3,可能只需要提供2个有效签名,但脚本格式上可能需要提供3个)。 - 隔离见证下的P2WSH多签:脚本逻辑更灵活,直接在见证数据中提供所需数量的签名。
