イーサリアムに飛び込む

今日、イーサリアムプラットフォームは、ブロックチェーンの分野で最も有名なブランドの1つになり、ビットコインの人気(および資本化)に非常に近づいています。 しかし、「本格的な」ロシア語のガイドがないため、国内の開発者は、それがどのような動物であり、どのように作業するかをまだよく理解していません。 したがって、この記事では、Ethereumのスマートコントラクトの開発のあらゆる側面を可能な限りカバーしようとしました。







開発ツール、PL自体、UIの追加プロセスなどについて説明します。 最終的には、通常の名刺サイトを取得しますが、「内部」では、Ethereumスマートコントラクトで動作します。 興味のある人-猫をお願いします。







プレビュー









内容





イーサリアムの紹介



この記事は、Ethereum(または一般的なブロックチェーン技術)に完全に不慣れな人を対象としていないため、ここではブロックトランザクション契約などの基本的な事項については説明しません。 私はあなたが少なくとも何が起こっているのか少し知っているということです。 それ以外の場合は、以下のリストから記事をめくると、戻ってきます:)









興味深い記事へのリンクは最後にあります。







PS私はUbuntu 16.04の下で働いているので、インストール、開発、展開の全プロセスはこのOSの下で説明されます。 それにもかかわらず、使用されるすべてのツールはクロスプラットフォームであるため(おそらく、私はチェックしませんでした)、必要に応じて他のOSで実験することができます。







ツール



ゲス



イーサリアムとの連携は、膨大な数のクライアントを通じて可能です。その一部は端末ベースであり、GUIの一部であり、いくつかのハイブリッドソリューションがあります。 一種の標準は[Geth]()で、これはEthereumチームによって開発されています。 以前の記事ですでに彼について書いていますが、 念のため 、繰り返します。







クライアントはGoで記述され、 標準的な方法でインストールされます







sudo apt-get install software-properties-common sudo add-apt-repository -y ppa:ethereum/ethereum sudo apt-get update sudo apt-get install ethereum
      
      





Geth自体にはGUIはありませんが、ターミナルからGUIを操作するのは非常に便利です。 コマンドライン引数のセット全体をここで説明しますが、最も一般的なものをいくつか説明します。







仕事でよく使うコマンドは$ geth --dev --rpc --rpcaddr "0.0.0.0" --rpcapi "admin,debug,miner,shh,txpool,personal,eth,net,web3" console



$ geth --dev --rpc --rpcaddr "0.0.0.0" --rpcapi "admin,debug,miner,shh,txpool,personal,eth,net,web3" console











パリティ



