千家信息网

区块链Oracle预言机实现方法是什么

发表于:2024-11-21 作者:千家信息网编辑
千家信息网最后更新 2024年11月21日,本篇内容主要讲解"区块链Oracle预言机实现方法是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"区块链Oracle预言机实现方法是什么"吧!1、为什
千家信息网最后更新 2024年11月21日区块链Oracle预言机实现方法是什么

本篇内容主要讲解"区块链Oracle预言机实现方法是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"区块链Oracle预言机实现方法是什么"吧!

1、为什么智能合约需要预言机/Oracle?

在智能合约中执行的逻辑不可以执行区块链之外的任何操作,例如它不可以访问互联网上的web服务。外部数据进入智能合约的唯一方法是将其置入一个交易中,通过向系统发送一个新的交易来触发区块链状态的更新。

试着考虑一下,如果智能合约在执行时可以访问外部的一个API来获取数据,会出现什么情况?

如果今天部署这个合约,那么API可能会返回如下的数据:

{ "foo": "bar" }

但是明天再部署时,API可能就会返回新的数据,例如:

{ "foo": "baz" }

那么可以想像,一个月以后如果有人进行以太坊区块链的同步,这个智能合约就会被执行,但是API的响应数据是和一个月之前不同的,这就会导致新同步的 区块链状态不同于之前已经存在的节点状态。

这就不再是完全自确定的区块链了。经历相同的同步过程,我的区块链和你的区块链却不一样!

让我们再换个说法:给定一组区块,一个节点必须能够从零开始重现区块链的最终状态,而无需互联网连接。

那么这一点对于智能合约的开发者意味着什么?Oralce(预言机),开发者必须构造一个预言机来和实现智能合约与外部世界的交互。

2、如何实现一个简单的预言机/Oracle?

现在让我们创建一个简单的预言机/Oracle,来将外部的天气数据传入智能合约:

在最底层的区块链平台,我们需要部署一个智能合约,这个合约有一个方法updateWeather()用来更新天气状态,只有在合约白名单里的地址才可以调用这个方法。updateWeather方法接受天气数据作为参数,同时触发一个以太坊合约事件并将天气数据作为事件的参数,这样JavaScript应用就可以订阅这个事件并获得异步通知了。

同时我们将创建两个nodejs进程,其中之一就是预言机/Oracle,它的实现逻辑就是周期性地轮询第三方天气API来获取天气数据,然后将天气数据提交给智能合约以便进行历史审计。

另一个nodejs进程则负责订阅智能合约的天气事件,然后在控制台输出事件参数。正如之前所述,每当预言机/Oracle调用合约的updateWeather()方法时,都会触发天气事件。

需要指出的是,为了便于理解预言机的核心实现思路,下面的代码进行了简化,剔除了必要的错误处理,因此并不适用于生产环境。

源代码在这里:

  • 预言机合约 - https://github.com/decentorganization/weather-oracle-contract

  • 预言机服务 - https://github.com/decentorganization/weather-oracle-service

接下来我们详细讲解这个简单的预言机的实现。

3、预言机智能合约实现

智能合约有一个公开的oracleAddress状态变量,用来表示允许调用智能合约的updateWeather方法的账户地址,我们在构造函数中对其进行赋值:

contract WeatherOracle {    address public oracleAddress;    constructor (address _oracleAddress) public {    oracleAddress = _oracleAddress;  }    // ...}

接下来我们要定义天气事件,这个事件将在weatherUpdate()调用成功时触发。同样为了简化,我们让这个事件简单的附带一个表示温度的字符串参数。

event WeatherUpdate (string temperature);

最后我们要实现updateWeather()方法。它的可见性为public,意思是可以从外部调用这个方法:

function updateWeather (string temperature) public {    require(msg.sender == oracleAddress);    emit WeatherUpdate (temperature);  }

请注意require语句。只有当调用地址(msg.sender)和白名单地址(oracleAddress)一致时才允许继续执行该方法,否则将回滚交易。

好了,就这么简单。

4、预言机服务

我们的预言机就是一个简单的nodejs服务。它使用request库来调用外部天气API,解析API的响应,然后构造并提交交易给智能合约,然后等一会儿,重复上面的工作,如此 周而复始。

让我们从访问API开始,我们将API的地址放在一个环境变量里,以便在开发/生产环境切换时避免修改源代码:

const options = { uri: process.env.WEATHER_URL, json: true };const start = () => {  request(options)  .then(parseData)  .then(updateWeather)  .then(restart)  .catch(error);};

下面的代码用来解析API的响应结果:

const parseData = (body) => {  return new Promise((resolve, reject) => {    const temperature = body.main.temp.toString();    resolve({ temperature });  });};

现在要做的就是构造一个调用智能合约的updateWeather()方法的以太坊交易。注意account()是一个异步方法,它的作用是载入一个以太坊账户,contract是一个js 对象,它包含了之前部署的WeatherOracle智能合约的部署地址和ABI接口数据。这些与智能合约相关的函数都来自于著名的web3开发包:)

const updateWeather = ({ temperature }) => {  return new Promise((resolve, reject) => {    account().then(account => {      contract.updateWeather(temperature, { from: account }, (err, res) => {        resolve(res);      });    });  });};

最后,我们只需要在指定超时后重新启动这个过程即可。 wait()函数将在指定的超时时间之后解析。

const restart = () => {  wait(process.env.TIMEOUT).then(start);};

搞定了!上面的代码实现了一个简单服务,它可以从API获取数据,然后再输入智能合约。

注意:

  • 当我们构造以太坊交易时,我们使用{from:account}来指定调用账户,account所指向的这个账户需要有一些以太币来支付交易的手续费。

  • 我们使用环境变量来配置一个私钥,用来实例化account对象。这个私钥必须是用来部署WeatherOracle智能合约时传入的那个白名单地址所对应的私钥。

5、天气事件的利用服务

这是另一个简单的nodejs服务。同样,contract是一个包含了合约的部署地址和ABI信息的js对象,调用WeatherUpdate并传入一个回调就是我们订阅天气事件的所有代码:

const consume = () => {  contract.WeatherUpdate((error, result) => {    console.log("NEW WEATHER DATA EVENT ON SMART CONTRACT");    console.log("BLOCK NUMBER: ");    console.log("  " + result.blockNumber)    console.log("WEATHER DATA: ");    console.log(result.args);    console.log("\n");  });}

当这个服务运行时,随着交易成功入块上链,它将会周期性地向控制台输出数据:

NEW WEATHER DATA EVENT ON SMART CONTRACTBLOCK NUMBER:  3424586WEATHER DATA:{ temperature: '74.75' }

到此,相信大家对"区块链Oracle预言机实现方法是什么"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0