Gincoでバックエンドを担当している高妻(@Tomokazu106)です。
2018年10月4日にヒカラボで開催した【Ginco Engineer Meetup】Firebaseを使ったモダンなブロックチェーンアプリ開発の裏側で話した内容についての解説記事になります。
当日の発表風景はこのような感じで、90名以上の方に参加していただきました。
GincoのバックエンドはGCP、Firebaseが基盤になっており、仮想通貨ウォレットのフロントからバックエンドまでの仕組みと、これまでの開発で得た知見をイベントでは発表しました。
私はGincoのバックエンドに焦点を当てた内容で、トランザクションの履歴管理とKyber Network連携について話しました。
そのとき使用したスライドはこちらになります。
仮想通貨ウォレットのバックエンドとDEX KyberNetwork連携
大きく分けて下記3つについて話しました。
- ウォレットの種類について
- ウォレットのバックエンドについて
- DEX Kyber Network連携について
今回の記事では登壇中に詳細に伝え切れなかった2と3について解説したいと思います。
ウォレットのバックエンドについて
上記がトランザクションの送受信履歴を管理するバックエンドになります。
バックエンドはGCP、Firebaseで構築しており、トランザクションはKubernetes上でGolangを使って処理しています。ブロックチェーンノードは自前で建てておりKubernetes上で運用しています。
トランザクション管理の処理の流れは下記のようになります。
- EthereumノードとWebsocketで接続し、Pending Transactionをリアルタイムに取得
- 取得したトランザクションはすぐさまCloud Pub/Subに渡し、Golangのworker(10~20)から取得
- workerは取得した各トランザクションに対してGincoで生成されたアドレスに関するものかチェック
- Gincoに関するトランザクションの場合、ユーザ情報を付加してCloud Firestoreにトランザクションを登録
Pending Transactionとはブロックに取り込まれる前のトランザクションのことを言い、ブロックに取り込まれたトランザクションをSuccess Transactionと呼びます。
Success Transactionも同様にWebsocketから取得していますが、取得しているのがブロックのデータになります。
ブロックに取り込まれたトランザクションを取り出し、Pending Transactionと同じようにCloud Pub/Subにトランザクションデータを渡しています。これ以降の処理はPending Transactionと同じになります。
補足情報として、Ethereumの場合ブロックは10~20秒間隔で生成されます。Pending Transactionはブロックチェーンノードにより1秒程度で全てのノードにブロードキャストされるため、Pending Transactionを取得・管理することでユーザがトランザクションの送受信確認を迅速にできるようになります。
バックエンド全体構成
Cloud Firestoreに登録されたトランザクションはクライアントから直接取得し、ユーザがリアルタイムに確認できるようになっています。
送金するための署名済みトランザクションはCloud Function経由でブロックチェーンノードに対してサブミットされます。
今回はEthereumのトランザクションに関して説明しましたが、Gincoで扱うブロックチェーンのトランザクションは同様の仕組みで管理されています。
DEX Kyber Network連携について
Gincoが10月に行ったアップデートでアプリ内からKyber Networkを使えるようになりました。
Kyber NetworkはEthereum上のスマートコントラクトを使ってトラストレスにETH、ERC20の交換ができます。
Kyber Networkは複数のコントラクトで構成されており、処理順を説明すると下記のようになります。
ExpectedRate
コントラクトから交換通貨のRateを取得するKyberReserve
コントラクトに対してtrade()関数で通貨交換を実行する
1に関してはコントラクトから取得するシンプルな仕組みとなっています。
2の交換はETH<->ERC20とERC20<->ERC20で交換の手順が少し異なるので説明したいと思います。
ETH<->ERC20の交換
ETH<->ERC20の交換はクライアントからKyberNetworkコントラクトに対してETHと一緒にtrade()
関数を実行するトランザクションを発行するだけです。
trade()
関数が実行されるとKyberReserveコントラクトからクライアントのEthereumアドレスに対してERC20の送金が行われます。
ETH<->ERC20の交換
ERC20<->ERC20の交換を行うにはまずはじめにクライアントが保有しているERC20を送金する権限をKyberNetworkコントラクトに委譲する必要があります。
委譲するにはERC20に実装されているapprove()
という関数を実行します。approve()
の引数にKyberNetworkのコントラクトアドレスと委譲する通貨量を渡して実行することでKyberNetworkのコントラクトに対して権限委譲できます。
approve()
を実行した後の通貨交換はETH<->ERC20と同様にtrade()
関数を使って交換を実行します。
このようにクライアントの送金権限を渡すことでKyberNetwork上のコントラクトでトラストレスにERC20の交換を行うことができます。
KyberNetworkのトランザクション取得
上記のスライドにあるクライアントから送信される①のトランザクションと③のトランザクションが最終的にGincoの履歴に入るトランザクションになります。
①を取得するのは簡単ですが、③のトランザクションはInternal Transactionといってコントラクト間のトランザクションとなり取得するのに一工夫必要となります。
下記のようにgeth(Ethereumブロックチェーンノード)の起動オプションを追加します。Internal TransactionはtraceChain()
、traceBlock()
、traceTransaction()
を使って取得します。
注意点としてtrace系の関数はgethのCPUをかなり使用するのでハイスペックな構成にしないといけません。
まとめ
GincoバックエンドとKyberNetwork連携について説明させていただきました。
実際にブロックチェーンノードからブロックやトランザクションを取得して触ってみることでPending/Success/Internal Transactionやブロックチェーンノードの仕組みを理解できるので おすすめです。
Tip us!
エンジニアチームがブログを書くモチベーションが上がります!