gg oracle tjs 同步_区块链研究实验室-以太坊预言机(oracle)直接从Solidity执行JavaScript...

项目中需要直接对接以太坊预言机(oracle)的需求。因此,我创建了一个:直接从以太坊的Solidity调用JavaScript的项目。

如何操作

以太坊预言机(oracle)谕称为CaptainJS。它负责JavaScript请求并在NodeJS容器中执行它们。如果你的合同是使用CaptainJS,那么你可以直接使用回调和JavaScript执行功能。

Captain需要一些预算来转移您的结果或回复您的合同。该预算(gas*gas price)将转入CaptainJS核心合同,并将用于调用您的合同。

简单回调{use.case.1}

在某些情况下,有必要建立一种机制去调用合同。例如每年都会向特定人员提取预算。但是Solidity不能调用自己。

因此从usingCaptainJS扩展并开始编码......

使用唯一的整数jobId来标识您的回调。使用足够的gas调用RingShipsBell并在方法RingRing中接收回调。

为了确保RingRing只由Captain而不是盗版者调用,只需将CaptainsOrdersAllowed添加到其声明中就可以。

pragma solidity ^0.4.25;

import "https://github.com/CaptainJavaScript/Solidity/usingCaptainJS.sol";

contract SimpleCallback is usingCaptainJS {

uint constant CALLBACK_ID = 3;

function CallbackExample() public {

RingShipsBell(

CALLBACK_ID, /* give the job a unique ID */

60 * 24, /* 24 hours */

45000, /* gas budget for callback */

DEFAULT_GAS_PRICE /* use default gas price */

);

}

function RingRing(uint UniqueIdentifier) external onlyCaptainsOrdersAllowed {

if(UniqueIdentifier == CALLBACK_ID) {

/* this will be executed 24 hours after CallbackExample

* was invoked

*/

}

}

}

使用Mathjs{use.case.2}

现在让我们看一个简单的JavaScript编程工作。 JavaScript的mathjs库有许多有用的功能,例如厘米到英寸的转换。

要使用此库,您需要调用Run函数并移交将厘米转换为英寸所需的JavaScript代码。

您要提交的JavaScript代码必须按以下方式编写:

module.exports = function(CaptainJSIn) { /* here goes your code */ }

CaptainJS将通过调用默认函数来调用容器中的代码,CaptainJSIn将包含您对JavaScript函数的输入, 然后CaptainJS将返回代码的结果, 如果您的JavaScript代码成功:将调用CaptainsResult, 返回结果始终是一个字符串。

如果你的JavaScript代码不成功或者它的结果无法发回(失败有可能是没有足够的gas),那么将调用CaptainsError。

为了确保CaptainsResult和CaptainsError都只由Captain而不是盗版者调用,只需将CaptainsOrdersAllowed添加到其声明中。

运行时片的持续时间为10秒,它包括所有必需的npm模块的下载和安装。 目前6个运行时切片是最大值。

这是完整的代码段:

contract SeamansExamples is usingCaptainJS {

...

uint constant CENTIMETER_JOB = 1;

function CentimeterToInchExample(string Centimeter) public {

Run(

CENTIMETER_JOB, /* give the job a unique ID */

/* JavaScript code I want to execute: */

"module.exports = function(CaptainJSIn) { var math = require('mathjs'); return math.eval(CaptainJSIn + ' cm to inch'); }",

Centimeter, /* Input parameter which will result in CaptainJSIn (see above) */

"mathjs", /* Nodejs libraries we need */

3, /* we need a maximum of 3 runtime slices */

DEFAULT_GAS_UNITS, /* use default gas units */

DEFAULT_GAS_PRICE /* we will transfer the default gas price for return */

);

}

function CaptainsResult(uint UniqueJobIdentifier, string Result) external onlyCaptainsOrdersAllowed {

if(UniqueJobIdentifier == CENTIMETER_JOB) {

// OK. It worked and we got a result

...

}

}

function CaptainsError(uint UniqueJobIdentifier, string Error) external onlyCaptainsOrdersAllowed {

if(UniqueJobIdentifier == CENTIMETER_JOB) {

// OK. It didn't work :-/

}

}

}

调用WolframAlpha{use.case.3}外部资源

如果你想调用WolframAlpha这样的外部资源也很容易, 让我们问WolframAlpha它是否知道法国国家的一切。 因此,您可以像在第二个用例中一样设计代码。

要查询WolframAlpha,请使用JavaScript的axios库。 默认函数必须是异步的,以便在调用axios.get(...)时等待结果。 axios将返回一个JSON对象,但我们需要将其展平为一个字符串:

module.exports = async function(CaptainJSIn) {

const axios = require('axios');

const WAlpha = await axios.get('http://www.wolframalpha.com/queryrecognizer/query.jsp?appid=DEMO&mode=Default&i=' + CaptainJSIn + '&output=json');

return JSON.stringify(WAlpha.data);

}

同样,CaptainJS将通过调用此默认函数来调用容器中的代码。 CaptainJSIn将包含您的输入,例如“France”。

同样,如果您的JavaScript代码成功:将调用CaptainsResult。 否则将调用CaptainsError。

而且由于Solidity有时候是一种糟糕的编程语言,你将使用非常昂贵的concat函数来使你的JavaScript代码更具可读性。

这是完整的代码段:

