以太坊預言機與智能合約開發


什么是以太坊預言機?智能合約就其性質而言,能夠運行各種算法並存儲查詢數據。預言機可以監控以太坊區塊鏈事件並能將監控結果發回智能合約。因為每個節點每次都需要大量計算,所以從Ethereum智能合約開發中進行頻繁的網絡請求是切不實際的。這樣,智能合約就可以與鏈外的世界進行互動了。

但是這樣有一個明顯的信任問題。與信任單一外部數據源的分布式智能合約有些矛盾。不過這可以通過讓多個獨立的預言機來響應相同的查詢最終形成共識來緩解這個問題。

有關預言機的更多信息,請查看在分布式應用程序之間提供“可靠連接”的FinTech公司Oraclize。 他們對預言機的解釋很不錯。

The Tinypay.co DNS Oracle

Tinypay的預言機做了三件簡單的事情:

  1. 從合同中提取'ClientCreated'事件
  2. 使用來自事件的數據驗證DNS記錄
  3. 域名確認后,向合約發送'ConfirmClient'交易

我經歷了幾次迭代,最終實現了,我希望通過它們來引導您了解以太坊的發展。

你也可以直接用RPC,不過似乎不應這么干

我第一次寫預言機,我用了Go-Ethereum。我想直接使用RPC API與Ethereum節點進行所有通信。

這很有趣,因為我能夠學習很多關於以太坊協議如何進行存儲和數據編碼等較底層的內容。我必須手動重新在代碼中創建ABI(應用程序二進制接口),並使用它來發送和解密消息。 ABI對於定義合約如何交互以及如何從線上的原始字節中提取數據是必需的。

從事件中實際提取數據證明比我想象的要復雜得多。Go-Ethereum的處理事件沒完成。我被迫手動輪詢RPC端點,並找出如何將來自原始事件的二進制數據解碼。Go-Ethereum當然似乎是以太坊團隊關注的焦點,他們應該很清楚Go-Ethereum在觀看和解碼事件方面的問題。我希望他們能很快有所提升,這會使得Go-Ethereum成為編寫預言機和其他以太坊客戶端應用程序的更好選擇。

低級別的RPC API和解碼API被證明是非常低效率的,並且他們正在更快地進行迭代,所以...

Web3 則是一個很好的抽象

對於第二次迭代,我切換到node.js並使用web3庫與geth節點進行通信。 這給了我內置的抽象了的事件查詢,數據提取和格式化,而且明顯使開發變得更容易。

我開始使用Alex Beregszaszi非常有用的'tinyoracle'指南,這讓我在第二版中獲得了不錯的成果

下面的代碼是經過選擇編輯的,完整的代碼可以在github存儲庫中找到(本次迭代的標簽為v0.0.2)

var Web3 = require('web3');
var web3 = new Web3();
var contracts = require(path.join(__dirname, 'gen_contracts.json'));

// First we instruct web3 to use the RPC provider
//首先我們指定web3使用RPC接口

web3.setProvider(
  new web3.providers.HttpProvider(
    'http://' + opts.rpc_host + ':' + opts.rpc_port));
// This isn't strictly necessary here, but goes to show the step 
//  required to "unlock" the account before sending transactions.
// 這並不是嚴格需要的,但它顯示了在發送交易之前“解鎖”帳戶所需的步驟。

if (!web3.personal.unlockAccount(
  web3.eth.coinbase, opts.wallet_password)) {
  console.error('Could not unlock');
  process.exit();
}

//Here we register the filter with the ethereum node, 
//and then begin polling for updates.
//在這里,我們用以太坊節點注冊過濾器,然后開始輪詢更新

function runLoop(o) {
  var filter = web3.eth.filter({address: o.contract_address});
  filter.watch(function (err, results) {
    if (err) {
      console.log('WATCH ERROR: ', err);
      process.exit();
    }
    console.debug(results);
  });
}

// If the contract isn't deployed yet, we deploy it here
//如果還沒有部署合約,我們在這里部署它。

if (!opts.contract_address) {
// This block of code loads the ABI for interpreting contract data.
// 該代碼塊加載ABI來解釋合約數據。

  var dmC = web3.eth.contract(JSON.parse(contracts.DomainMicropay.abi));
  var x = {
    from: web3.eth.coinbase,
    data: contracts.DomainMicropay.bin,
    gas: 1000000
  };

  // send the transaction for installing the contract.
//發送用於部署合約的交易。

  dmC.new(x, function (err, resp) {
    if (err) {
      console.error('Loading contract', err);
      process.exit();
    }
    var addr = resp.address;
    if (!addr) {
      console.log('Pending tx: ', resp.transactionHash);
    } else {
      console.log('Deployed Address: ', addr);
      opts.contract_address = addr;
      runLoop(opts);
    }
  });
} else {
  runLoop(opts); 
// in either case, start the polling event loop. 
//在任一種情況下,啟動輪詢事件循環
}

Truffle 應該是你最想用的框架

最后,在第三次迭代中,我放棄了自己搞的這一切。 我們已經在我們的網絡前端使用ConsenSys的優秀工具Truffle。 我只是將生成的構件復制到我的node.js項目中,並直接將其包含在內,然后就開始工作。

使用Truffle,我們能夠將我們的Solidity合約編譯成的一個JavaScript庫,它可以確認各種重要的細節,如合同的部署地址,並完全代替低級RPC通信。 查看事件,發送交易和查詢數據變成了直接從我們的合同中生成的簡單API調用。

// This code extract shows the whole event loop abstracted behind the actual event name: ClientConfirmed and ClientCreated.
// 這段代碼顯示了整個事件循環中的抽象后的實際事件:ClientConfirmed 和 ClientCreated。

startWatcher: function (rpcUrl, unlockPass) {
        password = unlockPass || password;
web3.setProvider(new web3.providers.HttpProvider(rpcUrl));
        DomainMicropay.setProvider(web3.currentProvider);
contract.ClientConfirmed({}, eventOpts(), function (err, data) {
          if (err) {
            console.log('Error ClientConfirmed: ', err);
            return;
          }
          console.log('Event ClientConfirmed: ', data.args.domain);
        });
contract.ClientCreated({}, eventOpts(), function (err, data) {
          if (err) {
            console.log('Error ClientCreated: ', err);
            return;
          }
          console.log('Event ClientCreated: ', data.args.domain);
          contract.getPaymentContractForDomain
            .call(data.args.domain)
            .then(beginDomainVerification(data))
            .catch(errFn('Unhandled Error: '));
        });
      }

正如您所看到的,Truffle為使用智能合約並與之交互提供了一些非常好的抽象。這並不完美,也不能解決合約版本問題等問題。但是我們需要在其他文章中再介紹這些內容。

希望贏得你喜歡,並可以幫助你開發下一個“DApp”。 如果您正在尋求幫助理解或利用區塊鏈技術,請聯系 we@mustwin.com 並參考本文。

原文:medium.com/@mustwin/building-an-oracle-for-an-ethereum-contract-6096d3e39551

安利兩個教程:1.以太坊入門實戰 2.以太坊電商DApp實戰


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM