比特币交易中的双引擎,解锁UTXO的两种脚本引擎
摘要:比特币网络的安全与灵活,很大程度上归功于其独特的交易验证机制,在每一笔比特币交易中,资金的转移并非简单的账户余额增减,而是通过脚本(Script)来锁定和解锁特定的UTXO(未花费的交易输出),这些脚...
比特币网络的安全与灵活,很大程度上归功于其独特的交易验证机制,在每一笔比特币交易中,资金的转移并非简单的账户余额增减,而是通过脚本(Script)来锁定和解锁特定的UTXO(未花费的交易输出),这些脚本如同精密的“密码锁”,只有提供正确的“钥匙”(签名或数据),才能解锁资金,比特币交易中的脚本主要分为两大类:锁定脚本(Locking Script)和解锁脚本(Unlocking Script),它们共同构成了比特币交易验证的“双引擎”。
比特币交易中的两种脚本
比特币作为一种去中心化的数字货币,其核心在于确保交易的安全性和所有权可验证性,这一目标的实现,离不开其精巧的脚本系统,在比特币交易模型中,每一个未被花费的交易输出(UTXO)都由一个“锁定脚本”锁定,而要花费这个UTXO,则必须提供一个对应的“解锁脚本”来满足锁定脚本的条件,这两种脚本的协同工作,构成了比特币交易验证的基础。
锁定脚本(Locking Script):设定花费条件的“门锁”
锁定脚本,也常被称为“脚本公钥(ScriptPubKey)”,因为它通常包含公钥或某种条件,规定了未来谁能花费这个UTXO,它附加在UTXO之上,就像一把锁,锁定了这笔资金。
核心作用: 定义花费UTXO必须满足的条件,这些条件可以是简单的公钥验证,也可以是复杂的逻辑组合。
常见类型与示例:
-
P2PKH(Pay-to-Public-Key-Hash,支付到公钥哈希): 这是最经典和常见的脚本类型之一。
- 锁定脚本示例:
OP_DUP OP_HASH160 <公钥哈希> OP_EQUALVERIFY OP_CHECKSIG - 解读: 这个脚本的意思是:“复制栈顶元素(即提供的公钥),计算其SHA-256哈希,再进行RIPEMD-160哈希,将结果与后面紧跟的
<公钥哈希>进行比较,如果相等且验证通过,则检查后续提供的签名是否对该公钥有效。” 谁能提供与该公钥哈希对应的私钥的签名,谁就能花费这笔钱”。
- 锁定脚本示例:
-
P2SH(Pay-to-Script-Hash,支付到脚本哈希): 为了增强灵活性和降低复杂交易的成本而引入。
- 锁定脚本示例:
OP_HASH160 <脚本哈希> OP_EQUAL - 解读: 这个脚本本身并不包含复杂的条件,而是“将后续提供的脚本进行SHA-256+RIPEMD-160哈希,然后将结果与
<脚本哈希>比较,如果相等则验证通过”,实际的花费条件被“隐藏”在一个单独的“赎回脚本”(Redeem Script)中,该赎回脚本需要由花费者在解锁脚本中提供。
- 锁定脚本示例:
-
P2WSH(Pay-to-Witness-Script-Hash,见证脚本哈希): SegWit(隔离见证)升级后的高级脚本类型,支持更复杂的脚本且具有更高的效率和隐私性。
- 锁定脚本示例:
OP_0 <脚本哈希>(对于原生SegWit) - 解读: 类似于P2SH,但见证数据(签名和公钥等)被隔离到单独的“见证”数据区域,脚本本身可以更复杂,哈希算法也升级为SHA-256。
- 锁定脚本示例:
-
P2TR(Pay-to-Taproot,支付到 taproot): Taproot升级引入的最新脚本类型,结合了P2PKH的简洁性和P2SH/P2WSH的灵活性,并通过Merkelized Abstract Syntax Trees (MAST) 实现了隐私和效率的平衡。
- 锁定脚本示例:
OP_1 <公钥/脚本哈希> - 解读: 允许多种花费路径(多种签名方案或复杂脚本),其中最常见或最简单的路径可以像P2PKH一样高效验证,而复杂路径则通过MAST树隐藏,只有在需要时才暴露,提高了隐私性。
- 锁定脚本示例:
特点: 锁定脚本是由交易输出者(付款人)创建的,它“锁定”了资金,并规定了未来花费者必须满足的条件,这个脚本会被存储在区块链上,供所有节点验证交易时使用。
解锁脚本(Unlocking Script):提供解锁凭证的“钥匙”
解锁脚本,也常被称为“脚本签名(ScriptSig)”,因为它通常包含签名(Signature)等用于满足锁定脚本条件的数据,它由交易输入的提供者(收款人或后续花费者)创建,作为尝试解锁UTXO的“钥匙”。
核心作用: 提供数据,证明自己有权花费被锁定的UTXO,并满足锁定脚本中设定的所有条件。
常见类型与示例(与锁定脚本对应):
-
对应P2PKH的解锁脚本:
<签名> <公钥>- 解读: 提供签名和对应的公钥,比特币节点会执行锁定脚本:先验证提供的公钥的哈希是否与锁定脚本中的公钥哈希一致,然后验证签名是否对该公钥有效。
-
对应P2SH的解锁脚本:
<赎回脚本> <赎回脚本所需的参数(如签名、公钥等)>- 解读: 首先提供赎回脚本(即实际的花费条件),然后提供该赎回脚本执行所需的参数,节点会先验证赎回脚本的哈希是否与锁定脚本中的脚本哈希一致,然后执行赎回脚本及其参数,验证是否能通过条件。
-
对应P2WSH的解锁脚本(见证数据):
<见证脚本> <见证数据(如签名、公钥等)>- 解读: 见证脚本(相当于赎回脚本)和见证数据被放在单独的见证数据区域,节点会验证见证脚本的哈希是否与锁定脚本中的脚本哈希一致,然后执行见证脚本及其数据。
-
对应P2TR的解锁脚本(见证数据): 通常为
< Schnorr签名 >,如果花费的是MAST树中的复杂脚本路径,则还需要提供相应的证明数据。
特点: 解锁脚本是由交易输入者提供的,它“解锁”资金,其内容本身并不是验证逻辑的一部分,而是作为数据被锁定脚本执行时使用,为了防止恶意构造的脚本导致节点拒绝服务(DoS),比特币脚本引擎会对解锁脚本的大小和操作码进行限制。
协同工作:交易验证的核心流程
一笔有效的比特币交易,其输入部分的解锁脚本和其引用的UTXO中的锁定脚本必须协同工作并通过验证,基本流程如下:
- 构建交易: 交易创建者指定要花费的UTXO(包含锁定脚本),并为该输入提供解锁脚本。
- 节点验证: 比特币网络中的节点在接收到交易后,会对每个输入进行验证: a. 将输入的解锁脚本和其引用的UTXO的锁定脚本分别加载到脚本栈中。 b. 按照比特币脚本操作码的定义,依次执行这两个脚本(通常是先执行解锁脚本,将其结果作为数据给锁定脚本执行)。 c. 如果脚本执行最终结果为“真”(True,即栈顶元素为1或非零),且执行过程中没有错误,则该输入验证通过。 d. 所有输入都验证通过后,交易才算有效,并被纳入内存池等待打包。
示例(简化P2PKH):
- 锁定脚本:
OP_DUP OP_HASH160 <PubKHash> OP_EQUALVERIFY OP_CHECKSIG - 解锁脚本:
<Sig> <PubK> - 执行过程:
- 解锁脚本
<Sig> <PubK>入栈,栈底到栈顶:[PubK, Sig]。 - 锁定脚本开始执行:
OP_DUP:复制栈顶PubK,栈变为[PubK, PubK, Sig]。OP_HASH160:对栈顶PubK进行哈希,得到PubKHash,栈变为[PubK, PubKHash]。OP_EQUALVERIFY:将栈顶PubKHash与锁定脚本中的<PubKHash>比较,若不等则失败;相等则继续,并弹出这两个元素,栈变为[PubK]。OP_CHECKSIG:使用Sig和PubK进行签名验证,若验证通过,栈顶变为1(真);否则失败。
- 解锁脚本
脚本系统的意义与演进
比特币的脚本系统虽然不像图灵完备的编程语言那样灵活,但其设计初衷是安全、简洁和可预测,它支持多种复杂的交易类型,如多签(要求多个签名才能花费)、时间锁(只有在特定时间之后才能花费)、原子交换
