區塊鏈Oracle預言機實現教程【含代碼】

區塊鏈自己是封閉的。區塊鏈的肯定性模型基於這樣一個事實:在交易執行時區塊鏈不能執行任何來自外部的邏輯,全部的外部數據只能經過交易進入到系統中。預言機/Oracle就是經過交易爲智能合約提供可信數據的服務。Oracle雖然聽起來神祕,但實現並不複雜,在這篇文章裏,咱們將介紹預言機的做用以及運做原理,並經過天氣數據預言機WeatherOracle的完整實現過程,來幫助你快速掌握區塊鏈預言機/Oracle的精髓。php

區塊鏈開發課程精選

一、爲何智能合約須要預言機/Oracle?

在智能合約中執行的邏輯不能夠執行區塊鏈以外的任何操做,例如它不能夠訪問互聯網上的web服務。外部數據進入智能合約的惟一方法是將其置入一個交易中,經過向系統發送一個新的交易來觸發區塊鏈狀態的更新。前端

試着考慮一下,若是智能合約在執行時能夠訪問外部的一個API來獲取數據,會出現什麼狀況?java

若是今天部署這個合約,那麼API可能會返回以下的數據:node

{ "foo": "bar" }

可是明天再部署時,API可能就會返回新的數據,例如:python

{ "foo": "baz" }

那麼能夠想像,一個月之後若是有人進行以太坊區塊鏈的同步,這個智能合約就會被執行,可是API的響應數據是和一個月以前不一樣的,這就會致使新同步的
區塊鏈狀態不一樣於以前已經存在的節點狀態。android

這就再也不是徹底自肯定的區塊鏈了。經歷相同的同步過程,個人區塊鏈和你的區塊鏈卻不同!git

讓咱們再換個說法:給定一組區塊,一個節點必須可以從零開始重現區塊鏈的最終狀態,而無需互聯網鏈接。程序員

那麼這一點對於智能合約的開發者意味着什麼?Oralce(預言機),開發者必須構造一個預言機來和實現智能合約與外部世界的交互。github

二、如何實現一個簡單的預言機/Oracle?

如今讓咱們建立一個簡單的預言機/Oracle,來將外部的天氣數據傳入智能合約:web

oracle arch

在最底層的區塊鏈平臺,咱們須要部署一個智能合約,這個合約有一個方法updateWeather()用來更新天氣狀態,只有在合約白名單裏的地址才能夠調用這個方法。updateWeather方法接受天氣數據做爲參數,同時觸發一個以太坊合約事件並將天氣數據做爲事件的參數,這樣JavaScript應用就能夠訂閱這個事件並得到異步通知了。

同時咱們將建立兩個nodejs進程,其中之一就是預言機/Oracle,它的實現邏輯就是週期性地輪詢第三方天氣API來獲取天氣數據,而後將天氣數據提交給智能合約以便進行歷史審計。

另外一個nodejs進程則負責訂閱智能合約的天氣事件,而後在控制檯輸出事件參數。正如以前所述,每當預言機/Oracle調用合約的updateWeather()方法時,都會觸發天氣事件。

須要指出的是,爲了便於理解預言機的核心實現思路,下面的代碼進行了簡化,剔除了必要的錯誤處理,所以並不適用於生產環境。

源代碼在這裏:

接下來咱們詳細講解這個簡單的預言機的實現。

三、預言機智能合約實現

智能合約有一個公開的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)一致時才容許繼續執行該方法,不然將回滾交易。

好了,就這麼簡單。

四、預言機服務

咱們的預言機就是一個簡單的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智能合約時傳入的那個白名單地址所對應的私鑰。

五、天氣事件的利用服務

這是另外一個簡單的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 CONTRACT
BLOCK NUMBER:
  3424586
WEATHER DATA:
{ temperature: '74.75' }

若是你想學習區塊鏈並在Blockchain Technologies創建職業生涯,那麼請查看咱們分享的一些以太坊、比特幣、EOS、Fabric、Tendermint等區塊鏈相關的交互式在線編程實戰教程:

  • java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Java代碼中集成比特幣支持功能,例如建立地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
  • php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Php代碼中集成比特幣支持功能,例如建立地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
  • c#比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在C#代碼中集成比特幣支持功能,例如建立地址、管理錢包、構造裸交易等,是C#工程師不可多得的比特幣開發學習課程。
  • java以太坊開發教程,主要是針對java和android程序員進行區塊鏈以太坊開發的web3j詳解。
  • python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
  • php以太坊,主要是介紹使用php進行智能合約開發交互,進行帳號建立、交易、轉帳、代幣開發以及過濾器和交易等內容。
  • 以太坊入門教程,主要介紹智能合約與dapp應用開發,適合入門。
  • 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
  • ERC721以太坊通證明戰,課程以一個數字藝術品創做與分享DApp的實戰開發爲主線,深刻講解以太坊非同質化通證的概念、標準與開發方案。內容包含ERC-721標準的自主實現,講解OpenZeppelin合約代碼庫二次開發,實戰項目採用Truffle,IPFS,實現了通證以及去中心化的通證交易所。
  • C#以太坊,主要講解如何使用C#開發基於.Net的以太坊應用,包括帳戶管理、狀態與交易、智能合約開發與交互、過濾器和交易等。
  • EOS入門教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、帳戶與錢包、發行代幣、智能合約開發與部署、使用代碼與智能合約交互等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。
  • 深刻淺出玩轉EOS錢包開發,本課程以手機EOS錢包的完整開發過程爲主線,深刻學習EOS區塊鏈應用開發,課程內容即涵蓋帳戶、計算資源、智能合約、動做與交易等EOS區塊鏈的核心概念,同時也講解如何使用eosjs和eosjs-ecc開發包訪問EOS區塊鏈,以及如何在React前端應用中集成對EOS區塊鏈的支持。課程內容深刻淺出,很是適合前端工程師深刻學習EOS區塊鏈應用開發。
  • Hyperledger Fabric 區塊鏈開發詳解,本課程面向初學者,內容即包含Hyperledger Fabric的身份證書與MSP服務、權限策略、通道配置與啓動、鏈碼通訊接口等核心概念,也包含Fabric網絡設計、nodejs鏈碼與應用開發的操做實踐,是Nodejs工程師學習Fabric區塊鏈開發的最佳選擇。
  • Hyperledger Fabric java 區塊鏈開發詳解,課程面向初學者,內容即包含Hyperledger Fabric的身份證書與MSP服務、權限策略、通道配置與啓動、鏈碼通訊接口等核心概念,也包含Fabric網絡設計、java鏈碼與應用開發的操做實踐,是java工程師學習Fabric區塊鏈開發的最佳選擇。
  • tendermint區塊鏈開發詳解,本課程適合但願使用tendermint進行區塊鏈開發的工程師,課程內容即包括tendermint應用開發模型中的核心概念,例如ABCI接口、默克爾樹、多版本狀態庫等,也包括代幣發行等豐富的實操代碼,是go語言工程師快速入門區塊鏈開發的最佳選擇。

原文:Building your first Ethereum Oracle

匯智網翻譯整理,轉載請標明出處

相關文章
相關標籤/搜索