Chainlink

Chainlink 查看完整档案

填写现居城市  |  填写毕业院校Chainlink  |  Developer 编辑 chain.link 编辑
编辑

全球领先的去中心化预言机网络

个人动态

Chainlink 发布了文章 · 9月8日

Chainlink是如何实现“万能插头”的--外部适配器的开发和应用

背景

在以太坊原生语言solidity中调用API可以将链下数据传输至链上智能合约应用。世界各地的开发者可以利用Chainlink的去中心化区块链预言机将链下真实世界的数据和事件接入区块链环境。Chainlink内置的核心适配器可以轻松配置并验证来自任何开放API的数据。

然而,Chainlink核心适配器往往在灵活性和功能性上无法满足开发者所有的需求,比如:

  1. API接口认证(保护API秘钥隐私)
  2. 保障隐私,降低延迟,并实现高吞吐量的链下计算,以降低gas费用
  3. 将数据传输至其他区块链(互操作性)
  4. 其他核心适配器无法满足的功能

外部适配器可以访问优质数据并使智能合约能够非常灵活地连接至付费web API。目前众多安全可靠的预言机网络都已接入外部适配器,其中包括超过35个价格参考数据,总共保障了30多亿美元的DeFi资产。本文将探讨以下问题:

  1. 什么是外部适配器?
  2. 如何开发外部适配器?
  3. 如何运行外部适配器?
  4. 如何使用外部适配器?

什么是外部适配器?

适配器通常分成两类:

  1. 核心适配器
  2. 外部适配器

核心适配器是Chainlink核心节点客户端内置的功能。HttpgetCopyJsonparse都属于核心适配器。而外部适配器则是指开发者根据具体要求基于Chainlink预言机网络定制化的功能。本文不会深入探讨接入其他区块链的技术细节,但是Chainlink外部适配器和外部启动器实现定制化,将使Chainlink能够与任何区块链兼容,因此能极大丰富其功能,这是Chainlink两大关键价值的其中一个。

这里顺便提一句,如果想要智能合约在端到端保持去中心化,就必须允许其他预言机节点也运行外部适配器。可以把外部适配器想象成Chainlink节点的开源软件包。也就是说,你可以选择不亲自运行节点,但同时也能够在智能合约中使用节点的定制化功能。你可以让其他节点帮你运行外部适配器,现在有许多项目集成了Chainlink但不亲自运行节点。这样,智能合约开发者就可以专注于去中心化应用的商业逻辑,并将节点运行工作交给专业的节点运营商处理。你可以在market.link等第三方节点分类信息平台上挂出你的外部适配器,也可以#ask-a-node-operator (委托节点运营商)运行你的外部适配器,你只需要负责测试和开发工作。

当然,如果你想要自己运行节点,也完全可以这么做!

如何开发外部适配器

快速启动

开发外部适配器最简单的方式就是把它做成一个API接口。这样一来,就可以灵活定制链下计算方式,使用任何编程语言,并且调用API传输并接收数据。关于如何开发API接口有许多教学资料,接下来我们将在nodejs中看一个简单的Chainlink适配器模板。另外还有python版本的示例 ,如果你感兴趣也可以查看。我们会基于下面这个代码库进行开发,这是一个功能完整的外部适配器,你可以轻松定制所需的数据。你也可以从零开始开发,不过用这个代码库开发会简单很多。

接下来,你需要使用yarnnodejs。首先,将代码库克隆到本地,使用cd命令进入到项目中。

git clone https://github.com/thodges-gh/CL-EA-NodeJS-Template.git ExternalAdapterTemplate
cd ExternalAdapterTemplate

然后,安装依赖并启动API服务器。

yarn
yarn start

API/外部适配器的服务器会被启动,并等待被调用。

patrick@iMac: [~/code/ExternalAdapterTemplate -  (master)] $ yarn start
yarn run v1.22.4
$ node app.js
Listening on port 8080!

要注意,Chainlink节点会扫描所有适配器,一旦发现了在它适配器/任务清单中的外部适配器,就会进行调用。我们可以自己调用一次,模拟Chainlink节点请求的过程。

这是一个curl命令,向我们刚开始运行的API服务器发送HTTP post请求。你可以在本地终端窗口尝试一下。

curl -X POST -H "content-type:application/json" "http://localhost:8080/" --data '{ "id": 0, "data": { "from": "ETH", "to": "USD" } }'

jsonhttp://localhost:8080/是API服务器等待响应的地址,--data后面的参数是我们为了让Chainlink节点看懂数据请求而发送的参数。Chainlink节点发送的请求包括:

  1. 一个id
  2. 一个data object

格式如下: {"id":"0", "data":{}}

data object中,可以清楚地看到fromto参数。这些是我们设置的定制化参数,让外部适配器能够获得各种不同的价格数据。可以看到,当运行curl脚本时,会返回以下结果:

{"jobRunID":0,"data":{"USD":441.49,"result":441.49},"result":441.49,"statusCode":200}

注:由于以太币价格一直在变动,因此这里的数字可能会发生变化!

json所有外部适配器都会返回一个对象,其中至少包含:

  1. jobRunID
  2. data object

最好还能包含statusresult字段,这样可以轻松处理并改正错误。在这个示例中,返回的结果是441.49,即当前以太币价格。我们之所以会获得这个数据,是因为我们的外部适配器也调用了一个API,那就是:

https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD

这个外部适配器实际上里面包裹着一个API接口,这也是外部适配器的常见框架。

以上就是外部适配器的功能,那么我们接下来看一下它的运行原理。

获取天气数据

在PatrickAlphaC模板代码库中的weather-api分支中可以查看。

OpenWeatherMap我们先来修改一下代码,以便从一个新的API接口()获取天气数据。为了方便教学,我们先在这里免费注册,获得一个免费的API秘钥。账号通过验证后,我们就可以在这里看到API秘钥,以及城市当前天气数据API文档。注:你注册后大概需要等待十分钟秘钥才会完全生效。

我们现在要把这个外部适配器稍作修改,本来它获取的是以太币价格,现在要改为获取城市天气数据。

我们要修改index.js文件(如果要上线则需修改test/index_test.js测试文件)。app.js定义了外部适配器/API服务器响应请求的方式,我们现在先不用管。在之前示例里的dataobject中,我们使用了两个参数,即fromto参数。我们可以通过更新customParams来定制化参数:

更新前的customParams:

const customParams = {
 base: ['base', 'from', 'coin'],
 quote: ['quote', 'to', 'market'],
 endpoint: false
}

更新后的customParams:

const customParams = {
 city:['q', 'city', 'town'],
 endpoint: false
 }

这样,我们无论输入citytown还是q ,都表示city

