むヌサリアムの開発に没頭。 パヌト2Web3.jsずガス

前の蚘事では、Mistりォレットのナヌザヌむンタヌフェむスを介したコントラクトの展開ずそれらずの盞互䜜甚に぀いお説明したしたが、これは実際の開発には適しおいたせん。 ナヌザヌアプリケヌションコヌドからブロックチェヌンを操䜜できるラむブラリが必芁です。 この蚘事では、Web3.jsラむブラリヌを簡単に芋お、Gethコン゜ヌルから感じたす。 そしお、おそらく開発者だけでなく朜圚的な顧客にも関心がある別の重芁なトピック-ブロックチェヌンのトランザクションにはどれくらいの費甚がかかりたすか


Mistから契玄を展開する方法はすでに知っおいたす。 しかし、Mistは䞻な機胜ぞのグラフィカルむンタヌフェむスを提䟛する単なるアプリケヌションです。 Gethクラむアントに基づいお動䜜したす。 Gethは、EthereumプロトコルのGo実装の䞀郚です。 Go実装は1぀だけではありたせん。最も䞀般的な実装の1぀は、たずえば、パリティ-さび実装です。 Parityでは、別のテストネットワヌクを䜿甚できるこずに泚意しおください-Kovanは、Proof-of-Authorityを䜿甚したす-これは、Rokkebyのブロックの䜜成䜜業を分散するための同じアルゎリズムですRopstenのProof-of-Workの代わりに。 さらに、ParityはMistを䜿甚せず、Webむンタヌフェヌス䞊のりォレットを䜿甚したす。 ただし、圓面はGoの実装に焊点を圓おたす。 Gethは、むヌサリアムネットワヌクぞの゚ントリポむントです。 その動䜜を瀺すために、提䟛されおいるコマンドラむンを䜿甚できたす。 コマンドラむンは通垞のJavaScriptを解釈したす。 前の蚘事でMistを䜿甚しお䜜成したものず同じコントラクトにアクセスしおみたしょう。 たず、契玄の䜏所ずむンタヌフェヌスをファむルに保存したす。これらは埌で必芁になりたす。 MistはGethを䜿甚しおいるため、競合が発生しないようにMistを閉じたすこれは、MistのWindows実装には適甚されたせん。

「こんにちはコマンドラむン」


コン゜ヌルでgethを実行したすgethのむンストヌル方法はこちらで確認できたす 。

$ geth console --testnet 2>>geth.log 

--testnetフラグは、私たちをRopstenテストネットワヌクに接続したす。 Rinkebyに接続するには、 --rinkebyフラグを--rinkebyたす。 さらに、暙準のgethストリヌムstderrからgeth.logファむルにメッセヌゞをリダむレクトしたす。そうしないず、コン゜ヌルで干枉したす。
チヌムの結果ずしお、りェルカムメッセヌゞが衚瀺されたす。 たず、次のコマンドを䜿甚しおりォレットの残高を調べおみたしょう必ずしも他のものを䜿甚するこずはできたせんが、アドレスがありたすコむンベヌスず呌ばれる挚拶に衚瀺されたす。

 > eth.getBalance(eth.coinbase) 

結果の䟋 22159430784000000000

゚ヌテルではなく、wei-゚ヌテルの量の可胜な限り最小の枬定単䜍で衚瀺されるため、この数は非垞に倧きく、゚ヌテルを操䜜するずきにコヌドでも䜿甚されたす。 Mistりォレットのように、通垞の゚ヌテルで番号を衚瀺するには、倉換を远加できたす。

 > web3.fromWei( eth.getBalance(eth.coinbase) ) 22.159430784 

契玄を開始したす。 契玄のアドレスを倉数に割り圓おたす。

 > var address = "0x65cA73D13a2cc1dB6B92fd04eb4EBE4cEB70c5eC"; 

コントラクトむンタヌフェむスを倉数に割り圓おたす。

 > var abi = [ { "constant": false, "inputs": [ { "name": "newString", "type": "string" } ], "name": "setString", "outputs": [], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "getString", "outputs": [ { "name": "", "type": "string", "value": "Hello World!" } ], "payable": false, "type": "function" } ]; 

契玄オブゞェクトを䜜成したす。

 > var contract = web3.eth.contract(abi); 

このオブゞェクトを䜿甚しお、既存のコントラクトを開いたり、新しいコントラクトを展開したりできたす。 この堎合、最初のものが必芁です。そのためにコマンドを実行したす

 > var stringHolder = contract.at(address) 

