本文深入探讨了比特币的可编程性,阐释了比特币编程的特点和局限性。通过闪电网络(LN)和谨慎日志合约(DLC)两个范例,展示了如何利用比特币可编程性的特点以及突破其局限性的方法。同时,文章也解释了比特币开发者限制可编程性的理由,以及这种限制对比特币网络参与者的保护。
作者:Anony
长期以来,人们对比特币的可编程性存在许多误解。人们大概知道比特币的可编程性具有许多的局限性,但并不理解边界在哪里,因此既难以把握什么是可以编程的,也不知道什么是不可能编程出来的。
本文的目的正是应对这些挑战,阐释比特币的可编程性的特点及其局限性。为此,我会先解释比特币的一些基本概念、比特币编程的基本工具,以此提炼其特点和局限性。然后,我将介绍两个范例 —— 闪电网络(LN)和谨慎日志合约(DLC)—— 展示它们是如何利用比特币可编程性的特点以及突破其局限性的。
虽然本文的目的是勾勒比特币可编程性的边界,但这并不意味着我认为这是一种缺陷、比特币的可编程性应该往另一个方向改进,相反,从链协议的角度看,形成这样的特性是有理由的。介绍这些理由,也是本文的任务之一。
这里并没有什么创见,有的只是总结。
众所周知,比特币的运行基于两个基本的概念:交易和 UTXO。你可以把比特币理解成一种可以熔化的金属, UTXO 就是一个一个的比特币块,而 交易 的作用就是把一些比特币块熔化、铸造成新的一些比特币块 [1]。也就是说,UTXO(未花费的交易输出)本身是交易的输出;交易一边消耗以前的交易铸成的 UTXO(以这些 UTXO 为输入),一边形成新的 UTXO;一个 UTXO 一旦被交易花过了,就不存在了。UTXO 有两个基本的属性,一是面值(以 “聪” 来计量);二是解锁条件(熔化条件),由 “锁定脚本”(或者叫 “脚本公钥”)来表达。当一笔交易要花费某个 UTXO 时,就必须提供一些数据(称为 “解锁脚本” 或者叫 “脚本签名”),使之能通过锁定脚本所指定的验证程序,否则就无法花费。
以我们最常接触到的一对一转账为例,其原理大概是这样的:假设你要给 Alice 支付 1 BTC,于是你使用自己可动用的一个或一些 UTXO 作为交易的输入,形成一个面额为 1 亿聪的 UTXO,并在该 UTXO 的锁定脚本中放入 Alice 公钥(并加上检查签名的操作符)。因为没有私钥就无法提供对应公钥的签名,所以这个 UTXO 成为了只有 Alice (的私钥)才能解锁的资金(其他人无法解锁),支付就这样完成了。
由此我们可知,若要编程比特币,使之能为不同的应用场景提供基于技术本身的保障,不外乎要在交易层面或者脚本层面做文章。
那么,在比特币编程中,我们经常用到哪些工具呢?
多签名(Multisig)
M <PUB-1> <PUB-2> ... <PUB-N> N OP_CHECKMULTISIG
,意思是,在它所记录的 N 个公钥中,需要提供 M 个公钥的签名,才能解锁此 UTXO时间锁
哈希原像检查(也叫哈希锁)
OP_HASH160 <hash> OP_EQUAL
,就是检查一个数据的哈希值是否等于锁定脚本中的这个(解锁脚本中的数据是不是锁定脚本中的哈希值的原像)流程控制(并列的解锁条件)
OP_IF
和 OP_ELIF
这样的操作码,可以在锁定脚本中安排多种解锁路径,只要任一路径的条件得到满足,就可以解锁这个 UTXO。上文提到的哈希时间锁合约,也是利用了这样的流程控制操作码。HTLC 的完整脚本形式 [4] 是这样的:## 检查解锁脚本所提供的 R 是否为 H 的原像
HASH160 <H> EQUAL
IF
# 检查公开 R 的人是否为事务最初的接收者
<Payee Public key> CHECKSIG
ELSE
# 检查时间锁是否已终止
<locktime> CHECKLOCKTIMEVERIFY
# 检查请求返回资金的是不是事务最初的发送者
<Payer Public Key> CHECKSIG
ENDIF
以上就是我们在编程比特币时经常会用到的工具。下面是一段脚本,请看看你是否能理解其大概意思:
IF
<Alice 的公钥> 检查签名
ELIF
3 个月 OP_CSV
2 <Bob 的公钥> <Carol 的公钥> <David 的公钥> 3 OP_CHECKMULTISIG
ELIF
1 年 OP_CSV
<Vincent 的公钥> 检查签名
还有一个很少被人注意,但确实也属于一种编程工具的东西,是签名。
比特币的交易在签名时允许使用 SIGHASH 标签 [6],这些标签为签名的有效性作了额外的指定,允许我们改动交易的部分而不会使签名作废。现在比特币支持的 SIGHASH 标签有:
SIGHASH_ALL
表示这个签名签署的是这笔交易的所有输入和所有输出,为被签名的交易增删任何输入和输出都会使该签名作废。用于我们日常的一对一转账SIGHASH_NONE
表示签名所有的输入,但对输出没有任何指定。意思是被签名的交易可以任意调整输出而不会使签名作废,但输入有所改变就会使签名作废。意思像是:“怎么花我的钱我无所谓,但我要求别人跟我一起花,不然我就不乐意”SIGHASH_SINGLE
表示签名所有的输入,但指定了 一个 输出(跟签名所在的输入的索引号相同的输出)。改变被指定的输出以外的输出不会使这个签名作废SIGHASH_ALL | ANYONECANPAY
签名所有输出,但输入可以任意增加。SIGHASH_NONE | ANYONECANPAY
仅提供签名,不对输入和输出作任何限制。本质上是把签了名的这个 UTXO 完全交出去SIGHASH_SINGLE | ANYONECANPAY
签名了输入以及与该输入使用同一个索引号的输出,但其余的输入和输出都可以改变,签名不会因此而作废。这个标签非常有趣,举个例子,Alice 可以签名价值 1 BTC 的输入和 100 XX 代币的输出(假设 XX 代币可以在比特币区块链上存在),这就变成了一种互换的邀约。任何愿意以 100 XX 代币交换 1 BTC 的人都可以补完这个交易并使之上链SIGHASH 提醒了我们,交易的签名也可以附带信息,表达签名人对这个签名的用途的希望;它们同样有可能或直接或间接地用在某个场景中。比如说,你可以用 SIGHASH_NONE 实现委托 [7]。
下文我们还将了解到使用数字签名来携带信息的例子:AnyPrevOut 和 Schnorr 适配器签名。
从上文中我们可以看出,比特币系统运作的基本模式是这样的:在一个 UTXO 形成时,其锁定脚本表达花费该 UTXO 的充分必要条件;锁定脚本中的操作符指明了数据的验证方式(签名验证、哈希原像验证,等等),而交易(中的解锁脚本)的作用就是提供一些数据,使之能通过锁定脚本所规定的验证程序。如果你所提供的数据不能通过验证程序,你的交易就是无效的,会被比特币网络拒绝;只要你能提供可通过验证程序的数据,你想怎么花这笔钱就随你高兴。
如果你曾接触过其它链协议(比如以太坊这样以可编程性著称的协议),你会意识到比特币的可编程性在这些方面有明显的限制:
我无法证明这个清单是完备的,也许我们能找出别的一些限制,不能归入上述四个类别。但在目前,我们都很容易理解这些限制何以是限制,或者说,这些缺失的特性在哪些场景下是有用的:
我想提醒各位的是,我们在此接触到的并不是一个简单的概念:从开发的便利性和用户体验来说,可编程性的限制当然越少越好,功能性越强越好,但从链协议的角度来看,所有的特性都是有代价,可编程性也一样;在边界之外,是不可能实现的东西,但在边界之内,却依然有许多空间,允许我们发挥想象力;在理论上想象它的局限性是容易的,但切实地理解它的工作原理和想象空间是困难的。
那么,在这些限制之下,比特币可以如何编程?当前的比特币的可编程性到底有多大的空间?
我准备了两个例子来帮助大家做难的这件事。相信这也是各位阅读本文的目的。
闪电网络是建立在比特币上的二层网络,目标是实现便宜快捷的小额支付。它基于两个概念: 支付通道 和 交易路由。
支付通道是两个参与者开设的一对一合约,其设计目标是允许双方无限次地相互支付、并且支付无需真正用到区块链(显然,如果需要用到区块链,从概念上来说就做不到 “无限次” 相互支付了)。具体的方法是:让双方把资金锁入一个只有双方都同意才能解锁的保险箱(UTXO),然后,双方通过交换带签名、可被覆盖的交易来表示和更新双方的所有权状态(也即双方的余额),从而实现支付的效果;这些交易都是有效的交易,因此它们可以随时拿到区块链上执行,因此这些交易无需得到区块链的确认,依然能为支付提供安全性;又因为这些交易不会用到区块链,而且发送较旧的交易到区块链上(也即欺诈对手)会遭受惩罚,所以双方可以无限次地相互支付;最后,当双方(或某一方)想退出通道时,只需发送一笔交易到链上,即可结算合约。
而当我们利用哈希时间锁合约,将多笔支付捆绑在一起时,我们就可以实现这样的效果:Alice 仅与 Bob 开设了通道,未与 Carol 开设通道;但 Bob 与 Carol 开设了通道,那么,Alice 就可以借助 Bob 给 Carol 支付。也就是说,当支付通道可以被串联起来、当支付可以跨越多条通道来送达,我们就得到了一个 网络。这就是支付路由和闪电网络的概念。
下面我们来看看闪电网络是如何用上文介绍的工具来实现的。
插一句话:比特币的交易本质上就是一条消息,只不过这种消息可以打包到比特币的区块中、得到比特币区块链的确认、触发比特币的转移(UTXO 的熔铸)。理解这一点将有助于理解支付通道的概念和闪电网络的强大之处。
一. 通道开启
如前所述,要让支付在链下发生(让收到支付的一方不需要将交易发到链上也能相信自己得到的支付是安全的、不能反悔的),我们需要约束支付方对资金的支配权。办法就是支付方和接收方进入一个 2-of-2 的多签名 UTXO。因为支付方不能任意转移走资金,所以它花费这个多签名 UTXO 所形成的支付,即使没有得到区块链的确认,对被支付一方来说也是安全的。
问题来了,如上所述,UTXO 的脚本中不允许存储资金的内部状态,双方一旦把资金锁入了 2-of-2 的多签名 UTXO 中,就只有双方都合作才能使用这些资金。如何防止对手方耍流氓,故意不配合、要挟你呢?
这就涉及到一个概念,叫做 “承诺交易”。在我们这个例子中,假定支付方和接收方将提供资金形成 UTXO #1,那么,双方就 预先签名花费 #1 的交易,比如将 #1 中的资金原样返回给双方。由于 #1 是一个 2-of-2 的多签名输出,这笔承诺交易需要得到双方的签名(双方可以各自给对方提供签名)。而一旦承诺交易得到签名,双方就可以放心签名为 #1 提供资金的交易并广播到比特币网络中,因为他们知道,即使在形成 #1 之后对方突然玩失踪,自己的资金也不会被锁死,这笔承诺交易发送到链上将导致 #1 被花费、自己的资金原样取回。这种提前确定合约状态推进路径的交易,就像是双方给对方的合作承诺,正是它得名的原因。承诺交易的用途非常广泛,实际上,我认为这也应该被当作比特币编程的一种基本工具。
但是,这还仅仅解决了实现链下支付的问题。如何允许双方无限次地相互支付呢?逻辑上来说,这需要我们能 “覆盖” 掉比较旧的支付交易,或者说保证只有最新的支付(所造成的资金分割效果)才能得到区块链的确认。我们知道,由于 UTXO 的锁定脚本表达的是资金解锁的充分条件,而且 UTXO 不会依赖锁定脚本以外的东西,那么,一笔有效的比特币交易将是永远有效的。如何 “覆盖” 掉它呢?
这需要我们进一步编程通道内支付交易的模式。
二. 通道状态更新
假设 Alice 和 Bob 开设了一条支付通道,各存入了 5 BTC。现在 Alice 要给 Bob 支付 1 BTC,于是她编写一条这样的交易,签名后发送给 Bob:
输入 #0:表示 Alice-Bob 支付通道的 2-of-2 多签名 UTXO, 10 BTC
输出 #0 <4 BTC>:
<Alice 的公钥> 检查签名
输出 #1 <6 BTC>:
IF
HASH160 <HASH-B1> OP_EQUAL #这个哈希值由 Bob 给出
<Alice 的公钥> 检查签名
ELIF
<100 个区块> OP_CSV
<Bob 的公钥>
检查签名
这笔交易花费了 Alice 和 Bob 形成的 2-of-2 多签名输出,并把第一个价值 4 BTC 的输出安排给了 Alice;第二个输出价值 6 BTC,但有点复杂;它既可以在 Alice 揭晓某个哈希值的原像之后(注意,这个原像在 Bob 手里),也可以在该交易得到确认的 100 个区块之后被 Bob 拿走。
Bob 也给 Alice 签名一条交易,跟 Alice 所签名的交易的结果刚好相反:
输入 #0:表示 Alice-Bob 支付通道的 2-of-2 多签名 UTXO, 10 BTC
输出 #0 <6 BTC>:
<Bob 的公钥> 检查签名
输出 #1 <4 BTC>:
IF
HASH160 <HASH-A1> OP_EQUAL #这个哈希值由 Alice 给出
<Bob 的公钥> 检查签名
ELIF
<100 个区块> OP_CSV
<Alice 的公钥>
检查签名
交换完带签名的交易之后,支付就算完成了。当两人下一次需要相互支付的时候,也各自签名格式相似的交易,依旧使用 2-of-2 的多签名 UTXO 作为输入,并使用输出的余额变化来表示支付的数额。同时,每当要支付时,双方就交换上一次支付时用到的原像,由新支付的接收方先给对方揭晓原像,支付方在上一次支付时使用的原像则要等收到对方的新承诺交易后揭晓。
就凭这个结构,我们就能实现通道内双方无限次的相互支付!
来详细分析一下这种模式的效果:
综上,这种可以覆盖的交易,帮助我们实现了免信任、可无限次相互支付的通道!(在现实中不是无数次,因为双方都要保存旧交易已经对应的哈希原像,来防止对方欺诈。这种存储负担使得实际允许发生的支付不会是无限次。有趣的是,人们已经提出了一种方案来免除这种存储负担,就是 SIGHASH_AnyPrevOut [9])。
三. 支付路由与闪电网络
如果我们只能实现支付通道,那它只能为需要频繁支付的两方提供便利,并没有特别大的应用价值,也不可能帮助比特币解决扩容问题。但是,我们有哈希时间锁合约。
假设 Alice 要给 Carol 支付,但两人没有直接的通道相连,只是各自跟 Bob 有一个通道。再假设 Alice 在 Alice-Bob 通道中有 3 BTC,而 Bob 在 Bob-Carol 通道中有 2 BTC,那么 Alice 最多能给 Carol 支付 2 BTC。流程如下:
由此可见,HTLC 可以将通道串联在一起,让没有直接通道相连的用户也能相互支付。它让支付通道可以连结起来形成网络。
四. 闪电网络的优点
闪电网络的这些特性使之成为了目前为止实现微支付、川流支付的最优方案,任何需要等待交易确认的系统(包括新兴的许多 Layer-2 方案)都无法与之匹敌。
谨慎日志合约解决的是如何隐私地使用链外数据的问题 [10]。
如果我们把区块链当成一个执行(结算)经济合约的平台,那我们就必须提供一种方法,使之能使用外部的数据。因为许多有意义的合约都是条件式的:举凡期权、期货、博彩、有担保的借贷,他们都要依赖于一些在合约签订时不可知的数据,来决定合约的结果;总要有人来提供相关的信息,合约才能执行。这些提供信息的人我们称为 “断言机(oracle)”。
在这一点上,比特币可编程性的局限性看起来又阻止了我们。在以太坊这样以链上计算为特点的协议中,断言机可以直接输入数据,并调用链上的计算来决定合约的结果。但这一套在比特币上是不可能做到的,因为脚本操作符给出的是验证方式,我们不能输入任意的数据并要求计算。
有什么办法为合约的执行注入额外的信息呢?有的,上文已经提示过了,我们可以通过签名来注入信息。
一. Schnorr 适配器签名
自 taproot 升级开始,比特币开始支持验证 Schnorr 签名。Schnorr 签名的基本结构是这样的:
Schnorr 签名:
R = r.G # r 就是这个签名的 nonce(一次性随机数),G 为椭圆曲线的生成点,. 表示椭圆曲线乘法
s = H(R||P||m) * p + r # 表示 R、公钥和被签名消息三者的哈希值乘以签名私钥,加上 r
验签方法:
s.G = H(R||P||m) * p.G + r.G = H(R||P||m) * P + R # P 和 m 都是公开信息,R 是签名者给出的,所以验签者无需知道签名者的私钥,就能验证一个签名 (R, s) 是由某个公钥对应的私钥生成的
Schnorr 签名的结构使我们能够实现一种非常有趣的技术,叫做适配器签名 [11],它有点类似于哈希锁:
假设私钥 p 的持有者生成这样一个签名:
R = r.G + x.G
s' = H(R||P||m) * p + r
显然,这个 (R, s') 不是一个有效的签名。但是,只有有人知道 x,TA 就可以令 s = s' + x,所得到的 (R, s) 就是一个有效的签名。
你可以把它当成一种隐式的哈希锁:只要签名的接收方知道秘密值 x,就能补完这个签名。只不过,这个秘密值是用椭圆曲线点来承诺的,不是用哈希值来承诺的。
Schnorr 签名还有一种有趣的特性:假设你持有私钥 p 并公开了公钥 P,你对外表示将使用 R 生成一条对 m 的签名,这时候,虽然没有人知道 s 是什么样的,但大家都知道 s.G 是什么样的 —— 验签公式就给出了使用 R、P、m、G 计算 s.G 的方法。
二. 谨慎日志合约
假设 Alice 和 Bob 准备各出 1 BTC 打赌后天的球赛的结果,其中,Alice 赌红队赢,Bob 赌蓝队赢。球赛的结果有三种:红赢、蓝赢、平局。对应的赌约结果分别是:Bob 给 Alice 支付 0.5 BTC、Alice 给 Bob 支付 0.5 BTC、资金原路返回就当没事发生过。
假设现在 Carol 公开表示,当球赛结果揭晓时,她会使用自己的公钥 Pc 和 Schnorr 签名算法签名结果,并提前给出了将要使用的 R 值(记为 Rc)。由于 Rc 已知,Pc 对任一种结果的签名 sci 的椭圆曲线点 s_ci.G
都是可知的,当然,sci 本身是不可知的。
Alice 和 Bob 都认为 Carol 是言而有信并且正直的人,于是选择使用 Carol 的签名作为合约结算的条件。流程如下如下:
R_a1 = r_a1.G + s_c1.G, s_a1_ = H(R_a1||P_a||m_1) * p_a + r_a1
,其中 m1 就是这笔交易。显然,这不是一个有效的签名,只有为 sa1 加上 sc1,才能使之成为一个有效的 Schnorr 签名。这等于是说,只有当 Carol 签名 “红赢” 并将签名 sc1 发布出来的时候,Alice 的这个适配器签名才能成为一个完整的 Schnorr 签名;否则,这个签名就无法用来解锁 2-of-2 多签名输出就这样,我们成功把外部的信息,通过 Schnorr 签名和适配器签名注入了合约,使之成为了合约结算的条件。
有了 DLC,许多金融合约都将可以在比特币上实现:比特币的远期合约、差价合约、其它金融资产的期货合约、期权合约,等等等等,这些金融合约实际上都是依赖于价格信息的条件式支付,所以都能用 DLC 来实现。
甚至于,前文提到的有担保借贷,也可以通过 DLC 来实现,只不过要牺牲一些隐私性:债权人向断言机公开自己的还款地址;至还款日时,断言机检查该地址有无余额、有多少余额,并以签名发布结果;债权人凭借这个签名,拿走债务人锁在 2-of-2 输出中的担保品的相应部分并结算合约。(修订:这是一种低效而且缺乏隐私性的方案,可以编程出只需要参与双方互动、更简洁的方案。)
当我们认为锁定脚本无法表达对其它 UTXO 的依赖是一种局限时,DLC 实际上已经突破了这种局限:其它 UTXO(或者地址)的状态,同样是外部信息,与别的外部信息没有什么不同,同样可以借助签名提供给合约。
三. DLC 的优势与不便
DLC 的一个显著的优势是隐私性:只要一个断言机公开了自己的公钥和 R 值,参与合约的双方无需通知这个断言机、无需告知其合约的内容,就可以直接使用这个断言机所提供的数据;此外,当 CET 被发送到链上导致合约结算时,由于其签名就是普通的签名,外人也根本看不出这是个 DLC。这跟当前在其它链上常见的模式 —— 合约的内容完全公开、断言机的身份和影响力公开 —— 完全不同。
而 DLC 最显著的不便在于,它要为每一种可能的结果都生成交易和签名,当合约有非常多种可能的结果时,需要生成和储存的交易和签名的数量也会非常庞大。此外,它还面临激励断言机提供数据和撮合合约参与方的问题。
一如闪电网络和谨慎日志合约,在利用比特币原生的技术编写应用(或者说协议)时,我们一再地接触到比特币可编程性的限制,但也一再地发现在这些限制之下能够编写应用的方法。闪电网络和 DLC 使我们发现,比特币原生的合约式协议有这样一些特点:
无论你对比特币的可编程性持乐观态度还是悲观态度,想必这份清单想必都会让你产生一种感觉:比特币的编程对应用开发人员和应用参与者都提出了更高的要求 —— 这些限制使得应用开发起来更不直观、更难分析,用户也不能依靠区块链来为他们提供充足的便利,而必须自己承担更多的责任(比如在闪电网络中,你需要自己保管历史状态交易和相应的哈希原像,或者至少要有人负责保管)。
我们不禁要问:这是为什么呢?为什么比特币的开发者不迈出一步,在我们看到的这些方面增强比特币的可编程性,为应用开发者和用户提供更多的便利呢?
或者,我们反过来问:这样限制可编程性,我们得到了什么呢?
无论在哪儿,可编程性始终与链协议(共识规则)息息相关。这不仅是说,链协议决定了可编程性的限制,也是说,为了实现一定的可编程性,链协议也要付出一定的代价(复杂性)。这种复杂性,最终也要由网络中的节点来承担:从短期来看,更复杂的协议需要节点投入更多的资源来运行;从长期来看,更复杂的协议也有更多的失序风险。
假设我们在第二章第(三)节所述的四个维度上全面改进比特币的可编程性,请问我们会得到什么?答案是,我们会得到一个相当接近于当前所谓的通用可编程协议的协议:既可以在链上存储状态,也可以在链上存储控制这些状态的代码,而且这些代码还可以无边界地相互调用 …… 那么,我们需要付出什么样的代价呢?
如果你觉得这一切似曾相识的话,很遗憾,你的感觉是对的,这就是现在通用可编程的区块链上常常出现的问题。这些问题都与底层的链设计相关。
比特币固守着一些限制,正是为了不走入这些陷阱。比特币的开发者希望比特币交易的有效性是长期有保证的、不希望得到一个复杂的资源定价系统 [12],也不希望链上的状态(UTXO 集)不断膨胀。如果你对比特币的链协议感兴趣的话,我非常推荐你阅读 Jameson Lopp 撰写的文章《比特币最重要的特性是哪些?》[13],他既指出了这些重要特性的相互关系,也指出了这些特性的具体体现以及它们是如何得到维护的;他的文章也为上述所有的局限性提供了链协议设计上的理由:为了让交易能够长期有效、也为了避免争抢进入(race condition),我们把 UTXO 封闭成一个独立的宇宙;为了资源使用最小化,脚本操作符被设计成规定验证方式而非实现计算。这些限制牺牲了应用开发者和用户的便利,但保护了比特币网络的参与者 —— 比特币全节点。
如果用我自己的话来说,比特币链协议的设计目标是 “链上状态最小化(最简化)”。为了防止链上状态的膨胀,脚本被设计成无法存储状态;为了防止状态变得复杂,一个 UTXO 自成一个宇宙,彼此不会依赖;包括使用 UTXO 数据结构而非账户模式,也是因为 UTXO 是可以即用即弃的,它不会像账户那样在弃用之后依然有残留的信息。
最能体现这种思想的是一种输出的类型:P2SH(支付到脚本哈希值)输出 [14]。这种输出将实质上的锁定脚本(称为 “赎回脚本”)作为原像产生出哈希值,在链上仅存储这个哈希值和两个操作码;要解锁这样的输出时,必须提供赎回脚本,以及能够通过赎回脚本验证程序的数据。也就是说,它甚至不希望你把锁定脚本明文存储在链上,因为存储锁定脚本的承诺(哈希值)更加节约。(当然,P2SH 的推出不止这一个原因。)等到隔离见证时,这种思想更加突出:隔离见证输出的锁定脚本字段只余一串乱码,连操作码也完全看不见了 [15]。输出类型上依然有 P2WPKH(支付到隔离见证的公钥哈希值)和 P2WSH(支付到隔离见证的脚本哈希值)的区别,但链上存储的数据(的体积)无疑变得更小了。
讲到这里,我又想插句话,跟上文提到的 “承诺交易(commitment txs)” 有关。
博弈理论也研究 “承诺(promises)” 和 “威胁(threats)” 这样的表态而非实际行动,在博弈中的作用。在博弈中,有些承诺和威胁是 “可信” 的,因为它们的执行成本低于可得到的好处,而有一些承诺是不可信的。博弈理论的创见在于,如果一个承诺(威胁)是可信的,那么承诺的内容不必付诸实践,也能对现实产生影响。这样的例子在生活中比比皆是。人们经常使用威胁来吓阻对手,只要这些威胁有可能实行,不必实行也能起到阻止对方得寸进尺的效果。
我认为,这种观念,最符合比特币开发者对 “可编程性” 和 “智能合约” 的想象。换言之,比特币可编程性的目标,是让交易可以变成一种可信的承诺,来推进双方的博弈动态。承诺交易就是这样的可信承诺:因为它自身是一笔有效的比特币交易,随时可以广播出去、触发资金的结算,因此,它不必真的广播出去,参与的各方也认为这样的交易所造成的状态变更效果,是真实、安全的。
在比特币开发的世界里,被描述成 “智能合约” 的东西(包括哈希时间锁合约 HTLC,闪电通道的状态更新交易 RSMC),实际上都是锁定脚本的模式,它的作用是构造可信的承诺,而不是用于计算。
在闪电网络中利用 HTLC 形成支付路由时,每一个 HTLC 的接收方,都知道这是一种可信的承诺:只要自己能揭开那个哈希值的原像,就能获得支付;因此,这个 HTLC 不必真的上链,接收方也不担心支付方反悔。支付方也知道这个 HTLC 是一个可信的承诺,因此,当接收方能够揭开原像时,支付方会配合地更新通道内的状态,而不是逼迫接收方拿着 HTLC 上链。
下次再有人问你 “比特币是否支持智能合约” 时,请回答 “比特币自始至终都支持智能合约”。但它支持的是基于验证的、无状态的智能合约;而不是以太坊那样基于计算的富状态智能合约。也不必相信未来的某种升级将允许我们在比特币上实现以太坊式的智能合约(在 taproot 升级的时候,经常有人产生这种误解,因为大家都说 taproot “增强了比特币的智能合约功能”),不是技术上不可能,而是那会打破我们一贯以来的共识,不会得到人们的认可的。
本文有多个写作目标,因此叙述显得凌乱。一方面,我希望总结在闪电网络和谨慎日志合约中体现出来的比特币编程的特点,帮助读者了解比特币的编程技巧;另一方面,我也认为,从 “局限性” 的角度来认识比特币的可编程性,也是不可或缺的的,因为这将给我们更清晰的边界感,还能告诉我们比特币链协议演化的方向以及它不会突破的底线;此外,我还希望解释比特币的开发者这样限制可编程性的理由 —— 这事关我们对比特币本身的理解,如果你不能接受这其中的思想,迟早你会站在功能性的角度批评比特币的可编程性。
过去的许多年来,这个行业的发展始终伴随着对功能和性能的强调:人们鼓吹通用可编程的协议,不断推出吞吐量更强的区块链。但是,很少有人来提醒大家,所有的功能和性能都是有代价的。不会有天上掉馅饼的事情。
而比特币,则一贯以 “去中心化” 为理由,限制人们用简单粗暴的方式追求功能、性能和便利性。如果失去了这种坚守,我不知道比特币会变成什么样,也不确定它是否还会得到这么多人发自内心的热爱。
最终,当我们解释了其可编程性的限制背后的理由,我们就得到了一个完整的论述。我们可以说,我们已经找到了比特币稳定不变的核心。而闪电网络和 DLC 则使我们相信,即使它面临这么多的限制,在边界之内,依然有很大的空间,依然可以产生伟大的项目,依然值得我们去探索和开发。
[1]:这个比喻在某些地方惊人地准确:UTXO 在被交易花费之后就不复存在,就像金属块被熔化之后就不可能再找回完全相同的一块。它来自 Gigi 检讨我们在比特币世界里的用词的文章: https://learnblockchain.cn/article/18058/
[2]: https://learnblockchain.cn/article/18096/
[3]: https://learnblockchain.cn/article/18095/
[4]: https://www.btcstudy.org/2021/09/15/lightning-network-in-depth-part-2-htlc-and-payment-routing/
[5]: https://learnblockchain.cn/article/18092/
[6]: https://learnblockchain.cn/article/18089/
[7]: https://learnblockchain.cn/article/18093/
[8]: https://learnblockchain.cn/article/18097/
[9]: https://learnblockchain.cn/article/18094/
[10]: https://learnblockchain.cn/article/18090/
[11]: https://learnblockchain.cn/article/18091/
[12]:在隔离见证之后,比特币交易的定价系统已经变得比原来更复杂了:同样内容和体积的交易,如果使用隔离见证的输入,会比使用非隔离见证输入的版本享有更低的交易费,也即,在众所周知的体积度量以外,它还增加了一个度量。但这样的复杂性在比特币中不是普遍的,它依然要比我们所知的大部分链协议更简单。
[13]: https://learnblockchain.cn/article/17973/
[14]: https://github.com/inoutcode/bitcoin_book_2nd/blob/master/%E7%AC%AC%E4%B8%83%E7%AB%A0.asciidoc
[15]: https://learn.saylor.org/mod/book/view.php?id=36376&chapterid=19010
(完)
- 本文转载自: btcstudy.org/2022/09/07/... , 如有侵权请联系管理员删除。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!