当前位置: 首页 > ai >正文

肖臻《区块链技术与应用》第九讲:比特币交易的“智能”核心:深入解析脚本语言Script

摘要:
每一笔比特币交易的背后,都由一套简洁而强大的脚本语言(Script)精确地定义其所有权转移的规则。本文基于北京大学肖臻老师的公开课内容,深入剖析了比特币这门简单、非图灵完备、基于堆栈的脚本语言。文章首先解构了比特币交易的基本组成——输入、输出与脚本,并阐释了“解锁”与“锁定”脚本如何协同工作以验证交易的合法性。随后,本文详细拆解了三种主流的脚本类型:P2PK、P2PKH和P2SH,并重点阐述了P2SH如何通过“复杂度转移”优雅地实现多重签名这一杀手级应用。最后,文章介绍了OP_RETURN脚本在数据存储和“销毁”比特币中的特殊用途,并总结了比特币脚本“功能有限但为场景高度优化”的设计哲学。


1. 交易的蓝图:输入、输出与脚本

要理解比特币脚本,首先需要了解一笔标准比特币交易的构成。一笔交易主要包含宏观信息(Metadata)、输入(Vin)和输出(Vout)三大部分。

1.1 解构一笔比特币交易
  • 输入(Vin): 指明这笔交易花费的比特币来自何处。每个输入都包含:
    • 一个指向之前某笔交易输出的指针(txidvout序号),表明资金来源。
    • 一段输入脚本(Input Script / scriptSig,它提供了“解锁”这笔资金所需的数据,最常见的就是数字签名。
  • 输出(Vout): 指明这笔比特币将流向何处。每个输出都包含:
    • 一个金额(value),表示转移的比特币数量。
    • 一段输出脚本(Output Script / scriptPubKey,它定义了一个“锁定”条件。只有能满足这个条件的人,才能在未来的交易中花费这笔钱。最常见的锁定条件就是指定一个公钥(或其哈希),要求花费者提供该公钥对应的私钥签名。
1.2 验证的核心:“解锁”与“锁定”脚本的共舞

比特币网络中的节点如何验证一笔新交易的合法性?核心就在于将当前交易的输入脚本与它所引用的上一笔交易的输出脚本进行配对和执行。

验证过程可以理解为:

将“钥匙”(当前交易的输入脚本)插入“锁”(上一笔交易的输出脚本)中,看是否能成功打开。

在执行时,系统会将这两个脚本拼接起来(早期实现是直接拼接,后来为安全起见改为分别执行),在一个堆栈(Stack)上运行。如果脚本能顺利执行完毕,且最终栈顶留下一个非零值(代表True),则验证通过,交易被认为是合法的。如果中途出错,或最终结果为零,则交易非法。

2. 三种主流的“智能锁”:详解比特币脚本类型

比特币的输出脚本定义了各种类型的“智能锁”。以下是三种最主要的形式,从简单到复杂。

2.1 Pay-to-Public-Key (P2PK):最古老、最直接的形式

这是比特币最早期的交易形式,逻辑非常直接。

  • 输出脚本(锁): <收款人公钥> OP_CHECKSIG
  • 输入脚本(钥匙): <付款人签名>
  • 执行过程:
    1. <付款人签名>压入堆栈。
    2. <收款人公钥>压入堆栈。
    3. 执行OP_CHECKSIG操作码:弹出栈顶的公钥和签名,验证签名是否由该公钥对应的私钥生成。若验证通过,则将True压入栈中。
2.2 Pay-to-Public-Key-Hash (P2PKH):最常用的形式

P2PK形式会直接暴露收款人的公钥,而P2PKH则通过一层哈希增加了安全性和便利性,是如今最普遍的交易形式。

  • 输出脚本(锁): OP_DUP OP_HASH160 <收款人公钥的哈希> OP_EQUALVERIFY OP_CHECKSIG
  • 输入脚本(钥匙): <付款人签名> <付款人公钥>
  • 执行过程:
    1. <付款人签名><付款人公钥>依次压入堆栈。
    2. OP_DUP:复制栈顶元素,此时栈顶有两个<付款人公钥>
    3. OP_HASH160:弹出栈顶的公钥,计算其160位哈希值,并将结果压入栈中。
    4. 将输出脚本中预设的<收款人公钥的哈希>压入栈中。
    5. OP_EQUALVERIFY:弹出栈顶的两个哈希值进行比较。如果相等,则验证通过,脚本继续执行;如果不相等,则立即报错,交易失败。这一步确保了提供公钥的人就是预定的收款人。
    6. OP_CHECKSIG:此时栈上剩下<付款人签名><付款人公钥>,执行最后的签名验证。
2.3 Pay-to-Script-Hash (P2SH):最灵活、最强大的形式

P2SH是比特币后续通过软分叉引入的强大功能,它将交易的锁定条件从一个简单的公钥,扩展到了一个任意复杂的脚本

  • 核心思想: 输出不再锁定给一个“人”(公钥哈希),而是锁定给一个“规则”(脚本哈希)。
  • 输出脚本(锁): OP_HASH160 <赎回脚本的哈希> OP_EQUAL
  • 输入脚本(钥匙): <满足赎回脚本所需的数据> <赎回脚本本身>
  • 验证过程(两阶段):
    1. 第一阶段:验证赎回脚本。 系统首先会验证输入脚本中提供的<赎回脚本本身>的哈希值,是否与输出脚本中锁定的<赎回脚本的哈希>相等。若不相等,则交易失败。
    2. 第二阶段:执行赎回脚本。 若哈希匹配,系统会接着执行这个被验证为正确的“赎回脚本”,并使用输入脚本中提供的<满足赎回脚本所需的数据>(如签名)来运行它。只有当赎回脚本也成功执行,整个交易才算合法。

3. P2SH的杀手级应用:多重签名(Multi-Signature)

P2SH最典型的应用场景就是多重签名(Multi-sig),它极大地提升了比特币的实用性和安全性。

  • 应用场景: 一个公司账户可能需要5位合伙人中的任意3人签名才能动用资金。这既能防止单人私钥泄露导致资金被盗,也能在有人丢失私钥时提供冗余。
  • “原生”多重签名的问题: 如果不使用P2SH,发送方(如客户)在创建交易时,必须在他的输出脚本里写明所有复杂的规则,包括5位合伙人的全部公钥、签名阈值(3-of-5)等。这给发送方带来了巨大的不便和复杂性。
  • P2SH的优雅解决方案:将复杂度转移给收款人。
    • 使用P2SH后,收款人(公司)可以将所有复杂的多签规则封装在一个“赎回脚本”里。
    • 公司只需对外公布这个赎回脚本的哈希(即一个P2SH地址)。
    • 付款方(客户)在转账时,只需向这个简单的P2SH地址付款即可,完全无需关心背后复杂的多签逻辑。
    • 当公司未来想要花费这笔钱时,再由他们自己提供满足条件的3个签名和完整的赎回脚本来解锁资金。

P2SH巧妙地将复杂性从发送方转移到了收款方,极大地简化了用户体验,使得复杂的智能合约逻辑得以在比特币上广泛应用。

4. 特殊脚本:用OP_RETURN在区块链上“刻字”

除了用于资金转移,比特币脚本还提供了一种特殊的操作码OP_RETURN,它允许用户在区块链上永久地记录少量数据。

  • 工作原理: OP_RETURN是一个会无条件返回错误的操作码。任何包含它的输出脚本,都会在执行到该指令时立即失败,从而使得这笔输出永远无法被花费
  • 应用场景:
    1. 证明销毁(Proof-of-Burn): 一些山寨币(Altcoin)的发行机制要求用户“销毁”一定数量的比特币来换取新币。OP_RETURN输出就是一种可验证的、不可逆的销毁方式。
    2. 数据存储: OP_RETURN后面可以附加一小段任意数据(目前限制在80字节)。任何人都可以通过构造一笔小额交易(甚至可以是0聪,只需支付矿工费),利用这个数据区域在区块链上“刻字”,实现数字承诺(Digital Commitment)、产权证明等功能。

与只能由矿工写入的Coinbase交易字段不同,OP_RETURN为所有普通用户提供了一条在区块链上永久记录信息的通道。

5. 总结:简单而强大的比特币脚本语言

肖臻老师在课程结尾总结道,比特币的脚本语言(Bitcoin Script)具有鲜明的特点:

  • 极其简单: 它甚至没有一个正式的名称,功能非常有限。
  • 非图灵完备: 故意不支持循环等复杂结构,从而从根本上杜绝了死循环和停机问题,保证了所有交易的可预测性和安全性。这与以太坊图灵完备但需要“Gas”机制来防止滥用的智能合约语言形成鲜明对比。
  • 为场景高度优化: 尽管通用功能有限,但它内置了OP_CHECKSIGOP_CHECKMULTISIG等极其强大的密码学原生操作,用一条指令就能完成通用编程语言需要大量代码库才能实现的功能。

比特币脚本语言的设计哲学,是在安全性和可预测性的基础上,为数字货币所有权验证这一核心场景提供一个“刚刚好”的、强大而可靠的解决方案。它正是比特币这座宏伟大厦最底层的、坚不可摧的逻辑基石。

http://www.xdnf.cn/news/17647.html

相关文章:

  • Windows已经安装了一个MySQL8,通过修改配置文件的端口号跑2个或多个Mysql服务方法,并注册为系统服务
  • 08--深入解析C++ list:高效操作与实现原理
  • DeepSeek-R1-0528 推理模型完整指南:领先开源推理模型的运行平台与选择建议
  • Android性能优化:架构层面的性能考量
  • Web 服务详解:HTTP 与 HTTPS 配置
  • 超详细!VMware12 安装win7操作系统
  • Linux下命名管道和共享内存
  • 邦纳BANNER相机视觉加镜头PresencePLUSP4 RICOH FL-CC2514-2M工业相机
  • 腾讯codebuddy.ai 安装实测【从零开始开发在线五子棋游戏:完整开发记录】
  • iceberg FlinkSQL 特性
  • QT(概述、基础函数、界面类、信号和槽)
  • 【SpringBoot】08 容器功能 - SpringBoot底层注解汇总大全
  • 《汇编语言:基于X86处理器》第13章 高级语言接口(2)
  • __base__属性
  • [ Mybatis ] 框架搭建与数据访问
  • 【Android】【bug】Json解析错误Expected BEGIN_OBJECT but was STRING...
  • Qt——信号和槽
  • 移动端网页调试实战,键盘弹出与视口错位问题的定位与优化
  • iOS 签名证书实践日记,我的一次从申请到上架的亲历
  • vue项目封装axios请求,支持判断当前环境及判断token是否过期等等(详细教程,可复制粘贴代码)
  • UE官方文档学习 C++ TAarry 查询(三)Contain,Find函数的使用
  • Java面试题储备11: mysql优化全面讲一下,及你遇到的对应业务场景
  • 第六十三章:AI模型的“跨界之旅”:不同硬件架构下的兼容性方案
  • RK3568 Linux驱动学习——Linux LED驱动开发
  • 数据分析与可视化
  • Java的异常机制
  • Supabase快速入门与实战指南
  • Effective C++ 条款37:绝不重新定义继承而来的缺省参数值
  • 存储过程作为系统逻辑核心的架构思考 —— 以 SaaS 系统为例
  • 计算机视觉(8)-纯视觉方案实现端到端轨迹规划(模型训练+代码)