イーサリアムスマートコントラクトは、単なる「新しいホットなもの」ではありません。彼ら(または関連する何か)は、インターネットの次の新しい時代に人間が互いにビジネスを行う方法を変える準備ができていると私は信じています。それが事実かどうかは時が経てばわかります。
これは、に関する3部構成の記事の最初の記事です。 イーサリアムのスマートコントラクト開発 Solidityを使用して、最も具体的には、いわゆる「オラクル」とのコントラクトの使用を調査します。これは基本的に、他のスマートコントラクトで使用するためにデータをブロックチェーンに送り込むコントラクトです。
このシリーズのパート1の目標は、オラクル契約の概念、その背後にある哲学、またはそれらが何であるかについて深く理解することではありません。イーサリアムオラクルチュートリアルのこの部分の目標は、単に次のことです。
定義:オラクル。スマートコントラクトがブロックチェーン外の世界からのデータにアクセスするための手段。オラクルはそれ自体がスマートコントラクトの一種であり、外部からデータを取得してブロックチェーンに入れ、他のスマートコントラクトが消費できるようにします。
この記事の最初の部分は、すべての前提条件を設定することで構成されます。次に、単一のイーサリアムコントラクトを設定し、Truffleでテストします。最後に、オラクルをクライアントから分離し、それらを共同でテストします。
この記事シリーズ できる スマートコントラクトの最初の紹介として機能しますが、より高度な概念に急速に移行します。初めてのスマートコントラクトチュートリアルの場合は、すぐに高度に登る準備をしてください。あなたが自信を持っていると感じたら、素晴らしいです。そうでない場合は、最初に、より単純な「HelloWorld」タイプのチュートリアルを1つか2つ入手してください。チェックアウト イーサリアムの記事の1つまたは以前 そして クリプトゾンビ 、初心者向け。
警告:スマートコントラクトスペースは非常に新しく、急速に変化します。この記事が書かれたときに新しくなったSolidity構文機能は、これを読んでいる時点で非推奨または廃止されている可能性があります。ゲスバージョンは行き来しているかもしれません。 Solidityは常に新しい言語機能を追加し、古い機能を廃止しています。現在、多くの新機能が開発中です。したがって、必要に応じて、この記事の情報を将来の新しい状況に適合させる準備をしてください。あなたがスマートコントラクト開発の学習に真剣に取り組んでいるなら、私はあなたを信じています。
ユースケース:ユーザーはボクシングの試合に賭けます。
スマートコントラクトはまだ新しいものです。それらはまだ主流になっておらず、それらがどのように機能するかについての非常に多くの側面がまだ打ち出されて標準化されていません。 「オラクル」のアイデアの背後にある推進力について簡単に説明し、辛抱強く説明します。これについては、後の部分で詳しく説明します。
ブロックチェーン契約のエンジニアリング クライアントサーバーアプリのプログラミングとは異なります。重要な違いの1つは、コントラクトが相互作用するデータがすでにブロックチェーン上にある必要があることです。呼び出しはありません でる ブロックチェーンの。言語でサポートされていないだけでなく、ブロックチェーンパラダイムでもサポートされていません。契約は、イーサリアムベースの通貨の形で賭けを行い、それらを契約に保存し、試合の勝者が宣言されたときに、式に従って正しいウォレットアドレスにリリースすることができます。しかし、契約はどのようにして勝者を知るのでしょうか? RESTAPIなどをクエリすることはできません。すでにブロックチェーンにあるデータのみを使用できます!スマートコントラクトの多くのユースケースで同様の問題が発生します。ブロックチェーン外の世界とやり取りできない限り、それらは深刻に制限されます。
コントラクトがブロックチェーン上のデータとのみ対話できる場合、明らかな解決策は、必要なデータをブロックチェーンに挿入することです。そしてそれがオラクルです。オラクルは別のコントラクトであり、データをブロックチェーンに挿入して、他のコントラクトがデータを消費できるようにします。それは信頼と信頼性についての疑問を提起するかもしれませんが、それがオラクルであるということを今のところ受け入れてください。このシリーズのパート3では、これらのニュアンスについて説明します。この例のユースケースでは、オラクルは、(a)利用可能な一致、および(b)一度決定されたそれらの一致に勝った人に関して、データをブロックチェーンに挿入するコントラクトになります。
基本的なセットアップでは、以下をインストールします。
この記事には、環境設定の完全なガイドとなるスペースはありませんが、大まかなガイドとして機能します。ただし、特定のOS向けの完全なセットアップガイドはすでにたくさんあり、インターネットには新しいものは必要ないため、問題ありません。だから私はあなたをすぐに道に連れて行き、必要に応じてより多くの詳細を得るためのいくつかのリソースにあなたを向けます。システムの要件とGoogleの指示に従って、要件と前提条件をインストールする準備をしてください。
Gethは、EthereumコアソフトウェアであるGo-ethereumです。この演習はまったく必要ありませんが、イーサリアムの開発者になる可能性のある人なら誰でもそれを持っていて、それに精通している必要があります。スマートコントラクトをライブのイーサリアムネットワークに展開する場合は、これが必要になります。
トリュフは私たちが開発に使用する主なものであり、このガイドの絶対的な要件です。お使いのOSの特定の指示を見つけてそれに従ってTruffleをインストールしてください。以下は、うまくいけばあなたを助けるいくつかのリンクです。
別のテストツールとして使用するためにGanacheCLIをインストールすることをお勧めしますが、チュートリアルでは実際には使用しません。オプションです。
このチュートリアル全体を、Notepad ++、gedit、viなどの単純なテキストエディター、または任意のテキストエディターやIDEを使用して実行することは可能です。私は個人的に次の拡張機能を備えたVisualStudioCodeを使用しています。
注:拡張機能は必須ではありません。拡張機能は、コーディング環境を改善するだけです。
Truffleは、スマートコントラクトをコンパイルしてブロックチェーンに移行するための非常に便利なツールであり、開発およびデバッグユーティリティも提供します。 Truffleと統合するには、いくつかのプロジェクト設定が必要になります。次に、Truffleとディレクトリ構造の両方でプロジェクトのシェルを設定します。ただ座って、今のところロボットで手順に従って、楽しんでください。
オープンソースプログラムのソースコードへの変更を製品に追加することはできません。
すべてのコードを格納するディレクトリを作成します。あれを呼べ oracle-example 。
最終的にプロジェクトは2つのサブプロジェクトで構成されるため、ルートディレクトリ内に2つのサブディレクトリを作成します。ディレクトリを作成します。
これが開発する最初のプロジェクトであるため、クライアントフォルダに移動します。でターミナル(コマンドライン)ウィンドウを開きます / oracle-example / client フォルダ。
コマンドtruffle init
を実行します。
作成された多くのファイルの中には truffle-config.js そして truffle.js 。両方は必要ないので削除します truffle-config.js (混乱や混乱を避けるためだけに)。
編集する必要があります truffle.js 、テストのためにトリュフを正しい方向に向けるため。の内容を置き換えます truffle.js 次のように:
module.exports = { networks: { development: { host: 'localhost', port: 8545, network_id: '*' // Match any network id } } };
https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/truffle.js
Truffleinitがというディレクトリを作成したことに注意してください 移行 (( oracle-example / client / migrations )。そのフォルダ内には、 1_initial_migration.js 。
移行ディレクトリに別のファイルを追加し、名前を付けます 2_deploy_contracts.js 、次の内容で:
var BoxingBets = artifacts.require('BoxingBets'); module.exports = function(deployer) { deployer.deploy(BoxingBets); };
https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/migrations/2deploycontracts.js
簡単なセットアップが邪魔にならないので、コーディングを開始する準備が整いました。記事のこの部分はまだ紹介とセットアップであるため、コードをかなりすばやく説明することを忘れないでください。パート2でコードのより詳細な説明を、パート3でアーキテクチャと概念のより詳細な説明を行います。それでも、コードで明らかないくつかのコア概念にすばやく触れます。追いつくために注意深く従ってください。
プロセスのこのステップの完全なコードは、GitHubで入手できます。 https://github.com/jrkosinski/oracle-example/tree/part1-step1
Solidityの「コントラクト」は、他のオブジェクト指向言語のクラスとほぼ同じです。言語自体は、とりわけGolangやJavaScriptと比較されています。 Solidityの他のいくつかの言語構造(後で例を示します)は、修飾子、ライブラリ、およびインターフェイスです。継承(多重継承を含む)は、コントラクトでサポートされています。 Solidityコントラクトファイルの拡張子は.solです。
このファイルをプロジェクトに追加します。 /oracle-example/client/contracts/OracleInterface.sol
https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/contracts/OracleInterface.sol
通常、オラクルのインターフェースはまさにそれ、つまりインターフェースです。この最初のイテレーションでは、今のところプレースホルダーとして、Solidityプロジェクトに含まれている単純なクラスです。 Truffleでコントラクトを正常にコンパイルして実行した後、次のステップで移動します。後でこれを実際のインターフェイスに変換すると、関数の実装は空になります。
このファイルをプロジェクトに追加します。 /oracle-example/client/contracts/BoxingBets.sol
国境税調整とは
https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/contracts/BoxingBets.sol
これはボクシングの試合データを消費し、ユーザーが利用可能な試合を照会し、それらに賭けることを可能にする契約です。後の反復では、賞金を計算して支払います。
今こそ、最初にすべてが正しく行われたかどうかを確認するときです。
でターミナルを開きます / oracle-example / client / フォルダ
次のコマンドでコードをコンパイルします。
truffle compile
別の方法:recompile.shシェルスクリプトを使用します( https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/recompile.sh )。
コードがまだ最終的な形になっていないため、多くの警告が表示されることに注意してください。
Truffle開発コンソールを開きます。
truffle develop
次に、Truffle開発者コンソールで、テストネットワークに移行します。
truffle(develop)> migrate
開発コンソールのプロンプトで、次のコード行を入力します。
truffle(develop)> BoxingBets.deployed().then(inst => { instance = inst })
現在、「インスタンス」はBoxingBetsコントラクトを参照する変数であり、そのパブリックメソッドを呼び出すために使用できます。
次のコマンドを使用してテストします。
truffle(develop)> instance.test(3, 4)
パブリック「テスト」機能が含まれていることに注意してください BoxingBets.sol 。コントラクトがコードを実行していること、およびTruffle開発コンソールから呼び出すことができることを示すために、渡した2つの数値を合計します。正気に見える応答(以下を参照)が得られれば、ここでの作業は完了です(少なくとも今のところ)。
これまでにすべてが成功した場合、私たちはこぶを超えています。次に行うことは、oracleコントラクトをBoxingBetsコントラクトから分離することです。実際の使用では、オラクルのコントラクトはブロックチェーン上のクライアントコントラクトとは別に存在するため、次のことができる必要があります。
つまり、これから行うことは、オラクルとクライアントを2つの別々のブロックチェーンコントラクトエンティティに分離し、それらを相互に通信させることです。クライアントは、アドレスによってオラクルをインスタンス化し、それを呼び出します。
githubフローとgitフロー
まず、具体的なクラスではなく、オラクルへの動的インターフェースを参照するように、クライアントコントラクト(クライアント)を変更します。次に、外部契約からオラクルをインスタンス化することを確認します。
に入る /oracle-example/client/contracts/OracleInterface.sol 。前に述べたように、これは現在インターフェースではありませんが、これからインターフェースにします。そこにあるものを次の内容に置き換えます。
https://github.com/jrkosinski/oracle-example/tree/part1-step2/client/contracts/OracleInterface.sol
pragma solidity ^0.4.17; contract OracleInterface { enum MatchOutcome { Pending, //match has not been fought to decision Underway, //match has started & is underway Draw, //anything other than a clear winner (e.g. cancelled) Decided //index of participant who is the winner } function getPendingMatches() public view returns (bytes32[]); function getAllMatches() public view returns (bytes32[]); function matchExists(bytes32 _matchId) public view returns (bool); function getMatch(bytes32 _matchId) public view returns ( bytes32 id, string name, string participants, uint8 participantCount, uint date, MatchOutcome outcome, int8 winner); function getMostRecentMatch(bool _pending) public view returns ( bytes32 id, string name, string participants, uint participantCount, uint date, MatchOutcome outcome, int8 winner); function testConnection() public pure returns (bool); function addTestData() public; }
に BoxingBets.sol 、次の行を置き換えます。
OracleInterface internal boxingOracle = new OracleInterface();
これらの2行で:
address internal boxingOracleAddr = 0; OracleInterface internal boxingOracle = OracleInterface(boxingOracleAddr);
ここで必要なのは、オラクルのアドレスを動的に設定する方法と、現在のオラクルアドレスを見つけるために呼び出すことができる関数です。これらの2つの関数をに追加します BoxingBets.sol :
/// @notice sets the address of the boxing oracle contract to use /// @dev setting a wrong address may result in false return value, or error /// @param _oracleAddress the address of the boxing oracle /// @return true if connection to the new oracle address was successful function setOracleAddress(address _oracleAddress) external onlyOwner returns (bool) { boxingOracleAddr = _oracleAddress; boxingOracle = OracleInterface(boxingOracleAddr); return boxingOracle.testConnection(); } /// @notice gets the address of the boxing oracle being used /// @return the address of the currently set oracle function getOracleAddress() external view returns (address) { return boxingOracleAddr; }
そして最後に、クライアントとオラクルの間の接続をテストするために、 テスト Oracle接続をテストする関数を備えたBoxingBetsの関数:
/// @notice for testing; tests that the boxing oracle is callable /// @return true if connection successful function testOracleConnection() public view returns (bool) { return boxingOracle.testConnection(); }
setOracleAddress
の定義に注意してくださいonlyOwner
がありますそれに続く修飾子。これにより、関数がパブリックであっても、この関数がコントラクトの所有者以外から呼び出されることは制限されます。それは言語機能ではありません。これは、OpenZeppelinの一般ユーティリティSolidity契約のライブラリから削除されたOwnable契約によって提供されます。その詳細についてはパート2で説明しますが、その使用を容易にするためにonlyOwner
修飾子、いくつかの変更を加える必要があります:
コピー Ownable.sol から https://github.com/jrkosinski/oracle-example/tree/part1-step2/client/contracts/Ownable.sol に / oracle-example / client / Contracts / 。
上部に参照を追加します BoxingBets.sol 、 そのようです:
import './Ownable.sol';
(インポートする行のすぐ下に追加できます OracleInterface.sol 。)
BoxingBetsのコントラクト宣言を変更して、Ownableから継承するようにします。
contract BoxingBets {
これに:
contract BoxingBets is Ownable {
そして、私たちはすべて準備ができているはずです。あなたが迷子になった場合に備えて、完全なコードはここにあります: https://github.com/jrkosinski/oracle-example/tree/part1-step2/client/contracts
BoxingBetsコントラクトがアドレスによって完全に別個のコントラクト(つまり、オラクル)を参照しようとしているので、次の仕事はそのオラクルコントラクトを作成することです。そこで、オラクルコントラクトを含むまったく別のプロジェクトを作成します。これは基本的に、クライアント契約プロジェクトに対してすでに行った設定と同じです。つまり、コンパイルと開発のためにTruffleをセットアップします。
あなたはすでにというフォルダを持っているはずです / oracle-example / oracle / これは前の手順で作成しました(そうでない場合は、先に進んで空のディレクトリを作成してください)。そのディレクトリでターミナルを開きます。
truffle init
を実行します。 module.exports = { networks: { development: { host: 'localhost', port: 8545, network_id: '*' // Match any network id } } };
ここの例を参照してください: https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/truffle.js
内部 / oracle-example / oracle / migrations / 、というファイルを作成します 2_deploy_contracts.js 、次の内容で:
var BoxingOracle = artifacts.require('BoxingOracle'); module.exports = function(deployer) { deployer.deploy(BoxingOracle); };
ここの例を参照してください: https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/migrations/2_deploy_contracts.js
この手順では、次の3つのファイルをからコピーするだけです。 https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/contracts/ あなたの/oracle-example/oracle/contracts/
にフォルダ:
さて、プロジェクトの現在の反復では、スマートコントラクトオラクルを徹底的にテストする必要があります。これは、プロジェクトの残りの部分を構築するためのベースになるためです。したがって、oracleプロジェクトを設定してコードをコピーしたので、次のことを行います。
/oracle-example/oracle/
に開いているターミナルで、次のコマンドを実行します。繰り返しますが、これらの手順は、クライアント契約をコンパイルして移行するためにすでに行った手順と同じです。
truffle compile
別の方法:recompile.shシェルスクリプトを使用します( https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/recompile.sh )。
awsソリューションアーキテクト学習ガイド
Truffle開発コンソールを開きます。
truffle develop
テストネットワークに移行します。
truffle(develop)> migrate
引き続きTruffle開発コンソールで、これを入力して、Oracleコントラクトへの使用可能なポインターをキャプチャします。
truffle(develop)> BoxingOracle.deployed().then(inst => { instance = inst })
これで、Oracleコントラクトに対して一連のテストを実行してテストできます(実行する必要があります)。次のコマンドを順番に実行して、結果を確認してください。
truffle(develop)> instance.testConnection() ... truffle(develop)> instance.getAllMatches() ... truffle(develop)> instance.addTestData() ... truffle(develop)> instance.getAllMatches() ...
この時点で、oracleコードを調べ、使用可能なパブリックメソッドを確認し、コード内のコメントを読んで、実行する独自のテストをいくつか考え出すことをお勧めします(そして、ここでコンソールで実行します。上に示しました)。
これで、最終テストの準備が整いました。クライアントコントラクトがすでにブロックチェーン上にあるオラクルコントラクトを呼び出し、そのデータを取得して使用できることをテストします。これらすべてが機能する場合は、さらに実験するために使用できるクライアントとオラクルのペアがあります。エンドツーエンドテストを実行するための手順:
2つのターミナルウィンドウを開きます。
私はあなたが保つことをお勧めします / oracle-example / client / 1つは左側に開いており、 / oracle-example / oracle / 1つは右側に開いており、混乱を避けるために注意深く進んでください。
で次のコマンドを実行します / oracle-example / oracle / ターミナル:
bash recompile.sh truffle develop truffle(develop)> migrate truffle(develop)> BoxingOracle.deployed().then(inst => { instance = inst })
で次のコマンドを実行します / oracle-example / client / ターミナル:
bash recompile.sh truffle develop truffle(develop)> migrate truffle(develop)> BoxingBets.deployed().then(inst => { instance = inst })
次のコマンドを実行して、 / oracle-example / oracle / ターミナル:
truffle(develop)> instance.getAddress()
この呼び出しからの出力であるアドレスをコピーします。次のステップで使用します。
アジャイルソフトウェア開発のドキュメント
次のコマンドを実行して、 / oracle-example / client / ターミナル:
truffle(develop)> instance.setOracleAddress('')
そしてそれをテストします:
truffle(develop)> instance.testOracleConnection()
出力がtrue
の場合は、問題ありません。
次のコマンドを実行して、 / oracle-example / client / ターミナル:
truffle(develop)> instance.getBettableMatches()
オラクル側にテストデータがまだ追加されていないため、空の配列が返されるはずです。
次のコマンドを実行して、 / oracle-example / oracle / テストデータを追加する端末:
truffle(develop)> instance.addTestData()
次のコマンドを実行して、 / oracle-example / client / ターミナル、クライアントから新しく追加されたテストデータを取得できるかどうかを確認します。
truffle(develop)> instance.getBettableMatches()
ここで、getBettableMatches()
によって返された配列から個々のアドレスを取得し、それらをgetMatch()
に接続するとします。
この時点で、クライアントコードを調べ、使用可能なパブリックメソッドを確認し、コード内のコメントを読んで、実行する独自のテストをいくつか考え出すことをお勧めします(そして、ここでコンソールで実行します。上記)。
この演習の結果は限られていますが、現実的なペースを維持するための目標も限られています。私たちのクライアントはまだ賭けをしたり、資金を処理したり、賞金を分割したりする能力を持っていません。私たちが持っているのは、知識と経験を除いて、次のとおりです。
そして、それは短い記事としてはそれほど悪くはありません。
に このシリーズのパート2 、コードをさらに深く掘り下げて、スマートコントラクト開発に固有の機能のいくつかと、Solidityに固有の言語機能のいくつかを見ていきます。この部分で説明したばかりのことの多くは、次で説明します。
に このシリーズのパート3 、特にオラクルでの使用に関連して、スマートコントラクトの哲学と設計について少し説明します。
単独実験は学ぶのに良い方法です。このチュートリアルを拡張して知識を深める方法を考えている場合は、いくつかの簡単な提案を次に示します(以下のいずれもパート2および3では取り上げません)。
幸運を祈ります。ご不明な点がございましたら、お気軽にお問い合わせください。必ずしも迅速な返信を保証することはできませんが、最善を尽くします。
イーサリアム開発で使用されるプログラミング言語はSolidityです。これは、JavaScript、Python、およびC ++に触発された契約指向のプログラミング言語です。
いわゆる* blockchain oracle *は、スマートコントラクトで使用されるさまざまな状態と発生に関する情報を提供する信頼できるデータソースです。
スマートコントラクトオラクルは、実際のイベントとデジタルコントラクトの間のリンクを提供するために使用されます。オラクルによって提供されるこの外部データは、スマートコントラクトの実行をトリガーする場合とトリガーしない場合があります。