contract SeamansExamples is usingCaptainJS {

...

uint constant WOLFRAMALPHA_JOB = 2;

function WolframAlphaExample(string Country) public {

Run(

WOLFRAMALPHA_JOB, /* give the job a unique ID */

concat ( /* JavaScript code I want to execute: */

"module.exports = async function(CaptainJSIn) { ",

" const axios = require('axios'); ",

" const WAlpha = await axios.get('http://www.wolframalpha.com/queryrecognizer/query.jsp?appid=DEMO&mode=Default&i=' + CaptainJSIn + '&output=json'); ",

" return JSON.stringify(WAlpha.data); ",

"}"

),

Country, /* Input parameter which will result in CaptainJSIn (see above) */

"axios", /* Nodejs libraries we need */

3, /* we need a maximum of 3 runtime slices */

200000, /* use 200,000 gas units */

DEFAULT_GAS_PRICE /* use default gas price */

);

}

...

}

JSON,XML / XPath或HTML / jQuery {use.case.4}请求

经典的oracle请求是一个简单的JSON,XML / XPath或HTML / jQuery请求。 而不是编写一个完整的JavaScript代码为您执行查询,而不是最新版本具有预定义的查询。

要调用简单查询,只需使用Run方法,就像在前两个用例中一样。 但是,不是提交JavaScript代码而是发送具有html:,xml:或json:前缀的URL。 Run方法的输入参数是JSON,XPath或jQuery表达式。 通常1个运行时切片就足够了。

如果您的JavaScript代码成功:将调用CaptainsResult。 否则将调用CaptainsError。

(客户端库现在包含一个测试模块,用于查看代码是否有效 - 在您提交到区块链之前)

function HTMLqueryExample() public {

Run(

HTML_QUERY_EXAMPLE, /* give the job a unique ID */

/* url needs to start with html: */

"html:http://www.amazon.co.uk/gp/product/1118531647",

/* Input parameter is the jQuery. Result will be stored in QUERY_RESULT variable */

"$('span.inlineBlock-display span.a-color-price').each(function(i, element) {var el = $(this); QUERY_RESULT = el.text(); })",

"", /* no modules required */

1, /* queries are fast */

DEFAULT_GAS_UNITS, /* use default gas units */

DEFAULT_GAS_PRICE /* we will transfer the default gas price for return */

);

}

function JSONqueryExample() public {

Run(

JSON_QUERY_EXAMPLE, /* give the job a unique ID */

/* url needs to start with json: */

"json:https://api.kraken.com/0/public/Ticker?pair=ETHUSD",

/* Input parameter is the JSON path */

"result.XETHZUSD.a[0]",

"", /* no modules required */

1, /* queries are fast */

DEFAULT_GAS_UNITS, /* use default gas units */

DEFAULT_GAS_PRICE /* we will transfer the default gas price for return */

);

数据加密{use.case.5}

对于那些喜欢加密存储在区块链中的数据的海员,我已经为最新版本添加了一个加密模块。 这允许您将加密数据发送到Captain的NodeJS容器。 在那里它将被解密和执行。 (字符串结果不会被加密回发送)

例如,您希望在事务发生后发送邮件,然后您可以使用nodemailer,登录到您的邮件帐户并发送邮件。 在这种情况下,您的代码看起来与此类似:

module.exports = async function(CaptainJSIn) {

var nodemailer = require("nodemailer");

var transport = nodemailer.createTransport({

host: "smtp-mail.outlook.com", // hostname

secureConnection: false, // TLS requires secureConnection to be false

port: 587, // port for secure SMTP

tls: {

ciphers:'SSLv3'

},

auth: {

user: "myaddress@outlook.com",

pass: "mysecretpassword"

}

});

var mailOptions = {

to: 'donald.trum@whitehouse.gov', // list of receivers

subject: "you're fired", // Subject line

text: "Dear Donald, ..."

};

// send mail with defined transport object

transport.sendMail(mailOptions, function(error, info){});

}

您的帐户详细信息将存储在您的代码中。 这些帐户详细信息将永久存储在以太坊的区块链中。只需将模块添加到MailSample.js等文件中即可;

使用CaptainJS-Encryption.js中的EncryptFile加密文件;

将加密代码添加到合同中

加密代码:

var ENC = require("./CaptainJS-Encryption.js");

async function RUN() {

await ENC.EncryptFile(false, "MailSample.js", "EncryptedMailSample.txt",

() => { console.log("Success!"); },

(ERROR) => { console.log(ERROR); }

);

}

RUN();

并将加密代码添加到基于Solidity的合同中:

function HTMLqueryExample() public {

Run(

ENCRYPTED_MAIL_EXAMPLE,

"crypt:8366268bd167a9f8318f99c71d0f489d0372b545735c2e10303c47bad2507e933171f72f...",

"",

"",

1,

DEFAULT_GAS_UNITS,

DEFAULT_GAS_PRICE

);

}

Captain永远不会读你的代码! 它只是在一个新的容器中执行。 换句话说:如果您加密数据,那么它将保持加密状态,直到它在容器中执行(并且容器将在执行后消失)。 加密使用Captain合同的公钥/私钥。 尽管Captain可以出于私人目的阅读您的加密数据,但它不会这样做,这是一个承诺和信任的证据。

本文转载:区块链研究实验室-以太坊预言机(oracle)直接从Solidity执行JavaScript​mp.weixin.qq.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值