Geth1.9の新機能GraphQLを試す

Geth1.9の新機能GraphQLを試す

はじめに


Gethの新しいバージョン1.9が2019年7月10日にリリースされました。様々な機能追加、修正、パフォーマンス向上などが行われていますが、その中でも新機能としてリリースされたGraphQL機能について、検証してみました。

GraphQLとは、Facebookが開発したSQLのようなクエリ言語で、条件を与えるとJSONのレスポンスデータとして返されます。GethにおけるGraphQLは、Gethがもつトランザクション情報やブロック情報などを、指定した条件に絞り込んだり、必要な項目情報のみを取得したりできる機能が提供されています。

Gethの起動オプション


Geth1.9では、コマンドオプションにGraphQLのためのオプションが追加されました。
  • –graphql
    • GraphQLサーバを起動するためのオプション
  • –graphql.addr <アドレス>
    • GraphQLサーバがアクセスを受け付けるネットワークインターフェイス。
    • このオプションを指定しない場合はローカルホストからのみ接続できる。
    • 外部のサーバから受け付ける場合は「0.0.0.0」を指定する。
  • –graphql.port <ポート番号>
    • GraphQLサーバが起動するポート番号
    • デフォルトは8547
  • –graphql.corsdomain <ドメイン>
    • クロスオリジンリクエストを受け付けるドメインを指定する(複数の場合はカンマ区切りで指定)
  • –graphql.vhosts <ホスト名>
    • リクエスト元の仮想ホスト名
    • デフォルトは”localhost”。ワイルドカードは”*”。


GraphQLの画面構成


GraphQLオプションを使ってGethを起動し、ブラウザから8547(デフォルト)ポートに対してアクセスすると、以下のようなGraphQLの画面が表示されます。

上記の画面は横に4分割になっています。
  • 左から1番目は、実行したクエリの履歴が表示される領域です。過去に実行したクエリをすぐに実行することができます。
  • 左から2番目は、GraphQLのクエリを記述する領域です。初期表示時にはクエリの書き方やサンプルが記述されています。
  • 左から3番目は、クエリの実行結果を表示する領域です。
  • 左から4番目は、クエリに関するドキュメントが記載されている領域です。クエリを書く際に、このドキュメントを見ながらどのように記述するのか確認することができます。

クエリの記載方法


GraphQLのクエリは全体を { } で括り、その中に結果表示したい項目(Fields)を記載します。結果がオブジェクトである場合には、さらに { } の中に表示したい項目を記載します。

シンプルな例


以下は、gasPriceを表示するクエリです。結果がBigIntで返ってくるため、項目名を記載するだけで実行することができます。
{
  gasPrice
}

このクエリを実行すると、以下のようなJSON形式のデータが表示されます。
{
  "data": {
    "gasPrice": "0x3b9aca00"
  }
}

オブジェクトの結果が返される場合の例


以下のクエリは、ハッシュ値を指定して1つのトランザクションの結果を表示するクエリです。戻り値がTransactionオブジェクトとなるので、Transactionが持つ項目名(hash, nonce, inputData)を指定しています。
{ transaction(hash:"0x858ea1a7647a64df0861f7e61cf856172adc787b23d828dbab5008903e283014")
  {
    hash,
    nonce,
    inputData
  }
}

このクエリを実行すると、以下が表示されます。
{
  "data": {
    "transaction": {
      "hash": "0x858ea1a7647a64df0861f7e61cf856172adc787b23d828dbab5008903e283014",
      "nonce": "0x5",
      "inputData": "0x484c00af000000000000000000000000000000000000000000000000000000000000162e"
    }
  }
}

どのようなクエリが書けるのかということや、どのような項目を出力できるのかについては、GraphQLの画面右端のドキュメントを参照してもらえると良いと思います。

独自のコントラクトを実行して確かめてみる


sendTransactionによる送金のトランザクションでもGraphQLを使って結果を表示することはできますが、より実践的でよく使われそうな場面としては、ログのフィルタリングではないかと思います。
そこで、独自のコントラクトが出力する、TransactionReceiptのlogsをGraphQLを使って表示・フィルタリングできるか検証してみます。

検証のコントラクトコードは以下を使います。
contract Locker {
    bytes32 passHash;
 
    event openLog(address _sender, string _logText);
    event errLog(address _sender, string _logText);
 
    constructor(uint _pass) public {
        passHash = keccak256(abi.encode(bytes32(_pass)));
    }
 
    function openLocker(uint _num) public {
        if(passHash != keccak256(abi.encode(bytes32(_num)))) {
            emit errLog(msg.sender, "[ERR]LOCKER OPEN FAILED.");
            return;
        }
        emit openLog(msg.sender, "[INFO]LOCKER OPEN SUCCESS.");
    }
}

