使用 Solidity 和 Node.js 构建简单的区块链预言机

更新日期: 2022-05-22阅读: 950标签: node

区块链上的预言机是允许区块链世界与来自网络其余部分的数据交互的框架,我们将其称为网络 2.0 世界。随着智能合约的应用不断扩大,处理独特用例所需的各种数据也将不断扩大。

事实上,web 2.0和web 3.0是两个截然不同的网络,目前最有用的数据都存在于web 2.0中。通过创建一组协议使智能合约能够访问这些数据,新一代的web、系统设计和区块链将出现。

目前的协议已经借鉴了预言机的概念,利用智能合约和链下api来构建混合系统,将web 2.0数据和其他区块链连接起来。最著名的预言机是Chainlink,它提供定价数据、与其他区块链的连接、对大多数api的访问以及各种其他数据馈送的服务。

其他主要的例子包括代币桥,它允许在链下服务的帮助下在链之间移动代币和数据。随着时间的推移,可能会出现更多独特的预言机。

事件驱动的预言机设计


在解决使用链下服务代表智能合约执行某些操作的问题时,最重要的是要记住,在智能合约和服务之间没有正式的消息传递过程。根据这个假设,我们知道智能合约不能“推送”,所以服务必须可听、可看。

只有两个链上项目,服务才有能力“监听”,就是状态变量和事件。观察状态变量很麻烦,因为它需要与合约进行多次交互。另一方面,事件不需要直接交互。

智能合约事件的触发方式如下:

emit newEvent(block.timestamp)

事件可以被看作是由开发人员定义的智能合约的操作日志。与其他类型的日志一样,其他服务也可以订阅此提要,以“监听”特定类型的事件,从它们的参数中收集数据,并对这些事件做任何它们想做的事情。这些日志对任何访问区块链的人都是可见的,并且可以通过像web3.js这样的库进行访问。

有了这种独特的通信系统,智能合约可以“通知”外部世界的服务事件,或需要完成的预言机案例工作。理解事件和链上到链下的消息传递是预言机设计中最重要的部分。

一旦服务发现了一个新的事件,并触发了它的操作,它就可以获取事件中的有价值的数据和惟一的jobID,并像其他任何程序一样执行链下操作。

任务完成后,服务可以使用 web3 库与合约进行交易。典型的交易可以“上传”带有jobID 的请求/事件的结果,这样智能合约就可以继续使用链下数据进行任何已计划好的工作。把所有这些放在一起,就会如下所示:

  1. 预言机智能合约会发出一个带有job信息的事件。
  2. 链下预言机服务“监听”事件并在事件被触发时提取信息。
  3. 链下预言机与任何服务或数据进行交互以接收结果。
  1. 链下预言机与预言机智能合约进行交易,以更新job数据。
  2. 智能合约生态系统会根据需要使用数据。

当然,这是预言机设计的过度简化,如Chainlink,它包括许多节点和共识协议,以确保预言机数据是去中心化的。虽然有趣且重要,但简单的理解将是构建概念的最佳背景。

构建一个简单的预言机

为了可视化预言机的概念,我们可以构建一个简单的单服务、单节点预言机,使这个概念不那么令人生畏。

我选择了像天气这样的服务,因为输入数据很容易传输,而且api很丰富。考虑到我们对事件驱动的预言机的理解,我们的系统设计将看起来像这样:


气象预言机系统图

正如所看到的,我们有一个solidity合约和一个node.js程序,因此这个设计的要求很简单:

  • Solidity 智能合约
  • node. js
  • Web3. js
  • 天气API (使用OpenWeather)

首先,我们可以开始智能合约:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract WeatherOracle {
    //mapping from jobId => completion status for smart contract interactions to check;
    //default false for all + non-existent
    mapping(uint => bool) public jobStatus;

    //mapping jobId => temp result. Defaultfor no result is 0.
    //A true jobStatus with a 0 job value implies the result is actually 0
    mapping(uint => uint) public jobResults;

    //current jobId available
    uint jobId;

    //event to trigger Oracle API
    event NewJob(uint lat, uint lon, uint jobId);

    constructor(uint initialId){
        jobId = initialId;
    } 

    function getWeather(uint lat, uint lon) public {
        //emit event to API with data and JobId
        emit NewJob(lat, lon, jobId);
        //increment jobId for next job/function call
        jobId++;
    }

    function updateWeather(uint temp, uint _jobId)public {
        //when update weather is called by node.js upon API results, data is updated
        jobResults[_jobId] = temp;
        jobStatus[_jobId] = true;

        //Users can now check status and result via automatic view function
        //for public vars like these mappings
    }
}

我已经逐行提供了更详细的注释,但是为了总结我们的合约,我们使用了一对映射来保存jobIDs(true = complete, false = incomplete)的状态和作业的结果。

合约提供了一个用于触发job的函数getWeather,该函数以位置数据作为参数,创建jobID,并发出带有相关位置和job信息的事件。

此预言机的一个重要特性是updateWeather函数上的操作符修饰符。为了只允许服务与这个函数交互,需要这个修饰符,否则任何人都可以更新job数据。

现在我们有了一个区块链预言机合约,可以在 node.js 中构建一个链下数据提供者;:

