深度学习
Oraclize是一种服务,旨在使智能合约可以访问来自其他区块链或者万维网的数据。该服务目前在比特币以及以太坊测试网和主网上可用。Oraclize的特殊之处是你不需要信任它,因为它可以为所提供给智能合约的全部数据做真实性证明。
在本章中,我们将学习如何在以太坊智能合约中使用Oraclize服务从万维网中抓取数据。
7.1.1 Oraclize的工作原理
下面来看以太坊智能合约使用Oraclize从其他区块链和万维网中抓取数据的过程。
为了抓取外部数据,以太坊智能合约需要发送一个查询给Oraclize,指定数据源(表示从哪里抓取数据)和数据源的参数(表示抓取什么数据)。
向Oraclize发送一个查询,意味着发送一个合约调用(即内部交易)给以太坊区块链中出现的Oraclize合约。
Oraclize服务端不断寻找新传入智能合约的查询。当它发现一个新的查询时,就抓取结果,并调用合约的_callback方法将结果返回。
7.1.2 数据源
Oraclize允许智能合约抓取数据的源列表如下:
·URL。URL数据源允许用户发送HTTP GET或者POST请求,即万维网中抓取数据。
·WolframAlpha。WolframAlpha数据源允许用户向WolframAlpha知识引擎提交查询,并得到答案。
·blockchain。blockchain数据源允许用户访问其他区块链的数据。可以提交给blockchain 数据源的查询包括bitcoin blockchain height、litecoinhashrate、bitcoin difficulty、1NPFRDJuEdyqEn2nmLNaWMfojNksFjbL4S balance等。
·IPFS。IPFS数据源允许用户抓取IPFS中存储的文件。
·nested。nested数据源是一个元数据源,它不提供访问其他服务的权限。它用来提供简单相加逻辑,允许单个查询在任何可用数据源的基础上进行子查询,并产生一个单独字符串作为结果,例如:
·computation。computation数据源允许特定应用的可审计执行进入安全的链下状,也就是说,它允 许抓取应用的链下执行结果。在退出前,该应用必须在最后一行打印查询结果(在标准输出栏)。执行环境用Dockerfile描述,创建和运行该文件会立即 启动主应用。Dockerfile初始化和应用执行应当尽快结束:在AWS t2.micro实例中最长执行时间为5min。这里考虑AWS t2.micro实例,因为Oraclize用它执行该应用。由于数据源输入是包含此类文件的ZIP文档包的IPFS多个哈希(Dockerfile和任 何外部文件依赖,且Dockerfile必须位于档案的根目录里),用户应当事前小心地准备这个档案,并推送给IPFS。
在写本书时,已经有这些数据源,但是未来还可能有更多数据源。
7.1.3 真实性证明
尽管Oraclize是可信服务,用户可能还想检查一下Oraclize返回的数据是否真实,也就是说,检查它在传输过程中是否受到Oraclize或者其他人的操控。
Oraclize提供的TLSNotary proof的来源是可选的,包括URL、区块链以及nested和computation数据源。该proof对WolframAlpha和IPFS数据 源不可用。目前,Oraclize仅支持TLSNotary proof,但是未来可能支持一些其他验证方式。目前,TLSNotary proof需要手动验证,但是Oraclize已经应用于链上proof验证,也就是说,智能合约代码可以自己验证TLSNotary proof同时从Oraclize接收数据,如果proof结果是非法的,就丢弃该数据。
这个工具(https://github.com/Oraclize/proof-verification-tool )是Oraclize提供的开源工具,以验证TLSNotary proof。
使用Oraclize或者验证proof不需要理解TLSNotary的工作原理。验证TLSNotary proof的工具是开源的,因此,如果它包含任何恶意代码,就会很容易捕获,故可以信任这个工具。
下面概括一下TLSNotary的工作原理。为了理解TLSNotary的工作原理,首先需要理解TLS的工作原理。 TLS协议提供一个让客户端和服务端创建加密session的方式,这样其他任何人都不能读取或操纵客户端和服务端之间的传输内容。服务端首先发送证书 (证书由受信任的CA颁发给域名所有者)给客户端。证书包含服务端公钥。使用CA的公钥解码证书,这样可以验证该证书确实是由CA颁发的,并得到服务端的 公钥。然后,客户端生成一个对称密钥和一个MAC密钥,并使用服务端公钥加密它们,发送到服务端。只有拥有私钥的服务端才能够解码这条信息。现在客户端和 服务端共享同样的对称密钥和MAC密钥,由于其他人都不知道密钥,他们可以开始彼此发送和接收数据。在对称密钥和MAC密钥一起被用于生成加密信息的签名 的地方,对称密钥用于加密和解密数据,这样一旦攻击者修改信息,另一方就可以知道。
TLSNotary是TLS的改进,Oraclize用它提供密码学proof,以表示它们提供给智能合约的数据就是数据源在特定时间提供给Oraclize的数据。事实上,TLSNotary协议是开源技术,由PageSigner项目开发使用。
TLSNotary在三方(服务端、审计方和被审计方)之间分解对称加密密钥和MAC密钥。TLSNotary的基本思想是被审计方可以向审计方证明某一个给定结果是由服务端在某个给定时间返回的。
TLSNotary实现上述功能的过程为:审计方计算对称密钥和MAC密钥,并且只向被审计方提供对称密钥。被审计方 不需要MAC密钥,因为MAC签名检测确保来自服务端的TLS数据在传输过程中不被篡改。有了对称密钥,被审计方可以解码来自服务端的数据。因为银行使用 MAC密钥“签署”所有信息,而且只有服务端和审计方知道MAC密钥,因此正确的MAC签名可以被当作特定信息来自银行且未经被审计方篡改的证明。
在Oraclize服务情况下,Oraclize是被审计方,而审计方是一个特别设计的开源Amazon机器图像锁定的AWS实例。
它们提供的证明数据是一个正常TLSNotaryproof确实已发生的AWS实例的已签名证明。它们还提供一些涉及AWS实例中软件运行的其他证明,即自初始化之后它是否被修改过。
7.1.4 定价
来自任意以太坊地址的第一个Oraclize查询调用都是完全免费的。Oraclize调用在测试网中都是免费的!这只适合在测试环境进行适度使用。
从第二个调用起,要进行查询就必须支付以太币了。在发送查询到Oraclize(即进行内部交易调用)时,会扣除一定费用(从调用合约向Oraclize合约转账以太币)。扣除的以太币数量取决于数据源和证明类型。
表7-1显示了发送查询时扣除的以太币数量。
所以如果正在发出HTTP请求,而且想要有TLSNotary proof,则调用合约必须有价值$0.05的以太币;否则,就返回异常。
7.1.5 开始使用Oraclize API
为了让合约使用Oraclize服务,它需要继承usingOraclize合约。用户可以在https://github.com/Oraclize/Ethereum-api 找到该合约。
usingOraclize合约可以代替OraclizeI和OraclizeAddrResolverI合约。事实 上,usingOraclize使得OraclizeI和OraclizeAddrResolverI合约的调用变得方便,也就是说,它提供了更简单的 API。也可以直接调用OraclizeI和OraclizeAddrResolverI合约。读者可以学习这些合约的源代码以发现所有可用API,本书 中,我们只学习最必需的那些。
下面来看设定proof类型、设定proof存储位置、进行查询、获取查询费用等的方法。
1.设置证明类型和存储位置
无论是否需要来自TLSNotary的proof,必须在发出查询之前指定proof类型和proof存储位置。
如果不需要proof,就把下面的代码放入合约:
如果需要proof,就把下面的代码放入合约:
目前,proofStorage_IPFS是唯一可用的proof存储位置,也就是说,TLSNotary proof只存储在IPFS中。
每次只能执行这些方法中的任意一个,例如在constructor中或者在其他任何时间(比如只需要某些特定查询的proof)。
2.发送查询
为了向Oraclize发送一个查询,需要调用oraclize_query函数。这个函数至少需要两个实参,即数据源和给定数据源的输入值。数据源实参不区分大小写。
oraclize_query函数的一些基础示例如下:
上述代码的执行过程如下:
·如果第一个实参是字符串,就假定它是数据源,第二个实参就假定为数据源的输入条件。在第一个调用中,数据源是WolframAlpha,我们向它发送的查询是0和100之间的随机数。
·在第二个调用中,向第二个实参中所示的URL发出HTTP GET请求。
·在第三个调用中,从IPFS获取QmdEJwJG1T9rzHvBD8i69HHuJaRgXRKEQCP7Bh1BVttZbU文件的内容。
·如果数据源之后的两个连续实参是字符串,就假定它是POST请求。在最后一个调用中,发出HTTP POST请求到https://xyz.io/makePayment 进行支付。POST请求内容是第三个实参中的字符串。Oraclize十分智能,能够检测基于字符串格式的content-type标头。
3.预约查询
如果想让Oraclize在未来某一预订时间执行查询,就指定从当前时间算起的延迟(以秒计算)作为第一个实参。示例如下:
Oraclize将在看到上述查询60s之后进行查询。所以,如果第一个实参是数字,就假定我们在预约查询。
4.自定义gas
就像其他任何交易一样,从Oraclize到_callback函数的交易要花费gas,即需要向Oraclize支 付gas费用。Oraclize_query进行查询收取的以太币还用于在调用_callback函数时提供gas。调用_callback函数 时,Oraclize默认提供200000个gas。
这个返回的gas费用实际上受用户控制,因为用户编写的_callback等方法中的代码可以预估费用。所以当用 Oraclize进行查询时,还可以在_callback交易上指定gasLimit应当是多少。但需要注意的是,因为是由Oraclize发送交易,所 以没有花费的gas将被返还给Oraclize,而非用户。
如果200000 gas(默认值,也是最小值)不够,可以指定一个更大的gasLimit,代码如下:
可以看到,如果最后一个实参是数字,就假定它是自定义的gas。在程序代码中,Oraclize将对回调函数交易使用 一个500000的gas上限,而非200000。因为我们让Oraclize提供gas,所以Oraclize在调用oraclize_query时将 扣除更多以太币(根据需要多少gas)。
注意:如果给出的gasLimit过小,且_callback方法很长,那么可能永远看不到回调函数。还应注意,自定义的gas一定要大于200000。
5.回调函数(callback function)
一旦结果准备好了,Oraclize将把交易发送回合约地址,并调用如下三个方法中的一个:
·对于每个查询来说,_callback(bytes32 myid,string result)“.”Myid都是一个独特的ID。这个ID由oraclize_query方法返回。如果合约里有多个oraclize_query调用,则将这用于匹配该结果的查询。
·如果需要TLSNortary的proof,则结果为_callback(bytes32 myid,string result,bytes proof)。
·如果没有其他方法,回退函数是function()。
下面是_callback函数的一个例子:
6.解析助手
HTTP请求返回的结果可以是HTML、JSON、XML或二进制等格式。在Solidity中,解析结果是很困难的,且代价很高。Oraclize提供了解析助手,在服务端上处理解析,最终得到的结果就是用户需要的那部分。
为了让Oraclize解析结果,用户需要把URL和下面某一个解析助手(Parsing helpers)“打包”:
·xml(..)和json(..)助手让Oraclize只返回部分JSON或者用XML解析的返回值,例如:
·为了得到全部返回值,使用带有api.kraken.com/0/public/Ticker?pair=ETHUSD URL实参的URL数据源。
·如果只想要最终价字段,需要使用JSON解析调用json(api.kraken.com/0/public/Ticker?pair=ETHUSD).result.XETHZUSD.c.0。
·html(..).xpath(..)助手用于HTML scraping,仅需指定想用作xpath(..)实参的XPATH,例如:
·为了抓取一个特定tweet的文本,使用html(https://twitter.com/oraclizeit/status/671316655893561344 ).xpath(//*[contains(@class,'tweettext')]/text())。
·binary(..)助手用于获得诸如证书文件的二进制文件,例如证书文件:
·为了抓取二进制文件的一部分,可以使用slice(offset,length)。其中第一个参数是位移,第二个参数是所需的slice长度(二者都用字节表示)。
·示例:从一个二进制CRL中只抓取开头300个字节,用binary(https://www.sk.ee/crls/esteid/esteid2015.crl ).slice(0,300)。二进制助手必须和slice选项同时使用,且只接受二进制文件(不接受编译文件)。
如果服务端不响应或连接不上,用户将收到一个空回应。可以在http://app.Oraclize.it/home/test_query 测试查询。
7.获取查询价格
如果在实际查询之前想知道查询需要多少费用,可以使用Oraclize.getPrice()函数获取所需的wei的数量。第一个实参是数据源,第二个实参是可选项,即自定义gas。
一个常见的使用示例是,当以太币余额不足以进行查询时,通知客户端向合约添加以太币。
7.1.6 加密查询
有时,用户可能不想暴露数据源和/或数据源的输入。例如,可能不想暴露URL中的API(如果有)。Oraclize提供了一种在智能合约中存储加密查询的方式,只有Oraclize的服务端才能解码。
Oraclize提供一个Python工具(https://github.com/Oraclize/encrypted-queries ),可以用于加密数据源和/或数据源的输入。它生成一个非确定性的加密字符串。
用于加密任意文本字符串的CLI命令如下:
其中长长的十六进制字符串是Oraclize服务端的公钥。现在用户可以使用前面命令的输出代替数据源和/或数据源的输入。
为了防止误用加密的查询(即重播攻击),第一个用一个特定加密查询Oraclize的合约成为合法的所有者。任何重复使用完全相同的字符串的合约将不被允许使用它,并且将接收一个空的结果。因此,切记在使用加密查询重新部署合约时,总是要生成新的加密字符串。
解码数据源
还有一个称为decrypt的数据源,它用于解码加密的字符串。但是这个数据源不返回任何结果,否则任何人就都有能力解码数据源和数据源的输入了。
它是专门应用于嵌套数据源的,用于对部分查询进行加密。这是它唯一的使用例子。
7.1.7 Oraclize Web IDE
Oraclize提供了一个Web IDE,使用它就可以编写、编译和测试以Oraclize为基础的应用(参见http://DApp.Oraclize.it/browser-Solidity/ )。
如果访问该链接,将注意到它和Browser Solidity看起来一模一样,它实际上就是Browser Solidity添加的一个额外功能。为了理解这个功能是什么,我们需要更深入地理解Browser Solidity。
Browser Solidity不仅允许用户为合约编写、编译和生成web3.js代码,还允许测试合约。到目前为止,为了测试合约,我们设置一个以太坊节点并向它发送 交易。但是Browser Solidity可以不用连接至任何节点就执行合约,所有操作都在内存中进行。之所以能够这样,是因为使用了ethereumjs-vm(EVM的一种 JavaScript实现)。用户可以使用ethereumjs-vm创建自己的EVM和运行字节码,也可以通过提供目标URL来配置Browser Solidity,以使用以太坊节点。UI的信息量很大,用户可以自己尝试一遍。
Oraclize Web IDE的特殊之处在于,它在in-memory执行环境下部署Oraclize合约,这样就不需要连接到测试网或者主网节点,但是使用Browser Solidity时必须连接到测试网或者主网节点,以测试Oraclize API。
如需更多关于Oraclize的资源,请访问https://dev.Oraclize.it/ 。
来源:我是码农,转载请保留出处和链接!
本文链接:http://www.54manong.com/?id=549
微信号:qq444848023 QQ号:444848023
加入【我是码农】QQ群:864689844(加群验证:我是码农)
全站首页 | 数据结构 | 区块链| 大数据 | 机器学习 | 物联网和云计算 | 面试笔试
var cnzz_protocol = (("https:" == document.location.protocol) ? "https://" : "http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1276413723'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s23.cnzz.com/z_stat.php%3Fid%3D1276413723%26show%3Dpic1' type='text/javascript'%3E%3C/script%3E"));本站资源大部分来自互联网,版权归原作者所有!
评论专区