createReqeust常量是最关键的一个环节,因为这里需要连接到URL。如果查看天气数据文档,可以看到这样的一个示例地址:`https://api.openweathermap.or...;CITY_NAME>&appid=<YOUR_API_KEY>

可以输入API秘钥和城市名boston,对API进行测试,然后将URL复制到浏览器(如果返回错误说API秘钥无效,可以等几分钟再试一次)

用这个URL就可以知道需要做哪些更新:

更改前:

const endpoint = validator.validated.data.endpoint || 'price'

更改后:

const endpoint = validator.validated.data.endpoint || 'weather'

更改前:

const url = 'https://min-api.cryptocompare.com/data/${endpoint}'

更改后:

const url = 'https://api.openweathermap.org/data/2.5/${endpoint}'

现在我们要添加参数。我们的两个参数是城市(文档里的城市是q)和API秘钥( appid

城市可以在原来的代码上进行修改:

const fsym = validator.validated.data.base.toUpperCase()

改成:

const q = validator.validated.data.city.toUpperCase()

然而,我们不能将API秘钥写死在代码中。

API认证

我们应该编辑这行代码:

const tsyms = validator.validated.data.quote.toUpperCase()

将它改成:

const appid = process.env.API_KEY;

要将API秘钥放到.envrc文件中,而不是放到源代码中,因此要新建这样一个.envrc文件:

export API_KEY=<YOUR_KEY_HERE>

别忘了要添加到.gitignore中!如果你在运行curl命令测试时遇到任何问题,也可以在终端运行 export API_KEY=<API_KEY>

注:点击这里了解关更多环境变量

然后需要将参数从:

const params = {
  fsym,
  tsyms
}

改成:

const params = {
 q,
 appid
}

将结果从:

response.data.result = Requester.validateResultNumber(response.data, [tsyms])

改成:

response.data.result = Requester.validateResultNumber(response.data, ['main','temp'])

然后就搞定了!现在,main object的temp值就等于天气API输出的气温了,因此我们的response.data.result参数如上所示。

现在你已经成功开发出了API秘钥认证的外部适配器!

我们来调用一下API。

curl -X POST -H "content-type:application/json" "http://localhost:8080/" --data '{ "id": 0, "data": { "city":"Boston"} }

示例返回值:

{"jobRunID":0,"data":{"coord":{"lon":-71.06,"lat":42.36},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"base":"stations","main":{"temp":296.81,"feels_like":298.49,"temp_min":295.15,"temp_max":297.59,"pressure":1008,"humidity":78},"visibility":10000,"wind":{"speed":2.6,"deg":360},"clouds":{"all":90},"dt":1599162213,"sys":{"type":1,"id":3486,"country":"US","sunrise":1599127933,"sunset":1599174905},"timezone":-14400,"id":4930956,"name":"Boston","cod":200,"result":296.81},"result":296.81,"statusCode":200}

很好!现在就能完美运行了!我们创建了关键内容,让Chainlink节点能够理解数据请求。你可以清楚地看到在链下展开运算的好处,智能合约可以将大量计算工作放到链下运行,然后再将计算结果返回至链上。

现在已经做出了外部适配器,接下来的问题就是如何让Chainlink节点运行外部适配器?如何调用外部适配器?我们这里先暂时跳过亲自运行外部适配器的部分,因为实际上我们不需要亲自运行。在index.js的底部有一些wrapper,可以让节点运营商采用无服务器的方式部署代码。所以我们可以这么做:

  1. 将适配器添加至第三方节点分类信息平台,比如market.link
  2. 让节点运营商运行我们的适配器(#ask-a-node-operator discord
  3. 亲自运行节点(不必要)

你可以发现,你甚至都不用亲自运行节点就可以使用自己的外部适配器。这是最理想的情况,因为我们希望自己的适配器可以被其他预言机节点使用,这样就可以有许多节点访问数据,并使Chainlink网络保持极高的去中心化水平。

我们将在之后的视频或博客文章中详细探讨如何运行外部适配器。如果你已经开发出了新的适配器,可以先暂时让节点帮你运行,并加入我们的社区!

使用外部适配器

假设现在有一个节点帮你运行外部适配器,那么你就可以通过这个节点将数据传输至你的智能合约。在这个示例中,我们开发出了一个叫做Alpha Vantage的外部适配器。Alpha Vantage是一个股票和加密货币价格数据API,需要API秘钥才能访问。我们来看看如何通过Linkpool kovan节点运行的外部适配器获取特斯拉股票价格数据。首先要找到这个外部适配器,我们需要在外部适配器的网页中寻找。将页面一直往下拉,直到找到我们想要的Alpha Vantage外部适配器

imgAlpha Vantage外部适配器

图中描述了外部适配器的所有功能。我们可以点击“supported nodes”按钮,查看可以运行这个适配器的节点。我们发现有一个节点可以支持它,然后可以在任务页面查看这个节点的具体信息。你可以看到Alpha Vantage适配器在这个节点的适配器清单中。

接下来就是如何使用适配器。我们先像往常一样将job ID和预言机ID添加至代码中。然后添加Alpha Vantage文档中的所有参数。

bytes32 jobId = “802ec94e00184b789a016b8e71ae9fb4”;
address oracle = 0x56dd6586DB0D08c6Ce7B2f2805af28616E082455;
 function requestTSLAPrice() public {
  Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfillEthereumPrice.selector);
  req.add("function", "GLOBAL_QUOTE");
  req.add("symbol", "TSLA");
  string[] memory copyPath = new string[](2);
  copyPath[0] = "Global Quote";
  copyPath[1] = "05. price";
  req.addStringArray("copyPath", copyPath);
  req.addInt("times", 100000000);
  sendChainlinkRequestTo(oracle, req, fee);
 }

以上是完整版代码,你可以尝试使用。你也可以使用任何API的文档进行尝试,因为现在你应该已经发现其实套路都是一样的!

总结

正如你所看到的,外部适配器是非常强大的工具,开发者可以用来丰富智能合约的功能并提升其连通性。另外,还可以使用API认证和链下计算等layer2解决方案来提升外部适配器的灵活性。如果这篇文章对你有任何启发,欢迎参加Chainlink黑客松,尝试应用你新学到的技能!这次黑客松的奖金超过4万美元,希望大家能踊跃参加!

如果当你读到这篇文章时黑客松已经结束了,那么也欢迎加入我们在Twitter, Discord, 或 Reddit上的社区,转发并加上#chainlink和#ChainlinkEA标签,了解Chainlink最新活动消息,并尝试应用你的技能!

如果Chainlink预言机可以为你目前开发的产品提供任何附加价值;抑或你希望参与Chainlink网络的开源开发工作,请查看开发者文档或加入我们在Discord频道上的技术讨论群。

加入中文开发者社区:neils_(开发者社区管理员团长)

img

查看原文

赞 0 收藏 0 评论 0

Chainlink 发布了文章 · 8月20日

深度分析DeFi智能合约的数据质量问题

随着去中心化金融(下文简称DeFi)的生态不断扩张,区块链预言机保障的价值也在同步增长,二者相辅相成,实现了良性循环。在DeFi应用价值飞速增长的同时,发展创新型DeFi生态系统并且提升其安全和可靠性也成为了一项重要工作。

区块链的“预言机问题”备受关注,有许多文章专门研究了这一课题。然而,关于预言机“数据质量”的问题却存在许多未知和误解,这种误解源自于许多人觉得预言机可以传输链下数据,也可以自己产生高质量的数据。我们在研究和开发安全的预言机解决方案时,发现预言机的作用是将数据传输至区块链,并保证数据无法被篡改,而不是自己产生数据。

Chainlink价格参考数据所采用的去中心化预言机网络将数据传输和数据质量做了区分,Chainlink是DeFi领域最受欢迎的预言机网络,服务于以太坊上超过90%的去中心化衍生品市场。Chainlink的预言机网络成功地为已上线的应用提供优质数据,并甄别出了保障数据质量的五大关键要素。

  1. 将预言机节点连接至付费数据提供商,确保用户合约连接至最高质量的数据。这需要预言机协议拥有密码和身份认证信息管理能力,让所有节点都能安全储存API密钥并管理付费订阅数据源的账户登录信息。
  2. 通过节点连接专业链下数据提供商,获取优质精准的价格数据;连接数据聚合商,覆盖所有市场,获取扣除交易量因素的市场价格数据。利用预言机基于一系列原始数据聚合出全球市场价格数据是极其困难的工作,而且这样做会为预言机产生巨大的安全漏洞,比如交易量快速转移以及数据出现异常值等,这些都是加密货币市场常见的风险。
  3. 在预言机网络中实现去中心化,保障安全和可靠性。从多个独立节点聚合数据,确保预言机向智能合约传输数据时具有防篡改性和较高的可用性。从多个优质数据提供商获取数据,并同时保障数据质量,在数据源层面提升去中心化水平。
  4. 让用户和开发者在设计预言机时可以洞悉每个节点和整个去中心化预言机网络的当前和历史服务水平,以综合所有信息做出理性判断。避免采取“不公开即安全”(security through obscurity)的策略,尽量减少隐藏风险,并尽可能保障各方监督,在重大问题发生前未雨绸缪,杜绝隐患。
  5. 规避重大风险,如:只从一个交易所获取数据,或预言机网络中的数据质量良莠不齐。如果在去中心化的同时不建立质量控制标准,那么智能合约就会面临更多更复杂的风险,而这样一来,高质量的预言机方案也将无法发挥其优势。
  6. 为了进一步扩展这些对数据质量至关重要的功能,我们将讨论安全的去中心化预言机网络理想的构成要素,如何正确利用Chainlink灵活丰富的服务创建优质数据,以及在设计价格预言机网络时应规避哪些重大数据风险。

安全的去中心化预言机网络具备哪些要素?

预言机是连接区块链和链下世界的中间件。有了预言机,智能合约就可以利用储存在区块链以外的数据,并连通真实世界中的日常事件。这种连通链下世界的能力极大丰富了智能合约的场景,让开发者可以在更多市场捕捉价值。随着智能合约连接性的提升,其攻击表面也不断扩大,如果要保持智能合约防篡改的核心属性,就必须解决这个问题。

去中心化的预言机网络是安全的中间件,连接链上和链下环境,为开发者提供了一个安全可靠的开发框架,让用户能放心地将价值高达几十亿美元的资产放进具有外部连通性的智能合约中。如果预言机的安全性和可靠性无法与底层区块链媲美,那么即使其代码写得天衣无缝,也同样会面临重大安全风险。

Chainlink价格参考数据集合了多个去中心化的预言机网络,是以太坊生态中规模最庞大的链上价格数据集,服务于领先的DeFi应用,并且用户规模正不断扩张。Chainlink的价格预言机网络采用了可验证去中心化的设计思路和最高数据质量的模式,为用户带来最可靠的安全保障。以下是Chainlink价格参考数据的四大核心特色,所有致力于保障数据质量的去中心化预言机网络都应具备这四个特点。

从付费数据提供商获取优质数据

虽然在区块链上挖矿是普遍通行的做法,但针对具体行业输出优质数据并保障数亿美元资产却不是人人都能做到的。相比起开发者使用预言机基于原始数据生成优质数据,更好的方法是让节点直接从数据聚合商采集优质数据,因为这些数据聚合商通常拥有庞大的团队和全栈基础架构,并专门针对某个行业生成优质数据。

内部生成优质数据成本高昂,因此访问这类数据需要收费,而且还要签订具有法律约束力的合约。节点必须向数据提供商(即API)付订阅费,或者获得数据提供商的具体授权(如:企业内部数据)。这两种许可模式都需要建立密码和身份认证信息管理能力,以实现节点和API间的交互。因此,节点运营商与付费数据提供商交互时需要建立API密钥储存和登录信息管理能力。

预言机如果无法管理身份认证信息,就不能连接付费API,因此只能选择免费的开源API或盗版API。这些API接口的数据通常质量低下、下载速度慢、响应时间不可靠且不具有法律约束力或无法保障服务质量。因此,此类数据源无法为各类高、中、低值智能合约提供可靠的服务。如果向智能合约传输低质量的数据,合约将无法保障其数据的准确性或可靠性,因此会扩大攻击表面。“垃圾进,垃圾出。”这句技术领域的至理名言放在这里也同样适用。

参与价格参考数据合约的Chainlink节点通过外部适配器连接至所有付费API接口。这些API接口的数据质量更高、响应速度更快并且可以保障可用性和服务水平。外部适配器采用模块化设计理念,可以用任何编程语言编写,并可以与Chainlink节点放在不同的服务器上。外部适配器可以从数据提供商、web API、企业系统、物联网设备、支付系统和其他区块链等各种环境获取数据。

建立去中心化的优质节点运营商

如果没有安全可靠的预言机向智能合约传输数据,那么数据质量将是一纸空谈。要防止意外宕机和避免单一实体在传输时篡改数据,就必须建立去中心化的优质节点网络。去中心化的共识能够大幅提升攻击成本,因为即使网络中有几个节点宕机或恶意发起攻击,对最终聚合的结果也不会产生实质影响。

Chainlink的价格参考合约基于去中心化的预言机网络,聚合来自多个独立节点的数据,这些节点都经过安全评估,且具有抗女巫攻击能力。这些Chainlink节点由全球领先的区块链DevOps和安全团队在云端和本地服务器中运营,以规避预言机单点失效风险。另外还有许多由社区运营的备用节点随时可以加入到网络中,以提升网络的去中心化水平。

建立去中心化的优质数据源

预言机解决方案可以在不影响任何一个数据源质量的前提下接入多个数据源,以此提高其稳健性。建立去中心化的优质数据源,能够避免某一数据提供商成为唯一数据源,并且能防止唯一数据源下线的情况。然而,有些情况下可能某个优质数据源也是唯一数据源,这时就需要更先进的加密技术来保障数据质量,比如基于权益质押的服务协议(注:下文会详细讨论)、TLS认证(Town Crier、DECO)以及零知识证明。

Chainlink价格参考合约在数据源层面实现去中心化。每个价格参考网络都会统一从多个可靠的独立数据提供商获取市场价格数据。这些数据提供商全部都是付费数据聚合商,他们覆盖了Brave New Coin、Kaiko和Amberdata等所有交易市场以及其他众多优质的数据API。然后,所有数据将聚合成统一的参考价格数据,储存在链上,智能合约可以用简单的read函数访问这些数据。

开源的可视化界面和监控

如果DeFi应用的底层智能合约实现了开源和实时监控,那么向智能合约提供数据的价格预言机也应该是公开透明的。如果预言机无法保障公开透明,dApp用户就无法验证数据来源、提供数据的节点、响应延时、预言机网络服务历史以及数据质量等信息。

每个Chainlink价格参考数据合约都拥有一个开源可视化界面,其中包括具体的链上数据,比如:

  • 每个参考数据源的最新价格
  • 提供数据源的DeFi项目
  • 保障价格数据安全的节点(且节点通过了安全评估)
  • 数据更新时间
  • 触发数据聚合所需的最少节点响应数量
  • 关于每个节点和整个节点网络的其他关键信息


Chainlink价格参考数据使用去中心化的节点网络和数据提供商为智能合约提供优质的价格数据;上图为比特币/美元价数据

除此之外,还可以查看某一节点为每次数据请求提供的服务质量,以判断节点是否有能力成功完成数据请求任务。节点运营商、数据提供商和用户可以使用Chainlink Explorer查看网络中每个节点的表现,以及为甄别错误采取的具体措施。

使用Chainlink预言机灵活采集数据

通用型预言机网络要成为DeFi行业标准,必须具备灵活性,让开发者能够根据个人需要灵活创建预言机,满足对安全性和可靠性的具体需求。虽然Chainlink价格参考数据网络中有许多数据聚合商贡献全球市场数据,但Chainlink协议不会对预言机网络的模式或数据源做强制性要求。相反,Chainlink会为用户提供市场上开放程度最高的模块化框架,以满足任何具体的需求。

可随意配置数据源、节点和聚合模式

开发者可以通过外部适配器快速将智能合约连接至任何所需的数据源。除此之外,开发者还可以随意设置所需的去中心化水平、数据源、聚合算法以及数据更新频率。因此,智能合约连接外部数据的方式变得极其灵活。


market.link 是一个第三方网站,开发者可以在上面选择预构建的外部适配器,并访问丰富的数据源

这个定制化的框架让开发者可以按照智能合约所需的安全保障轻松扩大或缩小预言机网络的规模。Chainlink拥有规模最庞大的安全节点运营商,同时还有许多社区节点互相竞争岗位,如果用户需要额外的安全保障,可将这些节点快速添加至任何预言机网络中。另外,数据源的格式也在不断丰富,聚合数据无须任何前期开发工作。

Chainlink用户还可以选择不同的聚合方式,比如取平均数、中位数或甚至使用加权和剔除异常值等更加复杂的算法。另外还可以设置数据更新频率,用户可以选择定时更新、基于价格偏差更新(比如价格每上下浮动0.5%时更新一次)或采用基于多个参数的混合模式。

数据提供商可以是传统API接口,也可以自己运行Chainlink节点

Chainlink具有灵活的框架,数据提供商可以选择以何种方式在新兴智能合约经济中提供数据,他们可以是传统的API接口,也可以直接运行Chainlin节点。

传统API接口

数据提供商可以保持现有的模式,向订阅用户收取以法币计价的数据服务费。Chainlink节点可以订阅这些API,并在节点中安装Chainlink外部适配器,将API数据传输至链上合约。这个模式适用于任何一个数据提供商,Chainlink价格参考数据网络已经开始采用这个模式,网络中的节点订阅了AmberdataCoinGecko等优质付费数据。Chainlink还针对交易所API开发了外部适配器,可以连接币安Coinbase等节点。

这个模式非常高效,因为数据提供商无须改变任何现有的商业模式或基础架构。即使数据提供商本身不太愿意主动为智能合约提供服务,Chainlink节点也可以通过外部适配器模块向开发者开放所需数据源。另外,节点还可以订阅本身就是Chainlink节点的数据提供商的数据服务(下文将详细阐述),进一步提升数据的去中心化程度。

既是数据提供商,也是Chainlink节点

另一个模式是让数据提供商成为Chainlink节点,直接向智能合约出售数据。这个模式可以丰富数据提供商的变现模式,目前已经被几个领先的数据提供商采用,比如KaikoAlpha Vantage(市场数据聚合商),以及火币(加密货币交易所)。

数据提供商成为Chainlink节点将拥有一个独一无二的优势,那就是可以在自己的数据上进行加密签名。用户和智能合约可以确信价格数据是直接来源于数据提供商或交易所的Chainlink节点,并且数据在传输过程中没有经过篡改,因为节点在链上广播前会用独一无二的私钥在数据上进行加密签名。签名过的数据可以通过节点的公钥在链上进行验证,确保数据的完整性和真实性。

这个框架可以让数据提供商直接在区块链上广播数据,无须通过外部第三方将数据传输到链上。这样一来,数据提供商就能够控制数据在链上广播的频率,并保障数据从生成到传输整个过程的安全性。因此,数据提供商可以拥有足够的灵活性,同时向多个不同的应用以独特的方式传输数据,比如向一组应用以每分钟一次的频率更新数据,同时向另一组应用基于价格偏差值更新数据(比如价格每上下浮动0.5%更新一次)。


数据提供商可以将数据卖给Chainlink节点运营商,也可以选择自己运行Chainlink节点

同一网关面向所有区块链环境

数据提供商不可能熟悉所有区块链环境,也不可能在每个区块链上都分别设立安全机制,特别是考虑到区块链是一个新很难了解所有区块链环境。

Chainlink预言机网络可以利用已有或新建的外部适配器/发起程序迅速接入任何区块链环境。Chainlink是开源网络,核心开发者无需任何许可就能集成Chainlink预言机,因此可消除开发瓶颈,实现横向扩展。以太坊PolkadotTezos、和Cosmos等众多领先的区块链都已经将Chainlink集成至其区块链网络。

这个机制可以为数据提供商和智能合约提供统一的网关,面向任何区块链出售和访问数据,最终向区块链上的dApp提供更多数据,并为数据提供商获得更多收入。值得一提的是,这个机制非常灵活,因此数据提供商无须选择把资源部署在哪里。

为数据和服务质量提供加密经济保障

在Chainlink预言机网络中,节点运营商和发起数据请求的智能合约会签订具有约束力的服务协议,协议将约定节点在服务期间必须满足的各项参数。参数包括数据交付(响应延迟)、数据质量(准确性)、质押的LINK金额(加密经济担保)、经济惩罚(罚款)以及其他由请求方约定的条款。节点运营商的报酬将取决于其是否成功履行了服务协议并按时将优质数据传输到链上。在这个机制下,运行Chainlink节点的数据提供商可以在最大程度上灵活设置数据服务保障,提升数据可信度、完整性、可靠性以及准确性。


具有约束力的服务协议为数据质量和数据交付提供加密经济保障。

服务协议建立在权益质押基础上,最终能让数据提供商为其预言机服务进行抵押担保,为请求数据的智能合约提供类似质量保险一样的保障机制,如果预言机违约,质押的权益将被没收。如果没有服务协议,预言机网络的数据交付和数据质量就不能得到约束,这样会导致数据请求方获得的数据质量或预言机服务无法得到很好的保障。

利用声誉框架和节点市场做出理性判断

实现灵活性最重要的一点是让用户可以综合判断将什么内容添加至预言机网络中。有两个功能可以实现这一点,即:声誉系统和节点市场。

声誉框架

声誉系统为用户提供了不可篡改的链上数据记录,其中记录了节点运营商和数据提供商的所有历史服务。以后,数据请求方可以查看节点历史服务的加密证明,并以此判断节点是否可靠。

通过第三方服务,可以在Chainlink节点中进行比较,选出最可靠的节点。这些网站中可以查看Chainlink网络整体的原始数据以及分析提炼出的数据,还可以看到每个预言机节点的具体数据,其中包括交易数量、响应时间、收入和成功率等。


Reputation.link 让开发者和用户可以深入洞悉Chainlink预言机网络整体的表现和性能,还可以查看每个单独的预言机和数据源。

节点市场

另一个关键要素是建立一个市场让用户可以发现预言机节点,通过筛选比较最终挑出最适合的节点加入预言机网络。目前有多个针对Chainlink节点的第三方分类信息平台,比如LinkPool的[Chainlink
Market](http://market.link/)和CLCG的Honeycomb Marketplace。开发者可以完全控制其预言机网络的架构,因为他们可以自行决定选择哪些节点以及节点的数量。

除此之外,还可以看到每个节点运营商的资质认证、安全评估结果、身份证明、外部适配器、数据源以及具体能为智能合约提供哪些链下服务。节点运营商可以为每个任务设置具体的价格和参数,建立一个自由市场经济,其中节点可以在不同的维度上竞争上岗。

market.link上的节点可以在链上积累声誉,并向开发者展示其声誉记录。

如何灵活地打造价格预言机,以规避重大数据源风险?

为了保障数据质量,在设计预言机时就必须提前考虑到一些可能出现的攻击向量,并防患于未然。如果开发者忽略了这些问题,就会导致用户资金面临巨大风险,并最终威胁到整个dApp的安全。

交易量转移/交易所锁定

加密货币市场与传统金融市场有所不同,因为交易所不会独家发行资产,因此无法锁定用户或占据某一资产100%的交易量。区块链技术的特点是无须许可,因此任何人都可以在其交易所中发行加密货币通证,交易者可以在任何时间交易这些通证。在这种情况下,加密货币的交易量分布在许多不同的交易所中,而且交易量会在各个交易所之间快速转移。因此,为了避免市场操纵攻击(比如绝大多数交易量转移到了某个不在聚合范围内的交易所),预言机必须要正视这个问题。

闪电崩盘

加密货币交易所通常没有熔断机制,因此很容易出现闪电崩盘,某一交易所的价格可能会与其他交易所出现严重偏差。即使规模再大的交易所都存在这种风险,在过去几年中多个交易平台都遭遇了闪电崩盘。比如Kraken就遭遇过闪电崩盘,BTC/CAD价格从11,200断崖式下跌至100CAD,跌幅接近99%。Coinbase也遭遇过一次极端的闪电崩盘,以太币价格暂时从322美元跳水至0.1美元。在2020年初,加密货币衍生品交易平台Bitmex也遭遇了闪电崩盘,XRP价格在一分钟内大跌60%,从0.33美元跌至0.13美元。

质量稀释

实现去中心化必须要同步建立质量控制标准,以避免低质量的数据源稀释聚合结果的质量。如果数据提供商和节点运营商的历史服务水平较低、没有声誉记录或无法证明其基础架构的安全性,则应被禁止加入任何预言机网络。要确保节点运营商和数据提供商有足够的资源和技能解决可能出现的任何问题,并建立预警机制和failsafe安全模式。

需要注意的是,发起向量攻击的恶意攻击者不一定都是经验丰富的开发者。任何散户交易者或一小群交易者只要发现了机会,都可以利用交易平台的UI操纵市场并篡改某一预言机的参考价格数据点,而单个预言机覆盖的市场是有限的。这在很大程度上扩大了攻击表面,因为任何人只要有网络连接和交易平台账户都可以操控存在风险漏洞的预言机。

Chainlink价格参考数据合约连接数据聚集商而非某一个交易平台的API或多个交易平台的API集合,因此可以规避这类风险。

优质的数据聚合商覆盖所有价格数据源

Chainlink价格参考数据可独家接入数据聚合商,覆盖最多的交易量。加密货币交易量相对传统金融市场仍然较小,有了这个功能,就可以确保向这些市场传输准确的数据。预言机网络创建者缺乏经验和资源,很难持续追踪交易所交易量,因此将这个工作交给专业的数据聚合商。

数据聚合商的团队遍布全球,在市场覆盖和精准价格数据维护方面拥有丰富的专业经验。他们会综合考量各个参数,比如流动性、交易量、时间以及不同交易所之间的参数差异。除此之外,聚合商还会剔除任何异常值。Chainlink价格参考合约的这些功能可以很好地应对交易量转移、闪电崩盘和质量稀释等问题。

另外,Chainlink价格参考合约还利用多个数据聚合商保障价格数据免受任何一个数据源的操控。这为dApp开发者和终端用户提供了更高的安全和可靠性。除此之外,通过安全评估的节点运营商以及业内顶尖的监控团队也会提供支持。


Chainlink价格参考数据合约的端到端流程

采集数据时不当使用预言机可能造成的重大风险

预言机网络如果忽略交易量转移风险或只从一个API获取数据,将导致重大风险,要充分了解这些风险,就需要讨论具体应用的案例以及最终会导致的结果。

忠告:避免预言机网络只从一个交易平台API获取数据

预言机网络如果只从一个交易平台获取价格数据,不仅在平台遇到宕机、闪电崩盘和价格操纵时无法提供有效保护,而且平台的市场覆盖将受到极大限制。这种模式在最初价格波动较低的时候似乎是有效的,但当市场价格波动上升,交易者会开始套利,交易量会在各个交易所之间频繁转移。即便升级预言机,使其从另一个交易所获取数据,新的价格点也可能非常不准确,因为市场交易量可能会出现新的变化。这就导致虽然数据源变了,仍然无法维持可靠的市场覆盖。

下面,我将与大家分享一个例子,一步步说明单一数据源的危害:

  • Joe是一名开发者,他开发了一个智能合约应用,需要从链下获取加密资产的价格数据。他决定建立一个预言机网络,从他指定的C交易所获取价格数据。在他创建预言机的那天,C交易所占资产交易量的80%,所以他觉得这是一个不错的选择。
  • 一周后,用户资金量不断增长。虽然C交易所现在只占资产交易量的50%,但市场价格波动较低,因此目前这个预言机模式并没有什么问题。Joe觉得他可以为他的dApp继续开发更多功能,对于预言机市场覆盖率越来越小这件事并没有想太多,因为毕竟也没出什么问题。
  • 又过了一个月,有一天半夜,Joe被一通电话吵醒,得知他的dApp中高达几百万的用户资金被卷走了。他很快发现C交易所大部分的交易量都转移到了别处,而C交易所是他预言机唯一的数据源,现在只占交易量的5%。而这个交易所被一个大型交易者操控,导致预言机报告了错误的价格数据,因此让其有机会通过不公平的方式吸走了一大笔用户资金。

  • Joe的dApp由于失去了用户信任,目前已经经营不下去了,而这件事也让他作为开发者的名誉严重受损。如果Joe的预言机建立了更好的市场覆盖机制,是完全可以避免这种情况的。

上述例子说明了预言机网络只从一个交易所获取数据可能导致的严重后果。市场覆盖是决定应用成败的关键因素,如果遇到闪电崩盘,那么后果将更加不堪设想。

预言机从预先设定的交易所聚合数据,无法规避交易量转移的风险

预言机如果直接从预先设定的交易所获取数据,那么当交易量转移到聚合范围以外的交易所,将产生巨大风险。在最初建立预言机网络时,被选为数据源的交易所可能确实具有充足的流动性,但随着时间推移,无法保障交易量是否还会继续留在这些交易所。这会降低恶意攻击者的攻击成本,因为他们只需操控一小部分资产交易量就可以达到攻击目的。

这似乎是一个很小的攻击向量,但想象一下这样的情况:

  • Bob也是一名智能合约开发者,他吸取了Joe只从一个交易所获取数据的经验教训,决定让预言机从一组预先设定的交易所A、B和C中获取加密资产价格数据。他的逻辑是:在各个交易所价格数据中取中位数,就能避免市场操纵行为。

  • 几周后,Bob很确信他的做法是对的,因为他的预言机从多个交易所获取数据,能够持续输出正确的结果,就算某一个交易所被操控也无法改变结果。因此,他将注意力转移到了提升应用的核心商业逻辑上。然后他就开始专注于开发新功能,并没有注意到市场上出现了两家新的交易所,并占到了85%的资产交易量。

  • 几天后,Bob猛然发现他遇到了和Joe一样的危机,他的智能合约也流失了几百万用户资金。最后他发现虽然他当初在建立预言机网络时选择的交易所流动性都是充足的,但随着时间推移,交易量逐渐转移到了新的交易所,而这些交易所不在他最初设置的聚合范围内。因此,他的预言机网络最终仅覆盖了15%的交易量,并不幸被交易者操控,从而谋取私利。

  • 虽然Bob建立去中心化预言机数据源这个想法是好的,但是他并没有考虑到交易量会在各个交易所之间转移,也没有想到新出现的交易所会占据某一资产大部分的交易量。即使不出现新的交易所,交易量仍有可能最终集中至一两家交易所,那么剩下流动性较低的交易所就可能被操控,中位数计算结果也可能遭到篡改。

Joe和Bob都没能保证充足的市场覆盖,因为他们想用预言机来生成数据。如果他们用预言机从数据聚合商采集数据,就完全可以避免这样的悲剧发生。因为数据聚合商在防止市场被操控和保障市场覆盖率方面拥有几十年的专业经验。

将低质量的预言机与高质量的预言机混用

一些人为了避免出现异常值,会同时接入多个不同的预言机并聚合出一个最终价格数据。同时接入多个预言机实现去中心化,听上去似乎是个不错的方案,但与此同时它也带来了更大的风险,因为很难确保网络中每个预言机的可靠性和数据质量都保持同一水平。

Chainlink价格参考数据网络拥有非常安全可靠的价格数据,而相比之下一些预言机则非常不成熟,透明度较低,不仅无法连接至付费API,还无法直接从交易所API获取市场数据,这类预言机输出的数据质量非常差。将Chainlink优质的预言机数据与某些劣质数据混合在一起,可能会产生极大的风险。随着DeFi应用的价值越来越高,这个问题将变得至关重要,因为通过预言机漏洞攻击DeFi dApp的经济诱惑会越来越大。

设想现在聚合了三个预言机解决方案,一个是Chainlink价格参考数据,它通过优质节点从付费数据聚合商获取数据;还有一个方案是从预先设定的一组交易所API获取价格数据;最后一个方案不支持身份认证信息管理,因此只能连接一个低质量的数据源或交易所API。


将Chainlink的优质数据与其他不安全的预言机输出的低质量数据聚合在一起,会降低最终聚合数据的质量。

在这个例子中:

  • 左手边是Chainlink的价格参考数据,从多个优质数据聚合商获取数据,最终输出交易量和流动性加权价格,这些价格覆盖了所有交易价格是100美元的交易环境。
  • 左上方的预言机方案从预先设定的一组交易所API(A、B、C)获取数据,当时仅占15%的市场交易量,而D和E交易所占85%的交易量。这将使最终数据结果遭到篡改,导致预言机报告了错误的价格:70美元。
  • 左下方的预言机方案只连接了一个低质量的数据源,这个数据源由于市场波动性较高而中断了服务。由于单点失效,因此预言机报告的价格是0美元。

智能合约在0美元、70美元和100美元三个值中取中位数,最终聚合出了错误的数值:70美元,而正确的市场价格是100美元。更糟糕的是,三个数值的均值是57美元。在这两种情况下,其他两个预言机解决方案传输的低质量数据会稀释Chainlink价格参考数据传输的高质量数据。

这种情况会导致最终生成低质量的数据,结果容易受到操纵,并稀释了Chainlink的优质数据(即扣除交易量因素的数据)。在预言机层面实现去中心化固然重要,但同时也应保障数据或节点的质量。将良莠不齐的数据掺在一起,会稀释Chainlinik价格参考数据网络的价值。我们强烈建议大家不要使用未知数据源的价格数据,不要接入算法存在明显漏洞的预言机,也不要使用无法获取付费数据或加密经济机制较弱的预言机。

为下一代应用提供优质数据

我们应该将预言机和数据源分开看待,这两个环节必须拥有同样高的抗风险能力,结合在一起才能实现全面的、端到端的安全性。为了为DeFi生态建立可靠的预言机网络,并保障几十亿甚至几万亿美元的资产,必须确保传输至DeFi应用的数据是安全可靠的。Chainlink一直以来都致力于打造安全的预言机和可靠的数据,实现端到端的安全,助力DeFi在未来几年不断繁荣发展,成为主流的解决方案。

如果你正在做DeFi项目,并希望开发自己的价格参考预言机网络或接入已有的预言机网络,请访问我们的开发者文档、加入我们在Discord上的技术讨论或点击此处安排一次电话会议与我们深入探讨集成相关事宜。你可以轻松快速在主网或测试网集成一个或多个Chainlink预言机网络,提升智能合约的安全性和并丰富其功能。

加入Chainlink开发者社区

image.png

查看原文

赞 0 收藏 0 评论 0

Chainlink 发布了文章 · 8月12日

Chainlink节点部署教程

Chainlink节点部署教程

本文主要参考Chainlink官方文档(https://docs.chain.link/docs/running-a-chainlink-node)编写,如果您可以阅读英文,推荐您直接阅读官方文档。

安装必须组件

服务器环境Ubuntu1804,我们以Ropsten测试网为例,以太坊主网的搭建只需修改相关配置选项即可。

Docker 安装参考文档

https://docs.docker.com/engine/install/ubuntu/

将当前用户添加至docker用户组

sudo usermod -aG docker $USER
exit
# 重新登录

PostgresSQL

Chainlink Node在0.8版本之后将PostgresSQL作为唯一的存储选项。PostgresSQL数据库可以是自己搭建的,也可以是云服务商提供的,只要可以提供数据库的访问接口即可。

本地安装参考:

https://www.postgresql.org/download/linux/ubuntu/

以太坊客户端

Chainlink节点通过与以太坊客户端节点连接,通过连接的以太坊客户端来获取链上的用户预言机请求,通过提交交易将获取到的数据写入到链上。所以Chainlink节点必须要依靠一个以太坊客户端节点才能发挥作用。您可以自己搭建以太坊客户端节点,也可以选择以太坊RPC服务提供方的服务,只需要一个WebSocket链接提供给Chainlink节点即可。

Chainlink的文档中(https://docs.chain.link/docs/run-an-ethereum-client)提供了搭建本地以太坊客户端节点的方法,也提供了几个外部以太坊API服务供您选择。由于以太坊客户端节点对硬件要求比较高,本文中我们选择infura提供的免费API来作为Chainlink节点的以太坊客户端选择。

部署Chainlink节点

创建Chainlink目录

Ropsten: mkdir ~/.chainlink-ropsten

配置环境变量

Ropsten:

echo "ROOT=/chainlink
LOG_LEVEL=debug
ETH_CHAIN_ID=3
MIN_OUTGOING_CONFIRMATIONS=2
LINK_CONTRACT_ADDRESS=0x20fE562d797A42Dcb3399062AE9546cd06f63280
CHAINLINK_TLS_PORT=0
SECURE_COOKIES=false
GAS_UPDATER_ENABLED=true
ALLOW_ORIGINS=*
ETH_URL=wss://ropsten.infura.io/ws/v3/<your-api-key>
DATABASE_URL=postgresql://postgres:password@localhost:5432/postgres
DATABASE_TIMEOUT=0" > ~/.chainlink-ropsten/.env

MIN_OUTGOING_CONFIRMATIONS : 节点发出交易所需要的最小确认块数,在达到最小确认块数之前,同一个run不会开始下一个任务。如果不设置,默认值为12。

LINK_CONTRACT_ADDRESS : LINK token的发行地址,这里有测试网和主网的LINK发行地址,您可以根据自己的网络进行配置。如果不进行配置,默认是主网的LINK发行地址。

GAS_UPDATER_ENABLED : 如果设置为true,节点会在提交事务失败时提高gas费用重新提交。默认为false。

ETH_URL : 以太坊客户端WebSocket RPC接口地址。您可以选择自建以太坊客户端,也可以选择第三方服务,只要提供WebSocket协议的RPC接口地址即可。

DATABASE_URL : Chainlink节点需要使用PostgresSQL数据库来进行一些数据的持久化存储。同样您可以选择自建数据库或使用第三方数据库服务,只需要提供数据库地址可以让节点读写数据即可。

DATABASE_TIMEOUT :数据库连接超时等待时间。默认500ms。

启动节点

cd ~/.chainlink-ropsten && docker run -p 6688:6688 -v ~/.chainlink-ropsten:/chainlink -it --env-file=.env smartcontract/chainlink local n

首次启动会首先要求管理员输入一个密码,这个密码是节点账户的keystore密码,这个密码必须牢记,丢失的话没有办法找回,并且私钥所管理的资金也会丢失。每次启动都会要求管理员输入这个密码,以解锁keystore。节点需要通过keystore的私钥来签署交易,提交到区块链上。

接下来还会要求节点管理员输入一对邮箱账户和密码,用于登录节点管理页面。

测试节点

登录浏览器管理页面

浏览器中打开ip:6688地址,就能看到Chainlink节点管理页面的登录入口。用我们在启动节点时填入的邮箱账户和密码,就可以登录到管理界面中了。

我们先去到**Configuration** 标签页,会发现有一个ACCOUNT_ADDRESS字段,这个address就是我们在首次启动节点时候设置keystore密码的私钥所对应的地址,在节点提供服务之前,需要向这个地址转入ETH,用于提交交易。

由于我们使用的是Ropsten测试网络,所以我们可以把这个地址复制到Ropsten faucet中,获取测试ETH。如果您是服务于以太主网上的应用,需要您想这个账户地址手动转入ETH。

创建oracle合约

Oracle合约是Chainlink节点在区块链上的桥头堡,它与用户合约直接进行沟通,接收用户的预言机请求,将请求结果通过用户注册的回调函数,写入到用户的合约中。

Oracle合约无需自己编写,我们直接部署Chainlink开源的Oracle合约代码即可。如果用remix部署,只需新建一个包含下面两行代码的文件即可:

pragma solidity 0.6.6;

import "https://github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/Oracle.sol";

需要注意的是,oracle合约会暂时接受用户发起Chainlink请求是所支付的LINK费用,所以请务必妥善保存合约owner的私钥。

部署好Oracle合约之后,需要将开放权限给节点的地址,允许节点可以提交事务。

Untitled.png

创建Jobs

按照文档中的例子,在节点中添加Job(作业)。

打开节点管理界面的Jobs标签页,点击New Job添加新的Job,将每个类型的Job的JSON拷贝到文本框中,用刚刚部署好的Oracle合约地址,替换JSON中的YOUR_ORACLE_CONTRACT_ADDRESS字段。每创建成功一个Job,都会生成一个Job ID,在Jobs标签页可以找到所有的Jobs。

测试节点可用性

接下来我们测试一下我们部署的Chainlink服务的可用性。

pragma solidity ^0.6.0;

import "https://raw.githubusercontent.com/smartcontractkit/chainlink/develop/evm-contracts/src/v0.6/ChainlinkClient.sol";

contract APIConsumer is ChainlinkClient {
  
    uint256 public ethereumPrice;
    
    address private oracle;
    bytes32 private jobId;
    uint256 private fee;
    
    constructor() public {
        setPublicChainlinkToken();
    // 填入我们刚刚部署好的oracle地址
        oracle = 0x5F66a231a29CE1513dc6c16407fDCe9D0aEE2cB0;
    // 填入我们刚刚创建的地址
        jobId = "4b9b6e7d89154a8d855affed3985aafd";
    // 支付给Oracle的最小费用,可用在Configuration页面MINIMUM_CONTRACT_PAYMENT字段查看到
        fee = 1 * 10 ** 18; // 1 LINK
    }
    
    function requestEthereumPrice() public returns (bytes32 requestId) 
    {
        Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
        
        // 设置所要请求的API地址
        request.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");
        
        // API返回结果的解析路径
        request.add("path", "USD");
        
        // 为去除小数点将结果乘以的倍数
        request.addInt("times", 100);
        
        // 发送请求
        return sendChainlinkRequestTo(oracle, request, fee);
    }
    
    function fulfill(bytes32 _requestId, uint256 _price) public recordChainlinkFulfillment(_requestId)
    {
        ethereumPrice = _price;
    }
}

部署好用户合约之后,向用户合约转入LINK,调用requestEthereumPrice方法,就可以测试我们的Chainlink预言机节点是否可以正常工作啦。

加入Chainlink开发者社区

image.png

查看原文

赞 0 收藏 0 评论 0

Chainlink 发布了文章 · 7月23日

随机数奖励会对区块链游戏产生哪些经济价值?

重点摘要:

  • 游戏中的随机数通常分为两类:输入型和输出型。
  • 区块链游戏采用随机数机制发放经济奖励,有潜力推动游戏产业增长至万亿级规模。
  • 区块链游戏奖励是不可篡改的稀缺性资产,这些资产可以在二级市场上交易,可能将很快实现跨游戏应用。
  • 现有的随机数解决方案存在诸多问题,无法为其创造的价值提供安全保障。
  • Chainlink VRF旨在为区块链游戏生成随机数,用户可独立验证其真实性。

背景介绍

随机数无处不在,以至于我们经常会忽略了它的存在,但实际上随机数是游戏中一个至关重要的元素,它能极大提升玩家在游戏中的愉悦感和沉浸感。总的来说,随机数可以应用在输入和输出两个维度上,对开发者来说,随机数既可以作为条件约束玩家行为(输入型随机数),也可以用来操控玩家行为所产生的结果(输出型随机数)。开发者兼理论工作者Jesse Schell表示,将这些不同类型的随机数与结构化的游戏元素有机结合,可以为游戏玩家提供一种“惊喜和愉悦完美交织”的体验,这也是Schell对“游戏愉悦感”的定义。

目前,区块链游戏开发者几乎完全无法获得随机数。随着区块链游戏产业不断发展壮大,随机数的重要性也将蔓延至游戏体验以外的领域,因此无法安全地获得随机数也变成了一个亟待解决的问题。区块链游戏中的随机数将对开发者和游戏玩家产生越来越重要的经济影响,使用随机数可以更好地将游戏时间和游戏内操作变现。这可以通过一系列方法实现,比如用通证代表游戏物品、创造“元界”(metaverse)扩大这些物品的应用范围、以及允许玩家验证游戏物品的稀缺性等。

区块链游戏要和传统游戏竞争,开发者就必须采用公正的随机数生成方案,在智能合约中安全地生成随机数。许多开发者曾尝试在区块链游戏中引入随机元素,但都面临一个困境,那就是到底选择中心化的链下随机数生成方案,还是冒着被攻击的风险使用链上随机函数生成随机数?而近期Chainlink针对这一问题发布了可验证随机函数(VRF),并有望成为区块链游戏颠覆创新的关键一环。

本文将讨论随机数在游戏中的应用模式、游戏随机数和其他玩家操作产生的经济影响、随机数对区块链游戏预期的经济影响力、以及Chainlink VRF与现有随机数方案相比的创新之处。

游戏中的随机数

开发者Raph Koster在2005年出版的《游戏设计快乐之道》(A Theory of Fun for Game Design)一书中将所有无聊游戏的通病总结为“太容易就能通关”。

Koster认为,“愉悦感”是认识规律、解决问题和吸取经验的副产品,这个过程最终目的是为了掌握某个信息。孩子在学会说话前就能学会井字棋游戏,而且还会玩得乐此不疲,因为这个游戏的规则很简单,规律也很好掌握。但他们的认知水平一旦发展到更高阶段,玩一会儿就会觉得无聊了,这是因为这个游戏太容易就能通关了。所以游戏中随机数的一个关键作用是使玩家操作和游戏环境更富有变化性,让玩家不会太快通关,而且还会向玩家不断提供新的游戏激励。

要实现这一目标,需要两种不同的随机数,即:输入型随机数和输出型随机数。输入型随机数在玩家进行操作前出现在游戏中,比如给玩家发一副牌;或者玩家进入某一游戏区域时随机生成怪兽;或游戏地图按照游戏进行顺序生成环境。以上这些例子中,游戏随机数通过改变具体的游戏场景为玩家不断设置挑战。玩家无法按部就班地进行操作在游戏里迅速通关,而是必须应对游戏中不断变化的场景和挑战,因此游戏时间变长,而且玩家会产生更大的成就感。

而输出型随机数则是操纵玩家行为产生的结果,或在结果中注入一些“杂音”。这类随机数包括战略游戏中对战获胜率;德州扑克中的翻牌、转牌和河牌圈;以及掷色子决定玩家是否通过技能判定。输出型随机数可以避免游戏出现完全随机的结果,玩家不得不学习游戏中各类风险的应对策略,以及在遇到小概率的重大打击时如何恢复元气,因此玩家需要花一定时间才能通关。
image.png
输入型和输出型随机数如何影响游戏场景

上述所有随机数应用场景都已在区块链游戏中实现或正在开发中。然而,有一类输入型随机数对区块链游戏开发者和玩家来说具有特别重要的经济价值,那就是用来确定玩家奖励的随机数。这其中包括战利品开箱、物品设计以及游戏成就奖励发放。

其他类型的随机数作用都是给玩家设置障碍,延长游戏时间,而这类随机数的作用则是给玩家提供奖励。“奖励型随机数”的独特之处在于游戏奖励通常可以在二级市场买卖,这在原本的游戏体验上又增加了额外的经济激励。这类随机数将在未来成为区块链游戏经济中不可或缺的元素。

奖励型随机数的经济价值

游戏调研公司NewZoo发布的一份报告预测2020年游戏产业的价值将达到1600亿美元,到2023年将有望突破2000亿美元。其中,游戏皮肤、物品包和额外的游戏内容年销售额目前为500亿美元,将近占到整个市场的三分之一。虚拟商品交易市场中到底有多少商品来自“战利品箱”(注:随机游戏物品或皮肤)等随机发放的道具,具体数字不得而知,但应该是占到了很大比例。

区块链游戏市场正在不断扩张,其中三个最受欢迎的游戏是CryptoKittiesGods UnchainedMy Crypto Heroes。这三款游戏在发行的第一年分别获得了700万美元、420万美元和150万美元的收入。其玩家在二级市场上交易游戏物品获得的收益超过2000万美元。
image.png
CryptoKitties是目前很火的一款NFT收藏类游戏

区块链内容协会主席Hironao Kunimitsu近期表示他相信区块链游戏市场的规模最终将超过日本GDP(注:目前日本GDP预估是4.7万亿美元)。其中最重要的手段是将随机发放的游戏物品用NFT通证表示。我们之前在《用Chainlink预言机创建非同质化通证的16种方式》一文中曾深入探讨过NFT是区块链上的一种加密安全通证,可以代表独特物品的所有权。

用NFT代表区块链游戏物品最大的价值是所有权可以验证,而且不可篡改。遗留游戏的物品所有权可以撤销,物品的状态和外形可以修改,如果游戏停止运营,物品也可随之被删除。用NFT通证代表游戏物品将解决上文提到的所有问题,NFT可以对物品所有权提供加密安全保障;NFT的元数据无法被篡改,除非发布特殊许可声明;由于NFT储存在区块链上,因此NFT游戏物品就算在游戏消失后也仍然存在。

另外,NFT可以跳脱出其原生游戏环境的限制,这也创造出了新的应用场景,我们称之为“元界”(metaverse)。元界是连接各个游戏的网络,NFT物品可以在所有不同的“游戏宇宙”中通用。举个例子,幻想游戏中的一件防弹背心在科幻游戏里也可以同样用来提升玩家的防御能力。允许NFT游戏物品跨游戏应用,开发者就可以提升物品的价值。

最后,NFT还可以增强二级市场的流动性和透明性。Fair Games等公司正在追踪游戏随机生成NFT的频率与物品市场价格之间的关系,并将结果与游戏玩家分享。这样一来,玩家就可以基于NFT战利品的变现能力挑选游戏,并且利用区块链公开透明的特质验证NFT物品的稀缺性。

专家认为用NFT通证代表游戏内的随机奖励已经实现了可观的经济价值,它将极大推动虚拟商品的发展规模。然而,随着虚拟商品的价值不断升高,我们越来越需要有一个安全可靠且可验证的随机数生成方案。

目前随机数生成方案存在的瓶颈

如果一个DeFi协议只有一台可轻易被操纵的预言机,将无法得到用户信任。同样地,如果游戏无法对随机数生成提供安全保障,也无法得到用户信任。特别是当游戏与现实世界的利益挂钩时(比如用NFT发放随机奖励),就更加需要安全可靠且可验证的解决方案,因为这类随机数生成的频率和本身的价值都很高。

如果是中心化的解决方案,随机数很可能会被拥有权限的开发者所操纵。他们这么做可能是为了把最有价值的NFT留给自己或其他有特权的人。另外,就算开发团队本身是清白的,随机数生成机制不透明也会招来游戏玩家的猜忌和怀疑。随机性本质上就意味着即使再小概率的事件也可能发生,如果时间线拉得够长,就难免会发生某一名玩家连续几次走运的情况。由于中心化随机数生成机制无法做到公开透明,当其他玩家看到某个人连续机次赢得了罕见或高值的游戏物品,肯定会对分配的公平性产生怀疑。

使用区块哈希值的链上解决方案无法为很高的价值提供安全保障。一旦游戏的价值足够高,就会有人来钻空子谋取私利,这些人可以用区块哈希值这样可以被操控的数据发起攻击向量。我们在介绍VRF的文章中具体解释过这类攻击:

“假设智能合约基于区块在某一高度时哈希值末位的奇偶性做判断。看似概率是50/50,但现在有一名矿工(或一群联合起来的矿工)生产的区块约占总量的1/3,该矿工可能会剔除哈希值末位数为1的中奖区块,损失价值约为2-3个以太币的区块奖励。这种情况下,矿工就能将末位数为0的结果的概率从正常的50%提升至2/3,并导致所有采用这个模式生成随机数的智能合约损失用户资金。”

之前发布的主流区块链游戏也曾经遭受过同样的攻击,开发团队不得不在NFT价值被稀释和向攻击者支付赎金之间艰难抉择。

Chainlink VRF为链上提供可验证的随机数

image.png
Chainlink VRF的基本工作原理

要为区块链游戏开发出完美的随机数解决方案,就必须解决上述问题,保障公平性并实现链上验证,提供安全保障,防止随机数被操纵或篡改。Chainlink VRF就是兼具这些特质的随机数生成方案,它能在链上生成随机数,并且无法被任何节点运营商、矿工或用户操纵。Chainlink VRF拥有加密证明技术,任何人都可以在链上验证随机数的真实性。

Chainlink VRF的运行分为五步:

  1. 用户向智能合约应用发送一个seed
  2. 智能合约用这个seed向Chainlink VRF提交数据请求
  3. Chainlink节点运营商生成随机数并在链上发布随机数生成的加密证明
  4. 在链上验证返回的随机数
  5. 基于经过验证的随机数执行智能合约

这个基础架构保障智能合约使用的随机数不受任何操纵。另外,随着Chainlink VRF不断迭代发展,其安全性也会不断提升。目前,节点运营商可以采用“扣块攻击”的方式操控随机数生成结果。虽然节点运营商无法直接篡改随机数,但他们有权利不提交随机数结果。之后我们可以使用多个预言机,通过门限签名技术提交数据,并实行保证金制度,以此来解决这一问题。这将为Chainlink VRF提供安全保障,以匹配区块链游戏领域不断增长的价值并满足该领域对安全的迫切需求。

目前有许多项目正在使用Chainlink VRF生成和发放随机奖励,其中包括PoolTogether(游戏平台,用Chainlink VRF向用户发放储蓄奖励)、Polyient Games(通证平台,用Chainlink VRF实现NFT随机数功能)、FaceGolf(用VRF判定比赛结果和奖励)、The Six Dragons(该游戏的武器装备制作功能结合了随机风险/奖励机制)、WildCards(基于哈伯格税收模式的NFT慈善项目,用VRF打造新的NFT通证)以及Texel(用VRF判定郁金香藏品的基因属性)。

image.png
越来越多的区块链游戏项目开始使用Chainlink VRF

随着区块链游戏日趋成熟,安全随机数的经济价值也将随之升高,我们相信越来越多的团队会意识到他们对Chainlink VRF这类安全随机数生成方案的迫切需求。

总结

区块链游戏是最具潜力的区块链应用场景之一,区块链技术可提升游戏资产的透明性和所有权的可验证性,因此可大幅增强游戏玩家的体验。除此之外,游戏玩家还能更好地变现其游戏时间和技能,这将从根本上颠覆传统游戏模式。这些创新目前已经产生了巨大的经济价值,并且将推动整个游戏产业的快速扩张。

然而,要实现这些宏大的愿景,开发者和玩家需要有安全可靠的基础架构,为游戏产业不断增长的价值提供安全保障。游戏随机数未来将不只是优化游戏体验的工具,还将成为创造和分发价值的的重要渠道。Chainlink VRF是专门为智能合约开发的随机函数,可以满足区块链游戏产业的新兴需求。

如何部署Chainlink VRF

如果你是一名智能合约开发者,并希望部署Chainlink VRF,请查看我们的开发者文档,并加入我们在Discord上的技术讨论群。如果你希望安排电话会议与我们详细讨论更多细节,欢迎随时联系我们。

详情请访问Chainlink官网或在Twitter或Reddit上关注我们。

加入Chainlink开发者社区

image.png

查看原文

赞 0 收藏 0 评论 0

Chainlink 发布了文章 · 7月20日

一文了解数据和API如何驱动未来经济

在前两篇科普系列文章中,我们讨论了区块链和智能合约如何作为新一代基础架构安全可靠地转移和储存价值。区块链上的智能合约就像未连接互联网的计算机一样,本身就具有其内在价值,智能合约的内在价值就是创建和交易通证。然而,计算机连接了互联网后,释放出了巨大的创新力和价值,同样地,智能合约一旦连接到快速增长的链下数据和API经济,也将变得无比强大。如果智能合约可以连接至链下数据提供商、web API、企业系统、云服务商、物联网设备、支付系统以及其他区块链等各种庞大的数据库,那么它将成为横跨各个行业的主流数字协议。本文中,我们将在以下几个方面深度解析数据和API:

  • 数据是什么?它如何驱动数据经济?
  • 数据是如何被生产出来的?
  • 如何通过API交换数据?
  • 什么是大数据分析?

本文将全面分析链下数据经济格局,下一篇文章中我们会接着探讨如何使用一种叫“预言机”的基础架构安全可靠地将智能合约连接至这些链下数据。o:p

数据与数据经济

数据

数据是通过观察得出的结果或信息,比如测量室外温度、计算汽车的地理位置或记录用户与应用的交互情况。原始数据本身既不具有特殊价值也不可靠,而是需要用其他数据对其进行解读或确认,以确保数据的真实性和有效性。

元数据

元数据是“关于数据的数据”。元数据中主要包含数据的基本信息,目的是大幅降低追踪和处理信息的难度。举个例子,某个消息的发送时间、某一温度数值的地理位置或某次电话沟通的时长,这些全都是元数据。其目的是为数据建立索引并赋予意义。

数据清洗

除此之外,重要的应用需要保障数据可靠性,因此需要对其进行处理和清洗。这个清洗过程包括去除异常值、发现错误并剔除不相关的信息。比如,将目前温度与历史温度进行比较,以甄别并剔除异常值。

数据经济

在数据经济中,各种类型的数据都会被搜集、提炼和交换,并产生有价值的洞察。这些洞察会产生最大的社会效益,比如在共享医疗数据库中储存临床研究数据,以便大家更好地了解最新医疗趋势;或私营企业追踪内部运营流程,以甄别并改善效率低下问题。

随着数据经济的不断发展,自动化程度也在不断上升。数据可以直接触发经济行为,而无须人为干预。举个例子,应用的算法规定只要满足三个条件,就会自动支付货款,这三个条件分别是:1)货物送达(GPS数据);2)货物品相完好(物联网数据);3)货物已清关(web API)。

数据生产

数据是某一流程或事件的副产品,数据的产生需要输入(即行为)、数据的记录需要提取(即测量)、而为数据赋予意义则需要聚合(即分析)。由于数据的输入、提取和聚合技术存在一定限制门槛,因此数据并不能做到“人人平等”,数据质量也是参差不齐的。

以下是获取新数据和原始数据的常见方式:

  • 表格(手动输入的数据):用户填写公开和私人表格(比如回答问卷调查、签署文档或在社交平台发言),手动输入的数据。
  • 应用/网站(经过用户同意的数据):在用户同意应用或网站的条款和协议后获取的数据。用户通常在同意这些条款和协议后,就会授权网站或应用追踪某些数据,比如APP中的操作、浏览习惯或甚至是性别和年龄等个人信息。
  • 物联网(实时监测的数据):安装了传感器和执行器的设备捕捉到的数据。并通过智能手机、智能家居、可穿戴式设备、射频识别装置等各种互联网设备传输数据。
  • 自有流程/个人经验(由内部或个人拥有的数据):企业由于拥有专利或市场领导地位而掌控了某一业务流程,从而获取到的数据;抑或是在个人独特的经验中产生的数据。
  • 研究和分析(聚合并诠释数据):搜集来自现有数据集的数据,并对数据进行分析,包括与历史数据进行交叉对比、对其他数据集进行交叉参考以及采用新的过滤和计算方法等。另外还有数据分销商,他们从数据聚合商或企业大量收购数据,然后转卖给终端用户。数据分销商虽然以更高的价格将数据转卖出去,但是他们在转卖之前会按照用户的需求将数据处理成适合的结构或格式。

数据交换

如果数据要成为下一代应用的核心支柱,那么就不能完全依赖内部产生数据,而是必须建立一个数据交易机制,因为买数据的成本比生产数据的成本低多了。举个例子,开发自动驾驶汽车的算法需要运用大量数据进行目标检测、目标分类、目标定位以及运动预测。开发者可以在内部产生这些数据,但代价是需要累计几百万英里的驾驶里程;而他们也可以通过API购买这些数据。

应用程序编程接口(API)其实是一组命令,控制外部应用如何接入系统内部的数据集和服务。API是目前数据和服务交易的标准方案。主流的打车软件Uber连接了MapBox的GPS API进行车辆定位、Twilio的短信息API发送即时消息以及Braintree的支付API进行付款。这些功能都是购买的已有技术方案,而非Uber自己从零开发。

(API经济自出现以来一直呈稳定上升趋势,自此期间产生了许多新的API和管理API的新方案。资料来源:Software Development Company Informatica)

API的收费模式通常是订阅模式,终端用户可以按使用次数付费,也可以按月付费,还可以按照某种阶梯制度付费。因此,数据提供商会得到经济激励生产数据,而终端用户无须自行生产这些数据。API提供方和付费用户之间还会签署具有法律效力的合约,以避免数据盗用或未经许可转卖等各种恶意行为,并约束数据提供商为自己的数据质量负责。

有许多API可免费供所有人使用,其中包括提供天气数据的Open Weather Map、提供航班信息的Skyscanner Flight Search以及提供全球人类行为和信仰数据的GDELT。除此之外,全世界各国政府也积极推出透明数据的倡议,并不断加大力度将API开源。然而,开源API的可靠性还是不如付费API,因为缺少经济激励和法律协议的约束,没法控制数据质量和延时风险。大多数优质数据仍然来自付费API,这些API通常拥有顶尖的数据源、全栈基础架构以及全职的监控团队,并为了超越竞争对手而不断努力创新。

大数据基础架构和分析

编程系统能够自主学习和自我完善,这个概念一直都受到热烈追捧。学习的过程包括采取行动、收到结果、与历史数据比对分析并产生新洞察,改进方法,最终实现目标。因此,目前的大趋势是开发出一个可以自主学习的基础架构,吸取大量数据、对数据进行过滤分类,并基于分析结果产生洞察。

美国的Facebook、Google和亚马逊以及中国的阿里巴巴、腾讯和百度之所以能成为今天的科技巨头,就是因为它们深耕互联网应用,并产生了海量的用户数据。这些数据为世界顶尖的数据分析工具,特别是人工智能和机器学习软件,奠定了坚实的基础。这些大数据分析技术能够针对消费者行为、社会趋势和市场趋势产生大量丰富的洞察。与此同时,业务管理软件也帮助企业更好地了解它们的运营情况。SAP、Salesforce和甲骨文等企业开发了企业资源规划系统(ERP)、客户关系管理系统(CRM)以及云端管理软件,使企业能够汇总内部业务流程中的所有数据和系统,并产生关键洞察。

云端计算和储存技术正受到越来越多的关注。有了云计算,用户可以共享云端基础架构储存和处理数据,从而无须占用自己的系统资源。云技术改善了应用的后端流程,增强了不同系统之间的共享,并降低了人工智能和机器学习软件的使用成本。举个例子,Google Cloud用户可以使用BigQuery,这是一个SaaS软件,可以批量分析千万亿字节的数据,并内置机器学习功能。

第四次工业革命即将到来

将人工智能/机器学习、业务管理软件以及云端基础架构相结合,能从数据中获得更加深刻的洞察。另外,边缘计算、5G通讯网络以及生物科技等技术的兴起也促进了实时数据和生物连接数据环境的发展。在这些新兴系统的推动下,经济体系不断朝着去人为干预和实时数据驱动决策的方向发展,而数据生成和分享的壁垒几乎消失,频率不断上升,这也进一步推动了大趋势的发展。许多人将这个大趋势称为“第四次工业革命”。

欢迎加入 Chainlink 开发者社区

了解更多内容请期待我们之后发布的文章。本科普系列中的下一篇文章将探讨智能合约的话题。欢迎关注我们的 Twitter 账号,收到文章更新通知。还可加入我们的电报群,了解 Chainlink 最新资讯。

查看原文

赞 1 收藏 1 评论 0

Chainlink 发布了文章 · 7月14日

什么是智能合约?为什么它比传统数字合约更具优势?

本科普系列的第一篇文章介绍了区块链,文中提到区块链是非常安全可靠的网络,能够在不可篡改的账本中交换价值并储存数据。区块链催生出了比特币等全新的货币工具,然而其应用价值远不止如此,区块链还可以驱动智能合约(注:这是一种预先设定条件的数字合约)。本文将详细探讨以下内容:

  • 什么是智能合约
  • 智能合约如何创造价值
  • 智能合约的发展历程

-智能合约目前的应用模式

什么是智能合约?

数字合约是在互联网上运行的数字化签名合约。举个例子,乘客在Uber的用户条款中点击“同意”,即同意在车辆将其送达目的地时付款给司机。

在大部分数字协议中,双方都互不认识,这种情况下如果任意一方不履约就会产生风险。为了规避此类对手方风险,数字协议通常由具有一定规模的营利性企业从中执行,这些企业能够可靠地执行合约条款。这类数字合约可以在用户与大公司之间签署,也可以在两个用户之间签署,而大公司则作为可信中介从中协调。虽然这个机制大大降低了对手方风险,拓宽了合约的应用场景,但却给了这些大公司极大的合约控制权。

智能合约本身也是一个数字协议,只是它是在区块链上不可篡改的软件,严格按照约定的条款执行。最简单的条件逻辑是:“如果事件X发生,则执行行为Y。”举个例子,如果A队赢得体育比赛,则付款给Bob;如果B队赢得比赛,则付款给Steve。智能合约无须手动输入比赛结果,而是直接连接比赛结果数据触发执行。智能合约收到数据后,会自动执行,通常执行的任务是付款。

商业逻辑(即合约)是基于概率的,也就是说合约有可能会按照约定条款执行也有可能不会;而智能合约则是高度确定的,也就是说合约百分之百会给按照规定条款执行。智能合约之所以能分毫不差地执行,是因为它们所在的块链环境具有去中心化、无须许可、防篡改和永远在线的特性。在这个框架下,合约是在中立的去中心化网络中运行,而且通过技术手段保障执行。

智能合约的价值

智能合约相比传统数字合约具有以下几个优势:

  • 安全性:在去中心化的基础架构中运行智能合约能够规避单点失效风险、去除中心化的中介,而且不论是合约任意一方还是系统管理员都无法篡改结果。
  • 可靠性:网络中多个独立节点会对智能合约逻辑进行重复处理和验证,以有效规避操纵风险并保障网络运行时间,确保合约按照规定条款按时执行。
  • 公平性:使用点对点的去中心化网络运行并执行合约条款,能够减少中心化的营利性实体榨取交易价值。
  • 高效性:将托管、维护、执行和交割等后端流程自动化,意味着合约双方都无须等待手动输入数据、交易对手方履行合约职责或中间方处理交易。

智能合约的发展历程

最早版本的智能合约叫多重签名智能合约。必须要有足够多的人(即公钥)使用对应的私钥对交易进行签名,才能使交易生效。比特币在2012年首次将多重签名交易引入了区块链。


比特币区块链上多重签名交易的简化框架

之后,开发者在这个基础上开发出了协议型智能合约,在区块链中嵌入了几条核心编程指令(注:也称opcode)。协议型智能合约是化身为应用的区块链,并能够执行opcode。然而,这种智能合约很难扩展,因为合约(即协议)每次更新都会出现一次硬分叉,而硬分叉意味着需要创建一条全新的区块链,而且每个节点都需要升级软件。

以太坊在2015年发布了脚本化智能合约,实现了重大突破,将区块链变成了一台“世界计算机”,可以同时运行多个不同的应用。开发者可自行管理智能合约,并可以随时进行更改,无须硬分叉。脚本语言将低层级的开发问题抽象化,开发者能够在几周或甚至几天的时间内开发出智能合约,而在此之前需要花费几个月到几年的时间。

而现在我们又迎来了新一轮创新,那就是让脚本化智能合约连接到链下真实世界的数据和系统。具有外部连接性的智能合约使用一种名为预言机的中间件,连接链下数据触发合约执行。预言机还允许智能合约向其他系统发送数据,比如向传统法币支付系统发送支付指令,在链下交割智能合约。


Chainlink预言机可将数据(左边)发送至区块链上的智能合约(中间),并将支付指令发送至链下支付系统(右边)

智能合约目前的应用模式

虽然智能合约目前仍处于早期发展阶段,但我们发现它正在四个市场开始生根发芽,发挥自身在安全和可靠性方面的独特优势。

权益管理(通证)

通证合约的作用是创建、追踪和分配所有权。此类合约会在其通证中嵌入具体的功能,比如为通证持有者提供dApp服务/带宽(效用通证)、按权重在协议中投票(治理型通证)、分配公司股权(证券型通证)和实物资产或数字资产所有权(非同质化通证)等。举个例子,SIA通证可以用来支付Siacoin的去中心化云储存服务,而COMP通证则可以用来参与Compound协议的治理。

金融产品(DeFi)

去中心化金融(DeFi)应用使用智能合约再造传统金融产品和服务,其中包括货币市场、衍生品、稳定币、交易所以及资产管理等。智能合约可以托管用户资金,并根据结果分配给相应用户。举个例子,Set协议使用市场数据自动进行投资组合管理,Opium交易所基于实时资产价格交割期权合约。

游戏

区块链游戏使用智能合约防游戏中欺诈行为。其中一个例子就是PoolTogether,这是一个保本储蓄游戏,用户将存款放在一个彩票智能合约中,并连接到货币市场。存款在货币市场中积累利息,并基于随机数生成机制(RNG)将利息发放给中奖者。公布中奖者后,所有人都可以取回最初的本金。同样地,智能合约还能用RNG创建罕见的游戏物品,比如一次性的神奇宝剑。可以用Chainlink的可验证随机函数(VRF)生成随机数,使用户相信结果的随机性,用户还能独立对结果进行验证,确保结果没有受到游戏开发者或数据提供商的操纵。

保险

参数化保险是新型的保险模式,保险赔付直接与预先设定的具体事件挂钩。智能合约可以为参数化保险提供防篡改的基础架构,基于数据输入触发合约执行。举个例子,Etherisc正在开发一款航班保险智能合约,当收到航班状态信息时可自动赔付。终端用户不仅可以获得更大的保障,而且个人投资者还能通过智能合约参与到保险的供应端,将资金存放在合约资金池中。智能合约基于用户对资金池的贡献比例分配收益。

欢迎加入 Chainlink 开发者社区

了解更多内容请期待我们之后发布的文章。本科普系列中的下一篇文章将探讨智能合约的话题。欢迎关注我们的 Twitter 账号,收到文章更新通知。还可加入我们的电报群,了解 Chainlink 最新资讯。

查看原文

赞 2 收藏 2 评论 0

Chainlink 发布了文章 · 7月14日

区块链及其对世界的影响

区块链是整个加密货币生态圈的底层技术和最根本的价值主张。它是比特币的安全保障,也是以太坊智能合约的价值来源。本文是我们区块链技术科普系列的第一篇文章,旨在深入探讨区块链的概念、价值及其如何重塑现代社会的信任机制。

区块链是什么?它是如何运行的?

区块链是高度安全、可靠和去中心化的网络。人们可以在区块链的共享账本中储存数据、交换价值并记录交易行为,这个账本不由任何一个中心化实体控制,而是由全世界各地的计算机共同维护。

账本是指记录经济活动的实体或电子文档。账本可以记录个人账户余额,也可以记录整个经济体中的资金流动。如今,大多数账本都由银行等各种中心化实体掌控,这些实体将账本储存在自己的服务器和犹如黑匣子般的数据库中。

区块链是储存在去中心化计算机网络中的虚拟账本。网络中的每台计算机(即节点)都运行同样的软件,并维护、储存和验证同一账本的副本。公链使用其原生资产(即加密货币)为节点提供经济激励,鼓励节点积极沟通,最终就账本的有效性达成一致意见(即共识)。

用户提交交易,将价值从一个账户转移到另一个账户,以此对账本添加内容。用户的账户被称为公钥或公有地址(public address),每个公钥都有对应的私钥。公钥就像是电子邮箱地址,而私钥就像是密码,持公钥的人必须输入密码(注:这个密码也叫数字签名),才能从账户转账出去。

待执行的交易会被打包进“区块”中,然后网络中的每个节点都会对这些交易进行处理和验证。让所有节点都验证交易是为了确保帐本中的变更得到重复验证。公钥中必须存放足够的资金并且数字签名必须正确无误,交易才能顺利执行。

一旦区块被确认,就会附加在账本中。账本就是由一个个区块连接而成的,因此被命名为“区块链”。节点提供服务会获得交易费或新创建的加密货币作为奖励,这也称为区块奖励。

Centralized bank transactions vs. decentralized blockchain transactions
区块链和银行处理用户转账的机制有所不同

区块链有许多不同的设计模式,每种模式都有其优缺点。

  • 网络权限和参与:不同区块链网络的开放程度或限制门槛有所不同。其中公链是完全开放的,私有链是完全封闭的,而联盟链开放权限但限制参与。这三种是主要的区块链类型。o:p
  • 共识机制:区块链可以通过不同的方式对交易达成共识。最常见的共识机制包括工作量证明(比特币)、权益证明(Tezos)以及权威证明(大多数私有链)。
  • 功能设计:区块链目前无法做到十全十美,而是需要在功能上做出一定取舍。其中重要的功能包括安全性、可扩展性、去中心化、隐私保障和交易最终确认等。

区块链具有哪些价值?

区块链具有以下中心化账本所不具备的价值:

  • 安全性:如果区块链的去中心化水平达到一定高度,即使网络中存在恶意攻击,也几乎无法使不合法的交易通过验证。
  • 不可篡改性:一旦区块得到重复验证,就会成为不可篡改的账本的一部分,账本越大就越难篡改。
  • 可靠性:区块链是覆盖全球的分布式网络,全天24小时不间断运行。区块链永远在线,而且不受地域或政治因素限制。
  • 点对点:区块链没有中间方榨取交易价值,各方可以直接展开交易,无须担心任何对手方风险(注:对手方风险指合约对手方不履约的风险)。总的来说,区块链为交易各方创造了一个安全、可靠且防篡改的经济交易基础架构。传统交易模式依靠可信第三方来控制对手方风险,而区块链则依靠高确定性的开源软件严格执行指令来控制风险。区块链帮企业免除了对账负担、取消了不必要的中间方并降低了对手方风险,因此极大提升了企业效率。

区块链如何创造价值?

互联网是分享数据的平台,数据的应用方式更是多种多样,比如电子邮件、即时消息、电信和社交媒体等。区块链的价值交换功能也具有丰富的应用场景,并有潜力为终端用户创造独特的价值。

货币体系

比特币展示了公链如何通过独特的货币政策,建立自给自足的金融生态系统。比特币区块链的原生通证是BTC,内置货币发行机制和经济激励机制,网络无须中心化调控,可自主运行。比特币设置了货币供应量上限,且具有抗审查的属性,BTC的总量绝对不会超过2100万枚。由于BTC具有抗通胀的货币属性,因此很多人认为它比法币更能保值。

智能合约

以太坊展示了公链如何作为一台安全可靠的世界计算机处理智能合约。用户在这个场景中不追踪资金流向,而是向区块链发送一条指令,即“如果发生事件X则执行行动Y。”区块链随即执行这个指令(即智能合约),基于输入的数据输出结果(即转移价值)。以太坊可以同时处理几百万份智能合约。

资产通证化

有一些项目用区块链进行资产注册。开发者可以用智能合约创建独特的非同质化通证,通证代表了真实世界中的资产所有权,比如房产、汽车和收藏卡片等。区块链可以验证资产所有权的真实性,公开资产的生命周期并打破地域限制,盘活资产流动性。

中间件

Baseline协议用区块链(注:主要是在以太坊主网)作为中间件,企业之间可以同步各自数据库中的部分数据,但却无须将敏感数据放到区块链上。以太坊主网一直在线,可以随时接受审计,无法被篡改,而且无须许可即可进入。因此企业可以将其行为数据储存在区块链上,以此来告知对方目前的状态。数据储存在区块链上,会使用一种叫做“零知识证明”的隐私保障技术,只有协议中的各方才能读懂数据。这个证明是各方对业务流程状态的共同参考框架,比如买家和卖家之间约定的折扣条款。

永久记录

区块链上可以储存历史记录,而且记录无法被篡改。拥有高度可信的记录可以减少由于不同数据库之间的偏差而导致的冲突摩擦。区块链上的记录可以永久保存,这将有助于更好地追踪金融合约、储存医疗记录以及查看身份信息等。

具体应用场景

区块链可以用来实现具体的应用场景。举个例子,去中心化的节点网络可以实现分布式在线流媒体、不可篡改的网络游戏或文件储存。与BT下载一样,区块链也发挥了去中心化网络的优势,创造出了共享的公共事业。

欢迎加入 Chainlink 开发者社区

了解更多内容请期待我们之后发布的文章。本科普系列中的下一篇文章将探讨智能合约的话题。欢迎关注我们的Twitter账号,收到文章更新通知。还可加入我们的电报群,了解Chainlink最新资讯。

查看原文

赞 0 收藏 0 评论 0

Chainlink 发布了文章 · 6月2日

使用Chainlink预言机,十分钟开发一个DeFi项目

Chainlink价格参考数据合约是可以在智能合约网络中值得依赖的真实价格数据的链上参考点。这些合约由多个Chainlink节点定时更新,提供高精度,高频率,可定制化的DeFi价格参考数据,可以方便的为DeFi项目的开发提供开箱即用的稳定基础设施。本文我们会教你如何使用这些合约。除此之外,Chainlink还提供了通过获取链下数据的方式,从用户指定的API获取价格数据。我们下面就介绍一下这两种方式。

直接从API获取价格

首先我们先简单回顾一下,一般情况下我们如何使用Chainlink来获取真实世界中的价格数据。我们知道,价格是通过交易来产生的,所以最直接的方式是通过交易所提供的接口来获取某个交易所的某个加密货币的价格。但是这只是来自于一个交易所的数据,可能会有个体性的误差。有一些加密货币行情网站,他们会汇总多个交易所的数据,或者根据自己的指标来计算数据,得到一个偏离度比较小也就是更真实的数据。所以我们就采用从行情网站的接口获得数据,然后通过提交交易,将价格数据送到智能合约中。

我们选择的行情网站的cryptocompare,它提供了一些非常好用的API来提供各类交易市场上的信息。我们就以它文档上给出的一个API来作为例子:

https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD,JPY,EUR

访问这个接口,会返回一个JSON对象,提供当前时间,BTC分别相对于美元、日元、欧元的价格。

{
    "USD": 9460.99,
    "JPY": 1018295.17,
    "EUR": 8640.8
}

好的,下面我们就来编写合约来获取BTC的美元价格。

1 创建truffle项目

mkdir MyChainlinkedContract
cd MyChainlinkedContract
truffle init 

如果您还没有安装truffle suite, 可以通过npm install truffle -g来安装。

2 安装Chainlink开发库

npm install @chainlink/contracts --save

3 创建用户合约

您可以用您喜欢的编辑器工具,比如VS Code, 打开项目目录。目录结构如下:

.
├── contracts
│   └── Migrations.sol
├── migrations
│   └── 1_initial_migration.js
├── test
└── truffle-config.js

我们在contracts目录中新建一个合约文件MyContract.sol,在文件中新建一个合约,继承自ChainlinkClient合约,并设置构造函数,参数分别是:

  1. _link 所使用网络环境下的LINK token 地址
  2. _oracle 所使用的oracle合约地址。如果您不知道选择什么哪个oracle,可以前往Chainlink市场market.link上选择。
  3. _specId 即jobId,用于完成规范命令序列的任务ID,同样可在Chainlink市场market.link上对应的oracle下选择。
pragma solidity ^0.6.0;

import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol";

// MyContract 通过继承 Chainlinked 合约获得了创建Chainlink请求的功能
contract MyContract is ChainlinkClient {
  constructor(address _link, address _oracle, bytes32 _specId) public {
    setChainlinkToken(_link);
    setChainlinkOracle(_oracle);
    specId = _specId;
  }
  
    bytes32 internal specId;
}

接下来我们就可以编写创建Chainlink请求的代码

  function requestEthereumPrice(string memory _currency, uint256 _payment) public {
    requestEthereumPriceByCallback(_currency, _payment, address(this));
  }

  function requestEthereumPriceByCallback(string memory _currency, uint256 _payment, address _callback) public {
    Chainlink.Request memory req = buildChainlinkRequest(specId, _callback, this.fulfill.selector);
    req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD,EUR,JPY");
    string[] memory path = new string[](1);
    path[0] = _currency;
    req.addStringArray("path", path);
    sendChainlinkRequest(req, _payment);
  }

其中的主要语句就是通过buildChainlinkRequest 创建了一个Chainlink请求,该请求会发起一次LINK的转账到oracle地址,并附带请求数据。请求数据可以通过add的方法添加到请求中。请求数据可以包括:请求地址、解析路径、倍数等。

另外我们还需要定义一个回调函数来接收oracle获取到的结果,这个函数需要作为参数在构建Chainlink请求时传入到函数buildChainlinkRequest 中:

  event RequestFulfilled(
    bytes32 indexed requestId,  // User-defined ID
    bytes32 indexed price
  );

    function fulfill(bytes32 _requestId, bytes32 _price)
    public
    recordChainlinkFulfillment(_requestId)
  {
    emit RequestFulfilled(_requestId, _price);
    currentPrice = _price;
  }

这样其实一个最简单的Chainlink消费者合约就创建完成了,下面是一段完整的代码,当然你也可以在此之上添加一些其他函数,比如提取LINK、取消请求等等。

pragma solidity ^0.6.0;

import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol";

contract MyContract is ChainlinkClient {
  
  constructor(address _link, address _oracle, bytes32 _specId) public {
    setChainlinkToken(_link);
    setChainlinkOracle(_oracle);
    specId = _specId;
  }
  
  bytes32 internal specId;
  bytes32 public currentPrice;

  event RequestFulfilled(
    bytes32 indexed requestId,  // User-defined ID
    bytes32 indexed price
  );

  function requestEthereumPrice(string memory _currency, uint256 _payment) public {
    requestEthereumPriceByCallback(_currency, _payment, address(this));
  }

  function requestEthereumPriceByCallback(string memory _currency, uint256 _payment, address _callback) public {
    Chainlink.Request memory req = buildChainlinkRequest(specId, _callback, this.fulfill.selector);
    req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY");
    string[] memory path = new string[](1);
    path[0] = _currency;
    req.addStringArray("path", path);
    sendChainlinkRequest(req, _payment);
  }

  function fulfill(bytes32 _requestId, bytes32 _price)
    public
    recordChainlinkFulfillment(_requestId)
  {
    emit RequestFulfilled(_requestId, _price);
    currentPrice = _price;
  }

}

4 将用户合约部署到Ropsten测试网络上

我们配置好truffle的config文件中的Ropsten network字段和相关的provider,添加一个migration文件,通过下面的命令,将我们的用户合约部署到Ropsten测试网络上。

truffle migrate --network ropsten

5 向合约地址转入LINK

由于发起Chainlink请求需要向oracle支付LINK作为费用,所以我们的用户合约需要拥有LINK才能成功获取数据。所以我们需要向刚刚部署好的MyContract合约转入一部分LINK。每次请求的费用可以根据所选择的oracle要求的费用来支付。

6 编写测试脚本

接下来我们就可以调用合约来获取我们想要的数据了。我们可以使用truffle给我们提供的控制台,也可以自己编写脚本文件来测试。脚本文件的编写也非常简单,我们写一个请求的文件和一个读取的文件

request.js

const MyContract = artifacts.require('MyContract')

module.exports = async callback => {
  const mc = await MyContract.deployed()
  const tx = await mc.requestEthereumPrice('USD', '1000000000000000000')
  callback(tx.tx)
}

read.js

const MyContract = artifacts.require('MyContract')

module.exports = async callback => {
  const mc = await MyContract.deployed()
  const data = await mc.currentPrice.call()
  callback(console.log(parseInt(data)))
}

通过以下命令来调用请求脚本:

npx truffle exec scripts/request.js  --network ropsten

成功之后稍等一段时间,因为需要以太坊网络对交易的确认,然后再通过以下命令读取oracle获取到的数据。

npx truffle exec scripts/read.js  --network ropsten

顺利的话,控制台上会打出当前BTC的价格9352

这样,我们就以一个非常直接的方式,通过一个我们指定的API,完成了一个在合约中获取BTC价格数据的用例。

价格参考数据Reference Data

下面我们就来讲一下Chainlink价格参考数据合约应该怎么来使用

使用价格参考数据合约和上面的直接从链下获取的方式是有很打不同的,我们先来了解一下Chainlink的价格参考数据合约。

Chainlink的价格参考数据是专门为DeFi项目设计的预言机,网址是feeds.chain.link。Chainlink的价格参考数据预言机网络极大提升了以太坊上Dapp数据的安全性和可靠性,而且大大加速了新DeFi产品成功上线的速度。Chainlink在去中心化的预言机网络中提供价格参考数据,这是一个共享资源社区,并受到用户支持。用户使用这些预言机网络的成本要低于自己传输数据的成本,而且由于预言机网络是去中心化的,安全水平也会大幅提升。更多的信息可以参考这篇博文

简单来说,Chainlink价格参考数据提供的价格是在链上可以直接访问的,不需要通过我们指定API来手动获取。

1 新建项目

我们新建一个目录就叫RefereceData,然后用上面的的方式建立一个truffle项目:

mkdir RefereceData
cd RefereceData
truffle init
npm install @chainlink/contracts --save

2 新建用户合约文件

constracts目录下新建一个ReferenceConsumer.sol文件,文件中需要引入聚合接口合约AggregatorInterface:

import "@chainlink/contracts/src/v0.4/interfaces/AggregatorInterface.sol";

3 找到我们需要的参考数据合约地址

Chainlink文档中给我们提供了非常多交易对的参考合约地址,不仅有主网的地址,还有Ropsten、Rinkeby、Kovan测试网的合约地址。

我们就选择Ropsten网络下的BTC/USD交易对的合约,地址为0x882906a758207FeA9F21e0bb7d2f24E561bd0981

4 配置参考合约地址

在合约中通过构造函数或者编写setter方法,配置好我们想要的参考合约的地址

构造函数方式:

AggregatorInterface internal ref;

constructor(address _aggregator) public {
  ref = AggregatorInterface(_aggregator);
}

setter方式:

AggregatorInterface internal ref;

function setReferenceContract(address _aggregator)
  public
  onlyOwner()
{
  ref = AggregatorInterface(_aggregator);
}

5 使用参考合约获取价格数据

AggregatorInterface接口给我们提供了5个方法供我们使用分别是:

latestAnswer() 最新的聚合结果

latestTimestamp() 最新一次聚合的时间戳

latestRound() 最新一次聚合的轮次号

getAnswer(uint256 roundId) 通过轮次号获取历史结果

getTimestamp(uint256 roundId) 通过轮次号获取历史时间戳

返回的价格结果中,所有USD参考数据合约的结果值会乘以100000000,所有ETH参考数据合约的结果值会乘以1000000000000000000

6 完整示例

我们分别就对这个几个方法做个包装就可以然后就可以获取到BTC/USD的价格啦。下面的一段完整的代码,大家可以在这个基础上,加入一些其他的业务逻辑,就可以创建一个DeFi项目啦。

pragma solidity ^0.4.24;

import "@chainlink/contracts/src/v0.4/interfaces/AggregatorInterface.sol";

contract ReferenceConsumer {
  AggregatorInterface internal ref;

  constructor(address _aggregator) public {
    ref = AggregatorInterface(_aggregator);
  }

  function getLatestAnswer() public view returns (int256) {
    return ref.latestAnswer();
  }

  function getLatestTimestamp() public view returns (uint256) {
    return ref.latestTimestamp();
  }
  
  function getLatestRound() public view returns (uint256) {
    return ref.getLatestRound();
  }

  function getPreviousAnswer(uint256 _back) public view returns (int256) {
    uint256 latest = ref.latestRound();
    require(_back <= latest, "Not enough history");
    return ref.getAnswer(latest - _back);
  }

  function getPreviousTimestamp(uint256 _back) public view returns (uint256) {
    uint256 latest = ref.latestRound();
    require(_back <= latest, "Not enough history");
    return ref.getTimestamp(latest - _back);
  }
}

7 编写测试脚本调用合约

在Migrations目录下新建一个文件2_referenceconsumer_migration.js ,将我们上面查到的BTC/USD的参考合约地址在部署时传入构造函数中:

const ReferenceConsumer = artifacts.require("ReferenceConsumer");

module.exports = function(deployer) {
  deployer.deploy(ReferenceConsumer, "0x882906a758207FeA9F21e0bb7d2f24E561bd0981");
};

然后部署到Ropsten网络上。

在scripts目录下新建一个测试文件,比如叫getdata.js

const ReferenceConsumer = artifacts.require('ReferenceConsumer')

module.exports = async callback => {
  const rc = await ReferenceConsumer.deployed()
  const data = await rc.getLatestAnswer()
  callback(console.log(parseInt(data)))
}

通过以下命令执行该测试脚本:

npx truffle exec scripts/getdata.js  --network ropsten

一切顺利的话就会在控制台得到920089000000的结果,这就是当前BTC的价格,即9200.89

有了Chainlink的价格参考数据合约,DeFi的开发变得非常简单了,开发者只需要关注自己的金融方面的业务逻辑即可。https://feeds.chain.link网站...,他们都是开源的,我们也可以去他们的GitHub页面,去学习如何用Chainlink来设计一个DeFi项目。


欢迎加入 Chainlink 开发者社区

IMG_1763.JPG

查看原文

赞 0 收藏 0 评论 0

Chainlink 发布了文章 · 6月2日

智能合约中使用更安全的随机数(代码实战篇)

智能合约中使用更安全的随机数(代码实战篇)

Chainlink最近推出一款革命性的产品,VRF—Verifiable Random Function可验证随机数,给智能合约带来了真正安全的随机数。本文我们就来介绍一下如何在智能合约中使用VRF吧。

vrf001.jpeg

我们先简要介绍一下Chainlink VFR的工作流程。

  1. 首先,智能合约应用,也就是我们的Dapp,需要先发起一个获取随机数的请求,这个请求需要给定一个合约地址,这个合约称为VRFCoordinator合约。
  2. 与VRFCoordinator合约所关联的Chainlink链下节点,会(通过椭圆曲线数字签名算法)生成一个随机数,以及一个证明。
  3. Chainlink节点将上面生成的随机数和证明发送到VRFCoordinator合约中。
  4. VRFCoordinator合约收到随机数和证明后,会对通过证明来验证所生成随机数的合法性。
  5. 随机数验证成功后,会将随机数发送回用户的智能合约应用

整个过程中有两次的交易提交确认的过程,用户合约需要支付LINK给VRF合约作为交易费用。

下面我们就通过写一个猜数字的小游戏,来学习如何使用Chainlink VRF。

首先,新建一个truffle项目,安装Chainlink开发包

mkdir vrf; cd vrf
truffle init
npm install @chainlink/contracts --save

contracts目录下新建一个合约文件MyVrfContract.sol。引入vrf的库文件:

pragma solidity 0.6.2;

import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";

VRFConsumerBase是我们需要继承的基类,使用Chainlink VRF的很多方法都在这个合约里定义了,因此我们来简单介绍一下这个合约。

abstract contract VRFConsumerBase is VRFRequestIDBase {
    ...
    function fulfillRandomness(bytes32 requestId, uint256 randomness)
    external virtual;

    function requestRandomness(bytes32 _keyHash, uint256 _fee, uint256 _seed)
    public returns (bytes32 requestId)
  {
        ...
    }
    ...
}

上面列出了VRFConsumerBase合约的两个基本方法,一个是requestRandomness方法,它是用来发起一个VRF请求的方法,在调用的时候呢,需要传入三个参数:

  • _keyHash: 节点的公钥哈希。因为随机数及其证明的生成,是通过椭圆曲线密码学来完成的,所以需要一对公钥和私钥。公钥是节点公开的密钥,目前可用的VRF节点公钥及VRF节点的其他相关信息,可用在Chainlink官方文档上查到。
  • _fee: 用户发起一次VRF请求所需要花费的费用,这个费用也可以在节点公布的相关信息中查阅到。如果费用没有达到节点的最低要求,那么VRF请求无法完成。费用是以LINK token形式支付,所以用户合约需要持有足够的LINK token。
  • _seed: 用户提供的种子,用于生成随机数。用户需要给出高质量的种子。这里我们需要解释一下VRF的特点,VRF是通过种子与节点私钥做椭圆曲线中的计算得来的,同一个种子对应的随机数也是相同的,所以用户需要每次都给出不一样的且不可预测的种子。这很重要。因为任何可以左右用户种子的因素,都可以与链下的节点勾结作恶,生成他们想要的随机数,从而损害用户的利益。区块链中,我们很容易就找到这么一个随机源就是区块哈希,但是区块哈希是可以被矿工控制的(虽然很难),所以建议不能仅使用区块链哈希,还需要与其他随机源一起使用生成种子。比如下面就是一个例子。
function makeRequest(uint256 userProvidedSeed) 
    public returns (bytes32 requestId) 
{
    uint256 seed = uint256(keccak256(abi.encode(userProvidedSeed, blockhash(block.number)))); // Hash user seed and block hash
    return requestRandomness(keyHash, fee, seed);
}

VRFConsumerBase合约中的另外一个重要的方法是fulfillRandomness,这是一个虚函数,需要在继承的类中加以实现。这个函数的主要作用就是接受节点生成的随机数。用户合约在复写这个函数的时候就可以添加一些自己的业务逻辑代码。

另外,VRFConsumerBase合约中海油一个构造函数,需要调用者提供_vrfCoordinator合约的地址和所在网络中LINK token的地址。

constructor(address _vrfCoordinator, address _link) public {
    vrfCoordinator = _vrfCoordinator;
    LINK = LinkTokenInterface(_link);
 }

在我们的用户合约中,需要通过构造函数,来进行一些初始化的工作。初始化的内容包括向基类,也就是VRFConsumerBase类的构造函数进行赋值初始化,还包括初始化本合约所用到的一些常量参数。

constructor(address _vrfCoordinator, address _link)
    VRFConsumerBase(_vrfCoordinator, _link) public {
        // 其他一些初始化参数
}

下面就需要发起VRF请求来获取随机数,调用一下基类里的requestRandomness方法就可以。

bytes32 internal constant keyHash = 0xced103054e349b8dfb51352f0f8fa9b5d20dde3d06f9f43cb2b85bc64b238205;
uint256 internal constant fee = 10 ** 18;

function getRandomness(uint256 userProvidedSeed) 
    public returns (bytes32 requestId) {
        require(LINK.balanceOf(address(this)) > fee, "Not enough LINK - fill contract with faucet");
        uint256 seed = uint256(keccak256(abi.encode(userProvidedSeed, blockhash(block.number)))); // Hash user seed and blockhash
        bytes32 _requestId = requestRandomness(keyHash, fee, seed);
        return _requestId;
 } 

在这个请求函数中,我们把用户合约和区块哈希共同作为种子。keyHash和fee就作为常量直接写在合约里,也可以写到setter方法中或者构造函数中。

接下来就是复写接收方法。

uint256 public random;
function fulfillRandomness(bytes32 requestId, uint256 randomness) 
    external override {
    random = randomness.mod(100).add(1);
}

这里我们就直接赋值给我们的一个公开变量,方便我们查看结果。节点生成的随机数是一个非常大的一个数,我们需要对原始的随机数做一个模运算,以方面我们后面的处理。加一是为了避免得到0值。

下面我们贴一下完整的代码:

pragma solidity 0.6.2;

import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";

// import this if you are using remix
// import "https://raw.githubusercontent.com/smartcontractkit/chainlink/develop/evm-contracts/src/v0.6/VRFConsumerBase.sol";

contract MyVRFContract is VRFConsumerBase {
  constructor(address _vrfCoordinator, address _link)
    VRFConsumerBase(_vrfCoordinator, _link) public {
    }

    bytes32 internal constant keyHash = 0xced103054e349b8dfb51352f0f8fa9b5d20dde3d06f9f43cb2b85bc64b238205;
    uint256 internal constant fee = 10 ** 18;

    function getRandomness(uint256 userProvidedSeed) public returns (bytes32 requestId) {
        require(LINK.balanceOf(address(this)) > fee, "Not enough LINK - fill contract with faucet");
        uint256 seed = uint256(keccak256(abi.encode(userProvidedSeed, blockhash(block.number)))); 
        bytes32 _requestId = requestRandomness(keyHash, fee, seed);
        return _requestId;
    }

    uint256 public random;
    function fulfillRandomness(bytes32 requestId, uint256 randomness) external override {
        random = randomness.mod(100).add(1);
    }
}

好了,这样一个简单的用户合约写完了,我们就可以写根据之前的方法测试一下啦。由于步骤都是类似的,这里就不在赘述了。可以参考这里进行测试。

总结,虽然VRF内涵了非常复杂深奥的密码学知识,但是得益于Chainlink工程师们的良好设计,已经把复杂性极大程度的掩盖了,作为Dapp开发者,我们在使用起来非常的容易上手,只需要注意提供好种子就可以了。快来尝试一下吧!

参考文档:

https://blog.chain.link/verifiable-random-functions-vrf-random-number-generation-rng-feature/

https://docs.chain.link/docs/chainlink-vrf

https://docs.chain.link/docs/vrf-contracts

https://learnblockchain.cn/article/1056

https://www.trufflesuite.com/docs/truffle/quickstart


欢迎加入Chainlink开发者社区

查看原文

赞 0 收藏 0 评论 0

Chainlink 发布了文章 · 6月1日

Chainlink VRF 可验证随机函数详解

Chainlinkvrf.png

Chainlink可验证随机函数(下文称Chainlink VRF)的测试版本在不久前发布,开发者可以用这个工具生成随机数,并在链上进行验证。Chainlink VRF将为众多优秀的智能合约项目带来巨大价值,尤其能证明智能合约使用的随机数不可被篡改和操控。

我们想要感谢与我们紧密合作的学术界专家和开发者社区,不断向我们反馈他们对Chainlink VRF的想法和建议。与此同时,我们还要感谢为初步实现VRF功能付出了精力和汗水的团队成员!

Chainlink VRF有助于加速区块链游戏、安全和layer2协议等众多领域的智能合约开发进程。开发者可以轻松集成Chainlink VRF,参考我们近期发布的开发者文档,在智能合约中使用可验证的随机数。

可验证随机数具有哪些价值

要开发安全的智能合约,并规避合约资金被盗风险,开发者必须在安全方面下大功夫。如果随机数是智能合约依赖的关键数据,那么开发者就自然会期望合约所有相关方都拥有同等的不确定性,并降低因某一方成功预测结果而钻空子的风险。

Chainlink VRF可以为智能合约提供随机数以及加密证明,在链上验证随机数具有不可预测性,因而可以满足上述两个要求。由于Chainlink VRF的随机数可以在链上进行验证,所以问题节点只能选择不对请求做响应,在Chainlink即将上线的staking机制下,这样的行为会遭到罚款,之后还可能会被移除出随机数生成者名单,因此会遭受经济损失。

开发者可以使用Chainlink VRF开发出基于随机数的可靠智能合约应用:

● 为游戏提供随机数,数据可在链上验证,提升游戏的可信度,并向对安全比较敏感的用户提供额外的保障。

● 为游戏带来更多挑战性和不确定性,比如随机向玩家提供奖励(如:loot drops)。

● 随机分配任务和资源,并保障可验证性,如:向案子随机分配法官,或向公司随机分配审计人员。

● 选择观察员代表投票决议智能合约提案,并达成共识(调查是实现额外抗女巫攻击能力的有效方法)

现有方法存在的安全隐患

Chainlink VRF的可验证随机数可以将现有随机数生成法存在的诸多限制一一攻克。使用区块哈希值等链上数据或将链下生成的随机数传输至链上,这两种方法都存在一定自身缺陷。

开发者应该尽量避免过度依赖基于区块哈希值产生随机数。假设一个智能合约基于某一高度的区块哈希值最后一位数的奇偶性判定结果。这样看似好像概率是50/50,但假设有一名矿工(或矿工联盟)产量占区块总量的三分之一,现在这名矿工决定把区块哈希值最后一位数是1的优胜区块全部扔掉,并放弃大约2-3个以太币的区块奖励。这样一来,这名矿工就能够将结果是0的概率从50%提升至2/3,导致所有依赖这个方法生成随机数的智能合约用户都会遭受损失。如果这样做可以为这名矿工带来12-18个以太币的额外收益,那么他的选择在经济上是合理的。因此,这个机制下的合约价值会有一定上限。

为了避免这样的问题,开发者已经转向链下解决方案,在链下生成随机数并传回至链上。然而,如果无法通过加密手段验证链下随机数,数据将有可能在链下生成和传输过程中被篡改。同样地,用户只能闭着眼睛相信链下生成的随机数是公正可靠的,并相信这些数据在传输的过程中没有被篡改过。

区块链开发者在为智能合约提供随机数的过程中还需规避以下关键痛点和安全风险:

● 智能合约无法访问或无法兼容

● 中心化的随机数生成者操纵数据

● 区块链上的矿工作为用户进行操纵以谋取私利

● 终端用户需要盲目相信应用的安全可靠性

为了解决上述问题以及其他安全风险,Chainlink VRF使随机数生成过程变得安全透明,并通过加密技术证明了每个结果的公正和公平性。

Chainlink VRF的工作原理

Chainlink VRF工作原理

简而言之,智能合约会向Chainlink或Chainlink预言机网络提供一个seed来请求随机数。这个seed是预言机无法预测的,会被用来生成一个随机数。每个预言机都会使用自己专属的密钥生成随机数。当结果和证明在链上发布后,可以使用预言机的公钥和智能合约的seed进行验证。这个方法利用了区块链著名的签名验证功能,合约只能使用在同一区块链环境中被验证通过的随机数。

使用Chainlink VRF工具最大的好处就是随机数是可以验证的。即使某一节点被攻陷,该节点也无法操控或影响最终结果,因为它无法通过链上的加密验证。最糟糕的情况无非是沦陷的节点不对请求做出任何响应,而这将立刻被区块链记录下来,并且会被永远保存在链上。用户可以参考有效的证明,不再使用有过无法响应或无法提供有效签名记录的节点。即使节点被操控,最终生成的随机数也不会受影响。沦陷的节点只能选择不响应请求,而在Chainlink即将上线的staking机制下,这种行为将被罚款,而且问题节点之后会从随机数生成者名单中被移除。因此,低质量或违规的节点将遭受巨大的短期和长期经济损失。简而言之,Chainlink VRF只要正确接入,就绝对无法被操控,唯一可能发生的就是问题节点下线或不响应,之后被彻底移除出去。这个机制为智能合约开发者和用户提供了极大的安全保障。

Chainlink VRF还有一个优势,那就是随着使用人数不断增加,用户支付给节点操作者的费用也会相应上涨,因此节点会更有动力提供尽可能多的安全保障。之后,用户可能会要求通过staking的方式进行加密安全保障,付更多费用获得额外的安全性。这样一来,用户付费就会形成一个全球共享资源池,本来需要花钱自主开发RNG(注:随机数生成器)解决方案的用户会将这笔钱用于提升整个区块链生态圈共享资源的安全水平。Chainlink现已接入Polkadot、Tezos等多条区块链,这意味着Chainlink生态圈用户将形成网络效应,持续扩大,用户数量和加密安全水平也将形成一个相辅相成的良性循环。

集成案例详解:PoolTogether

PoolTogether是以太坊上的一个保本型储蓄彩票游戏,我们认为这是一个非常新颖有趣的概念。PoolTogether团队在开展了广泛技术调研后,决定使用Chainlink VRF为其应用提供可验证的随机数

PoolTogether是如何使用Chainlink可验证随机数的

PoolTogether是一个保本型储蓄游戏,将用户存款集中在一起,每天或每周进行一次抽奖,将存款利息当作奖金发放给中奖者。这个游戏通过彩票机制激励用户的储蓄行为。

PoolTogether使用Chainlink VRF生成可验证的随机数,可向其用户证明每期中奖者是由完全随机的数字选出来的。这样做除了为了保障自身安全以外,还可以向用户证明其关键环节的安全性是有迹可循的,且随机数生成过程是可以验证的。这样一来,用户就更有信心参与到智能合约中,相信他们享受着同样的中奖概率。

技术详解

Chainlink VRF是Goldberg可验证随机函数(VRF)的实现,具体细节请参考这篇论文。“可验证随机函数”中的“随机”指“任何没有seed或密钥的人都完全无法预测(即概率均匀分布)”。

VRF密钥是预言机以加密的方式在均匀分布的{0, …, #secp256k1-1} 中挑选出的一个数字(注:secp256k1是以太坊加密算法中的椭圆曲线)。与该密钥相对的有一个公钥,这个公钥对应着一个预言机。预言机将公钥与链上VRF和Chainlink任务ID绑定。

当智能合约请求随机数时,它会提供一个seed。为了确保VRF结果无法被预测,需要在seed中植入无法被预测且难以被篡改的值,比如最近一次的区块哈希值,或者是经过加密验证的链下数据,比如某项资产最近更新的价格。你可以将这些数据转换成bytes32,使用keccak256算法生成seed。链上VRF将智能合约seed与其他数据混合在一起,以避免重放攻击,为合约提供一些基本的保护,但除此之外,提供一些专门的保护也是至关重要的。

一旦链上VRF确定了seed,就会在以太坊log中进行广播,向智能合约要求的预言机请求相应VRF结果。预言机看到这条log后会做出如下操作:

首先,它将seed和预言机公钥作为数据输入, “对输入取哈希值作为曲线方程输入”,从secp256k1获得安全加密的随机样本。方法是使用keccak256算法,用递归法对数据取哈希值,直到输出小于secp256k1算法的basefield(即secp2561算法中描述的p值),并且是secp256k1曲线上某一点(x,y)的x坐标(basefield中 y2=x3+7 )。因此(x,y)是对输入取哈希得出的结果。

接着,将secp256k1曲线 的(x,y)坐标乘以密钥,得出Ɣ点。用keccak256算法取Ɣ哈希值,以uint256格式作为VRF的输出结果。它会生成一个证明,证明Ɣ除以(x,y)的倍数等于预言机公钥除以secp256k1生成器的倍数。这个证明方式与Schnorr签名很接近:首先,他从{0, …, #secp256k1-1}中随机安全地取出一个nonce,这与私钥生成的方式很像。然后,计算公式u=n×g,其中g为secp256k1生成器,u为以太坊地址。然后计算公式v=n×(x,y)。接着,将(x,y)、VRF公钥、Ɣ、u的地址以及v合并取哈希, 并将哈希取模运算#secp256k1的余数称为c。最后,计算s=n-c×k 取模运算 #secp256k1,k为VRF密钥。因此证明包含公钥、Ɣ、c、s以及seed。然后将结果发回至链上VRF,验证证明,如果验证通过,则将数据返回至智能合约。

为了验证证明,合约应做到以下几点:

  • 检查公钥和Ɣ是否是secp256k1曲线上有效的点
  • 验证c×pk+s×g点的地址是否与u的地址一致(注:其中pk指代预言机公钥)
  • 用公钥和seed取哈希作为曲线方程的输入,检查 c×Ɣ+s×(x,y)的keccak256哈希值是否等于c。

若有兴趣直观了解此方案的加密安全逻辑,请参考Jimmy Song的《Programming Bitcoin》一书中第三章“签名和验证”中关于“箭头”的类比。我们在此希望实现的特殊“目标”是c。若想完整了解此方案的安全证明机制,请参考Making NSEC5 Practical for DNSSEC的附件B。

然而,用secp256k1做纯量乘法(比如c×Ɣ),在以太坊虚拟机上直接运算的成本极其高昂。因此为了提高效率,我们借鉴了Vitalik的方法将一个证人传入证明,验证证人的c×Ɣ运算结果是否与实际相等。这样一来,我们就能把c×Ɣ的运算工作转移到链下,只需验证链下运算结果是否与实际相等即可,这样就可以大幅降低运算成本。

因此,除了上述数据输入和步骤之外,链上验证还包括c×Ɣ以及s×(x,y)的证人。需要检查这些证人是否是secp256k1曲线上有效的点,并且用Vitalik的方法验证这些证人的运算结果是否与实际匹配。另外,以太坊上的地址用u表示,同样也用Vitalik的方法验证u是否与c×pk+s×g点匹配。

Chainlink VRF发展计划

Chainlink预言机网络中包含一千多个优质节点,使用门限签名技术,网络具有高度扩展性,并以高成本效益的方式实现去中心化。这将为Chainlink VRF带来极高的去中心化水平和可用性。我们将两者合二为一,既利用Chainlink VRF的独特优势为链上提供可验证随机数,又利用Chainlink网络中几千个节点实现高成本效益和高可用性。
Chainlink以去中心化的方式实现可验证随机函数

Chainlink丰富的生态系统一旦加入Chainlink VRF,我们就能建立遍布全球的分布式节点网络,在经济激励的驱动下在链上生成并广播可验证的随机数。Chainlink门限签名技术与高度去中心化的节点网络相结合,将有效规避用户资金被盗风险。不仅Chainlink VRF端反馈的数据能在链上得到验证,还能保证极高的可用性。目前Chainlink已接入多条可能需要可验证随机数的区块链,再加上虚拟货币经济的激励机制,Chainlink VRF很有可能成为智能合约使用随机数的新标准。

除了上述优势之外,我们目前正在完善Chainlink VRF的功能,研发去中心化的随机数生成技术,并积极与其他RNG(注:随机数生成器)系统开展合作。根据我们的初步研究,我们相信Chainlink VRF能与VDF以及其他随机数生成法在链上和链下结合使用。我们很高兴能够跟区块链圈和学术圈通力合作,共同推动智能合约可验证随机数生成技术向前发展。

欢迎试用Chainlink VRF并给出你的宝贵意见

如果你是一名智能合约开发者,并希望了解如何使用Chainlink VRF的初始版本,请访问开发者文档,在测试网上开始使用,并加入我们的技术社区讨论。

我们目前处于Chainlink VRF安全评估的最后阶段,并希望与开发者社区和学术界的用户交流反馈。如果你对VRF及其完善方案有任何意见或建议,欢迎发邮件至china@smartcontract.com告诉我们。

如果你热衷于开发安全可靠的智能合约并解决现实世界的问题,欢迎现在就加入我们的核心团队!详情请关注我们官网的招聘页面。

如果想要了解更多关于Chainlink的资讯,请访问Chainlink官网,或在微博或微信上关注我们。

欢迎加入Chainlink开发者社区

IMG_2456.JPG
(添加时请备注开发者或其他信息哦)

查看原文

赞 0 收藏 0 评论 0

认证与成就

  • 获得 3 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 2 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2019-10-10
个人主页被 214 人浏览