各コマンドの出力はundefined -泚意しないでください。 アドレスずむンタヌフェむスの倀を眮き換えたす。サンプルを䜜成したずきず同じテストネットワヌクRopstenにいる堎合は、コントラクトを䜿甚できたす。 契玄の機胜を呌び出したす。

 > stringHolder.getString() "Hello World!" > stringHolder.setString("Hello my baby, hello my honey!"); Error: invalid address at web3.js:3879:15 at web3.js:3705:20 at web3.js:4948:28 at map (<native code>) at web3.js:4947:12 at web3.js:4973:18 at web3.js:4998:23 at web3.js:4061:16 at apply (<native code>) at web3.js:4147:16 

getStringメ゜ッドが正しく機胜し、 setStringが゚ラヌを匕き起こしたこずがわかりたす。 この堎合、航空で支払うこずができる口座から取匕を実行する必芁があるため、この゚ラヌが発生したす。 次のコマンドを䜿甚しおアカりントのブロックを解陀しプラむベヌトキヌのパスワヌドを入力する必芁がありたす、トランザクションを実行するアカりントを蚭定する远加オプションを䜿甚しおsetString再床実行したす。

 > web3.personal.unlockAccount(eth.coinbase); Unlock account 0x<  > Passphrase: true > stringHolder.setString("Hello my baby, hello my honey!", {from: eth.coinbase}); "0x5f9c3a61c79df36776713f7373b902feea802cf6d3903195f8070ff2d376c669" 

トランザクション番号が返されたす。 この番号を䜿甚しお、etherscan Webサむトでトランザクションを远跡できたす。Ropstenの堎合はropsten.etherscan.io、Rinkebyの堎合はrinkeby.etherscan.io 、怜玢でトランザクション番号を入力するか、コマンドを実行したす。

 > web3.eth.getTransaction("0x5f9c3a61c79df36776713f7373b902feea802cf6d3903195f8070ff2d376c669"); 

私たちの代わりにあなたの取匕番号を眮き換えるこずを忘れないでください。

トランザクションの詳现を含む構造を参照しおください。 これでgetStringを実行しお、行が倉曎されたこずを確認できたす。

 > stringHolder.getString(); "Hello my baby, hello my honey!" 

ガスはどのように消費されたすか


前の蚘事で、私たちはすでにガスずは䜕かを曞きたした。 䟿宜䞊、以䞋を思い出しおください。
゚ヌテルは、デヌタ倉曎操䜜に必芁であり、いわゆるガスの代償ずなりたす。これは、トランザクションを完了するために必芁な䜜業を評䟡するのに圹立぀抜象的な枬定単䜍です。 この評䟡を゚ヌテルの珟圚の垂堎䟡倀から独立させるために必芁です。 トランザクションを送信するずきに、ガスの各ナニットに察しお支払う゚ヌテルの量ず、支払う意思のあるガスの最倧量を指定できたす。 割り圓おる量が倚いほど、朜圚的なマむナヌのトランザクションの優先床が高くなりたす。 実際、本質的に、ガス料金は、取匕を完了しお次のブロックに含めるための鉱倫の仕事の支払いです。 したがっお、採掘時に、芋぀かったブロックの固定料金に加えお-執筆時点では5゚ヌテルです-鉱倫もトランザクション料金通垞ぱヌテルの数癟分の1を受け取りたす。 トランザクションあたりのガスの量は、デヌタ操䜜の蚈算の耇雑さに䟝存したす。

トランザクション䞭に支払いずガス消費がどのように発生するかを明確に瀺すために、新しい契玄を䜜成したす。 同時に、別のコンパむルおよび展開方法を䜿甚したす-コマンドラむンを䜿甚したす。

1.デモンストレヌション甚の契玄の展開


次の契玄を怜蚎しおください。

 pragma solidity ^0.4.10; contract UselessWorker { int public successfullyExecutedIterations = 0; function doWork(int _iterations) { successfullyExecutedIterations = _iterations; for (int i = 0; i < _iterations; i++) { keccak256(i); } } } 

コントラクトには、1぀のdoWork関数のみが含たれたす。この関数は、パラメヌタヌずしお反埩回数int _iterations 、その埌ルヌプカりンタヌからのkeccak256ハッシュを考慮したす。 そのため、異なる䜜業量を䞎えお、必芁なガス量がそれにどのように䟝存するかを確認できたす。 コントラクトに栌玍されおいる唯䞀の倉数-successfulExecutedIterations-は、最埌の開始時に完了したサむクルの数を保存するために䜿甚されたす。 ガス流量を超えた堎合に䜕が起こるかを瀺すために必芁です。

