上篇文章讲到,比特币交易的输出,可以被“绑定”到收款方的公钥或公钥的哈希(数字指纹)上。
在之后需要消费这个 UTXO 时,除非提供了正确的证明和授权信息(签名),否则无法支付。
通过交易链条,任何人都可以验证交易的合法性。
这篇文章记录与比特币脚本有关的细节,说说验证交易的工具。
栈
栈(Stack)是计算机中一种简单的数据结构,你可以把栈想象成弹匣。

栈允许两个操作:
Push
,向栈中压入一个元素,就像你向弹匣中压入一枚子弹Pop
,弹出栈顶的一个元素,就像你从弹匣最上面退出一枚子弹
能看到,栈中的元素,都是后进先出(LIFO,Last In First Out)的。
基于栈执行的脚本
脚本,可以理解成一系列动作和数据依次执行的说明书。脚本包含两类元素:
- 动作,定义操作是什么,称为操作码
- 数据,操作码操作的对象,称为操作数
举个例子,定义:
ADD
,加法运算,做两次弹出栈顶元素的操作,先将这两个数相加,再将计算结果压入栈中EQUAL
,判等运算,做两次弹出栈顶元素的操作,先判断这两个数是否相等,再将计算结果压入栈中- 如果当前元素是一个操作数,则直接将操作数压入栈中
脚本从左到右执行,内容为
2 3 ADD 5 EQUAL |
模拟一下脚本执行的过程,左边的STACK
表示栈的当前状态,EXECUTION POINTER
表示脚本当前执行到的位置。

最后,脚本的运行结果为真(TRUE)。
比特币的交易脚本,正是这种基于栈结构执行的脚本,只不过定义了更丰富的操作码,具体可以参考比特币操作码说明书。
锁定脚本与解锁脚本
容易想到,可以
- 在交易的输出上,附上包含公钥或公钥哈希的锁定脚本,将输出与公钥关联
- 在交易的输入上,需要提供包含数字签名的解锁脚本,只有对应私钥的持有者,才能提供正确的签名
这样在验证交易时,只需要将解锁脚本和锁定脚本连起来从左到右执行,验证签名即可。如果
- 脚本在执行过程中没有发生错误(例如在没有元素的栈中弹出元素会发生错误)
- 脚本执行完时,栈顶元素为真,或栈中没有元素
则视为交易有效。
只有有效合法的交易才会被比特币网络接受。
这样的设计让任何人都可以验证交易,得到确定且一致的结果。
一般的,
锁定脚本(Locking Script)是放置在输出上的加密难题(cryptographic puzzle),指定了今后花费这笔 UTXO 必须要满足的条件,是交易输出的一部分。锁定脚本往往包含一个公钥或公钥的哈希,常用scriptPubKey
表示,也被称为见证脚本(Witness Script),但锁定脚本有更广泛的可能性。
解锁脚本(Unlocking Script)解决或满足了,之前放置在这笔 UTXO 上的加密难题或条件,解锁 UTXO 用于支付,是交易输入的一部分。解锁脚本往往包含一个数字签名,常用scriptSig
表示,但解锁脚本有更广泛的可能性。
组合不同的操作码,能写出更多样更复杂的脚本,来满足不同的使用场景,这就是为什么比特币被称为“可编程加密货币”的原因。
如果一笔 UTXO 上的锁定脚本为
2 3 ADD EQUAL |
提供什么样的解锁脚本,才能花费这笔 UTXO?欢迎留言。 😋
总结
- 栈是一种后入先出的数据结构
- 比特币的脚本语言基于栈结构执行,定义了各种操作码,规则简单同时又十分强大
- 锁定脚本是放置在交易输出上的加密难题,指定了今后花费这笔 UTXO 的条件
- 锁定脚本有广泛的可能性,一般会包含一个公钥或公钥哈希,常用
scriptPubKey
表示 - 解锁脚本是交易输入的一部分,解决或满足之前放置在 UTXO 上的加密难题或条件
- 解锁脚本有广泛的可能性,一般会包含一个数字签名,常用
scriptSig
表示 - 任何人都可以验证交易,得到确定且一致的结果,只需要将解锁脚本和锁定脚本连起来从左到右执行即可