知能契約web 3.js ABI Addressの3つの関係


web 3.jsは太閤坊が提供するJavascriptライブラリであり、エーテル坊のJSON RPC APIをカプセル化し、ブロックチェーンと対話する一連のJavascriptオブジェクトと関数を提供しており、ネットワークの状態を確認すること、取引とブロックを見ること、取引を送信すること、コンパイルすること、インテリジェント契約を呼び出すことなどを含みます.その中で最も重要なのは、知能契約と相互作用するAPIである.
web 3.jsから提供されたインターフェースを使ってスマート契約を呼び出す方法を紹介します.
システムとソフトウェア
Ubuntu 16.04 64 
nodejs 6.10.0
npm 3.10.10
  • 1
  • ,
  • 4
  • 模範契約
    本論文では、下記のMetaCoin契約を例にとって、web 3.jsを使ってスマート契約を操作する方法を説明します.
    //       MetaCoin  
    pragma solidity ^0.4.2;
    
    contract MetaCoin {
        mapping (address => uint) balances;
    
        event Transfer(address indexed _from, address indexed _to, uint256 _value);
    
        function MetaCoin() {
            balances[tx.origin] = 10000;
        }
    
        function sendCoin(address receiver, uint amount) returns(bool sufficient) {
            if (balances[msg.sender] < amount) return false;
            balances[msg.sender] -= amount;
            balances[receiver] += amount;
            Transfer(msg.sender, receiver, amount);
            return true;
        }
    
        function getBalance(address addr) returns(uint) {
            return balances[addr];
        }
    }
    
  • 1
  • ,
  • 4
  • 5
  • ,
  • ,
  • 8
  • 9,
  • 10
  • 11
  • 15
  • ,
  • ,
  • ,
  • ,
  • ,
  • 23
  • この契約には三つの関数があります.
    MetaCoin:構造関数は、契約がブロックチェーンに展開された時に実行されます. get Balance:あるアカウントの残高を返します.データだけ読んでいます.データは変更されません. sendCoin:指定された数のMetaCoinを別のアカウントに送信します.ステータス変数balancsを変更します. エーテル坊ノードを起動し、上記の契約をブロックチェーンに展開し、契約の住所を記録して、truffleを通じて配備することができます.具体的にはこの記事を参照してください.次の手順でプロジェクトのweb 3.jsを通じてこの契約を使用することができます.
    プロジェクトにweb 3を追加します.
    まずNodejsプロジェクトを新規作成して初期化します.
    $ mkdir web3test && cd web3test
    $ npm init
    
  • 1
  • ,
  • 項目情報を入力するようにヒントを与えます.すべてのデフォルトでOKです. 次はweb 3.jsをダウンロードしてプロジェクトに行きます.
    $ npm install web3 --save
    
  • 1
  • 以上のコマンドはweb 3.jsをweb 3 test/node_にダウンロードします.modulesディレクトリでは、–saveパラメータはweb 3.jsにpackage.jsonプロファイルに追加されます.
    web 3オブジェクトを作成
    web 3.jsを使用してブロックチェーンと対話するには、まずweb 3オブジェクトを作成し、その後エーテルノードに接続する必要があります.web 3 testディレクトリの下でindex.jsファイルを新規作成します.ここに以下のコードを入力します.
    var Web3 = require("web3");
    //   web3  
    var web3 = new Web3();
    //         
    web3.setProvider(new Web3.providers.HttpProvider("http://localhost:8545"));
    
  • 1
  • ,
  • 4
  • 5
  • ,
  • 展開されている契約のインスタンスを取得します.
    知能契約を使用するには、ブロックチェーンから契約のインスタンスを取得しなければなりません.契約のインスタンスを取得するには、契約のABIと契約の住所が必要です.
    //   ABI
    var abi = [{"constant":false,"inputs":[{"name":"receiver","type":"address"},{"name":"amount","type":"uint256"}],"name":"sendCoin","outputs":[{"name":"sufficient","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"}];
    //     
    var address = "0xb2cdd356e58280906ce53e1665697b50f88aac56";
    //   ABI             
    var metacoin = web3.eth.contract(abi).at(address);
  • 1
  • ,
  • 4
  • 5
  • ,
  • metacoinは取得した契約の対象例であり、このときmetacoinオブジェクトには契約関数と同名のJavascript関数が含まれています.その後、metacoinオブジェクトを通じて契約の関数を呼び出すことができます.
    契約関数を呼び出します
    MetaCoin契約には2つの関数があります.getBalanceとsendCoinは、metacoinオブジェクトを通じて直接にこの2つの関数を呼び出すことができます.
    まずgetBalanceを見に行きます.getBalance関数はブロックチェーンからデータを読むだけで、データを修正しないので、getBalanceの後に.call()を加えることによって呼び出されます.
    var account_one = web3.eth.accounts[0];
    var account_one_balance = metacoin.getBalance.call(account_one);
    console.log("account one balance: ", account_one_balance.toNumber());
    
  • 1
  • ,
  • 4
  • ここ:
    getBalanceの後に.call()を加えて明示的に指定します.コールで呼び出します. コールで呼び出すとget Balance関数の戻り値が得られます. コールで呼び出された関数は、ノードのローカル仮想マシンでのみ実行され、トランザクションが生成されず、費用がかかりません.データは変更されません. 次はsendCoin関数を見てみます.sendCoinは契約内部のデータを修正しますので、sendCoinを有効にするには、ブロックチェーンに取引を送信しなければなりません.sendCoinの後に、sendCoinを追加することができます.
    var account_one = web3.eth.accounts[0];
    var account_two = web3.eth.accounts[1];
    //         ,       hash,                    
    var txhash = metacoin.sendCoin.sendTransaction(account_two, 100, {from:account_one});
    console.log(txhash);
    
  • 1
  • ,
  • 4
  • 5
  • ,
  • ここ:
    sendCoin関数に加えて.sendTransationはブロックチェーンに取引を送信することを指定します. 契約コードの中でsendCoin関数は二つのパラメータしかないですが、web 3では.sendTransaction()が契約関数を呼び出す時は最後のパラメータを追加する必要があります.javascriptオブジェクトです.中でfrom/value/gasなどの属性を指定できます.上記の例はfromで取引の送信者を指します. 上記の呼び出し文が実行されたら、ブロックチェーンに取引を提出します.この取引の送信者はaccount_です.one、受信者はmetacoinの住所です.取引の役割はaccount_です.twoと100はパラメータとして契約を実行するsendCoin関数です. 関数はすぐに取引のhashに戻ります.取引はブロックチェーンに提出されましたが、取引がいつ処理されるかは分かりません.取引は無断でブロックに収録されてから有効になります. 契約事件を傍受する
    sendTransactionを通じて(通って)契約を呼び出すと、取引はブロックチェーンに提出されて処理されます.この処理は一定の時間が必要です.取引が完了してから他の操作を実行するなら、取引がいつ完了するかを知る必要があります.契約のイベントを傍受することで実現できます.
    契約ではイベントを定義できます.イベントにはパラメータが含まれています.契約関数の内部でいくつかの操作が完了すると、イベントをトリガして、外部にいくつかの情報を伝えることができます.例えば、MetaCoin契約で定義されたイベントはTransferといい、振込のイベントを表しています.3つのパラメータがあります.取引の送信者、受信者、振替の数です.sendCoin関数では、転送が成功するとTransferイベントが発生し、対応するパラメータをイベントに転送します.このように外部からイベントを傍受すると、イベントのパラメータを取り出して、取引の送信者、受信者、数量を得ることができます.また、イベントには取引hashなどの他の情報が含まれています.
    web 3でイベントを使用して、まずイベントオブジェクトを取得し、イベントを待ち受けます.イベントが発生すると、コールバック関数でイベント情報を取得します.
    //       
    var myEvent = metacoin.Transfer();
    //     ,             
    myEvent.watch(function(err, result) {
        if (!err) {
            console.log(result);
        } else {
            console.log(err);
        }
        myEvent.stopWatching();
    });
    
    //   :
    { address: '0xb2cdd356e58280906ce53e1665697b50f88aac56',
      blockNumber: 651,
      transactionIndex: 0,
      transactionHash: '0xcc71bc2824cc84d1ee831c46189e3a80cf0af05697ba0370693aa97390c8067b',
      blockHash: '0x1d53f04206f3926d0f311b1230a9dd0b0c5aadac35b169a6a609e384ab130c6f',
      logIndex: 0,
      removed: false,
      event: 'Transfer',
      args: 
       { _from: '0x68b73956d704007514e9257813bdc58cdf3c969a',
         _to: '0x9c3c1a2f5ef913fac44f0348a78f68d835f3f26e',
         _value: { [String: '100'] s: 1, e: 2, c: [Object] } } }
    
  • 1
  • ,
  • 4
  • 5
  • ,
  • ,
  • 8
  • 9,
  • 10
  • 11
  • 15
  • ,
  • ,
  • ,
  • ,
  • ,
  • 23
  • ,
  • 出力から分かるように、取得したイベント情報は、イベントのパラメータ、イベント名、ブロック番号、取引hashなどを含む.
    イベント中のtrantionhashと契約関数を呼び出して戻ってきた取引hashが一致しているかどうかを検出することにより、ある取引が完了したかどうかを判定することができます.
    var account_one = web3.eth.accounts[0];
    var account_two = web3.eth.accounts[1];
    
    var account_one_balance = metacoin.getBalance.call(account_one);
    console.log("account one balance:", account_one_balance.toNumber());
    
    var txhash = metacoin.sendCoin.sendTransaction(account_two, 100, { from: account_one });
    
    var myEvent = metacoin.Transfer();
    myEvent.watch(function (err, result) {
        if (!err) {
            if (result.transactionHash == txhash) {
                var account_one_balance = metacoin.getBalance.call(account_one);
                console.log("account one balance after sendCoin:", account_one_balance.toNumber());
            }
        } else {
            console.log(err);
        }
        myEvent.stopWatching();
    });
    
    //   :
    account one balance: 7000
    account one balance after sendCoin: 6900
    
  • 1
  • ,
  • 4
  • 5
  • ,
  • ,
  • 8
  • 9,
  • 10
  • 11
  • 15
  • ,
  • ,
  • ,
  • ,
  • ,
  • 23
  • ウォッチの中のコールバック関数が実行されれば、イベントがトリガされたということです.つまり、ある取引はすでに処理済みで、取引のhashが一致しているかどうかを確認します.このイベントが発生した取引は自分が送った取引かどうかを判定できます.