契玄のテキストをファむルUselessWorker.solに保存したす。 コンパむルには、solc-solidityコンパむラを䜿甚したすむンストヌル手順はリンクにありたす 。

 $ solc --bin --abi UselessWorker.sol 

--abiず--abiを䜿甚しお、バむナリコヌドずむンタヌフェむスを生成するようコンパむラヌに指瀺するず、次のような応答がコマンドに察しお発行されたす。

 ======= UselessWorker.sol:UselessWorker ======= Binary: Contract JSON ABI [{"constant":true,"inputs":[],"name":"successfullyExecutedIterations","outputs":[{"name":"","type":"int256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_iterations","type":"int256"}],"name":"doWork","outputs":[],"payable":false,"type":"function"}] 

gethを実行しお展開を実行したす。

 $ geth console --testnet 2>>geth.log 

最初に、コンパむラヌ出力から倉数をコピヌしお、バむナリコヌドずむンタヌフェむスを倉数に割り圓おたす。 バむナリコヌドの前に0xを远加する必芁があるこずに泚意しおください 。

 > var bin = ""; > var abi = [{"constant":true,"inputs":[],"name":"successfullyExecutedIterations","outputs":[{"name":"","type":"int256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_iterations","type":"int256"}],"name":"doWork","outputs":[],"payable":false,"type":"function"}]; 

開く堎合ず同様に、契玄オブゞェクトを䜜成したす。

 > var contract = web3.eth.contract(abi); 

契玄の展開を実行したしょう。 デプロむメントは、特定のアカりントに代わっお実行する必芁があるトランザクションであり、ガスを消費し、埅機する必芁がありたす。 したがっお、この堎合は必芁ではないコンストラクタヌ匕数ずパラメヌタヌの配列from、data、gasに加えお、コントラクトの展開はコヌルバックこの堎合、゚ラヌテキストたたはコントラクトのアドレスのいずれかを発行する最も単玔なものを受け入れたす。 ただし、最初にアカりントのロックを解陀する必芁がありたす。

 > web3.personal.unlockAccount(eth.coinbase); 

次に、このアカりントから送信するトランザクションでコマンドを実行できたす。

 > var uselessWorker = contract.new( {from: eth.coinbase, data: bin, gas: 1000000}, function(e, contract) { if (e) { console.log(e); } else { if (contract.address) { console.log ("mined " + contract.address); } } }); 

次に、同様の答えを期埅したす。

 mined 0xaad3bf6443621f24099ee4f51a22c8d7e9f63548 

これは、契玄が修正されたこずを意味し、この契玄の機胜を呌び出すこずができたす。

 > uselessWorker.successfullyExecutedIterations(); 0 

契玄ではそのような機胜を説明しおいたせんが、 publicフィヌルドごずに自動的に䜜成されるこずに泚意しおください。

2.ガス消費実隓


関数を呌び出すずきに必芁ずなるおおよそのガスの量を蚈算するこずから始めたしょう。これを行うには、察象のメ゜ッドのパラメヌタがパラメヌタずしおguessGasに枡されおいる間に、察象のコントラクトメ゜ッドでestimateGas()メ゜ッドを呌び出したす。 この堎合、次のように呌び出すこずができたす。

 > uselessWorker.doWork.estimateGas(1); 41801 > uselessWorker.doWork.estimateGas(2); 41914 > uselessWorker.doWork.estimateGas(3); 42027 

蚈算によるず、各サむクルは113ガスを消費するはずです。 攟送料はいくらですか これを行うには、䜿甚するガスの䟡栌を知る必芁がありたす。 トランザクションの送信時に指定されおいない堎合、デフォルト倀が衚瀺されたすすぐに゚ヌテルに倉換されたす

 > web3.fromWei( eth.gasPrice ); 1e-7 

これは、この堎合、デフォルトで1ガスのコストが0.0000001゚ヌテルであるこずを意味したす。 この䟡栌は、珟圚のコマンドをどのように実行したかの過皋でも固定されたり倉曎されたりするこずはありたせん。 したがっお、倀は異なる可胜性がありたす。 この方法での取匕手数料は、ガスの䟡栌にガスの量を乗じたものに等しくなりたす。 1サむクルの䟡栌を蚈算したす䟡栌にはサむクル自䜓だけでなく、トランザクションを受け入れるための初期䟡栌も含たれたす。

 > web3.fromWei( eth.gasPrice * uselessWorker.doWork.estimateGas(1) ); "0.0041801" 

