作为一种无状态的现金系统,比特币网络上的“智能合约”并非去中心化商城,而是一套用脚本语言 Script 定义执行规则的密码学协议。它们看似简单,却让“不可篡改、抗审查、可预期”成为可能,同时也是 2021 年 Taproot 升级改造的灵魂基础。
比特币交易的真面目:UTXO 与脚本对话
为什么说“余额”并不存在?
很多新手把比特币想象成“某地址上写了 1 个 BTC”,但实际上链上只保留了 一个个未经使用的输出(UTXO)。钱包通过扫描链上所有 UTXO,找出由你私钥能解锁的那些面额并求和,瞬间生成可用“余额”。
- 输入=用解锁脚本(unlocking script)去“吃”掉指定的 UTXO
- 输出=再给下一任持有者留下“带锁”的比特币
- 变成 STXO(已花输出)之后的 UTXO,从此无法再被任何交易引用
比特币为什么没有“无限循环”?
脚本 Script 被故意做成“非图灵完备”:
- 没有 for / while —— 交易验证时间可预期
- 只有堆栈操作 —— push、pop、运算顺序一目了然
- 执行失败即交易无效 —— 网络节点无需承担漫长计算
换言之,那些看似“简陋”的指令,正是抵御拒绝服务攻击的防火墙。
脚本语法速成班:堆栈计算实例
在 Python 里 1 + 1 = 2;换到脚本 Script 得这么做:
OP_1 OP_1 OP_ADD- 栈:
1 → 1 → {执行 +} → 2 - 运行完顶部唯一元素 = 2,验证通过
P2PKH:绝大多数日常交易的脚本模板
锁定脚本(ScriptPubKey):
OP_DUP OP_HASH160 <公钥哈希> OP_EQUALVERIFY OP_CHECKSIG解锁脚本(ScriptSig):
<签名> <公钥>节点验证
把两段脚本拼接起来,确认:
- 公钥 → 公钥哈希 与锁定脚本里的值一致
- 公钥 + 签名 匹配 → 原 UTXO 一解锁,交易即合法
P2SH:多签、时间锁等多条件扩展
当交易逻辑复杂(比如 3/4 多签),直接把所有条件放进 ScriptPubKey 会导致地址臃肿。因此引入“支付到脚本哈希值 P2SH”:
- 锁定脚本只放赎回脚本的哈希
- 解锁脚本提供完整赎回脚本及签名
- 早期节省空间,后期再验证全部条件是否满足
示例赎回脚本(3-of-4 多签):
<3> <Pub1> <Pub2> <Pub3> <Pub4> <4> OP_CHECKMULTISIG锁定脚本:
OP_HASH160 <脚本哈希> OP_EQUAL典型应用场景速览
- 冷/热钱包多签:3 把私钥分别放在不同地点
- 时间锁:约定“区块高度 ≥ N”才能解锁
- escrow 托管:买家、卖家、仲裁者三方合约
这些功能早在 2012 年就由比特币原生脚本支持,核心依旧围绕“UTXO + 脚本条件”。
常见问题解答(FAQ)
Q1:比特币脚本能做 DeFi 贷 与别人 杠杆对冲吗?
A:受限于非图灵完备与 UTXO 模式,本身只能做预先锁定的“条件触发”。若需要更复杂的 借贷利率模型,需借助 L2 或 侧链,再在主网通过脚本完成资金结算。
Q2:为什么我常听到“比特币没有智能合约?”
A:这是市场语义的误会。比特币的智能合约更像是 极简可验证脚本,跟以太坊 Solidity 的高自由度不是同一量级,但它把“少量指令发挥到极致”。
Q3:Taproot 对脚本有什么改变?
A:Taproot 引入 MAST 结构,允许多个复杂脚本仅暴露真正被执行的路径,减少链上数据并提升隐私,却仍由同一份 Script 体系驱动。
Q4:如何自行体验 P2SH?
A:下载开源钱包 Electrum 创建多签账户,勾选“使用 P2SH 地址”,用 12 个助记词导入 2/3 的密钥试试水,就能看到锁定脚本的哈希与赎回脚本明文。
Q5:手续费会因为脚本复杂而飙升吗?
A:会,字节长度直接影响矿工费用。但在主网,平均多签脚本每千字节依旧比 ERC-20 代币转账省不少,这也是比特币做“简单可验证结算层”的优势。
小结:把复杂留给二层,把可预测还给 Layer-1
锁定脚本、解锁脚本、UTXO、堆栈运算——这些看似“原始”的设计,正是比特币十年如一日 确定性结算 的幕后功臣。虽然脚本无法一口气实现以太坊级别的 DeFi 乐高,但在 价值存储 + 可编程结算 领域,它已经一直在静静地发挥作用。
下一篇《脚本,Part-2》将带你深入 OP_CSV、OP_CLTV 等时间锁指令,以及 Taproot + Schnorr 签名 如何让脚本更省链上空间,敬请期待!