本文档详细介绍了数字结果 DLC 的 CET 构建、适配器签名和签名验证的完整流程,包括四舍五入间隔、合约执行交易计算和签名以及合约执行交易签名验证。通过数字分解、赔付曲线和确定性舍入等技术,优化了 DLC 的效率和可扩展性,并提供了签名验证的额外步骤,以应对机器之间精度差异。
本文档结合了 数值结果压缩 和 赔付曲线 规范,以及独立引入的 舍入区间,以指定 CET 的完整流程构建、适配器签名和数值结果 DLC 的签名验证。
当处理枚举结果时,DLC 只需要一个 nonce,并且合约执行交易 (CET) 使用单个 oracle 证明进行声明。 这种方案产生的 DLC 包含每个可能结果的唯一适配器签名,这只有在可能结果的数量可管理的情况下才是可行的。
如果结果可以是很大范围的数字,那么使用对该范围内所有可能数字的简单枚举是笨拙的。 我们通过使用数字分解来优化这种情况,其中 oracle 单独签署结果的每一位数字,以便通过忽略某些数字可以将许多可能的结果压缩到单个适配器签名中。
我们还压缩了传达所有结果所需的信息,因为这通常可以看作是由几个数字参数化的赔付曲线,这些数字决定了整个可能域的赔付。
最后,我们引入了一种确定性舍入方法,允许 DLC 参与者在他们愿意在赔付中允许一些额外舍入误差的地方增加数值结果压缩。
我们将所有这些部分放在一起,以指定数值结果 DLC 的 CET 计算、适配器签名和签名验证程序。
该规范以及赔付曲线和 数值结果压缩 规范主要关注协议级别的确定性再现和通用更高级别信息的简洁通信。 这些文档不太可能涉及到应用程序级别和 UI/UX 开发人员,他们应该在自己的抽象级别上操作,只有在与最低级别的核心 DLC 逻辑交互时才将应用程序级别的信息编译成此处指定的格式。
正如 数值结果压缩文档 中详细说明的那样,任何时候域的某个连续区间导致恒定的赔付值时,我们可以压缩该区间所需的适配器签名,使其大小相对于在该区间上对每个结果使用一个适配器签名呈对数关系。 因此,舍入赔付函数的输出可能是有益的,以便允许通过恒定赔付区间对赔付曲线的各个部分进行有界近似。 例如,如果双方都愿意将赔付值四舍五入到最接近的 100 satoshis,他们可以在强制执行其合约所需的适配器签名数量上节省大量资金。 为此,我们允许各方协商可能沿曲线变化的舍入区间,从而允许在更可能的结果附近进行更少的舍入,并允许在极端情况下发生更多的舍入。
每个参与方都有自己最小的 rounding_intervals
,并且在给定的 event_outcome
要使用的舍入是双方舍入模数的最小值。
如果 R
是要用于给定 event_outcome
的舍入模数,并且该 event_outcome
的函数评估结果为 value
,那么要在此参与方的 CET 输出中使用的数量将是 value - (value % R)
或 value - (value % R) + R
中更接近的值,在出现平局的情况下向上舍入。
bigsize
:num_rounding_intervals
]u64
:begin_interval_1
]u64
:rounding_mod_1
]u64
:begin_interval_num_rounding_intervals
]u64
:rounding_mod_num_rounding_intervals
]num_rounding_intervals
是此函数中指定的舍入区间的数量,可以为零,在这种情况下,到处都使用 1
的舍入模数。
每个序列化的舍入区间由两个 u64
整数组成。
第一个整数被称为 begin_interval
,指的是该范围开始时的 x 坐标 (event_outcome
)。
第二个整数被称为 rounding_mod
,包含要在此范围中使用的舍入模数。
如果 begin_interval_1
严格大于 0
,那么 0
和 begin_interval_1
之间的区间具有 1
的精度。
begin_interval_1
(如果存在)必须是非负数。begin_interval
必须严格增加。给定 offerrer 的 赔付函数,一个 total_collateral
金额和 舍入区间,我们希望计算数字前缀(即整数数组)和 Satoshi 值的列表对。
然后,这些对中的每一个将被转换为 CET,其用于签名的适配器点是从数字前缀计算的,并且其输出值将等于 Satoshi 赔付和 total_collateral
减去该赔付。
我们必须首先通过应用舍入来修改给我们的纯函数(例如,通过插值点),然后设置所有负赔付为 0
,并将所有高于 total_collateral
的计算赔付设置为等于 total_collateral
。
接下来,我们将函数的域分成两种区间:
这可以通过评估域中每个点的修改函数并跟踪值是否已更改来构造区间来完成,但这不是一个特别有效的解决方案。 有很多方法可以使这个过程更有效,例如二进制搜索函数值变化或查看未修改函数的导数。
无论如何计算这些区间,都要求常数值区间尽可能大。 例如,如果你有两个连续的具有相同值的常数值区间,则必须合并这些区间。
最后,一旦计算出这些区间,数值结果压缩 算法将对每个常数值区间运行,生成一个数字前缀(整数列表)与该区间的(常量)赔付配对。 每个区间只需要一个 CET(因为这些区间具有恒定的赔付),其中每个区间接收多个适配器签名。
下图说明了从所有可能结果的域和修改后的赔付曲线开始的整个过程,然后按赔付划分为恒定值区间(红色),运行数值结果压缩以获得数字前缀,将这些前缀转换为其区间的 CET 的适配器点,最后使用这些适配器点在其相应的 CET 上创建适配器签名。
要验证在 dlc_accept
或 dlc_sign
消息中给出的 CET 的适配器签名,请执行上述过程,计算数字数组和赔付值的列表对,以构建 CET 及其适配器点,然后运行 adaptor_verify
函数。
但是,如果 adaptor_verify
导致验证失败,请不要终止 CET 签名验证过程。
相反,你必须查看你是向上舍入(到 value - (value % rounding_mod) + rounding_mod
)还是向下舍入(到 value - (value % rounding_mod)
)。
如果你向上舍入,计算从向下舍入产生的 CET 和适配器点,或者如果你向下舍入,计算从向上舍入产生的 CET 和适配器点。
使用这个新的适配器点对这个新的 CET 调用 adaptor_verify
函数,如果它通过验证,则认为该适配器签名有效并继续。
这个额外的步骤是必要的,因为如果没有引入比整个规范大得多的复杂性,就无法将确定性浮点计算引入到这个规范中。 这是因为硬件、操作系统或编程语言编译器不保证两次执行相同的浮点计算会产生相同的结果。 因此,本规范反而采取了客户端必须能够容忍机器之间精度偏差(相差一 * rounding_mod)的立场。
Nadav Kohen <nadavk25@gmail.com>
<br>
This work is licensed under a Creative Commons Attribution 4.0 International License.
- 原文链接: github.com/discreetlogco...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!