新しいスマートコントラクトのプログラミングとデプロイ方法

著者: Yongxin Xu
前回の記事では、自動販売機 DApp のモデルと、このアプリケーション向けに定義した「aggregate transaction」という新しいスマートコントラクト(トランザクションプロトコル)を紹介しました。その後もスマートコントラクトのプログラミングとオフチェーンシミュレーターの構築を進めてきました。そこで今回は、新しいスマートコントラクトを実装・デプロイする手順の概要と、ArcBlock の Forge Framework を使った感想を紹介します。
まず aggregate transaction を簡単に振り返ります。以前の記事で説明したとおり、私の DApp は自動販売機事業の信頼できる台帳として機能します。ブロックチェーンの役割は、台帳の全データが信頼でき、改ざん不能であることを保証することです。そのため DApp がブロックチェーンに求めるのは、請求データの記録だけです。この要件を満たすため、新たなスマートコントラクト、つまり「aggregate transaction」という新しいトランザクション型を定義します。請求が発生するたびに、自動販売機のウォレットアカウントが aggregate transaction を送信し、関連情報をすべてチェーンへ記録します。送信に成功すると、関係者の利益額が各ウォレットアカウントで自動更新されます。すべてがチェーンに記録されれば改ざんできないため、台帳は常に信頼できます。


新しいスマートコントラクトを実装・デプロイする手順は次のとおりです。
第一に、カスタムチェーンを作成する。
Forge Framework が提供する Forge CLI を使えば、カスタムチェーンを簡単に作成できます。forge start コマンドでローカルにノードを作成し、起動できます。
第二に、新しいスマートコントラクトを実装する。
新しいスマートコントラクトには、次の 4 ファイルを実装する必要があります。
- protocol.proto
protocol.protoはトランザクションのデータ構造を定義します。つまり、そのトランザクション型がどのような形で、どんな情報を含むかをチェーンに伝えます。Forge Framework のトランザクションは、外側の transaction と inner transaction の 2 層で構成されます。簡単に言えば、外側には送信者や送信時刻など全トランザクション型に共通する情報が入り、内側には各型固有の情報が入ります。したがってprotocol.protoは、この内側の層の構造と内容を定義します。


- protocol.yml
protocol.ymlはパイプラインを作成し、新しいスマートコントラクトを処理する手順をチェーンに伝えます。Forge Node は基本的に、すべてのトランザクションを次の 3 段階で処理します。
- Check。Forge Node がトランザクションを受け取ると、まず全体に目を通し、未入力フィールドなど明らかな問題がないか確認します。
- Verify。check より徹底した検査で、検証を通過したトランザクションはチェーンに対して完全に有効と判定されます。
check と verify の違いは空港の保安検査に例えると理解しやすいでしょう。通常、まず身分証明書と搭乗券の情報を確認し、次に全身スキャナーで禁止物がないか検査します。この保安検査を通過して初めて飛行機に搭乗できます。
- Update。最後に、検証済みトランザクションを反映してチェーン全体の状態を更新します。
Forge Framework は、開発者がブロックを組み立てるようにパイプラインを構築できる、事前定義済みの多数の「pipe」を提供します。独自の pipe も実装できます。トランザクション型ごとに更新するチェーン上のデータが異なるため、通常は最後の update 用 pipe をカスタマイズします。

- protocol.ex
protocol.exではカスタム pipe を実装します。プログラミング言語は Elixir です。Elixir は馴染みがないかもしれませんが、プログラムのロジックは単純です。Elixir での実装について詳しくはリファレンスをご覧ください。 - config.yml
config.ymlには、チェーンが参照するスマートコントラクト全体の基本情報を記載します。これまで紹介した 3 ファイルと現在のバージョン番号を指定します。スマートコントラクトを変更するたびに、バージョン番号も更新する必要があります。更新を忘れたまま修正版をデプロイしても、チェーンは何も更新しません。

第三に、新しいスマートコントラクトをデプロイする。
Forge CLI を使えば、新しいスマートコントラクトを簡単にデプロイできます。ドキュメントの手順に従うだけです。
第四に、新しいスマートコントラクトをテストする。
Forge remote console では Elixir SDK を使って新しいスマートコントラクトをテストでき、SDK も非常に使いやすくなっています。ただ、私は Python が好きなので、ここでは Python SDK を使ったテスト方法を紹介します。主に 3 段階です。
- 新しいスマートコントラクトをコンパイルする。Google が提供する Protocol Buffer Compiler を使って、
protocol.protoを Python 対応ファイルへコンパイルできます。
protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/protocol.proto- ウォレットアカウントを作成する。前回説明したように、ウォレットはチェーン上のすべてのトランザクションの送信元または受信先です。相手のウォレットアドレスが分かれば、チェーン上でやり取りできます。そこで aggregate transaction の送信元となる自動販売機と、受信先となる関係者のウォレットアカウントを作成します。Python-SDK では次のコマンドでウォレットを作成でき、アドレスと残高も簡単に確認できます。
from forge_sdk import ForgeConn
f = ForgeConn('127.0.0.1:28210')
rpc = f.rpc
vm = rpc.create_wallet(moniker='vending_machine', passphrase='vm1234')
addr = vm.wallet.address
rpc.get_account_balance(address)- 最後に、トランザクションを送信する。次のコマンドで aggregate transaction を送信できます。送信後、チェーンはハッシュ値を返します。この値を使って、トランザクションがチェーンへ正常に送信されたか検証できます。
itx = protos.AggregateTx(sku=sku, value=value, time=time, operator=op.wallet.address, manufacturer=ma.wallet.address, supplier=su.wallet.address, location=lo.wallet.address)
itx2 = utils.encode_to_any(type_url="fg:t:aggregate", data=itx)
rpc.send_itx(tx=itx2, wallet=vm.wallet, token=vm.token, nonce=0)
rpc.is_tx_ok('[return-hash]')
以上が、新しいスマートコントラクトの実装とデプロイの手順です。問題がなければ、DApp のオンチェーン部分はほぼ完成です。次は、私たちがより慣れているオフチェーン部分に集中できます。
Forge Framework でスマートコントラクトをデプロイして最も強く感じたのは、独自チェーンのカスタマイズが本当に簡単だということです。Forge Framework が複雑なブロックチェーン基盤技術を解決してくれます。DApp を作りたいだけのときに不要な高度な知識を覆い隠し、DApp 構築の難易度を大幅に下げ、従うべきテンプレートも提供してくれます。次回は、自動販売機 DApp と、オフチェーン部分を完成させる過程を紹介する予定です。最終的にどんなアプリケーションになるのか、私自身も楽しみにしています。また、この 3 週間の学習と実践から多くの経験を得て、ブロックチェーン技術と、それが生活をどう変えられるかについて理解を深めました。それらも次回共有します。それでは、また!