CordaがOSSで公開されるとは思ってなかったので、少しだけ触ってみました。
Cordaとは
金融機関が参加するコンソーシアム(R3 CEV)で開発されていた分散型台帳プラットフォーム「Corda」です。コードがオープンソース化され、Linux Foundationの「Hyperledger Project」に寄付されていたので動かしてみました。
コードはJavaやKotlin(コトリン)で書かれています。
KotlinはJetBrainsの中の人たちが作成したJava仮想マシン上で動く静的型付けのオブジェクト指向プログラミング言語です。Pythonのように簡潔なところが個人的に気に入ってます。JetBrainsの中の人が作ったのでIntelJのIDEとの相性もいいです。
Cordaの環境周りは綺麗に整っています。GradleやIntelJがやや前提になっていますが、この前提に違和感がなければ非常に開発がしやすそうでした。
セットアップもシンプルで、ドキュメントもしっかりしていたので、習得がしやすそうです。
以下、簡単なセットアップ方法と簡単な動作確認まで。
セットアップ
動作環境:Mac OS X
ダウンロード
$ git clone https://github.com/corda/cordapp-template.git
Cloning into 'cordapp-template'...
remote: Counting objects: 1144, done.
remote: Compressing objects: 100% (450/450), done.
remote: Total 1144 (delta 467), reused 1136 (delta 461), pack-reused 0
Receiving objects: 100% (1144/1144), 1.26 MiB | 192.00 KiB/s, done.
Resolving deltas: 100% (467/467), done.
Checking connectivity... done.
$ cd cordapp-template
$ git checkout -b corda-m6-template tags/release-M6.0
Switched to a new branch 'corda-m6-template'
ビルド
$ ./gradlew deployNodes
Downloading https://services.gradle.org/distributions/gradle-2.10-all.zip
.........................................................
Unzipping /Users/abenben/.gradle/wrapper/dists/gradle-2.10-all/a4w5fzrkeut1ox71xslb49gst/gradle-2.10-all.zip to /Users/abenben/.gradle/wrapper/dists/gradle-2.10-all/a4w5fzrkeut1ox71xslb49gst
Set executable permissions for: /Users/abenben/.gradle/wrapper/dists/gradle-2.10-all/a4w5fzrkeut1ox71xslb49gst/gradle-2.10/bin/gradle
Download https://repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.0.5/kotlin-gradle-plugin-1.0.5.pom
:
:
Download https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-io/9.3.9.v20160517/jetty-io-9.3.9.v20160517.jar
Download https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-util/9.3.9.v20160517/jetty-util-9.3.9.v20160517.jar
:compileKotlin
:compileJava UP-TO-DATE
:copyMainKotlinClasses
:processResources
:classes
:jar
:assemble
:compileTestKotlin
:compileTestJava UP-TO-DATE
:copyTestKotlinClasses
:processTestResources
:testClasses
:test
objc[4030]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
:check
:build
:deployNodes
BUILD SUCCESSFUL
Total time: 6 mins 58.844 secs
This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.10/userguide/gradle_daemon.html:
ノードの起動
runnodesコマンドを実行すると、フォルダ以下にあるコントローラ用ノード(controller)と、通常ノード(nodea,nodeb,nodec)の計4つが同じPC内で起動します。
(windowsの場合はrunnodes.batを起動)
各ノードの設定は、各ノードフォルダ内にあるnode.confで行います。
cd build/nodes/
$ sh runnodes
tab 5 of window id 39863
各サーバーに分散して実行する場合は、各nodeフォルダをそれぞれのサーバーにコピーしてnode.confの設定でlocalhostを各サーバーのIPアドレスに変更し、1ノードづつ起動(java -jar corda.jar)するばOKです。
動作確認
自ノードの確認
ブラウザまたコマンドから自分自身の情報を取得
# コントローラ
$ curl 'http://localhost:10003/api/example/me'
{
"me" : "Controller"
}
# node A
$ curl 'http://localhost:10005/api/example/me'
{
"me" : "NodeA"
}
# node B
$ curl 'http://localhost:10007/api/example/me'
{
"me" : "NodeB"
}
# node C
$ curl 'http://localhost:10009/api/example/me'
{
"me" : "NodeC"
}
ネットワークノードの確認
コントローラーからはすべてのノード、ノードからは自分以外のノードが表示される
# コントローラ
$ curl 'http://localhost:10003/api/example/peers'
{
"peers" : [ "NodeA", "NodeB", "NodeC" ]
}
# node A
$ curl 'http://localhost:10005/api/example/peers'
{
"peers" : [ "NodeB", "NodeC" ]
}
# node B
$ curl 'http://localhost:10007/api/example/peers'
{
"peers" : [ "NodeA", "NodeC" ]
}
# node C
$ curl 'http://localhost:10009/api/example/peers'
{
"peers" : [ "NodeA", "NodeB" ]
}
台帳への記入
ノードA(localhost:10005)からノードB(localhost:10007)へ商品を注文してみます。
コマンドラインから
$ echo '{"orderNumber": "1","deliveryDate": "2018-09-15","deliveryAddress": {"city": "London","country": "UK"},"items" : [{"name": "widget","amount": "3"},{"name": "thing","amount": "4"}]}' | curl -T - -H 'Content-Type: application/json' http://localhost:10005/api/example/NodeB/create-purchase-order
node Bのブラウザ(UI)からの場合は
http://localhost:10005/web/example/
で「Create purchase order」ボタンをクリックして以下を入力
(自ノードに関する)台帳の確認
コマンドラインから
$ curl -H 'Content-Type: application/json' 'http://localhost:10005/api/example/purchase-orders'
{
"1_d09e72a9-5ae6-4756-9938-7803cb10b308" : {
"state" : {
"data" : {
"po" : {
"orderNumber" : 1,
"deliveryDate" : 1536969600000,
"deliveryAddress" : {
"city" : "London",
"country" : "UK"
},
"items" : [ {
"name" : "widget",
"amount" : 3
}, {
"name" : "thing",
"amount" : 4
} ]
},
"buyer" : "NodeA",
"seller" : "NodeB",
"contract" : {
"legalContractReference" : "4C8742993015156C5364274BD512DC59E720E2F886AB2B09E4822A7F9FB8FA9B"
},
"linearId" : {
"externalId" : "1",
"id" : "d09e72a9-5ae6-4756-9938-7803cb10b308"
},
"ref" : "1",
"parties" : [ "NodeA", "NodeB" ],
"participants" : [ "RmXQnCD2y3tf6xV1MUgVzjJaxCU2JELELoRSKpmW3HEeakaRuba5j4v3t7Y6zhZUTLoZGnh6TbMdqM1mutFTJNq9nXEodm69ea83yuG2", "RmXQnCD2y3tf6xV1MUgVzjJaxCU2JELELoRSKpmW3HEeakaRuba5j4v3t7Y6yWAw3qoZ9NtEbz93kd8BgfWWPwwUQB9v28Eh9sEEWe3p" ],
"encumbrance" : null
},
"notary" : "corda.notary.validating|Controller"
},
"ref" : {
"txhash" : "09035D73EDAA666BA86067F445943B2EC4014DFE585FF6F79A63DC27D97AEE8B",
"index" : 0
}
}
}
node Aのブラウザ(UI)からは以下のURLで確認
http://localhost:10005/web/example/
この分散台帳のままでも何かのビジネスにそのまま使えそうですが、モデル設計が綺麗なのでKotlinでルール等を書き換えるだけで、いろんなユースケースに対応できそうな気がしました。
他にもサンプルがあるのでもう少し探ってみます。
Tim Swanson氏が来日した時、何度か講演を聴いたり、直接質問をしたことがあるのですが、私の英語リスニングが未熟なのと、彼がとても早口なのでその時はよく理解ができませんでしたが、ソースコードをみたり、ドキュメントを見みると、参考になりそうな箇所がいくつかありました。もう少し自分の中で腹落ちしたら改めてブログに書いてみます。
最後に遅れてしまいすみませんでした。
参考文献
ドキュメント:https://docs.corda.net
GitHub:https://github.com/corda/cordapp-template