本文主要讲解外部预言机ORACLE定义和原理,并讲解蚂蚁BAAS系统如何通过ORACLE预言机方式使用外部数据源的方法。
2018年11 月 6 日,中国人民银行发布的《区块链能做什么?不能做什么?》报告中,是这样对预言机定义的。
区块链外信息写入区块链内的机制,一般被称为预言机 (oracle mechanism) 。
预言机的功能就是将外界信息写入到区块链内,完成区块链与现实世界的数据互通。它允许确定的智能合约对不确定的外部世界作出反应,是智能合约与外部进行数据交互的唯一途径,也是区块链与现实世界进行数据交互的接口。
听上去很难理解,我们举例来说。
大家会很形象的把公链比作操作系统(Windows、IOS、安卓),DAPP 类比的话就是 APP,那么预言机可以形象的比做 API 接口。API 是一组定义、程序及协议的集合,通过 API 接口实现计算机软件之间的相互通信。这样类比虽然不准确,但意思就是预言机是区块链和现实世界之间的纽带,可以实现数据互通的工具。
Oracle 为什么被中译为预言机?
跟别人提起预言机,很多人的反应都是预测市场,预言机这个名字确实容易想到预测。
Oracle 最初是来源于古希腊宗教,意为“神谕、先知、预言”。而在互联网领域,预言机(英语:oracle machine),又称谕示机,是一种抽象电脑,用来研究决定型问题。可以被视为一个多了个黑盒子(预言者)的图灵机,这个黑盒子的功能是可以在单一运算之内解答特定问题。
也许你会好奇这跟甲骨文公司有什么关系吗?其实没有关系。
Oracle 在中国叫甲骨文公司的原因可能是另一个故事。在中国商朝晚期,王室把在动物骨骼或龟甲上做占卜记事的文字叫甲骨文,甲骨文被英译为 Oracle bone script,后来 Oracle 公司到中国中译为了甲骨文公司。(很有道理的猜测 哈哈哈?)
区块链是一个确定性的、封闭的系统环境,目前区块链只能获取到链内的数据,而不能获取到链外真实世界的数据,区块链与现实世界是割裂的。
一般智能合约的执行需要触发条件,当智能合约的触发条件是外部信息时(链外),就必须需要预言机来提供数据服务,通过预言机将现实世界的数据输入到区块链上,因为智能合约不支持对外请求。
具体原因是这样的。区块链是确定性的环境,它不允许不确定的事情或因素,智能合约不管何时何地运行都必须是一致的结果,所以虚拟机(VM)不能让智能合约有 network call(网络调用),不然结果就是不确定的。
也就是说智能合约不能进行 I/O(Input/Output,即输入/输出),所以它是无法主动获取外部数据的,只能通过预言机将数据给到智能合约。
我们通过一个例子来说明一下。假设现在我被关进了一个小黑屋里(不要多想,只是例子 =-=),我对外面的世界发生了什么几乎一无所知,不知道外面是否有人,即使呼叫也没有人回应,只有外面的人在门口把他看到的听到的都告诉我,我才可以得知外面的世界。
例子虽然不太恰当,但智能合约就像这个例子中的我一样,它无论何时何地,都无法主动向外寻求信息,只能外部把消息或数据给到里面。而预言机就是这个在外面输送消息和数据的人。
好像这么看来,智能合约并不是很智能呀,是的,智能合约其实是完成的不智能的事情,即写好了条件和结果,当给它条件的时候,就可以触发,但也不会马上执行,还需要合约相关的人进行私钥签署才可以执行。
所以,网上很多文章其实都有水分,比如智能合约某个时间或者触发某个条件就可以自动执行之类的,只能说这样的句子在逻辑上是有问题的。关于预言机的很多文章也有水分,描述的并不准确。
好了,上面就是区块链为什么需要预言机,因为智能合约无法主动去获取链外的数据,只能被动接受数据。
这就是理想中预言机的工作流程,即用户的智能合约把请求给链上 Oracle 合约,通过链下的 API 接口获得外部数据,更确切的说是外部把数据给链上的 Oracle 合约,然后 Oracle 合约再把数据给用户的智能合约。
或许很难理解,因为在互联网中,调用数据是非常容易的,只需要在程序中写调用的代码就可以了。但是区块链与外部世界的数据交互,确实不能进行这样的操作。
预言机作为区块链与现实世界进行数据交互的桥梁,应用场景非常多,可以说一切需要与链下进行数据交互的DApp都需要预言机。比如金融衍生品交易平台、借贷平台、快递追踪/IoT、稳定币、博彩游戏、保险、预测市场等等。
我们还是举例来说。
**先说最近币圈比较火热的博彩游戏为什么需要预言机。**博彩游戏的核心是不可预测、可验证的随机数,从而决定赌注的最终结果,但是在链上是无法生成随机数的或者说在链上的随机数是可以被预测和破解的,这时候就需要预言机从外部给智能合约安全的、不可预测的随机数。
现在的大多数博彩游戏都是在链上生成随机数,所以很容易被预测和破解,导致资产被盗,大家有兴趣的可以去看一下DApp被盗的相关研究报告,很多因为随机数问题被盗的。比如 BetDice、Dice2Win。
如果大家很感兴趣,可以看一下我男神 DOS Network 创始人@nrek jonny 关于《智能合约中的随机数》的分享。
其实,早在 Fomo3D 这个游戏出来之前,以太坊的 Team Leader 就在推特上说过链上是无法生成随机数的。Dear devs… you can`t generate random numbers on chain!
我们再来看一个关于快递追踪的例子。
假设当我通过某个 DApp 购物平台购买某件物品快递过来的时候,真实世界中的快递寄送或到达信息,就可以通过 Oracle 把数据传递到链上,然后触发链上的智能合约,我用自己的私钥确认收到了快递,并完成付款。
大家发现了吗?这里的智能合约不能自动执行,而是需要我用自己的私钥进行确认,智能合约保证的是没有第三方机构做担保和资金周转(比如支付宝),这就是智能合约的价值。
其他的案例就不细说了,比如稳定币需要链下的利率,保险需要链下的病例或车况等,具体可以看这篇文章《Oracle—区块链与现实世界的纽带》。
目前在预言机领域探索的项目还不是很多,每一个项目的预言机解决方案都略有差异,我找了几家典型的预言机项目,做一个简单的阐述。
Oraclize 依托亚马逊 AWS 服务和 TLSNotary 技术,是一个可证明的诚实的预言机服务,不过它是中心化的,目前只能在以太坊网络使用,而且gas费较高。但是不妨碍它是目前很受欢迎的预言机服务,也可能是因为还没有更好的选择吧。这里有 Oraclize 详细的使用说明:Oraclize Documentation
ChainLink 的解决方案是通过在链上的智能合约和链下的数据节点,通过奖惩机制和聚合模型的方式,进行数据的请求和馈送。不过也有一些不足,比如链式聚合成本较高,拓展性差,基于声誉系统容易集中化。他们更关注支付场景的应用,比如帮助银行与企业之间建立智能合约。
欧链很早就提出了预言机的想法和方案,采用自主的 PoRD 机制(Proof-of-Reputation&Deposit),本质上是一种抵押代币奖惩机制的声誉系统,奖励数据节点惩罚作恶节点,可以实现 Augur、Gnosis 等预测市场应用的功能,还能支撑对链外数据有更高频率访问需求的智能合约业务。预测市场的结果本身有时也可以作为 Oracle 的输入数据源,欧链更像是预测市场,而且不足是单纯的声誉系统容易集中化。目前欧链只在 EOS 上开发。
DOS Network 是一个 Layer-2 的预言机解决方案,它通过在链上部署一个轻量级智能合约,链下是一个 p2p 网络,服务节点的选取和数据验证采用 VRF+阈值签名等技术,保证了去中心化和数据安全,并达到快速反应。可以适配所有主流公链,比如以太坊、EOS、Tron、Thunder。目前已在以太坊测试网发布 alpha 版本 https://dosnetwork.github.io/docs。
我们也期待预言机技术的不断成熟,进而促进更多区块链与现实世界进行数据交互的 DApp 落地。
区块链预言机(Oracle)是区块链与外部世界交互的一种实现机制,它通过可信计算技术或者其他建立信任的约束关系,在区块链与外部世界间建立一种可信任的桥接机制,使得外部数据可以安全可靠地进入区块链。
外部数据源服务是基于可信执行环境(Trusted Execution Environment,TEE)技术实现的区块链预言机服务,该服务旨在为区块链智能合约提供可信访问外部数据源能力。
外部数据源服务会在智能合约平台部署一个外部数据源服务合约,用户合约通过调用该服务合约发送外部数据源请求,链下的 TEE 外部数据源服务对接该服务合约,监听用户的请求,然后去对应的外部数据源取数据,最后将结果返回给用户合约。
外部数据源服务使用 TEE 技术实现,对于每笔外部数据请求都将在可信硬件环境中执行。可信硬件环境会验证外部数据源的 TLS 通讯证书以确认数据源的身份,通过 TLS 协议确保拿到的数据没有被第三方篡改。可信硬件环境得到数据后,会使用硬件私钥对数据进行签名,并返回给智能合约,智能合约将自动验证可信硬件的签名,确保数据是可信硬件执行结果,没有被第三方篡改,从而安全可靠地获取来自指定外部数据源的数据。
数据安全可信
区块链预言机底层使用 TEE 技术实现,TEE 是一个安全隔离的执行环境,提供隔离执行、可信应用的完整性、可信数据的机密性、安全存储等安全特征,使预言机服务数据服务安全可信。
支持 HTTPS 协议
通过 HTTPS 协议,区块链预言机会与目标数据源建立端到端的安全通行通道,并且可以完成对数据源的证书校验以确定身份,从而安全、可靠地获取来自指定外部数据源的数据。
支持 JSON API
JSON 是一种轻量级的数据交换格式,广泛地被采用为 API 的数据交换格式。区块链预言机内置 JSON 解析器,如果请求的 URL 响应格式是 JSON 格式,可以在请求命令中设置 jsonpath 命令,使区块链预言机根据 jsonpath 读取部分 JSON 数据,只返回这部分数据上链。
支持访问要权限认证的 API
一些 API 需要认证授权访问,例如使用 OAuth 2.0 协议实现的 API,需要在请求中携带服务端认证鉴权需要的参数,但这些参数属于私密信息不可泄露。这种情况下,利用 TEE 技术提供的机密性,与区块链预言机的 TEE 环境建立端到端的加密信封,使得请求只在 TEE 硬件可信执行环境里面解密,从而不会泄露请求机密。
高可用预言机集群
区块链预言机服务使用集群架构实现,为合约提供高可用的数据访问服务。
外部数据源服务适用于以下任意场景:
外部数据源服务在区块链上部署了区块链预言机(Oracle)合约,提供异步查询互联网数据接口(CURL)供用户合约使用。正常情况下,用户合约调用预言机合约发起查询请求后,预言机合约在 1~3 个区块内就能得到外部数据源服务取回的数据,然后回调用户合约传入数据。
通过外部数据源服务,让智能合约获取指定外部数据源数据的开发流程如下:
用户的智能合约调用预言机合约的 CURL 接口发起查询请求,预言机合约同步返回查询结果,即请求单据号(reqeust_id)。预言机合约获取到查询结果数据后,会异步回调查询用户合约的回调接口。
OracleInterface.sol 中定义了用户合约与预言机合约的通信接口,其中用户通过 curlRequest 接口调用预言机合约。用户合约需要实现 oracleCallbackCurlResponse 接口,用于接收预言机合约的请求结果回调。
// OracleInterface.sol
pragma solidity ^0.4.22;
// 使用预言机 API 需要在用户合约中开启 ABIEncoderV2 特性
pragma experimental ABIEncoderV2;
interface OracleInterface {
/**
* function: 发送 CURL 请求
* parameters:
* _biz_id : 用户自定义的业务请求 ID
* _curl_cmd : CURL 命令,参考 CURL 命令使用文档进行构造
* _if_callback : 是否需要预言机将请求结果回调用户合约
* _callback_identity : 预言机请求结果回调的合约 ID,可以是发送请求的合约,也可以是其他合约
* _delay_time : 该特性未激活,填 0 即可
* return value: : 预言机请求 ID,是预言机合约为本次请求生成的唯一请求 ID
*/
function curlRequestDefault(bytes32 _biz_id, string _curl_cmd, bool _if_callback, identity _callback_identity, uint256 _delay_time) external returns (bytes32);
/**
* function: oracleCallbackCurlResponse
* parameters:
* _request_id : 预言机合约请求 ID(在发送请求时预言机合约会返回此 ID)
* _biz_id : 用户合约的业务请求 ID
* _error_code : 请求结果码,如果值是 0,则表示预言机请求处理成功;如果是其他值,则为请求处理失败,详见合约错误码表
* _resp_status : HTTP 响应的状态码,一般 200 表示 HTTP 请求处理成功,5xx 表示服务端处理错误,调用者可根据自己的使用场景做判断
* _resp_header : HTTP 响应的 header,如果 CURL 中指定了要返回 HTTP 响应的 header,则回调时会返回对应的值
* _resp_body : http 响应的 body
* _call_identity : 发起该请求的合约 ID
* return value : 无
*/
function oracleCallbackCurlResponse (bytes32 _request_id, bytes32 _biz_id, uint32 _error_code, uint32 _resp_status, bytes _resp_header, bytes _resp_body, identity _call_identity) external;
}
curlRequestDefault
是业务合约向预言机合约发送请求的接口。
function curlRequestDefault(bytes32 _biz_id, string _curl_cmd, bool _if_callback, identity _callback_identity, uint256 _delay_time) external returns (bytes32);
参数 | 必选 | 类型 | 说明 |
---|---|---|---|
_biz_id | true | bytes32 | 用户自定义的业务请求 ID,预言机合约回调结果时,会回传此 ID。 |
_curl_cmd | true | string | CURL 命令,参考 CURL 命令使用说明 进行构造。 |
_if_callback | true | bool | 是否需要预言机将请求结果回调用户合约。 |
_callback_identity | true | identity | 预言机请求结果回调的合约 ID,可以是发送请求的合约,也可以是其他合约。 |
_delay_time | true | uint256 | 该特性未激活,填 0 即可。 |
返回字段 | 字段类型 | 说明 |
---|---|---|
_request_Id | bytes32 | 预言机请求 ID,是预言机合约为本次请求生成的唯一请求 ID。 |
回调接口需要业务合约实现,用于接收预言机合约的请求结果回调,如果未能正确实现该合约,则将无法接收请求结果。
业务合约通过 oracleCallbackCurlResponse 来接收预言机合约的 CURL 请求结果回调。
function oracleCallbackCurlResponse (bytes32 _request_id, bytes32 _biz_id, uint32 _error_code, uint32 _resp_status, bytes _resp_header, bytes _resp_body, identity _call_identity) external;
参数 | 必选 | 类型 | 说明 |
---|---|---|---|
_request_id | true | bytes32 | 预言机合约请求 ID,在发送请求时预言机合约会返回此 ID。 |
_biz_id | true | bytes32 | 用户合约的业务请求 ID |
_error_code | true | uint32 | 请求结果码,如果值是 0,则表示预言机请求处理成功;如果是其他值,则为请求处理失败,详见 合约错误码表。 |
_resp_status | true | uint32 | HTTP 响应的状态码,一般 200 表示 HTTP 请求处理成功,5xx 表示服务端处理错误,调用者可根据自己的使用场景做判断。 |
_resp_header | true | bytes | HTTP 响应的 header,如果 CURL 中指定了要返回 HTTP 响应的 header,则回调时会返回对应的值。 |
_resp_body | true | bytes | HTTP 响应的 body |
_call_identity | true | identity | 发起该请求的合约 ID |
无返回字段。
pragma solidity ^0.4.22;
// 使用预言机 API 需要在用户合约中开启 ABIEncoderV2 特性
pragma experimental ABIEncoderV2;
import "./OracleInterface.sol";
// 实现一个demo合约
contract BizContract {
// 业务 ID 与预言机请求 ID 的关联关系
mapping(bytes32 => bytes32) request_id;
// 调用预言机合约的 CURL 接口
function rawCURLRequest(identity oracle_address, bytes32 biz_id, string cmd) public{
// 1. 跨合约调用,需要通过合约 API 定义及合约 ID 生成一个合约对象
OracleInterface oracle = OracleInterface(oracle_address);
//
// 2. 发送 CURL 请求
// (例如查询股票行情信息,cmd 参数的值可以是“https://hq.sinajs.cn/list=hk00941”)
bytes32 request_id = oracle.curlRequest(service_id, biz_id, cmd, true, this, 0);
// 3. 记录预言机返回的request id
request_id[biz_id] = request_id;
// 4. 请求阶段结束,等待回调
return;
}
// 业务合约用于接收预言机合约的 CURL 请求结果回调
function oracleCallbackCurlResponse (bytes32 _request_id, bytes32 _biz_id, uint32 _error_code, uint32 _web_status, bytes _resp_header, bytes _resp_body, identity _call_identity) external {
// 业务处理回调结果
}
}
本文主要对外部数据源服务涉及到的 CURL 命令的用法进行说明。
说明:当前外部数据源服务版本暂不支持 HTTP 分块传输编码,即不支持 HTTP 响应的 Transfer-Encoding 为 chunked,后续版本会支持该特性。
NAME
curl
VERSION
1.0.0_BETA
SYNOPSIS
curl https://address[:port][/path][?args] [options]
DESCRIPTION
CURL 命令是预言机提供的 Web API 接口必要传入参数之一。CURL 命令描述了指定预言机访问目的互联网资源的 URI,以及其他可选配置项。
当前外部数据源服务版本暂不支持 HTTP 分块传输编码,即不支持 HTTP 响应的 Transfer-Encoding 为 chunked,后续版本会支持该特性。
OPTIONS
--request
HTTP 访问的方法,支持 GET 和 POST。缺省使用 GET 方法。
e.g.
--request GET
--request POST
--header
指定 HTTP 请求中附带的 header 信息。
header 名和 header 值使用冒号分割。如果 header 名或者值包含空格,应该使用单引号将其作为整体包起来,譬如 --header 'content-type:plain text'。
--header 选项可以重复使用多次来配置多对 header,最多不超过 100 对。
以下为保留 header,用户配置不生效:"Host"、"Accept"、"User-Agent"、"Connection"、"Content-Length"。
e.g.
--header SomeHeader:SomeValue
--header 'Some Header:Some Value' --header k2:v2
--data
HTTP 使用 POST 方法时附带的 body 信息,建议使用单引号包起来。
e.g.
--data 'Hello world!'
--json-path
指定了对 HTTP 原始响应 body 进行 JSONPath 处理。
JSONPath 语法说明:https://goessner.net/articles/JsonPath/
目前支持:$.[]*
e.g.
--json-path '$.obj' 取子对象
--json-path '$[0]' 从数组取下标
--json-path "$['obj']" 取子对象
--json-path '$[0,1].obj' 取多个对象
--body-plain-text
指定了返回正文内容格式,缺省 --body-plain-text。
--resp-header
指定了从 HTTP 原始响应 header 全集中返回给查询方的子集。
如果指定的 header 不在原始响应 header 全集中,则返回 value 为空字符串。
可以指定多次 --resp-header 来指定返回多个 header。
--header-plain-text
指定了返回 HTTP 响应 header 的格式,缺省 --header-plain-text。
具体格式为每个"header:value"占一行,使用 \r\n 换行。
--header-to-json
指定了返回 HTTP 响应 header 使用 JSON 格式组织,每个 header:value 为顶层 kv。
--encrypted-envelope
加密信封字段,传递机密信息给预言机 TEE 实例。
加密信封为以下 JSON 格式字符串的 BASE64 编码:
{ "cipher_text": "", // 机密信息密文,使用 aes-256-gcm 加密
"aes_iv":"", // 对称加密 iv
"gcm_aad": "", // 对称加密 add
"gcm_tag": "" // 对称加密 tag
"encrypted_aes_key": "" // 经过 TEE 公钥加密后的对称加密 key
"rsa_key": "", // TEE 实例的 RSA 公钥
}
其中 cipher_text 字段为机密信息,值为以下固定结构的 JSON 字符串:
{"macro_replacement":{}, "content_hash":"", "nonce_str":"", "timestamp":"", "time_to_live":""}
其中 macro_replacement 存放宏替换内容,可以在 URL path、body、header 中嵌入宏,然后将替换值写在macro_replacement 中,只对 TEE 可见。合法宏只能从 'ORACLE_SUB_MACRO_0' ~ 'ORACLE_SUB_MACRO_4' 选择,并且替换值中不能包括合法宏。
content_hash 存放 CURL 命令明文部分内容计算的哈希值,锁定加密信封只能与锁定的明文一起使用。
nonce_str、timestamp、time_to_live 暂未启用。
机密信息使用 AES/GCM/NoPadding 加密,再用 TEE 的公钥使用(TEE 的公钥在跨链服务页面中查询)RSA/None/OAEPPadding 加密 AES 密钥。
错误码 | 16 进制错误码值 | 10 进制错误码值 | 描述 | 解决方法 |
---|---|---|---|---|
OE_SUCCESS | 0x0000 | 0 | 查询成功 | |
OE_UNKNOWN_ERROR | 0x0002 | 2 | 未知错误 | 联系管理员。 |
OE_QUERY_COMMAND_PARSE_ERROR | 0x1000 | 4096 | 命令解析错误 | 检查命令语法是否正确。 |
OE_REQUEST_QUERY_COMMAND_NONSUPPORT | 0x1001 | 4097 | 非法命令 | 检查命令,目前仅支持 CURL。 |
OE_TLS_ERROR | 0x1002 | 4098 | 网络连接错误 | 联系管理员。 |
OE_UNRECOGNIZED_OPTION | 0x1200 | 4608 | 非法选项 | 查命令选项是否拼写有误,检查命令选项是否存在拼写错误或者存在 CURL 命令使用说明 中没有的选项。 |
OE_OPTION_CONFLICTS | 0x1201 | 4609 | 选项存在冲突 | 检查是否同时使用了语义互斥的命令选项。 |
OE_INVALID_JSONPATH | 0x1202 | 4610 | JSONPath 语法错误 | 检查 JSONPath。 |
OE_REQUEST_ENVELOPE_PARSE_ERROR | 0x1203 | 4611 | 信封解析错误 | 检查信封字段。 |
OE_REQUEST_ENVELOPE_MISS_FIELD | 0x1204 | 4612 | 信封缺失字段 | 检查信封是否缺失必要字段,具体参考 CURL 命令使用说明。 |
OE_REQUEST_ENVELOPE_DECRYPT_ERROR | 0x1205 | 4613 | 信封解密失败 | 检查信封是否使用了规定的加密算法,具体参考 CURL 命令使用说明。 |
OE_REQUEST_ENVELOPE_CONTENT_PARSE_ERROR | 0x1206 | 4614 | 信封内容解析势必 | 检查信封结构是否遵循规定的结构,具体参考 CURL 命令使用说明。 |
OE_REQUEST_ENVELOPE_CONTENT_MISS_FIELD | 0x1207 | 4615 | 信封内容缺失字段 | 检查信封是否缺失必要字段,具体参考 CURL 命令使用说明。 |
OE_REQUEST_ENVELOPE_CONTENT_HASH_CHECK_ERROR | 0x1208 | 4616 | 信封内容哈希不一致 | 检查是否采用了规定的哈希算法,具体参考 CURL 命令使用说明。 |
OE_REQUEST_ENVELOPE_CONTENT_MACRO_CHECK_ERROR | 0x1209 | 4617 | 信封内容宏错误 | 检查信封中关于宏的使用方法是否正确。 |
OE_CONTENT_EXCEED_LIMIT | 0x1400 | 5120 | 返回原始内容超长 | 检查数据源串长度是否超出限制。 |
OE_RESPONSE_ERROR | 0x1401 | 5121 | 数据源返回失败 | 远端数据源返回失败,需要用户根据需求重新发起请求。 |
OE_JSON_PATH_NOT_IN_CONTENT | 0x1402 | 5122 | 返回内容中不存在指定 JSONPath | 检查数据源的返回数据格式,根据实际情况使用 JSONPath 命令。 |
OE_JSON_PATH_FOR_NON_JSON | 0x1403 | 5123 | 返回内容不是 JSON 但指定了 JSONPath。 | 检查数据源的返回数据格式是否为 JSON,否则不能使用 JSONPath 命令。 |
OE_CURL_INVALID_SCHEMA | 0x2000 | 8192 | 非法 URL Schema | 仅支持 HTTPS。 |
OE_CURL_INVALID_PORT | 0x2001 | 8193 | 非法端口 | 检查端口是否有效,可以使用 Linux CURL 工具进行测试。 |
OE_CURL_INVALID_PATH | 0x2002 | 8194 | 非法路径 | 检查 path 的语法是否正确,具体参考 CURL 命令使用说明。 |
OE_CURL_HEADER_NUM_EXCEED_LIMIT | 0x2003 | 8195 | —header 选项个数过多 | 最多指定 100 个 header。 |
OE_CURL_HTTP_HEADER_PARSE_ERROR | 0x2004 | 8196 | —header 的值格式错误 | 必须是“key:value”。 |
OE_CURL_METHOD_NON_SUPPORTED | 0x2005 | 8197 | 非法的请求方法 | 仅支持 GET 和 POST 方法。 |
REJECT_SYSTEM_ERROR | 0x5000 | 20480 | 服务处理请求解析失败,拒绝该请求。 | 预言机系统处理该笔请求错误,需要客户端重新发起请求。 |
REJECT_ILLEGAL_REQUEST | 0x5100 | 20736 | 服务处理请求解析失败,拒绝该请求。 | 非法 CURL 语法。检查 CURL 命令是否按照 CURL 命令使用说明 中的约束构建。 |
REJECT_ILLEGAL_CMD | 0x5101 | 20737 | 服务处理请求解析失败,拒绝该请求 | 非法 CURL 语法。检查 CURL 命令是否按照 CURL 命令使用说明 中的约束构建。 |
REJECT_ILLEGAL_SERVICE_ID | 0x5102 | 20738 | 不存在请求指定的 Service ID。 | 使用正确的 Service ID。 |
REJECT_OVERSIZE_CMD | 0x5104 | 20740 | 请求内容过大 | CURL 命令不大于 10240 字节。 |
REJECT_ENVELOPE_ILLEGAL_BASE64 | 0x5105 | 20741 | 加密信封 Base64 解码失败 | 检查加密信封 Base64 编码。 |
REJECT_ENVELOPE_NOT_EXIST_KEY | 0x5106 | 20742 | 加密信封的 key 不存在 | 检查加密信封的结构是否正确传入 key。 |
REJECT_ENVELOPE_UNKNOWN_KEY | 0x5107 | 20743 | 加密信封的 key 未能识别 | 检查加密信封的 key 是否使用约定的用法传入。 |
REJECT_BY_REQUEST_FILTER | 0x5301 | 21249 | 请求白名单限制 | 配置请求白名单。 |
REJECT_BY_RESPONSE_FILTER | 0x5302 | 21250 | 请求结果安全校验失败 | 请求结果中内容安全处理失败,检查数据源的安全性。 |
(1)外部数据源服务
https://tech.antfin.com/docs/2/108575
(2)预言机(oracle)2.0:用完即走,为智能合约可信地与外部世界交互提供必要条件(上)
https://zhuanlan.zhihu.com/p/35007714
(3)什么是区块链预言机(BlockChain Oracle)
https://zhuanlan.zhihu.com/p/52369816
截止2019.04.10,针对创新大赛的TEE硬件隐私合约链的外部预言机功能还未开放出来,但是标准合约链的外部预言机ORACLE功能已开放。