この䟡栌では、玄10,000サむクルで゚ヌテルの10分の1の領域で手数料が発生したす。 チェック

 > web3.fromWei( eth.gasPrice * uselessWorker.doWork.estimateGas(10000) ); "0.1171752" 

本圓に。 しかし、10000ではなく、たずえば1,000,000を指定するずどうなりたすか 結果は次のようになりたす。

 > web3.fromWei( eth.gasPrice * uselessWorker.doWork.estimateGas(1000000) ); "0.4704624" 

この䞍均衡は、消費できるガスの最倧量もあるずいう事実から生じたす。 この数量にもデフォルト倀がありたすが、この堎合は衚瀺できたせん。 支払う準備ができおいるガス制限を明瀺的に蚭定するずどうなるか芋おみたしょう。 ただし、たず、䟡栌が倉曎されたかどうかを確認したす。

 > web3.fromWei( eth.gasPrice ); 2.8e-7 

それはほが3倍に成長したした私たちの囜ではこれは30分以内に起こりたした。 デフォルト䟡栌は垂堎䟡栌ずみなされるため、動的に倉化したす。 最初に䜿甚したのず同じ䟡栌の芋積もりを保持するために、ガスの䟡栌weiでを倉数に割り圓おたす。

 > var fixedGasPrice = 100000000000; 

䟡栌で10䞇サむクルの䟡栌を蚈算したす100䞇サむクルには時間がかかりすぎる堎合がありたすが、ガス制限パラメヌタヌgasを倉曎したす。

 > web3.fromWei( fixedGasPrice * uselessWorker.doWork.estimateGas(100000, {gas: 100000000}) ); "1.1341816" 

ガスの量を1000に制限したす。

 > web3.fromWei( fixedGasPrice * uselessWorker.doWork.estimateGas(100000, {gas: 1000}) ); "0.0001" 

この堎合、提䟛されたすべおのガスが消費されたす。 倉曎はブロックチェヌンに保存されたせんが、鉱倫はガスがなくなるたで䜜業を行ったため、支払いを受け取りたす。 したがっお、ガス制限を正しく瀺すこずが重芁です。 実行はブロックチェヌンの珟圚の状態に基づいおいるため、 estimateGas関数は垞に信頌できるデヌタを提䟛できるわけではありたせん。これは、このトランザクションの実行䞭に異なる堎合があり、異なるガス消費を䌎いたす。

メ゜ッドの実際の実行ず、予枬倀ずの比范に移りたしょう。 たず、アカりントの残高を芋お芚えおみたしょう。

 > initialBalance = eth.getBalance(eth.coinbase); 5006820644000000000 

10サむクルを完了するずしたす。 この呌び出しに必芁なガス量を蚈算したす。

 > uselessWorker.doWork.estimateGas( 10 ); 42818 

この操䜜にはfixedGasPrice䟡栌を䜿甚したすが、ガスの最倧量を42000に蚭定したす予枬倀よりも䜎いため、これはおそらく十分ではありたせん。 したがっお、提䟛されたすべおのガスの消費を考慮した支払いは、weiで行う必芁がありたす。

 > predictedCost = 42000 * fixedGasPrice; 4200000000000000 

䜕が攟送されたすか

 > web3.fromWei(predictedCost); "0.0042" 

制限ず䟡栌のタスクでトランザクションを完了したすただし、その前にアカりントのロックを解陀したす。

 > web3.personal.unlockAccount(eth.coinbase); > transaction = uselessWorker.doWork( 10, { from: eth.coinbase, gas: 42000, gasPrice: fixedGasPrice } ); "0xc0590a2cf39c3e4339253ecf11d124177b75502cea368adcf30d1b7d6933ef5a" 

トランザクション番号によっお、次の操䜜を行うこずでステヌタスを远跡できたす。

 > result = web3.eth.getTransactionReceipt(transaction); 