Gethはかなり優れていますが、最近ではRustで書かれた別のクライアントであるParityに会うことができます。 Gethとの主な違いは、統合されたWebインターフェイスです。私の意見では、既存のインターフェイスの中で最も便利です。 インストール:







 sudo <(curl https://get.parity.io -Lk)
      
      





ダウンロードが完了したら、コンソールでparity



を実行し、 localhost:8180でウォレット自体を見つけることができます。







パリティ







別のプラス:パリティは競合他社よりも高速です。 少なくとも著者はそう言っていますが、私の意見によると、これは特にブロックチェーンの同期に関しては本当にそうです。







唯一の注意事項-同等のコンソールはありません。 ただし、次の目的でGethを簡単に使用できます。







 $ parity --geth # Run parity in Geth mode $ geth attach console # Attach Geth to the PArity node (Do it in another window)
      
      





Testrpc



このツールは、以前のツールとは異なり、開発者のみに役立ちます。 1つのtestrpc



チームは、RPCプロトコルをオンにしてプライベートブロックチェーンを作成し、アカウントにETHを含む事前に作成された多数のアカウント、稼働中のマイナーなどを作成できます。 リスト全体はこちらです。 実際、 testrpc



は同じgeth --dev --rpc ...



testrpc



は、アカウントの作成、マイナーのオン/オフ、およびその他の日常的なアクションに時間を費やす必要はありません。







インストールnpm install -g ethereumjs-testrpc









testrpc







ミスト



Ethereumで最も人気のあるウォレットですが、実際にはもっと多くのことができます。 Mistを使用するプロセス全体をステップごとに説明した素晴らしい記事を次に示します。 リリースページから最新バージョンをダウンロードできます 。 ウォレットの使用に加えて、契約を使用することもできます。







霧







リミックス



コントラクト開発用の最も人気のあるIDE。 ethereum.github.io/browser-solidity/のブラウザーで機能し、膨大な数の機能をサポートします。









ただし、オートコンプリートはありません。これは非常に悲しいことです。







リミックス







コスモ



Meteorで作成されたスマートコントラクトを開発するための別のIDEは、そのまま使用できます。 開始するには、新しいターミナルを開き、RPCインターフェイスが有効になっているノードを起動しますgeth --rpc --rpcapi="db,eth,net,web3,personal" --rpcport "8545" --rpcaddr "127.0.0.1" --rpccorsdomain "localhost" console



。 その後、IDE自体を実行できます。







 $ git clone http://github.com/SilentCicero/meteor-dapp-cosmo.git $ cd meteor-dapp-cosmo/app $ meteor
      
      





次に、 localhost:3000を開き、作業を開始できます。







cosmo_screenshot







エーテル原子



スマートコントラクトの開発を加速する今日の最新ツール。 これは、 apm install atom-ethereum-interface



を使用してapm install atom-ethereum-interface



されるAtomエディターのプラグインです。 事は便利です、私は自分でそれを使用します。 JS EVMを使用したり、RPCを介してノードに接続したりできます。 CTRL + ALT + C



のコントラクトをコンパイルし、 CTRL + ALT + S



ネットワークに展開しますCTRL + ALT + S



まあ、それは契約自体を操作するための良いインターフェースを提供します。







atom_ethereum







エディター内でこのような機能豊富な機能が必要ない場合は、Atomの場合、 Solidity - language-ethereumを強調する構文を持つ別のプラグインがあります。 後者は、本質的にSublime textのプラグインであり 、Atomでのみ動作するように変換されます。







堅牢性



Solidityだけでなく、たとえばSerpent (Pythonのように見える)などの他の言語でも契約を作成できるという事実を聞いたことがあるかもしれません。 しかし、開発ブランチイーサリアム/ヘビの最後のコミットは約半年前だったので、どうやら、言語は悲しいかな、廃止されました。







したがって、Solidityについてのみ記述します。 これまでのところ、この言語は開発の比較的初期の段階にあるため、複雑な構造や独自の抽象化はありません。 したがって、それについて個別に話す理由はありません-プログラミングの経験がある人なら誰でも、 ドキュメントを読んでから20分後に自由にそれを書くことができます 。 そのような経験がない場合は、以下に契約コード全体について詳しく説明しました。







自習については、最も詳細な説明を含むいくつかの非常に良い例があります。









繰り返しますが、私は(素晴らしい!)言語のドキュメント時にはロシア語に翻訳されたものにさえ注意します。







名刺契約を作成する



契約を作成する時が来ました。 最終的には、「履歴書」自体を配置する名刺アプリケーションになります。









最初のステップ



最初に、契約テンプレートとコンストラクター関数を作成します 。 コントラクト自体と同じように呼び出す必要があり、一度だけ呼び出されます-コントラクトをブロックチェーンにロードするとき。 これを使用して、単一の変数address owner



を初期化します。 おそらく既に推測したように、ネットワークに契約をアップロードした人の住所が記録されます。 また、契約管理者の機能を実装するために使用されますが、これについては後で詳しく説明します。







 pragma solidity ^0.4.0; contract EthereumCV is Structures { address owner; // ===================== // ==== CONSTRUCTOR ==== // ===================== function EthereumCV() { owner = msg.sender; } }
      
      





基本情報



次の手順では、作成者に関する基本情報(名前、メール、アドレスなど)を指定する機能を追加します。 これを行うには、最も一般的なmapping



を使用します。これは、契約の開始時に宣言する必要があります。







 address owner; mapping (string => string) basic_data;
      
      





契約からこのデータを「受信」できるようにするには、次の関数を作成します。







 function getBasicData (string arg) constant returns (string) { return basic_data[arg]; }
      
      





ここではすべてが単純です。 constant



修飾子に注意する必要があります。これは、アプリケーションの状態を変更しない関数に使用できます(および使用する必要があります)。 このような関数の主なプラス(sic!)は、通常の関数として使用できることです。







運営



履歴書をコンテンツで埋めることを検討する価値があります。 最も単純なケースでは、次のような関数を使用して取得できます。







 function setBasicData (string key, string value) { basic_data[key] = value; }
      
      





ただし、この場合、たとえばsetBasicData("name", "New Name")



呼び出すことで、だれでも名前を変更できます。 幸いなことに、このような試みを1行で停止する方法があります。







 function setBasicData (string key, string value) { if (msg.sender != owner) { throw; } basic_data[key] = value; }
      
      





同様の構成を複数回使用する必要があるため(たとえば、新しいプロジェクトを追加する場合)、特別な修飾子を作成する価値があります。







 modifier onlyOwner() { if (msg.sender != owner) { throw; } _; // Will be replaced with function body } // Now you can use it with any function function setBasicData (string key, string value) onlyOwner() { basic_data[key] = value; }
      
      





必要に応じて、パスワードなどの他の認証方法を使用できます。 ハッシュはコントラクトに保存され、各関数呼び出しで入力されたものと比較されます。 しかし、誰もレインボーテーブルと辞書攻撃をキャンセルしなかったため、この方法はそれほど安全ではないことは明らかです。 一方、 owner



アドレスにアクセスできなくなると、何も編集できなくなるため、この方法も理想的ではありません。







モジュール性



次のステップは、プロジェクト、教育、スキル、出版を記述するためのいくつかの構造を作成することです。 ここではすべてが単純で、構造はCとまったく同じ方法で記述されています。 しかし、現在の契約でそれらを記述するのではなく、別のライブラリーに(新しいファイルで)配置します。 したがって、膨大なコードのシートを回避し、プロジェクトを構成できます。







これを行うには、同じディレクトリで、新しいstructures.sol



ファイルとStructures



ライブラリを作成します。 そして、すでにその内部で各構造について説明します。







 pragma solidity ^0.4.0; library Structures { struct Project { string name; string link; string description; } struct Education { string name; string speciality; int32 year_start; int32 year_finish; } struct Publication { string name; string link; string language; } struct Skill { string name; int32 level; } }
      
      





結果のファイルをインポートするためだけに残ります







 pragma solidity ^0.4.0; import "./structures.sol"; contract EthereumCV { mapping (string => string) basic_data; address owner; Structures.Project[] public projects; Structures.Education[] public educations; Structures.Skill[] public skills; Structures.Publication[] public publications; // ... }
      
      





最も賢いのは、 Structures.Project[] projects



表記がProject



型の要素を持つ動的配列を作成することを意味することをすでに推測していることです。 しかし、 public



修飾子を使用すると、より複雑になります。 基本的に、 get_project(int position) { return projects[position]; }



ような関数に置き換えget_project(int position) { return projects[position]; }



get_project(int position) { return projects[position]; }



-コンパイラーはそのような関数を作成します。 これは変数と同じ方法で呼び出されprojects



。この場合、 projects



です。







あなたは尋ねることができます-なぜ最初にmapping (string => string) public basic_data



ず、代わりに自分でそのような関数を作成したのですか? 理由は単純です-これまでのところ、 public



は、キーが動的データ型である変数の操作方法を知りません( string



はそのような型です)。







 Unimplemented feature (/src/libsolidity/codegen/ExpressionCompiler.cpp:105): Accessors for mapping with dynamically-sized keys not yet implemented.
      
      





これを行うには、例としてmapping (bytes32 => string)



としてbasic_data



を宣言しmapping (bytes32 => string)









ところで、念のために、ローカルファイルに加えて、 RemixはGithubへのリンクを使用して、さらにSwarmプロトコルを使用して.sol



ファイルをインポートできることに注意してください(これはEthereumの分散ストレージのようなものです。詳細はこちら







データをダウンロードして削除する



皆さんの多くは、新しいデータを使用して作業を実装する価値があることをすでに推測していると思います。 出版物のリストの例で示しますが、他の場合はすべてが似ています。







 function editPublication (bool operation, string name, string link, string language) onlyOwner() { if (operation) { publications.push(Structures.Publication(name, link, language)); } else { delete publications[publications.length - 1]; } }
      
      





operation



パラメーターを使用して、最後のパブリケーションを削除する別の関数を作成する必要がなくなりました(これは松葉杖ですが、学習しているだけです)。 配列内の要素を削除するこの方法は、実際にはまったく正しくないことに注意してください。 もちろん、要素自体は削除されますが、インデックスの代わりに空のスペースが残ります。 私たちの場合、これは致命的ではありません(クライアント側で個々の要素の空を確認します)が、一般的に言えば、それを忘れないでください。 さらに、配列全体をシフトし、長さカウンターを減らすことはそれほど難しくありません







データを提供します



既に述べたように、 Project[] public projects



行のpublic



修飾子は、インデックスi



プロジェクトprojects[i]



を返す関数を提供しました。 しかし、プロジェクトの数はわかりません。2つの方法があります。 最初の方法は、存在しない要素に関するエラーが発生するまでi



を反復処理することです。 2つ目は、 projects



のサイズを返す別の関数を作成することです。 2番目の方法に進みます。少し後で、理由を説明します。







 function getSize(string arg) constant returns (uint) { if (sha3(arg) == sha3("projects")) { return projects.length; } if (sha3(arg) == sha3("educations")) { return educations.length; } if (sha3(arg) == sha3("publications")) { return quotes.length; } if (sha3(arg) == sha3("skills")) { return skills.length; } throw; }
      
      





通常の方法で2行を比較できないことに注意してください'aaa' == 'bbb'



。 理由は同じですが、 string



は動的なデータ型であり、それらを操作するのはかなり苦痛です。 そのため、ハッシュを比較するか、文字ごとの比較に関数を使用するかのいずれかです。 この場合、一般的なライブラリstringUtils.solを使用できます。このような機能があります。







展開する



異なる開発環境では、コンパイルと展開のプロセスはもちろん異なります。そのため、私は最も人気のあるRemixに限定します。







最初に、もちろん、コード全体を入力します(最終バージョンはプロジェクトリポジトリにあります )。 次に、 [実行環境選択]ドロップダウンリストで、[ Javascript VM



選択します。ここでは、JSブロックチェーンエミュレーターでコントラクトをテストします。少し後で、実際の実行方法を学習します。 すべてが契約どおりになっている場合は、[ 作成 ]ボタンが使用可能になります。クリックして表示します:







remix_create







コントラクトがブロックチェーンにアップロードされたので(エミュレーションではありますが、本質ではありません)、関数を呼び出して何が起こるかを確認できます。 たとえば、電子メールをコントラクトに保存できます。これには、 setBasicData



関数を見つけ、フィールドに入力して、関数名のボタンをクリックします。







remix_set_basic_data







関数は何も返さないため、 result: 0x



です。 これで、契約から電子メールをリクエストできますgetBasicData



関数を探して試してください:







remix_get_basic_data







残りの機能については、自分で実験することをお勧めします。







UIを追加



以下に、UIを契約に追加する最も一般的な方法について説明します。 JSとHTMLを使用して任意の複雑なインターフェイスを作成できます。Ethereumワーキングノード(またはその類似物)にアクセスできれば十分です。







Web3.js



これは、 汎用JSON RPC仕様を実装するイーサリアム互換のJavaScript APIです。 これは、npmでノードモジュールとして、bowerおよびコンポーネントとして、埋め込み可能なjsおよびmeteor.jsパッケージとして利用できます。

これは、通常のJSを使用してイーサリアムAPIを使用することを奨励するJSライブラリです。 実際、その助けを借りて、ノードに接続するだけで、ブラウザにgethコンソールのようなものが表示されます。 npm



またはbower



経由でインストール:







 $ sudo npm install web3 $ bower install web3
      
      





node.jsを介してweb3を操作する例を次に示します(最初にtestrpc



またはRPCインターフェイスを備えた他のノードを実行します)。







 $ node > var Web3 = require('web3'); > var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); > web3.eth.accounts [ '0x5f7aaf2199f95e1b991cb7961c49be5df1050d86', '0x1c0131b72fa0f67ac9c46c5f4bd8fa483d7553c3', '0x10de59faaea051b7ea889011a2d8a560a75805a7', '0x56e71613ff0fb6a9486555325dc6bec8e6a88c78', '0x40155a39d232a0bdb98ee9f721340197af3170c5', '0x4b9f184b2527a3605ec8d62dca22edb4b240bbda', '0x117a6be09f6e5fbbd373f7f460c8a74a0800c92c', '0x111f9a2920cbf81e4236225fcbe17c8b329bacd7', '0x01b4bfbca90cbfad6d6d2a80ee9540645c7bd55a', '0x71be5d7d2a53597ef73d90fd558df23c37f3aac1' ] >
      
      





同じこと、JSブラウザコンソールからのみ( <script src="path_to/web3.js"></script>



忘れないでください)







browser_js_web3







つまり、この時点でノードを起動し、現在のチェーンと同期させることができ、アプリケーションを作成するだけです。 ただし、2つの微妙な点があります。まず、Ethereumブロックチェーンを同期する必要があり、まだ同期していない可能性が高いです。







2番目のニュアンスは、RPCには認証メカニズムが組み込まれていないため、だれでもJSソースからノードのアドレスを見つけて、好きなように使用できることです。 もちろん、ここでは、最も単純なHTTP基本認証を使用して、Nginxに何らかのラッパーを書くことができますが、これは別の機会です。







メタマスク



したがって、メタマスクプラグイン(alas、Chromeのみ)を使用します。 実際、これはノードとブラウザーの間のレイヤーであり、ブラウザーでweb3を使用できますが、独自のノードはありません。 メタマスクは非常に簡単に機能します。各ページにweb3.jsを埋め込み、メタマスクRPCサーバーに自動的に接続します。 その後、Ethereumを最大限に活用できます。







プラグインをインストールした後、左上隅でTestnet



を選択し、 メタマスクタップでエーテルを取得します。 この時点で、次のようなものを取得する必要があります(もちろん、クリーンなストーリーがあります)。







metamask_ready







メタマスクを使用してデプロイする



Metamaskを使用すると、ネットワークへのコントラクトの展開は、JS EVMの場合と同じくらい簡単です。 これを行うには、Remixを再度開き、 [実行環境選択]リストから[ Injected Web3



れたInjected Web3



を選択します(ほとんどの場合、自動的に選択されます)。 その後、[作成]をクリックして、ポップアップウィンドウを表示します。







metamask_popup







少し後に、 Waiting for transaction to be mined..



公開された契約に関する情報に置き換えられます-これは、彼がブロックチェーンに陥ったことを意味します。 メタマスクを開いてフォームのエントリをクリックすると、契約アドレスを確認できます。







metamask_info







ただし、たとえば、 editProject(...)



関数を呼び出す場合は、トランザクションを確認して、ブロックにマイニングされるまで待機する必要があります。









Web3を介して契約からデータを受信する方法を学ぶのはあなた次第です。 これを行うには、まず、ページ上のweb3の存在を判断する方法を学ぶ必要があります。







 window.addEventListener('load', function() { // Checking if Web3 has been injected by the browser (Mist/MetaMask) if (typeof web3 !== 'undefined') { // Use Mist/MetaMask's provider console.log("Web3 detected!"); window.web3 = new Web3(web3.currentProvider); // Now you can start your app & access web3 freely: startApp() } else { alert('Please use Chrome, install Metamask and then try again!') } })
      
      





startApp()



内で、コントラクトを操作するロジック全体を定義し、 startApp()



やエラーを回避しました。







 function startApp() { var address = { "3" : "0xf11398265f766b8941549c865d948ae0ac734561" // Ropsten } var current_network = web3.version.network; // abi initialized ealier, in abi.js var contract = web3.eth.contract(abi).at(address[current_network]); console.log("Contract initialized successfully") contract.getBasicData("name", function(error, data) { console.log(data); }); contract.getBasicData("email", function(error, data) { console.log(data); }); contract.getSize("skills", function(error, data) { var skills_size = data["c"][0]; for (var i = 0; i < skills_size; ++i) { contract.skills(i, function(error, data) { // Don't forget to check blank elements! if (data[0]) { console.log(data[0], data[1]["c"][0]); } }) } }) }
      
      





js_logs







まとめ



すべてを理解したので、レイアウトとJSを引き受けることができます。 Vue.jsSpecter.cssを使用し、スキルの視覚化のためにGoogle Chartが追加されました。 結果はpavlovdog.github.ioで見ることができます:







cv







結論の代わりに



ブロックチェーンテクノロジーを最も直接使用するアプリケーションをすばやく作成する方法を見ました。 シンプルさを追求するため(結局、これはトレーニング記事です)、私は良い方法で許可されるべきではないいくつかの単純化を行いました。







たとえば、ノードで作業する代わりに、他の誰かのゲートウェイ(メタマスクについて話している)を使用します。 これは便利ですが、ブロックチェーンテクノロジーは主に分散化と仲介者の不在です。 私たちはこれをすべて持っているわけではありません-メタマスクの人々を信頼しています。







別の、それほど重大ではない問題として、契約とトランザクションをそれらに展開するコストを忘れていました。 実際には、 bytes



代わりにstring



を使用する前に10回考える価値がありbytes



。そのようなことは、主に契約を扱う際のコストに影響するためです。 繰り返しになりますが、この例ではTestnet



を使用したため、お金は一切使いませんでしたが、 Main net



作業するときはそれほど無駄にすべきではありません。







いずれにせよ、質問があれば、コメントで尋ねるか、私に電子メールを書いてください。







参照資料






All Articles