理解比特币 Miniscript(二):工作原理
作者:benma
来源:https://shiftcrypto.ch/blog/understanding-bitcoin-miniscript-part-2/
本文为 “理解比特币 Miniscript” 系列的第二篇。
在本系列的第一篇文章中,我们检视了使用 Bitcoin Script(比特币的原生编程语言)来编程 (1 号人物可以随时解锁) or (2 号人物可在一年后解锁)
这样精心设置的资金锁定条件的例子。这些例子证明了,因为 Bitcoin Script 的缺点以及陷阱,这样的条件构造起来、使用起来多么地难。既难以开发出能够编码我们想要的花费条件的脚本,也难以为这样的脚本构造有效的见证数据(从而花费资金)。
Miniscript 通过引入封装了 Bitcoin Script 代码的片段、运用这些片段来编写脚本,解决了上面说的问题。
本文将深入讲解 Miniscript 的工作原理,以及它是如何映射成 Bitcoin Script 的。
如果你还没读过本系列的第一篇文章,请务必花上一点时间,因为我们将依赖于那篇文章介绍过的 Bitcoin Script 的概念,例如 Bitcoin Script 是如何执行,以决定资金是否可被花费的。
什么是 “Miniscript”?
Miniscript 编程语言由两个独立的部分组成:
Policy 语言
Policy(“花费策略”)语言是一种抽象的表达式语言,是可以组合且易于直接阅读和编写的。Policy 句子可以由编译器自动编程成合适的 Miniscript 代码。Policy 句子的一个例子是 or(pk(key_1),pk(key_2))
,意思是 “公钥 1 和公钥 2 都可花费”。
Miniscript
Miniscript 表达式,举例来说,是这样的: or_b(pk(key_1),s:pk(key_2))
,这是使用 sipa 的编译器,从上面那个花费策略编译而来的;它是 or_b
、pk
这样的片段的组合。
每一种片段都可以映射成特定的 Bitcoin Script 代码。 比如说, pk(key)
会映射成 <key> OP_CHECKSIG
,而 or_b(X, Y)
会映射成 [X] [Y] BOOLOR
。
Miniscript 自身也是一种表达式语言,容易用计算机读取,也易于被人类阅读。
对于计算机来说,这是很重要的,这样你的钱包应用可以解码一个 Miniscript 表达式,并转化成收款地址、让你能够花费其中的资金。
对于人类来说,它的意义在于你只需在纸上记录下来,就可以备份你的钱包的描述符,而且还可以使用同一个描述符跟不同的应用和工具交互。举个例子,你可能想要将你的钱包描述符导入一个投资组合监控工具中,或者一个报税工具中,或是导入一个移动端的观察钱包。钱包描述符可以包含一个 miniscript 表达式,然后就能推导出地址。
Miniscript 表达式语言看起来跟 policy 语言很像,所以很容易将两者搞混。但你要理解,它们是两种完全独立的语言:
Policy 语言是一种帮助开发者创建花费条件的工具,因为它是很容易编写的。它只有少数几种元件,例如 and(X,Y)
、or(X,Y)
和 older(time)
;而且这些元件彼此之间可以完美组合。Policy 语言只是一种给开发者使用的工具,并不是标准。不能保证同一个 policy 表达式总能产生同一个 Miniscript 表达式。
相反,Miniscript 是得到充分说明的。只有 Miniscript 会被用于推导 Bitcoin Script 代码、有效的见证数据,以及执行正确性分析。
那么,为什么开发者不直接编写 Miniscript 表达式呢?为什么我们还要依赖于 policy 编译器?原因是,手写 Miniscript 表达式并不容易,而且,因为它是 Bitcoin Script 的一种封装,它也继承了 Script 的复杂性:
Miniscript 语言比 policy 语言有更多的片段。举个例子,在 Miniscript 中,至少有如下几种表达
X or Y
的方式:or_b(X,Y)
、or_c(X,Y)
、or_d(X,Y)
和or_i(X,Y)
,每一种都对应着不同的表示X or Y
的 Script 代码,这些代码的脚本体积、见证数据体积、与其它代码的组合方式,都各不相同。可能有许多 Miniscript 表达式可以编码同一种花费条件。而 policy 编译器可以帮助你优化表达,例如,通过降低脚本体积来减少所需的交易手续费。
不是所有的 Miniscript 表达式都能产生有效的脚本:这些片段必须以某些方式组合起来,才能获得正确性。policy 编译器可以确保只会产生有效的 Miniscript 表达式。
实际操作:映射成 Bitcoin Script
为了理解一个 Miniscript 表达式是如何编码一个 Bitcoin Script 代码的,我们看看下面这个表达式:
or_b(pk(key_1),s:pk(key_2))
每一个片段都可以映射成特定的 Bitcoin Script 代码。 pk(key)
映射成 <key> OP_CHECKSIG
,而 or_b(X, Y)
映射成 [X] [Y] BOOLOR
。
每一种片段都可以用封装器来封装,这是用冒号 :
来表示的: s:X
封装器会映射成 OP_SWAP [X]
。封装器跟其它片段基本上是一样的,不过更准确一些。如此一来,它们就只是语法上的点缀。你可以认为(比如说)s:X
跟 s(x)
是一样的, dv:older(144)
跟 d(v(older(144)))
是一样的。
所以,整个 Miniscript 可以翻译成这样的 Bitcoin Script 代码:
<key_1> OP_CHECKSIG OP_SWAP <key_2> OP_CHECKSIG OP_BOOLOR \_________________/ \ \________________/ / \ X \ X / / \ \__________________/ / \ Y=s:X / \_______________________________________________/ or_b(X,Y)
在这一个案例中,可以花费这笔资金的见证数据的形式将是 <signature2> <signature1>
这样的,其中至少要有一个签名是有效的。需要 OP_swap
,这样 <key2> OP_CHECKSIG
才不会对栈顶的元素操作 —— 这时候的栈顶元素将包含 <signature1> <key_1> OP_CHECKSIG
的结果 ——而是对栈顶之下的第一个元素操作,这个元素包含的是第二个公钥的签名。
Miniscript 总共有 22 种定义好的片段和 11 种封装器,每一种都可以准确映射成 Bitcoin Script 代码。可在这份规范中了解这些片段以及它们的映射。
我们再分析一个更复杂的表达式:我们在本系列的第一篇文章中提到的那个一针见血的例子:
pubkey1 OR (pubkey2 in one year)
我们用来编码这个花费条件的 Script 代码是非常复杂的,而且很难手动开发出来:
<pubkey1> OP_CHECKSIG OP_IFDUP OP_NOTIF <pubkey2> OP_CHECKSIGVERIFY <52560 (one year)> OP_CHECKSEQUENCEVERIFY OP_ENDIF
但是,使用 Miniscript,上述的花费条件就可以用这样的 policy 语句来表达:
or(10@pk(pubkey1),and(pk(pubkey2),older(52560)))
编程成 Miniscript 表达式:
or_d(pk(pubkey1),and_v(v:pk(pubkey2),older(52560)))
通过将表达式中的片段映射成对应的 Script 代码,我们就可以得到上面的复杂 Script 代码:
older(52560)
概括了<52560> OP_CHECKSEQUENCEVERIFY
v:pk(pubkey2)
概括了<pubkey2> OP_CHECKSIGVERIFY
and_v(X,Y)
概括了[X] [Y]
,在这个例子中就是<puybey2> OP_CHECKSIGVERIFY <52560> OP_CHECKSEQUENCEVERIFY
pk(pubkey1)
概括了<puybey1> OP_CHECKSIG
or_d(X,Y)
概括了[X] OP_IFDUP OP_NOTIF [Y] OP_ENDIF
,最终得到上面那段复杂的代码
这里的 10@
给了 policy 编译器一个提示:我们预计,这种花费路径比其它路径更有可能被使用。编译器可以使用这个信息来优化总的脚本大小。
一旦我们有了最终的 Bitcoin Script 代码,钱包应用就可以将它转化为一个 bc1...
这样的收款地址,然后你就可以拿它来收款。这些资金将使用上面的 policy/Miniscript 表达式所表达的花费条件。
生成见证数据
对应的有效见证数据也可以从 Miniscript 表达式中自动生成出来,因为每一种片段都定义了如何构建有效的 “满足(satisfaction)” 和 “避开(dissatisfaction)”(译者注:分别指能够通过验证的数据,以及不能通过但不会让脚本终止执行的数据)。一种运用了 Miniscript 的钱包应用,将使用这种方法来允许用户发送交易。
所有片段的 satsifaction 和 dissatisfaction 的清单,可以在这个网页的 “Basic satisfactions” 找到。
举个例子, pk(key)
这个片段可以映射成 <key> OP_CHECKSIG
,这样的见证脚本可以用 <signature>
(签名)这样的见证数据来满足。最终的执行脚本将是 <signature> <key> OP_CHECKSIG
;如果签名有效的话,它会留下 1
在堆栈中 ,不然就会在堆栈中留下 0
。同一个片段,也可以用空的无效签名 <>
来 “避开”。“避开” 意味着脚本不会终止执行,只会在堆栈中留下一个 0
然后继续执行。
请参考本系列的第一篇文章,了解见证数据和见证脚本是如何组合在一起、通过执行来确定资金是否可被花费的。
我们为上面案例中的同一个表达式生成见证数据:
or_b(pk(key_1),s:pk(key_2))
pk(key)
片段可以用<signature>
来满足,也可以用空签名<>
避开or_b(X,Y)
片段([X] [Y] OP_BOOLOR
)有三种不同的满足方式:X 和 Y 都被满足,或者其中一个被满足(另一个被避开):[satisfaction for Y][satisfaction for X]
,或[dissatisfaction for Y][satisfaction for X]
,或[satisfaction for Y][dissatisfaction for X]
。结合两者:
or_b(pk(key_1),s:pk(key_2))
有这三种有效的见证数据 :<signature2> <signature1>
<> <signature1>
<signature2> <>
结论
在这篇文章中,我们看到了 Miniscript 是如何简化复杂花费条件的开发的,以及它是如何让钱包应用能够使用这些条件来收账和发账的。
在下一篇文章中,我们会使用 Go 语言编写一个真正成熟的 Miniscript 解析器和正确性分析器。他将能够从任意的 Miniscript 表达式中创建比特币收账地址。敬请期待!
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场
您可能感兴趣
-
Web3入门知识 -- 什么是区块链,区块链的特性分析,公链,联盟链,跨链和链抽象
一、什么是区块链 区块链是一种去中心化、可追溯、不可篡改的分布式账本技术,账本中记录了所有的交易数据。其核心特性通过以下机制保障:去中心化:由共识网络保障,无单一控制中心。可追溯:账本数据公开,交易记
-
「加密概念股高管访谈」博雅互动戴志康:香港正在以监管政策和金融基础重塑 Web3 竞争格局
上市公司的 Web3 战略及布局已成为公众越来越多关注的热点话题。在此背景下,MetaEra 正式启动「高端对话」加密概念股高管访谈系列。我们将对话那些在数字化转型浪潮中敢为人先的企业领袖,通过决策者
-
「加密概念股高管访谈」从汽车金融到全球矿企:灿谷 CEO Paul Yu 解码 Web 3.0 算力生态战略
文章作者:Lesley 文章来源:MetaEra 核心观点 • 相比于单纯的持币策略,以挖矿作为进入 Web 3.0 的战略路径具备三重优势:较强的抗波动能力、稳定的现金流韧性、以及资产的协同增值潜力
-
「加密概念股高管访谈」文化共识驱动金融创新:Bit Origin 的 DOGE 财库战略解析
文章作者:0x9999in1 文章来源:MetaEra 上市公司的 Web3 战略及布局已成为公众越来越多关注的热点话题。在此背景下,MetaEra 正式启动「高端对话」加密概念股高管访谈系列。我们将
-
1000 万如何获得 10% 的年化收益?Web3 语境下的“稳健高回报”悖论
最近,一个看似简单的问题在加密圈热度讨论:“如果我有 1000 万,应该投到哪里去?还能实现 10% 年化收益吗?” 乍一听像是中产焦虑的延续,但这背后,其实是加密市场的真实写照——激励红利逐渐退潮,
-
中心化交易所进军 DeFi:Bybit 为何计划推出 ByReal?
作者:Chi Anh和Ryan Yoon, Tiger Research这篇报告由Tiger Research撰写,分析了为什么像Bybit、Binance和Coinbase这样的主要中心化交易所(C
-
项目方必读:如何通过群体心智做市场
1981 年,16 岁的释永信进入了当时几乎被遗忘的少林寺。那时寺里只有 9 个和尚,靠种地和香火艰难度日。转折点出现在一年后:李连杰主演的《少林寺》电影引爆全国,古寺一夜之间成为大众关注的焦点。 释
-
特朗普强推亲加密联储理事!九月降息已成定局?
加密货币市场表现 当前,加密货币总市值为 3.86万亿美元,BTC占比 60%,为 2.3万亿美元。稳定币市值为 2698亿美元,最近7日增幅1.04%,其中USDT占比61.21%。 CoinMar
- 成交量排行
- 币种热搜榜

