作者:Lloyd Fournier

来源:https://mailmanlists.org/pipermail/dlc-dev/2022-August/000149.html

dlc-dev 邮件组的各位:

你们好。如你们所知,我们一直在思考如何使用批量的 “你切我选(cut-and-choose,本意为在分配利益时由一方来切分但让另一方先选择)” 可验证加密(而不是适配器签名 1 )来实现谨慎日志合约(DLC)。我们近期取得的重大进展是充分地优化协议,让使用 BLS 签名断言机的比特币 DLC 具备了实用的可能性。直观地估计性能,通过揭露 11 个 BLS 签名(每个签名 1 比特)以批量可验证地加密 2048 个 Schnorr 签名(是对 2048 种可能结果的见证消息(attestation)的签名),在我的笔记本电脑上要花去大约 2.57 秒(如果经过预处理,可以降至 1.7 秒),可获得 30 比特的静态安全性。

关于性能,还有很多可说的,而且还有一些优化需要做,但从论证的角度,我们已经可以说这是 “实用的” 了,至少已经很解决了。我希望各位记住的一种优化措施是,我认为这套协议还可以再快大约 50%,只要支付函数是单调的,因为这样一来,在按位分解的见证消息中,你就只需要可验证地加密数值 1 或者数值 0(而不需要加密两者)。

那么,基于 BLS 的见证消息变得实用,有何意义呢?最明显的一点是,我们可以在断言机的公告中剔除 nonce 这种东西,因为 BLS 签名不需要随机性。只需要知道一个断言机的公钥,我们就能对任何事件创建 DLC 了,只要你知道这个断言机会见证那个事件就行。嗯 ,这又怎么样呢?不还是得查询断言机来看 TA 会不会、以及如何见证那个事件,不是吗?从表面上来看,这甚至连一次 HTTP 查询都省不下来。

但事实证明,抛弃 nonce 会产生巨大的影响。请考虑一种全新的断言机:它们根本不发公告。它只有一个 HTTP POST 端点:“/attest”。假设你希望这个断言机见证 BitMEX 交易所中的 BXBT 在 2022-08-03T12:00:00.000Z 的价格。在 POST 的主体中,你会发送类似于这样的内容:

{
    "input" : {
         "url":  "'
https://www.bitmex.com/api/v1/instrument/compositeIndex?symbol=.BXBT&startTime=2022-08-03T12:00:00.000Z
",
         "kind" : "jq",
         "filter": ".[]|select(.timestamp ==
\"2022-08-03T12:00:00.000Z\")|select(.symbol == \".BXBT\")|.lastPrice >
23000 | round",
    },
    "output" : {
        "kind" : "bit-decomposition",
        "n_bits" : 20
    }
}

而目标断言机 —— 在你发起请求的时候 —— 会访问 bitmex.com/api,然后获取 JSON 结果,然后应用 jq 过滤器、抽取出需要的数值。

如果你自己操作一遍,你会得到这样的输出:

$ curl -sSL '
https://www.bitmex.com/api/v1/instrument/compositeIndex?symbol=.BXBT&startTime=2022-08-03T12:00:00.000Z'
| jq '.[]|select(.timestamp == "2022-08-03T12:00:00.000Z")|select(.symbol
== ".BXBT")|.lastPrice | round'
23409

然后,这个断言机就会 —— 当场 —— 为数值 23409 按大端序(big-endian)排列的 20 个比特 —— 00000101101101110001 —— 逐个生成 BLS 签名,共计 20 个。每个 BLS 签名都包含了请求的内容、比特的位置和比特值。将请求内容也包含在签名里是一个关键,因为它允许你提前(在发起请求之前)预测每个比特值的 BLS 签名。

我认为这是对当前的断言机模式的巨大提升。我们来看看这会如何影响 DLC 的开发者和用户。

断言机会变得更强大、更简单

这里需要指出的关键一点是,在上面这个例子中,断言机完全不需要提前知道 BitMEX 和 BXBT。它可以见证互联网上的任何东西。我也可以见证互联网上的任何东西。它甚至可以使用 css 选择器见证 HTML 页面上的值,等等。用户可以打赌任何可以从互联网上获得权威来源的信息(维基百科可不算哦!)。

人们可能会批评道,断言机不应该只是拿到互联网的随便什么东西然后见证它:断言机应该对自己的见证消息的正确性负责,而不是把责任推卸给一个网站。我不认为这种意见有什么道理,因为(1)从互联网上获取内容,本就是现实中断言机正在做的事;(2)(举例而言)对 BXBT 来说,除了 URL,没有更权威的信息来源了;(3)在这个模式中,用户同样可以要求断言机从多个来源处获得数据并取平均值,或检验 5 个信息源中至少有 3 个保持一致,等等;(4)某个断言机主动发布自己认为权威的结果,跟这种模式是完全兼容的。

这种断言机实现模式的主要好处在于,断言机可以是完全无状态的(completely stateless)。自己运行断言机的人就知道这是多么大的生活品质提升。对用户来说,主要的好处是应用开发者可以添加新的项目,无需等待某个断言机表示自己会见证某个事件。我还很喜欢一个特点:你打赌的内容是完全明确的,所以你可以去除当前的 DLC 规范中对 “边界错误(bounder error)” 的处理措施。

断言机可以在发布见证消息之前处理 web 数据

