Daml とは
第三回は VMware Blockchain がサポートするスマートコントラクトの一つ Daml について見ていきましょう。ブロックチェーンの普及によってスマートコントラクトという言葉を散見する機会が増えてきましたが、その実態を理解するために海外のソースや文献を読み解くのは少々難しい作業かもしれません。そのような中で今回は VMware の製品ではありませんが Daml について触れていきたいと思います。
まず Daml とは Digital asset modeling language のことで Digital Asset 社が開発しているコンピュータ言語の事です。運営元の Digital Asset 社というのは金融関係の業務プロセスを改善しリスク低減をテクノロジー用いてサービスすることを目標に掲げて2014年に設立された新興企業で、その後 Elevence と言うスイスに本拠地を構えるモデル言語を開発する企業を買収することで現在の布陣になったようです。
Daml のホームページ(外部サイト)でも紹介されているように金融機関の要望を念頭に置いて開発されたスマートコントラクトに類似する言語というのが公式の立ち位置です。実際にどのように使われるのか、そして VMware Blockchain との関わり方を順を追って見てみましょう。
Install
まずは SDK をインストールする必要がありこちら(外部サイト)を参照に操作していただければ OK です。
本 blog 執筆時点では SDK のバージョンが2.0.0 までリリースされていますが、VMware Blockchain のバージョンによっては少し古い版を利用する必要があります。今回は VMware Blockchain 1.5 を使って検証するため Daml SDK は1.13.1 を利用します。またホスト PC は ubuntu 20.04.1 LTS を用意しました。
Sample
SDK インストール後に Daml が用意しているサンプルのアプリを動かしてみましょう。このサンプルは Alice と Bob二つのパーティーが登場し、スマートコントラクトを用いた決済の概念が理解できるようなデモとなっております。
全体の手順としては、
- プロジェクト作成
- 台帳ファイルのビルド
- 台帳ファイルの中身を確認
- サンプルアプリの開始
それでは先ずプロジェクトを作成します。daml new ファイル名 で作成できます。
xxx@ubuntu:~/daml$ daml new vmtest
Created a new project in "vmtest" based on the template "skeleton".
vmtest と言うスケルトンが完成しました。次にディレクトリを移動します。
xxx@ubuntu:~/daml$ cd vmtest
リストをとり、中身を確認すると…
xxx@ubuntu:~/daml/vmtest$ ls
daml daml.yaml
まだ空っぽな状態です。ここで Build コマンドを発行します。
xxx@ubuntu:~/daml/vmtest$ daml build
Compiling vmtest to a DAR.
Created .daml/dist/vmtest-0.0.1.dar
.dar ファイルが完成しました。この dar ファイルが台帳となり、今後例えば他の Daml project で利用したり、VMware Blockchainにimport して利用したりします。
.dar ファイルはアーカイブなので無理やりvi で開いても解読できません。daml damlc inspect-dar –json を利用することで中身を確認できます。こちらのコマンドはパッケージ ID を調べるのにも重宝します。
xxx@ubuntu:~/daml/vmtest$ daml damlc inspect-dar --json .daml/dist/vmtest-0.0.1.dar { "packages": { "e22bce619ae24ca3b8e6519281cb5a33b64b3190cc763248b4c3f9ad5087a92c": { "path": "vmtest-0.0.1-b2f2fa939ac7ca54f8d0f6deda27b69ad79e713fa556163779efaeafa342ec20/daml-stdlib-DA-NonEmpty-Types-e22bce619ae24ca3b8e6519281cb5a33b64b3190cc763248b4c3f9ad5087a92c.dalf", "name": null, "version": null },
注:コマンドの結果は一部割愛しております。
最後にサンプルアプリを起動してみましょう。 daml start コマンドで Sandbox, navigator が起動します。その後赤字のlocalhost へアクセスするとサンプルアプリを確認できます。
- Sandbox:daml ledger のシミュレーター環境
- Navigator : daml ledger にアクセスして内容を調べることができるフロントエンド。
Daml の dApp 開発中にこれらを利用利用してモデルのフローや具体的な動作を調べることとなります。
xxx@ubuntu:~/daml/vmtest$ daml start Compiling vmtest to a DAR. Created .daml/dist/vmtest-0.0.1.dar Waiting for sandbox to start: INFO: Slf4jLogger started INFO: Listening on localhost:6865 over plain text. Running the initialization script. ____ ____ / __/__ ____ ___/ / / ___ __ __ _\ \/ _ `/ _ \/ _ / _ \/ _ \\ \ / /___/\_,_/_//_/\_,_/_.__/\___/_\_\ INFO: Initialized sandbox version 1.13.1 with ledger-id = 901de0d9-90d6-4b16-8655-294f0c1fc359, port = 6865, dar file = List(.daml/dist/vmtest-0.0.1.dar), time mode = wall-clock time, ledger = in-memory, auth-service = AuthServiceWildcard$, contract ids seeding = strong Waiting for navigator to start: _ __ _ __ / |/ /__ __ __(_)__ ____ _/ /____ ____ / / _ `/ |/ / / _ `/ _ `/ __/ _ \/ __/ /_/|_/\_,_/|___/_/\_, /\_,_/\__/\___/_/ /___/ Version 1.13.1 ....................................... Press 'r' to re-build and upload the package to the sandbox. Press 'Ctrl-C' to quit. Frontend running at http://localhost:7500. ............Waiting for JSON API to start:
注:コマンドの結果は一部割愛しております。
localhost にアクセスすると下記の画面が表示されてサンプルアプリの起動が確認できました。
この後、先ほどの Alice or Bob どちらかのパーティーを選択して利用するイメージです。(本 blog では詳細は割愛)
VMware Blockchain への接続
最も簡単なスケルトンアプリの起動を確認したところで、VMware Blockchain のノードに先ほどのサンプルアプリケーションを接続させてみます。接続させると言っても大変簡単で下記の3つのコマンドを発行するだけです。先ほどのサンプルを一旦アボートした後に下記のコマンドを順に発行するだけです。(1と2はほぼ同じ意味のコマンドですが念のため)
- daml deploy :現在のdaml プロジェクトを指定したホスト先に展開
- daml ledger :インタラクティブにDAR を指定したホストに展開できます
- daml navigator server :ledger にナビゲーターを接続します
例:
daml deploy –host <ip_addr> –port XXXX
xxx@ubuntu:~/daml/vmtest$ daml ledger list-parties --host <ip_addr> --port xxxx Listing parties at <ip_addr> PartyDetails {party = 'Issuer', displayName = "Issuer", isLocal = True} PartyDetails {party = 'Alice', displayName = "Alice", isLocal = True} PartyDetails {party = 'Bob', displayName = "Bob", isLocal = True} PartyDetails {party = 'USD_Bank', displayName = "USD_Bank", isLocal = True} PartyDetails {party = 'EUR_Bank', displayName = "EUR_Bank", isLocal = True}
Pruning Service
唐突に出てきた Pruning、 これは剪定と言う意味ですが、今後 ledger を積極的に利用するとこれが肥大化してパフォーマンスが劣化します。そのため定期的に ledger を剪定して適切なサイズに抑える必要があります。VMware Blockchain の場合はクライアントノードより剪定可能なブロック ID を各レプリカノードから集めて prune command を作成して剪定作業を進めていきます。当然剪定されたデータは復元できませんのでバックアップを取って作業することとなります。
この剪定作業に必要となるのが Daml Ledger API です。これらAPI を利用することで様々な操作が可能になるのですが、利用方法は少し複雑です。ので実際の剪定作業はここでは語らず、以下 API の利用方法をサンプルアプリから見てみましょう。
Daml Ledger API
Daml API の利用方法を取得するには、サンプルコードを理解するのが一番早いです。まず、環境を整える必要がありgRPC を一部使用しますがコンパイル には異常に時間がかかるので注意が必要です。ちなみに postman のv9.7.1 からgRPC のリクエストがサポートされましたので工夫すれば使えるかもしれません。
環境:個々のインストール方法については割愛いたします。
- gRPC
- Protobuf
- Maven
サンプルコード
コードは下記の場所にあります。
xxx@ubuntu:~/tmp/ex-java-bindings/src/main/java/examples/pingpong/grpc$ ls
PingPongGrpcMain.java PingPongProcessor.java
got clone した後に、mvn compileします
xxx@ubuntu:~/tmp/ex-java-bindings$ mvn compile java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) [INFO] Scanning for projects... [INFO] [INFO] ----------< com.daml.ledger.examples:example-ping-pong-java >----------- [INFO] Building example-ping-pong-java 0.0.1-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- Downloading from central: https://repo.maven.apache.org/maven2/io/grpc/grpc-api/maven-metadata.xml Downloaded from central: https://repo.maven.apache.org/maven2/io/grpc/grpc-api/maven-metadata.xml (2.2 kB at 1.3 kB/s) Downloading from central: https://repo.maven.apache.org/maven2/io/grpc/grpc-core/maven-metadata.xml Downloaded from central: https://repo.maven.apache.org/maven2/io/grpc/grpc-core/maven-metadata.xml (3.8 kB at 14 kB/s) [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ example-ping-pong-java --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 1 resource [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ example-ping-pong-java --- [INFO] Nothing to compile - all classes are up to date [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 7.498 s [INFO] Finished at: 2022-04-25T10:23:59+09:00 [INFO] ------------------------------------------------------------------------
コンパイル後に sandbox を起動します。ついでにnavigator が連動して動きますがここでは無視します。サンプルコードを実行後にUI で実行結果が確認できます。
xxx@ubuntu:~/tmp/ex-java-bindings$ daml start --sandbox-port 7600 Compiling ex-java-bindings to a DAR. Created .daml/dist/ex-java-bindings-0.0.1.dar Waiting for sandbox to start: INFO: Slf4jLogger started INFO: Listening on localhost:7600 over plain text. Waiting for navigator to start: ____ ____ / __/__ ____ ___/ / / ___ __ __ _\ \/ _ `/ _ \/ _ / _ \/ _ \\ \ / /___/\_,_/_//_/\_,_/_.__/\___/_\_\ INFO: Initialized sandbox version 1.0.0 with ledger-id = 1f3a3ca4-d737-4a6d-9f1c-e5b821b5e110, port = 7600, dar file = List(.daml/dist/ex-java-bindings-0.0.1.dar), time mode = wall-clock time, ledger = in-memory, auth-service = AuthServiceWildcard$, contract ids seeding = strong
Sandbox が動いているターミナルはそのまま放置し、新しくターミナルを開きます。そこからプログラムを動かしてみましょう。下記コマンドで起動できますが、java で記述されているので main class を指定する必要があります。
mvn exec:java -Dexec.mainClass=<mainClass> -Dexec.args=”localhost 7600″
Main Class は下記のおとりです。
-
examples.pingpong.grpc.PingPongGrpcMain
-
examples.pingpong.reactive.PingPongReactiveMain
xxx@ubuntu:~/tmp/ex-java-bindings$ mvn exec:java -Dexec.mainClass=examples.pingpong.grpc.PingPongGrpcMain -Dexec.args="localhost 7600" java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) [INFO] Scanning for projects... [INFO] [INFO] ----------< com.daml.ledger.examples:example-ping-pong-java >----------- [INFO] Building example-ping-pong-java 0.0.1-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- exec-maven-plugin:3.0.0:java (default-cli) @ example-ping-pong-java --- Alice starts reading transactions. Bob starts reading transactions. Bob is exercising RespondPong on 009ec6b29ceedc659e44830903da4df0767add2c10d24e48f564806ce27279d349 in workflow Ping-Alice-7 at count 0 Alice is exercising RespondPong on 00ac2e1eb5bc0368938c0beeb0bc8ed91d6f02b99fd3dbb04ad08b7b241a83fd66 in workflow Ping-Bob-5 at count 0 Alice is exercising RespondPong on 00a63c84f6c88a583300f2bf9cac68264d9c39d008653bd0f4bbf49ab0cba9b349 in workflow Ping-Bob-3 at count 0 Bob is exercising RespondPong on 00a3fde066d99d2b5a230f824dab600f480b953ef84409fe8878bc7964525d9cbb in workflow Ping-Alice-2 at count 0
これでサンプルが動くようになりました。あとは API リファレンスをを見ながら自由に ledger にアクセスすることが出来ます。今回はサンプルプログラムで具体的にどの様な動きをしているかは触れませんが、git の方には詳しい説明があるのでそちらを参考にすると良いかと思います。
まとめ
VMware Blockchain は Daml ledger API と簡単に接続できることが分かったかと思いますが、途中 VMware の製品以外を利用するため慣れない方は予想以上に時間がかかるかもしれません(特に gRPC など)。 もし java に知見がありコードが読める方は是非サンプルコード( PingPongGrpcMain )をご覧ください。 スマートコントラクトの実装方法が理解できるような作りになっています。