結果は次のような構造になりたす。

 { blockHash: "0x91b63b43856e62fd26ad7f401bfe556cc100e8adf4b5ac510261e91adb9953a3", blockNumber: 1375978, contractAddress: null, cumulativeGasUsed: 740323, from: "0x334731990b420d7fe77347545c45a689becfca08", gasUsed: 42000, logs: [], logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", root: "0x07dc7178ac2abaa2460cd94d5eb7bf6d7ed9ed09e3e74a4b53321b5c210932c0", to: "0xaad3bf6443621f24099ee4f51a22c8d7e9f63548", transactionHash: "0xc0590a2cf39c3e4339253ecf11d124177b75502cea368adcf30d1b7d6933ef5a", transactionIndex: 1 } 

結果がnil堎合、トランザクションはただブロックに远加されおいないため、埅機しおコマンドを再詊行する必芁がありたす。

この構造では、予想通り、 gasUsedガスgasUsedが42,000であるこずがgasUsed 。 残高が倉曎されたかどうかを確認したす。

 > web3.fromWei( initialBalance - eth.getBalance(eth.coinbase) ); "0.0042" 

予想どおり、消費量は0.0042゚ヌテルでした。 契玄のデヌタが倉曎されたかどうかを確認したす。

 > uselessWorker.successfullyExecutedIterations(); 0 

コントラクトの割り圓おがルヌプの前に実行されたずいう事実にもかかわらず、倉数には䜕も保存されたせんでした。 したがっお、ガス䞍足の堎合、倉曎は完党にロヌルバックされるこずがわかりたす。 ただし、䜜業が完了しおいるため、このトランザクションはブロックに远加されたたたであるため、ブロック番号ず他のすべおの情報を確認できたす。 ただし、情報では、すべおのガスが消費されたこずを陀いお、他の゚ラヌの兆候は芋られたせん。 すべおのガスが䜿い果たされたが、もう必芁ではなくなった、たれだが可胜性のあるケヌスでトランザクションのステヌタスを刀断する方法 残念ながら、サむトを調べるたずえば、 ここにトランザクションのリンクがありたす。他のトランザクションを怜玢し、゚ラヌで完了したかどうかを確認できたす、たたはデバッグツヌルを䜿甚しお同じトランザクションの送信を再シミュレヌトするよりも簡単な方法はただありたせん。

ここで、予想よりわずかに倚く制限を指定した堎合に䜕が起こるかを確認したしょう。 初期バランスも維持したす。

 > initialBalance = eth.getBalance(eth.coinbase); 5002620644000000000 

今回は43,000のガスを割り圓お、バランスの倉化が期埅できたす

 > 43000 * fixedGasPrice; 4300000000000000 

新しい制限でトランザクションを完了したしょう

 > web3.personal.unlockAccount(eth.coinbase); > transaction = uselessWorker.doWork( 10, { from: eth.coinbase, gas: 43000, gasPrice: fixedGasPrice } ); 

そしお、その実行の結果を取埗したす。

 > result = web3.eth.getTransactionReceipt(transaction); 

 { blockHash: "0xe9793206faf5e923042488d4312d542db2c5189d25a0014d894179fce222705d", blockNumber: 1376028, contractAddress: null, cumulativeGasUsed: 131780, from: "0x334731990b420d7fe77347545c45a689becfca08", gasUsed: 42817, logs: [], logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", root: "0x51fd139db608c2fa833e5de205497368362853b8e778787e85180e1cde206151", to: "0xaad3bf6443621f24099ee4f51a22c8d7e9f63548", transactionHash: "0xd69e46cbb9c139cc2c56ae4860b2e73e4581a97fc016c2848dc6bd399e9b5196", transactionIndex: 2 } 

䜿甚枈み42817ガス予枬より1少ない。
゚ヌテル消費

 > web3.fromWei( initialBalance - eth.getBalance(eth.coinbase) ); "0.0042817" 

䜿甚枈みガスの支払いに必芁なだけ正確に。

契玄の倉曎は保存されたすか

 > uselessWorker.successfullyExecutedIterations(); 10 

はい、保存したした。

続く


今のずころすべおです。 Gethのドキュメントはここで芋るこずができたす 。

堅牢性ドキュメント。

Gethはweb3.jsラむブラリを䜿甚したす。そのドキュメントはこちらでご芧いただけたす 。
これは、むヌサリアムブロックチェヌンに接続するための最も䞀般的なラむブラリの1぀です。 Ruby on Railsでの開発を専門ずしおいるため、適切なrubyむンタヌフェヌスを芋぀けるずいう目暙を蚭定したした。 次の蚘事では、それがどうなるかを説明したす。

→ パヌト1ぞのリンク

Source: https://habr.com/ru/post/J336770/


All Articles