设想一下,假设断言机不是像上面的例子那样使用 jq 过滤器,而是允许执行一个 WASM 二级制包来处理 HTTP 响应。那么,用户应用就可以编写强大的处理逻辑,输出一个比特数组。例子如下:

  1. 这个 WASM 程序可以处理来自多个信息源的数据,并在输出最终数值之前应用完全定制化的逻辑(多数决、取平均值,等等)
  2. WASM 可以不输出像案例中的 23409(比特币的价格)这样的 “结果” 数值,而是将这个价格直接映射成 CET(DLC 的合约执行交易)的值。所以,如果你希望为覆盖 10000 到 100000 的价格而生成 1024 个不同的 CET,这个 WASM 可以直接将 23409 映射成间隔,例如 (23_409 - 10_000)/(100_000 - 10_000)/(1024 - 1)) ~ 152 ,所以,断言机会见证 152 而不是 23_409。这意味着,见证消息与 CET 之间可以做到 1 对 1 映射。
  3. 这种处理后的结果的 “支付” 函数总是能够做成单调的函数,因此非常易于处理(我在文章开头提到的优化措施也总是能够应用)。

对于 Itchaysat 2 的用户来说,第一点是非常重要的,因为它除了获得最终的结算值,还需要检查在 DCL 存续期间,数值从没有高过或低过某个值。当前(就我所知)他们会为合约存续的每一分钟创建一个新的预签名交易来执行这个规则。如果能移除这一点,并让断言机通过检查 BitMEX 的 API 中的所有值来确定各时间段中价格有无低于某个下限、再见证一个布尔值,那是很棒的。

在我看来,第二点完全消除了遵循当前的规范文档的需要。文档中包含的逻辑将放在断言机输出见证消息前要运行的 WASM 程序中,并且这个程序是得到应用层的各方同意的。

  1. https://github.com/discreetlogcontracts/dlcspecs/blob/master/PayoutCurve.md
  2. https://github.com/discreetlogcontracts/dlcspecs/blob/master/NumericOutcome.md
  3. https://github.com/discreetlogcontracts/dlcspecs/blob/master/NumericOutcomeCompression.md

这种想法有一个缺点,就是用户会向断言机泄露更多自己的合约的信息(相比当前的模式)。当前你最多只会泄露事件本身,但不会泄露你使用了哪些事件的组合,也不会泄露事件的结果与支付间隔之间的关系。泄露支付间隔(payout intervals)可能会有糟糕的后果,因为只要一笔相关的交易会发到链上,别人就可以检查 CET 输出的数值是否能从支付间隔中推导出来,从而把它们关联起来。在实操中,有三种办法可以混淆这种关联(这是我留给读者的一项练习!)。也许还有一些我没有想到。

对断言机来说,还有一个缺点,就是必须见证来自匿名用户的请求。你可能需要保护自己不要遭到 DoS 攻击:不要生成太多的签名、不要让 WASM 跑太长事件。作为一个参考,在我的笔记本电脑上,一条 BLS 签名需要耗时 1ms 来生成。

BLS 签名可以实现非交互的门限见证

我们的协议 1 允许实现 t-of-n 的 DLC 协议,时间复杂度差不多是线性的(与 n 呈线性)(现实中是次线性的)。所以,如果只使用一个断言机,处理 2048 个 CET 它需要 2.57 秒,但对于 5-of-10 的门限断言机群体,只需要 21 秒。协议的这一部分跟非 BLS 的见证消息也是兼容的。但是,BLS 允许在群体内非交互式地创建一套门限机制。也就是说,如果 10 个断言机同意组成一个阈值为 5 的群体,它们可以使用一个交互式的协议生成共有公钥,然后整个团体对外就可以作为一个断言机,因此不会有性能上的损失。每个断言机都可以通过原有的公钥单独使用,然而一旦你从 10 个断言机处获得了 5 个签名,你就可以计算出对应于群体聚合公钥的签名。

技术上来说,非 BLS 的方案也能做得到(例如 Schnorr 签名下的 FROST 协议),但这会需要至少 5 个断言机在见证期间在线交互,所以做不到同样实用。

- - -

我对这一切非常兴奋,但是技术方面的东西就写到这里。我认为,这是将比特币和外部世界连接起来的正确方式。请告诉我你的想法。

祝好,

LL

P.S. 用于基准测试的代码还没有公开,因为 2FA 问题我无法改变代码的访问权限。我会尽快修复。1 处所引的论文也会持续更新以包含性能上的进展。

后续

我想追加一个想法。

在我们上次通话中,Nadav 提到了 “离链的智能合约(smart contracts unchained)” 的想法:https://zmnscpxj.github.io/bitcoin/unchained.html

这把我们带到了一个有趣的地方:要是用户同意被外包的智能合约的结果,他们甚至无需联系双方都信任的服务。这一点在我们这里也是适用的。在 BLS 方案中,如果双方愿意合作,就无需请求断言机。这对于隐私性来说是个好消息。

举个例子,考虑我们之间有一个对 BXBT 的 CFD 合约,是用 WASM 智能合约来实现的。当我想要结算合约时,我可以先访问 bitmex.com/api,获得有效的 HTTP 响应,通过本地的 WASM 合约程序来运行它,然后看看哪个 CET 会被激活。然后我请求我的对手方跟我做一遍同样的事。要是我们都同意这个结果,那就完全无需通知断言机。这非常有利地改变了这个方案的隐私评价。在这种情形中,用户对断言机将拥有完美的隐私性。当然,现在用户自己会访问 bitmex.com/api,这就向 bitmex 泄露了你对某个事件的 BXBT 感兴趣的事实。但已经好很多了。因为向一个 API 端点请求内容是一个非常平常的事,并不意味着你有或者没有缔结什么合约(至少在我们这个例子中,许多 app 都从这个 API 请求数据。

这非常酷,因为这意味着断言机甚至无法估计有多少人在使用它的服务!

LL

(译者注:作者忽视了一点,在当前使用适配器签名实现的 DLC 中,双方合作同样可以完全不使用断言机的数据,所以从用户的角度看,在这一点上,BLS 模式的隐私性并不比适配器签名更好,最多只是一样好。)

(完)