require('dotenv').config();
const fs = require("fs");
const https = require('axios');
const Web3 = require('web3');

//intialize Web3 with the Url of our environment as a variable
const web3 = Web3(new Web3.providers.HttpProvider(process.env.RPC));
//get contract address and abi file path from env vars
const contractAddress = process.env.CON_ADDR;
const contractAbi = JSON.parse(fs.readFileSync(process.env.ABI)).abi;
//initialize contract variable
var contract =  new Web3.eth.Contract(contractAbi, contractAddress);

//simple function for calling API with lat and long, returning temp from JSON(see included doc link in article)
function callAPI(lat, long){
    axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${process.env.API_KEY}`)
        .then(res => {
            return res.data.main.temp;
  })
  .catch(err => {
    return "ERROR"
  });
}

//While loop until program is canceled to continue to receive events
while(true){
    //initialize a contract listener for emmisions of the "NewJob" event, see web3.js for docs
    contract.on("NewJob", (lat, lon, jobId) => {
        //use lat and lon to call API
        var temp = callAPI(lat, lon);
        if(temp != "ERROR"){
            //send data to updateWeather function on blockchain if temp is received
            await contract.methods.updateWeather(temp, jobId).send();
        }
    })
}

交互的钱包地址必须是一个运营商,我们必须确保我们的web3提供商包含该帐户。

使用我们订阅的web3库来“监听”事件。对于新事件来说,代码使用内置API接口和事件参数来获取我们请求的天气数据。

对于调用的结果,web3库通过合约abi调用updateWeather函数,将结果上传到合约中。一旦成功,初始设计需求就全部满足了,智能合约就可以访问该工作的结果,完成它需要做的任何事情。

虽然这是一个简单的示例,但它可能会让我们了解如何为独特的用例构建简单的链下接口。

结论

总之,区块链的预言机将为web 3.0世界打开web 2.0数据源的大门。这反过来又允许web 3.0开始实现更多的优势。事件驱动的预言机设计创建了一个将智能合约功能与传统软件工程技术相结合的框架。

随着这一概念的扩展,可能会出现一个完整的生态系统,可以实现最流畅的数据接入网络。

为这个生态系统做出贡献可能有很大的机会,从一个像天气这样简单的应用程序开始,是深入探索和发现新事物的第一步。

Source: https://medium.com/better-programming/building-a-simple-blockchain-oracle-with-solidity-and-node-js-29eacdad31f1

关于

ChinaDeFi– ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、梳理更为系统的内容,以最快的速度同步到中国市场提供决策辅助材料。

原文 https://chinadefi.com/1964.html


链接: https://www.fly63.com/article/detial/11559

关于 Node.js 里 ES6 Modules 的一次更新说明

关于 Node.js 里 ES6 Modules 的一次更新说明,总结来说:CommonJS 与 ES6 Modules 之间的关键不同在于代码什么时候知道一个模块的结构和使用它。

用node.js开发一个可交互的命令行应用

在这个教程中,我们会开发一个命令行应用,它可以接收一个 CSV 格式的用户信息文件,教程的内容大纲:“Hello,World”,处理命令行参数,运行时的用户输入,异步网络会话,美化控制台的输出,封装成 shell 命令,JavaScript 之外

Node启动https服务器

首先你需要生成https证书,可以去付费的网站购买或者找一些免费的网站,可能会是key或者crt或者pem结尾的。不同格式之间可以通过OpenSSL转换

nodejs 异步转同步

nodej项目在微信环境开发,nodejs的异步特效,会导致请求没有完成就执行下面的代码,出现错误。经过多方查找,可以使用async模块来异步转同步,只有前一个function执行callback,下一个才会执行。

基于node服务器的大文件(G级)上传

3G的大文件分1500个2M二进度文件,通post方法发送给node服务,服务器全部接收到文件后,进组装生成你上文件。

为什么要把 JavaScript 放到服务器端上运行?

JavaScript比C的开发门槛要低,尽管服务器端JavaScript存在已经很多年了,但是后端部分一直没有市场,JavaScript在浏览器中有广泛的事件驱动方面的应用,考虑到高性能、符合事件驱动、没有历史包袱这3个主要原因,JavaScript成为了Node的实现语言。

了解node.js事件循环

node.js的第一个基本论点是I / O的性能消耗是很昂贵。因此,使用当前编程技术的最大浪费来自于等待I / O完成。有几种方法可以处理性能影响

Node.js 应用:Koa2 使用 JWT 进行鉴权

在前后端分离的开发中,通过 Restful API 进行数据交互时,如果没有对 API 进行保护,那么别人就可以很容易地获取并调用这些 API 进行操作。那么服务器端要如何进行鉴权呢?

Node.js 前端开发指南

我们经常跟Node.js打交道,即使你是一名前端开发人员 -- npm脚本,webpack配置,gulp任务,程序打包 或 运行测试等。即使你真的不需要深入理解这些任务,但有时候你会感到困惑,会因为缺少Node.js的一些核心概念而以非常奇怪的方式来编码。

happypack提升项目构建速度

运行在 Node.js 之上的 Webpack 是单线程模型的,也就是说 Webpack 需要处理的任务需要一件件挨着做,不能多个事情一起做。happypack把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!