ロッカーの施錠を管理するコントラクトで、デプロイ時に解錠するためのパスワードを指定します。openLocker関数が呼ばれると、指定されたパスワードがロッカーのパスワードと一致するか確認し、
  • OKの場合は、「[INFO]LOCKER OPEN SUCCESS.」
  • NGの場合は、「[ERR]LOCKER OPEN FAILED.」

というイベントログを出力します。

実行するアドレスやOKとNGを変化させながら、以下の結果となるように実行しました。
No実行ユーザ(アドレス)OK/NG
10x53e65a57c88086b8cf4e13c4086c0d92ca1908f9OK
20x53e65a57c88086b8cf4e13c4086c0d92ca1908f9NG
30x53e65a57c88086b8cf4e13c4086c0d92ca1908f9NG
40x53e65a57c88086b8cf4e13c4086c0d92ca1908f9OK
50xce2e4ccafeacae712db09435bbeff5567df32b67NG
60xce2e4ccafeacae712db09435bbeff5567df32b67OK

上記の結果をすべて取得するクエリとして、以下を作成しました。
{
  logs(filter: {fromBlock: 0}) {
    data
    topics
    account {
      address
    }
  }
}

表示するデータとして、data, topics, address を指定しています。
実行結果は以下の通り6件になりました。
{
  "data": {
    "logs": [
      {
        "data": "0x00000000000000000000000042676035ce252b3556827f54c32ab03bd2c071760000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a5b494e464f5d4c4f434b4552204f50454e20535543434553532e000000000000",
        "topics": [
          "0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1"
        ],
        "account": {
          "address": "0x53e65a57c88086b8cf4e13c4086c0d92ca1908f9"
        }
      },
      {
        "data": "0x00000000000000000000000042676035ce252b3556827f54c32ab03bd2c07176000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000185b4552525d4c4f434b4552204f50454e204641494c45442e0000000000000000",
        "topics": [
          "0xeb8310da52cb60437f19d78102e8b4468b889171946f10c00d3ab705b03944f2"
        ],
        "account": {
          "address": "0x53e65a57c88086b8cf4e13c4086c0d92ca1908f9"
        }
      },
      {
        "data": "0x000000000000000000000000e5708328111aa61edb27e116026c237e0232dc43000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000185b4552525d4c4f434b4552204f50454e204641494c45442e0000000000000000",
        "topics": [
          "0xeb8310da52cb60437f19d78102e8b4468b889171946f10c00d3ab705b03944f2"
        ],
        "account": {
          "address": "0x53e65a57c88086b8cf4e13c4086c0d92ca1908f9"
        }
      },
      {
        "data": "0x000000000000000000000000e5708328111aa61edb27e116026c237e0232dc430000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a5b494e464f5d4c4f434b4552204f50454e20535543434553532e000000000000",
        "topics": [
          "0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1"
        ],
        "account": {
          "address": "0x53e65a57c88086b8cf4e13c4086c0d92ca1908f9"
        }
      },
      {
        "data": "0x000000000000000000000000e5708328111aa61edb27e116026c237e0232dc43000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000185b4552525d4c4f434b4552204f50454e204641494c45442e0000000000000000",
        "topics": [
          "0xeb8310da52cb60437f19d78102e8b4468b889171946f10c00d3ab705b03944f2"
        ],
        "account": {
          "address": "0xce2e4ccafeacae712db09435bbeff5567df32b67"
        }
      },
      {
        "data": "0x000000000000000000000000e5708328111aa61edb27e116026c237e0232dc430000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a5b494e464f5d4c4f434b4552204f50454e20535543434553532e000000000000",
        "topics": [
          "0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1"
        ],
        "account": {
          "address": "0xce2e4ccafeacae712db09435bbeff5567df32b67"
        }
      }
    ]
  }
}

16進数表示のためわかりにくいですが、dataの後半部分にある、
「5b494e464f5d4c4f434b4552204f50454e20535543434553532e」をASCII変換すると
「[INFO]LOCKER OPEN SUCCESS.」となり、
「5b4552525d4c4f434b4552204f50454e204641494c45442e」をASCII変換すると
「[ERR]LOCKER OPEN FAILED.」となります。


また、OKとなる場合のtopicsは「0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1」、
NGとなる場合のtopicsは
「0xeb8310da52cb60437f19d78102e8b4468b889171946f10c00d3ab705b03944f2」
となりました。


