chainlink源码分析
预言机简介
在区块链当中,我们需要任何一次操作产生的结果都是具备确认性的。也就是,任何节点任何事件执行操作产生的结果都是确定的。只有这样,区块链才能验证操作并达成一致。
但是在和链下世界的交互当中,产生的结果收到链下世界自身状态的影响,从而会导致交互的结果不具备确认性。比如,链上想要通过访问 API 去获取关于温度的信息,不同时间调用这个 API 所获取到的结果都可能是不一样的。也就是说,不同节点运行同样的操作,产生了不一致的结果,很明显无法对于这种行为启动共识流程。
为了解决这个问题,使得链上链下的信息能够交互。我们需要赋予链下信息确定性,使得链上节点在访问链下世界的信息的时候,总是能获取到一致的信息。这便是预言机的诞生。
预言机作为链上获取链下确定性信息的桥梁进行工作。也就是说预言机会对链下信息进行共识,从而使得链上节点通过预言机访问到的信息总是一致的。
chainlink服务
chainlink 就是目前最火的预言机项目,它本质上是一种软件协议。他规范了链上节点,预言机,链下数据之间的交互规则。
在 chainlink 中,主要有三种类型的服务
- Data Feed 对于一些特定类型的链下数据(如通证价格等),提供经过多节点共识的可信结果。
- Any API 帮助链上合约访问链下世界的任何 API 。为 API 数据提供了确定性,但是本质是单节点模式,没有多节点共识提供可信性。
- VRF 帮助链上合约产生不可预测的随机数。这里和上面一样,也是单节点模式。一个链下节点产生 VRF 随机数,并上传到链上合约当中去。不过因为 VRF 本身的特质,使得单节点返回的结果是可验证的。同时 VRF 随机数的产生是由两个条件决定的
- 链下节点自身的私钥
- 区块的hash值
VRF 是如何保证 不可预测性 的呢,并且解决 MEV 问题的呢?
- 对于链上节点来说,链下节点的私钥,对于他们来说是未知且不可控的,所以他们无法单单通过区块hash来影响或者预测随机数。
- 对于链下节点来说,区块的hash对于他们来说是不可预测且不可控的,所以他们无法蛋蛋通过私钥来影响或者控制随机数。并且链上节点还可以通过公钥验证链下节点是否严格按照 私钥+区块hash 的规则生成随机数。
- Keeper 提供自动合约服务
chainlink模型
根据上面的服务,我们可以看到,chainlink 当中主要有 单节点服务 和 多节点共识服务 两种模式。
其中单节点服务,主要使用的模型是 Basic Request Model。其流程,主要是链上用户合约发起服务请求并支付费用,链下对应节点检测任务并执行后,返回结果给链上合约。请求的发起和结果的返回时发生在不同区块上的。
而多节点共识服务,主要使用的模型分新旧两种
- On-Chain Aggregation 链上聚合
- Off-Chain Reporting 链下聚合
多节点共识的整体逻辑其实很简单,就是多个节点汇报自身数据源上获取到的数据结果,然后通过一个 聚合规则,将收集到的多个结果聚合成一个共识结果。这个 聚合规则 是可以自己设计的。比如跟比赛裁判打分一样,对于收集到的结果,去掉一个最高分,去掉一个最低分,剩下的取平均值。
这里我们也可以明白,为什么 Any API 没有多节点共识。因为不同 API 获取到的结果多种多样,我们没办法给他适应性的附加聚合规则,但同时,对于一个 API ,如果我们真的需要一个多节点共识的可信结果,我们其实也可以自己设计一个聚合规则,并进行多节点共识。
知道了多节点怎么通过聚合规则来进行共识。我们现在可以来看看两种聚合模式的区别。
-
链上聚合 ,指的是,链上有一个聚合合约,每个链下的共识节点,自发性的给链上合约发送自己的结果。然后链上的聚合合约通过收集到的结果,聚合出一个共识结果。 我们可以看到,这种方式的的优点是,设计简单,而且链下节点之间不需要交流。 而这种设计的缺点就是开销大,因为每一个链下节点的汇报过程,都需要发起交易,都会被收取 gas 费。
-
链下聚合 ,其实这里指的是,链下节点先通过签名互相进行一轮结果沟通,然后一个汇报节点会将收集到的所有结果打包成一个 report ,一次性提交给链上合约去聚合。这样每一次共识,只有一个节点会花费 gas 费
chainlink经济模式
chainlink 中会通过 link token 合约发行 link 代币。
整体的支付场景是非常简单的,跟常规的 ERC20 代币没有太大的区别,唯一的区别就是新增了 transferAndCall 函数,支持在付费后,通过 LinkToken 合约再去 call 一个其他合约的方法。
在我们使用 AnyAPI 或者 VRF 服务的时候,我们的支付方式就是申请就付费。我们在发起一个 AnyAPI 或者 VRF 请求的时候,我们首先是将请求发送给 LinkToken 合约的 transferAndCall 方法。当 LInkToken 会在这里进行扣费,当扣费完成后才会将请求发送给对应的 oracle 合约。
而 data feeds 服务,每一个 data feed 都是一个单独的聚合合约。当节点加入这个 data feed 合约后,会通过为其提交数据的方式获取代币奖励。也就是说这个合约想要正常运行,其中就必须有足够的 link 代币。而提供这些 link 代币的人,被称为这个合约的 sponsors 。这个合约的 sponsors 越多,代币就越充足。也就可以雇佣更多的 oracle node 节点也可以设置更频繁的喂价。这就是说这个 data feed 合约的去中心化和实时性就更好。
chainlink声誉系统
一般来说,作为 oracle 节点的都是一些大的运行商。节点的贡献过程,每一次喂价提交的结果,都在链上永久记录,并且公开透明。用户也可以通过查看 oracle 节点的贡献历史,从而探查这个 oracle 节点服务的可靠性。这就是 chainlink 的声誉系统,chainlink 官方提供了一个 market 供使用者去浏览节点的声誉,并选择这些节点。同时如果一个节点作恶了(需要注意,chainlink 目前的软件设计上对于作恶的限制很弱),那么就可以上报给 chainlink 官方,因为这个节点所有的行为都是透明的,所以作恶行为也比较好验证,一旦验证后,chainlink 官方就可以对其进行一些惩罚措施。比如,将其加入黑名单,这样其他人在 market 上就永远不会选择这个节点了。
综上,我们在选取 oracle 节点的时候,尽量从官方的 market 里面选取,这样如果节作恶被我们发现了,我们就可以上报官方给予惩罚。
架构梳理
| 模块 | 概要描述 | | —- | —- | —- | | LinkToken | link代币的合约,主要提供transferAndCall功能 | | AnyAPI | chainlink提供的对于任意API访问的服务 | | VRF | 生成不可预测随机数的服务 | | DataFeed (On-Chain Aggreation) | (旧版)提供链上聚合共识保障的可信数据 | | DataFeed (Off-Chain Reporting) | (新版)提供链下聚合共识保障的可信数据 | | Keeper | 自动合约服务 | | chainlink链下节点 | 链下节点的运行规则 |
- LinkToken link代币的合约,主要提供transferAndCall功能
- AnyAPI chainlink提供的对于任意API访问的服务
- VRF 生成不可预测随机数的服务
- DataFeed (On-Chain Aggreation) (旧版)提供链上聚合共识保障的可信数据
- DataFeed (Off-Chain Reporting) (新版)提供链下聚合共识保障的可信数据
- Keeper
- chainlink链下节点