市场数据预言机的可靠性和安全性
让我们聊一聊可靠性的话题…
预言机的本质和作用要求它具有极高的可靠性(Reliability),因为不准确的价格数据或者预言机服务的中断可能会给下游用户造成财产上的损失。
例如,一个贷款协议如果接收到预言机提供的不准确价格,就可能错误地对其用户进行资产清算,导致用户和协议双方的利益受损。
随着预言机数据所提供保障的价值越来越大,提供错误数据的后果将变得更加严重。即使是很小的故障概率也会变得不可接受。
令人惊讶的是,我们在开发者社区中很少有听到关于预言机可靠性的讨论。市场上有这样一种看法:所有的预言机都是平等的:每一个数据喂价都是完美的,总是会发布正确的价格数据。
“oracle”这个词的含义并没有被正确地解读出来 — — 它听起来像一个永远都会说真话的权威。然而,这种看法并不正确。预言机的正确性不是与生俱来的,建立一个高度可靠的系统是非常困难的!
即使是大型的软件公司也会出现服务中断的情况,传统的金融市场参与者也会花费大量精力来清理不准确的数据。可靠性是极为重要的,同时保证可靠性也需要付出非常多的努力。
预言机自身必须对自己的可靠性负责。使用预言机数据的其他协议开发者不应该被迫承担预言机出错的后果。
此外,协议部署的任何下游的保障措施必然是不精确的 — — 例如,协议可以检查预言机价格的变动是否过大,从而过滤掉潜在的不良价格,但这种方式可能会导致协议错过价格的突然性变动。
这种数据的出错问题更适合在预言机内部来处理。这种方法也为开发者提供了友好的用户体验,他们不再需要承担预言机出错的后果。
在 Pyth,我们对可靠性有三重保障。当聚合价格存在很大的不确定性时,我们会通过聚合置信区间来告知数据使用者这个不确定性的存在。
另外,我们的可靠性 back up 计划会在预言机出错时为协议开发者提供财务补偿;Pyth Network 白皮书中为这个财务补偿的过程提出了一种机制。
虽然我们认为这些措施构成了一个可靠的故障安全保障计划,但最好的方式仍然是在故障发生之前就把它扼杀。
因此,我们的第一道防线是构建稳健的保障机制并聚合数据来源,使我们的喂价数据天生就具有可靠性。
这篇文章详细介绍了我们在可靠性方面的一些想法。我们想要精确地定义可靠性,并基于这种理解将可靠性构建到我们的喂价数据中。
我们决定对 Pyth 喂价数据背后的机制进行概率建模,这样我们就可以对可靠性进行量化和优化。这篇文章解释了我们在这方面的一些想法。
什么是数据可靠性?
可靠性是可用性(availability)和准确性(accuracy)的缩写:
- 可用性是预言机能够正常发布价格数据的时间占总时间的百分比。
- 准确性是预言机价格数据与大盘价格数据保持一致的时间占总时间百分比。
预言机需要在不同程度上保证可用性和准确性。准确性是至关重要的:发布哪怕仅仅是一个不准确的价格数据都可能引发不必要的清算和损失。因此,发布一个不准确价格数据的可能性必须非常小。
可用性也很重要,但是比起预言机的错误,我们更能容忍预言机有一定程度的离线 — — 对于预言机来说,不确定比盲目自信和错误要好得多。
然而,可用性太有限也是很危险的,因为缺乏可用性可能会阻止下游协议执行清盘或其他对时间敏感的行动,这反过来也可能会给用户造成损失。
我们想要把可靠性进行量化,所以我们需要首先量化可用性和准确性。为了做到这一点,我们可以从概率统计的角度考虑,并将在线喂价的概率和准确性作为可靠性的标准度量。
喂价数据可靠性的基准模型
如果我们愿意做一些假设的话,其实有一种简单的方法来考虑可靠性的问题。Pyth 聚合了不同发布者的数据报告来生成一个聚合的数据值。
假设有个别的数据发布者是容易犯错的,意味着他们偶尔会发布不准确的价格或不能及时发布价格数据(即离线)。Pyth 预言机通过聚合多个发布者的数据报告,能够实现从不太可靠的数据源中构建出更可靠的喂价数据。
聚合的过程是稳健的,这样即使一些数据发布者离线或发布不准确的数据,也不会导致聚合值出现问题。对于任何喂价,只要至少有 3 家数据发布者在线,Pyth 就可以提供喂价数据,而且只要大多数发布者的数据是准确的,Pyth 就可以提供准确的喂价数据。
如果我们假设数据发布者是独立的,我们可以直接计算出聚合数据值离线(Offline)或者不正确(Inaccurate)的概率。举例来说,假设有 3 个数据发布者,每个发布者在发布数据时都有 99% 的可用性和 99.9% 的准确性。为了让聚合价格能够发布,这 3 个数据发布者必须同时在线;我们可以计算这个事件的概率为:
这意味着有 2.97% 的离线率。如果喂价是在线的,那么 3 个发布者中至少有 2 个是准确的,聚合值才会准确。我们可以计算出该事件发生的概率为:
这意味着有 0.0039% 的出错概率。
相关错误的危险
这种分析的一个问题是数据发布者的出错情况可能具有相关性(correlation)。简单的分析忽略了这些相关性,这可能导致这个分析大大高估了喂价的可靠性。
为了证明相关性造成的影响,假设我们从上面的简单模型中引入了一些更复杂的因变量相关关系。
特别地,让我们将前两个发布者联系在一起,假设它们的可用性和准确性状态完全相同(例如,它们在相同的基础架构上运行并使用相同的算法来发布价格数据)。然后我们可以计算聚合值在线的概率如下:
这意味着有 1.99% 的离线率。聚合值在线且准确的概率变为:
因为三个数据发布者都在线时聚合值准确这个事件等于两个具有相关性的发布者发布值准确的事件(如上图)。这意味着有 0.098% 的出错概率。上面的简单分析大大低估了整体喂价的失败概率!
为发布者之间的相关性建模
我们希望以准确考虑数据发布者之间相关性的方式对 Pyth 喂价数据的可靠性进行建模。此外,我们希望阐述清楚 Pyth 通过聚合价格和置信区间提供预估聚合值的独特方式。
构建此模型的一种方法是直接阐述价格出现在链上的过程。典型的数据发布者会从几个交易所中读取喂价数据,并将这些数据聚合成一个预估喂价,然后将他们在交易中估算的价格数据提交给链上程序。
这整个过程是在一个长期运行的软件程序中实现的,这个程序不断地读取数据并推送更新。在这个流程中,有几个地方可能会出现问题:
- 源头的喂价数据可能不准确。这个错误可能会同时影响使用该喂价数据作为数据源的所有数据发布者。
- 数据发布者处理喂价数据的程序可能存在错误,导致他们报告不准确的价格。
- 数据发布者的基础设施可能出现故障,导致他们无法提交交易。最简单的情况可能包括发布者的软件程序崩溃,或者他们的基础设施中断。
- Solana 网络拥塞、RPC 节点中断或发布者自己的代理问题,也可能发生此类交易确认失败。请注意,这些故障情况中,许多情况下都将同时影响多个发布者。
我们的目标是估计这些故障对 Pyth 的聚合价格和置信区间造成影响的概率。这些故障情况中每一种都有一定的发生概率,我们可以从历史数据中估计出来。
聚合价格和置信区间是多个发布者提供的价格数据的集合,因此我们需要一种方法来整合各个故障情况的概率。
一种方法是使用贝叶斯网络(Bayesian network),它是一种根据许多较小的分量分布来表示概率分布的工具。我们构建了以下贝叶斯网络来阐述这个的问题:
贝叶斯网络表示一组变量的概率分布。上图中的每个圆圈代表一个变量,边代表变量之间的依赖关系。每个变量都可以取几个值之一;例如,聚合(Aggregate)可以是准确(ACCURATE)、不准确(INACCURATE)或离线(OFFLINE)。贝叶斯网络会确定每个此类值的概率。有关贝叶斯网络的入门知识,请参阅这些说明。
我们的贝叶斯网络假设有 N 个数据发布者和 M 个交易所的集合。该网络包含每个数据发布者和交易所的多个变量;数据发布者的变量由 i索引,交易所的变量由 j 索引。上面的网络对以下变量的概率分布进行了编码:
- mⱼ 表示来自交易所 j 的喂价数据。该变量有 2 个可能的值,准确(ACCURATE)或不准确(INACCURATE)来表示交易所的当前价格是否准确。
- Bᵢ 表示数据发布者 i 是否遇到软件错误。该变量有 2 个可能的值,遇到错误(BUG)或未遇到错误(NO_BUG)。当这个变量的值为 BUG 时,发布者会向链上程序报告一个不准确的价格。
- Z_Gᵢ 表示发布者 i 的基础设施是否在线。该变量有 2 个可能的值,在线(ONLINE)或离线(OFFLINE)。我们将发布者分组在一起以表示多个发布者共享基础设施的事实;Gᵢ 变量代表第 i 个发布者所在的组。因此,同一组中的所有发布者将会一起下线(因为他们共用同一个基础设施)。
- μᵢ 代表数据发布者 i 向链上程序提交的价格数据。该变量有 3 个可能的值:准确(ACCURATE)、不准确(INACCURATE)或离线(OFFLINE)。该变量取决于数据发布者获取数据的交易所(来自 mⱼ 变量的值),以及数据发布者的程序错误状态(来自 Bᵢ 变量的值)和数据发布者的在线状态(来自 Z_Gᵢ 变量的值 )。例如,如果数据发布者的基础设施是离线的,则 Z_Gᵢ = OFFLINE),那么数据发布者的价格数据也是离线的。
- 聚合(Aggregate)代表聚合价格。该变量有 3 个可能的值:准确(ACCURATE)、不准确(ACCURATE)和离线(OFFLINE)。该变量取决于所有数据发布者的价格数据(来自 μᵢ 变量的值)。它的值是通过将链上程序的聚合逻辑编码为概率分布来确定的。具体来说,除非有 3 个或以上的数据发布者发布价格数据,否则它就是离线的。如果超过 50% 的在线发布者所发布的数据是不准确的,那么聚合价格就是不准确的。否则,它就是准确的。该分布中使用的百分比阈值是 Pyth 聚合逻辑的特性。
这个模型允许我们计算出上面所示的预言机故障情况的概率,然后结合这些概率来确定是否聚合值是准确的(Aggregate = ACCURATE)。这个过程使用了一种叫做信念传播(belief propagation)的算法。信念传播是一种在贝叶斯网络中有效计算概率的方法。如果你想要了解更多关于信念传播的细节,请参阅这些注释和这个有用的介绍视频。
利用贝叶斯网络确定喂价的可靠性
贝叶斯网络的一个用例是用于估计 Pyth 的喂价数据的可靠性。我们想知道一个喂价数据发布不准确或离线的概率。我们可以通过使用历史数据来估计上述每种失效情况的概率,然后将它们与上述贝叶斯网络结合起来,从而确定此概率。
我们使用 Pyth 的历史数据存档来估计每个失效情况的概率。这个存档记录了链上程序在每个 Solana 插槽中存储的所有数据,包括每个数据发布者的状态(即他们是否在线)、他们的价格数据和置信值,以及聚合价格和聚合置信区间。我们从存档中计算了以下数值:
- 不同交易所(mⱼs)发布数据不准确的概率。我们实际上是通过抽取单个交易所的数据来计算这一点的,假设每个数据发布者代表一个单一的数据源,我们计算出数据发布者的价格数据与聚合价格相差超过 10% 的概率。*这是因为我们无法确切知道每个数据发布者是如何发布他们的价格数据的。
- 每个数据发布者 Bᵢ 发生程序错误的概率。我们通过寻找历史价格序列中的极端异常情况来计算这个概率,例如价格为 0 或价格与聚合价格相差一个数量级的时候。这种异常现象通常是数据发布者程序的缺陷造成的。
- 哪些数据发布者在同一个共享的基础设施组 Gᵢ 中(使用同一组基础设施)。我们通过计算每个数据发布者可用性(availability)之间的成对相关性(correlation)来组成分组,如果它们的成对相关性大于某个阈值,比如 0.2,则将两个数据发布者视为在同一个基础设施组中。
- 各基础设施组的离线概率 Z_Gᵢ。我们保守地将这一概率设置为该基础设施组中所有数据发布者的最高的离线率。
一旦我们计算出了这些概率,我们就可以简单地运用信念传播理论来获得聚合的不同可能值的概率估计。
样本结果
作为该模型的一个应用实例,我们使用它来分析 ONE/USD 喂价的可靠性。在 2 月中旬,ONE/USD 测试网中有 3 家数据发布者。这些数据发布者有以下可用性:
- 数据发布者 1:22.1%
- 数据发布者 2:99.9%
- 数据发布者 3:21.84%
基准模型(Baseline Model)预测了聚合价格在线的概率:
然而,当时的实际在线率是 21.81%,因为第一和第三个数据发布者的可用性几乎是完全正相关的。当我们对这些经验数据进行贝叶斯网络推理时,我们得到以下预测:
- P(聚合价格 = 不准确)= 0.007%
- P(聚合价格 = 离线)= 78.20%
- P(聚合价格 = 准确)= 21.80%
这些预测更接近于经验观测的概率。贝叶斯网络的预测效果比简单的基线模型更准确,因为它模拟了不同发布者之间具有相关性的失效情况。
请注意,尽管我们可以直接从历史数据集中计算离线概率,但此模型仍然具有价值。价格不准确的概率是非常低的,以至于我们需要大量的数据样本才能相信由经验估计的概率。
贝叶斯网络模型允许我们从较小的数据样本中推断出错误概率。
我们可以用这些结果来做什么?
我们现在正在使用贝叶斯网络系统地测试在 Pyth 上上架的喂价产品的可靠性。这个模型让我们能够回答两个重要的问题:
1. 哪些喂价产品可以达到上线主网的标准?
我们通常会在测试网中添加新的喂价产品,然后在足够多的数据发布者提供数据时将其上限至主网。现在,我们将明确的可用性和准确性阈值纳入到这个过程中:每个新喂价产品离线的时间必须小于 1%,发布不准确聚合价格的概率必须小于 0.001%。(在实践中,离线率 < 1% 是数据发布者面临的主要挑战。价格数据或置信区间不准确的概率通常在 0.001% 以下的数量级。)
例如,在 ONE 的案例中,2 月中旬的结果显然没有达到这些门槛。因此,我们寻找了更多的数据发布者。到 3 月中旬,我们有 6 家数据发布者来提供 ONE/USD 喂价。再次运行该模型产生了以下结果:
- P(聚合价格 = 不准确)= 0.000013%
- P(聚合价格 = 离线)= 0.78%
- P(聚合价格 = 准确)= 99.22%
在这个阶段,喂价数据满足了我们对准确性和可用性标准,因此我们将其上线到了主网。
2. 哪些喂价产品需要改进?
我们目前的主要工作之一是提高主网中所有现有喂价产品的可靠性。这个过程需要我们去招募那些为这些产品提供价格数据的数据发布者;招募数据发布者可能很耗时。
这个模型允许我们对现有的喂价产品进行排序,从而将我们的招募工作集中在最有价值的地方。
Pyth Network 兢兢业业的开发人员们一直在致力于构建高度可靠的数据源。我们认识到,DeFi 应用程序非常依赖于可靠的预言机,而预言机故障可能会导致严重的经济损失。
这篇文章详细介绍了我们在测试和改进 Pyth 的喂价数据可靠性方面所做的一些工作。我们希望这项工作能够传达出我们致力于成为 DeFi 最可靠的预言机的承诺。
欢迎向我们提出任何问题、评论、考虑或建议。你可以直接在 Twitter 中找到我们:@anihamde 和 @jayantkrish。
比较精细的读者可能会注意到,我们似乎没有考虑到个别交易所的错误概率。相反,在这个将网络参数化过程中,我们抽象掉了单独的交易所,并为每个数据发布者分配了自己独特的数据喂价。然后,我们根据在我们数据中观察到的误差相关性在任意两个发布者的喂价数据之间设定了一个相关性。这在实践中已经包含了数据发布者准确性的潜在相关性,而不需要在交易所级别上的细粒度数据。
感谢你的阅读!如果你已经读到了这里,请再往前一步,加入我们的 Pyth Network 社交账号:Pyth 中文 Twitter、Pyth Discord、Telegram。