この結果に対して、OKの場合のみ表示対象となるようにフィルタリングしてみます。クエリのフィルタにtopicsを追加し、OKとなる値を指定します
{
  logs(filter: {fromBlock: 0,
          topics:[["0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1"]]
  }) 
  {
    data
    topics
    account {
      address
    }
  }
}

結果は以下のように3件に絞り込まれました。
{
  "data": {
    "logs": [
      {
        "data": "0x00000000000000000000000042676035ce252b3556827f54c32ab03bd2c071760000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a5b494e464f5d4c4f434b4552204f50454e20535543434553532e000000000000",
        "topics": [
          "0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1"
        ],
        "account": {
          "address": "0x53e65a57c88086b8cf4e13c4086c0d92ca1908f9"
        }
      },
      {
        "data": "0x000000000000000000000000e5708328111aa61edb27e116026c237e0232dc430000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a5b494e464f5d4c4f434b4552204f50454e20535543434553532e000000000000",
        "topics": [
          "0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1"
        ],
        "account": {
          "address": "0x53e65a57c88086b8cf4e13c4086c0d92ca1908f9"
        }
      },
      {
        "data": "0x000000000000000000000000e5708328111aa61edb27e116026c237e0232dc430000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a5b494e464f5d4c4f434b4552204f50454e20535543434553532e000000000000",
        "topics": [
          "0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1"
        ],
        "account": {
          "address": "0xce2e4ccafeacae712db09435bbeff5567df32b67"
        }
      }
    ]
  }
}

さらに、アカウント「0xce2e4ccafeacae712db09435bbeff5567df32b67」でも絞り込んでみます。
{
  logs(filter: {fromBlock: 0,
          topics:[["0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1"]],
        addresses:["0xce2e4ccafeacae712db09435bbeff5567df32b67"]
  }) 
  {
    data
    topics
    account {
      address
    }
  }
}

結果は1件となりました。
{
  "data": {
    "logs": [
      {
        "data": "0x000000000000000000000000e5708328111aa61edb27e116026c237e0232dc430000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a5b494e464f5d4c4f434b4552204f50454e20535543434553532e000000000000",
        "topics": [
          "0xbe04ac4b001aacb9b5103c731f8ccaa8d53e7d2db724485f5bd08074f1d120a1"
        ],
        "account": {
          "address": "0xce2e4ccafeacae712db09435bbeff5567df32b67"
        }
      }
    ]
  }
}

このようにフィルタリングすることで、誰が解錠したのかということがすぐに確認することができました。

まとめ


GraphQLを使うことで、欲しい項目に絞り込んだり、条件を指定してフィルタリングすることが簡単にできるようになります。 従来は、JavaScript等のロジックで絞り込みを行っていた手間と比較すると、大幅に削減されるのではないかと思います。

     

免責事項

本記事に掲載されている記事の内容につきましては、正しい情報を提供することに務めてはおりますが、提供している記事の内容及び参考資料からいかなる損失や損害などの被害が発生したとしても、弊社では責任を負いかねます。実施される際には、法律事務所にご相談ください。

技術・サービス・実装方法等のレビュー、その他解説・分析・意見につきましてはblock-chani.jp運営者の個人的見解です。正確性・正当性を保証するものではありません。本記事掲載の記事内容のご利用は読者様個人の判断により自己責任でお願いいたします。

     

コンセンサス・ベイス(株)とブロックチェーン事業を行なってみませんか?

当サイトを運営するコンセンサス・ベイス株式会社は、2015年設立の国内で最も古いブロックチェーン専門企業です。これまでに、大手企業の顧客を中心に、日本トップクラスのブロックチェーンの開発・コンサルティング実績があります。

ブロックチェーンに関わるビジネスコンサル・システム開発・教育・講演などご希望でしたら、お気軽にお問い合わせください。

     
     

ブロックチェーン学習に最適の書籍の紹介

図解即戦力 ブロックチェーンのしくみと開発がこれ1冊でしっかりわかる教科書

ブロックチェーン イーサリアムへの入り口 第二版 (ブロックチェーン技術書籍)

本書は、ブロックチェーン技術に興味を持ったエンジニアや、その仕組みを学び、自分の仕事に活かしたいビジネスパーソンを対象にして、ブロックチェーンのコア技術とネットワーク維持の仕組みを平易な言葉で解説しています。この本を読んだうえで、実際にコードを書くような専門書、ブロックチェーンビジネスの解説書を読むことで、理解度が飛躍的に高まるでしょう。(はじめにより)

イーサリアム(Ethereum)カテゴリの最新記事