クライアント型ウォレットの仕組み

クライアント型ウォレットの仕組み

こんにちは。iOSエンジニアの松井(@ippo_012)です。

この記事は、2018年10月4日にヒカラボで開催した【Ginco Engineer Meetup】Firebaseを使ったモダンなブロックチェーンアプリ開発の裏側で話した内容についての解説記事になります。

私は「クライアント型ウォレットの仕組み」をテーマに、クライアント型ウォレットの仕組みと、Gincoがどのようにしてクライアント型ウォレットを運用しているかを話しました。

発表資料はこちらです。

発表では、以下の3つを話しました。

  1. ウォレットとは?
  2. Gincoのアーキテクチャ
  3. ウォレットの処理の流れ

本記事ではその中から「Gincoのアーキテクチャ」と「ウォレットの処理の流れ」について解説したいと思います。

Gincoのアーキテクチャ

GincoはFirebaseをProduction環境で利用しており、サーバーレスなアーキテクチャになっています。

FirebaseはGoogleが提供しているMobile Backend as a Service(MBaaS)と呼ばれるクラウドサービスです。 FirebaseではCloud Firestore(データベース)、Cloud Messaging(Push通知)、Firebase Authentication(認証)などアプリ開発で必要となるバックエンドの機能を多く提供しています。 一定の品質が担保されたこれらの機能を利用することは大幅な開発コストの削減、開発スピードの向上に繋がり、提供するサービス自体の開発や品質向上に注力することができます。

複数のブロックチェーンを扱うGincoでは、Firebaseをフルに活用してサービスの開発を行なっています。

Gincoの主な構成要素

次にFirebaseを含めたGincoの主な構成要素について、いくつか紹介していきます。(注 以下iOS主体の解説になっています)

Wallet Core

Wallet Coreは自社開発のウォレット用ライブラリです。iOS/Androidから利用ができ、マルチブロックチェーンに対応しています。主な機能は、ニーモニックの生成、HDウォレットの対応、アドレスの生成、トランザクションの署名などです。 こちらは今後OSS化を予定しているので、公開された際にはぜひ利用してみてください。

Keychain

iOS標準の暗号化データストレージです。ニーモニックの保存に利用しています。

Cloud Firestore

Firebaseサービスの1つで、スケーラブルなNoSQLクラウドデータベースです。リアルタイムリスナーを介して、クライアントアプリ間でデータの同期が行なわれます。[1]

Gincoでは、ユーザーデータの管理、トランザクション履歴の表示などに利用しています。

以下の記事でFirestoreのセキュリティルールについて解説しています。

Firestoreのルール設定

Cloud Functions

Firebaseサービスの1つで、Firebaseの機能やHTTPSリクエストによってトリガーされたイベントに応じて、関数を実行できます。[2] スケーラブルなAPIを非常に簡単に実装することができます。

主な用途としては、トランザクションの送信などのブロックチェーンノードのRPC呼び出しのAPIやマーケット情報の取得です。

より詳しい利用事例は以下の記事で解説しています。

GincoにおけるCloud Functionsの利用とその高速化

Full Node

Full Nodeはブロックのすべての情報を持つノードです。Gincoでは各ブロックチェーン毎にFull Nodeを建てており、Google Kubernetes Engine上で運用しています。

ノード運用は以下の記事で詳しい解説をしています。

Kubernetesを使ったブロックチェーンノード運用

Blockchain Explorer

Blockchain Explorerはブロックを常時監視し、トランザクションをサービスに利用しやすい形に整形する役割を担っています。こちらも各ブロックチェーン毎に用意しており、Google Kubernetes EngineとCloud Pub/Subを利用して運用しています。整形したトランザクションはCloud Firestoreに格納され、クライアントにリアルタイムに同期されています。

詳細はGincoのバックエンドとDEX KyberNetwork連携 の「ウォレットのバックエンドについて」の章で解説しています。

ウォレットの処理の流れ

先ほど紹介したGincoの構成要素を利用して、実際にGincoがどのような処理をしているのかを一部解説します。

補足

  • HDウォレット:秘密鍵をツリー構造で管理する仕組み、1つのSeedから複数の鍵を生成できる
  • ニーモニック:バイナリや16進数からではなく、覚えやすい簡単な単語の組み合わせからSeedを生成する仕組み

ニーモニックの生成

ニーモニックの生成の処理の流れは以下のようになります。

  1. Wallet CoreのgenerateMnemonic()関数を利用して、ランダムなmnemonicを生成する。
  2. 生成したmnemonicをKeychainに保存する。

ニーモニックの生成はBIP39 [3]に準拠しており、Gincoでは現在(2018/10/23日時点)英語と日本語に対応しています。

アドレスの生成

アドレスの生成の処理の流れは以下のようになります。

  1. Keychainに保存しているmnemonicを取得する。
  2. Wallet CoreのgetAddress()関数にmnemonicを与え、アドレスaddressを取得する。

getAddress()関数は各ブロックチェーン毎に用意されています。また、複数のエンコード方式にも対応しています。 getAddress()関数の内部ではBIP32 [4], BIP44 [5],などで提案されているHDウォレットの形式でアドレスが生成されています。

トランザクションの送信

トランザクションの送信の処理の流れは以下のようになります。

  1. Keychainに保存しているmnemonicを取得する。
  2. Wallet CoreのsignTransaction()関数にmnemonicとトランザクションのパラメータtxParamsを与え、署名済みトランザクションtxDataを生成する。
  3. 生成した署名済みトランザクションtxDataをCloud FunctionsのsendTransaction()関数を利用してFull Nodeにブロードキャストする。ブロードキャストに成功すればtxHashが返る。

signTransaction()関数、sendTransaction()関数共に各ブロックチェーン毎に用意されています。

履歴の表示

履歴の表示の処理の流れは以下のようになります。

  1. Blockchain ExplorerがFull Nodeを監視し、整形したトランザクションをCloud FirestoreのtxHistoryコレクションに格納する。
  2. クライアントからCloud FirestoreのtxHistoryコレクションを監視し、トランザクションの履歴を表示する。

トランザクションはpending(手続き中)、success(処理中)のように状態が変化するため、それをリアルタイムに反映できるCloud Firestoreは履歴の表示に相性が良いです。

まとめ

本記事ではGincoのアーキテクチャとウォレットの処理の流れについて解説しました。

ニーモニックやHDウォレットの詳しい仕組みや実装については今後また記事にする予定です。Firebaseに関してはまだまだサービスでの運用事例が少ないため、トライアンドエラーを繰り返して今後も積極的に情報発信を行いたいと思います。

Tip us!

エンジニアチームがブログを書くモチベーションが上がります!

image

参考文献