CordaのTransactionにおける署名検証の仕組みを学べます。署名検証のプロトコルはCorda4とCorda5で変わりはないですが、Corda5ではSignatoriesの導入によって、より理解しやすくなりました。
Cordaの署名検証
Cordaは、UTXOモデルを前提としたブロックチェーン/分散台帳 基盤です。UTXOとは、Unspend Transaction Outputの略で、お金や証券のような 複製を許さないデータをモデル化する一つの方法になります。例えばステーブルコインといったユースケースであれば、200円をAさんからBさんへ渡す と言った内容(=契約)をTransactionというデータ形式で表現します。
さて、Cordaでは、他のブロックチェーンと異なり、このTransaction形式のデータはネットワーク全体で共有されることはありません。 必要な相手にのみ(先ほどのステーブルコインの例であれば、AさんとBさんだけに)共有されます。 そして、関係者であるAさんとBさんの電子署名を付与することでこのTransactionが成立したというプロトコルになっています。(正確にはもう一つ価値 の二重支払いを防止するためのNotaryというの特殊な署名も付与します) Cordaのスマートコントラクトには、署名検証という仕組みが用意されており、Transactionに含まれるデータに従って、どう言った人の署名が必要であるかを 定義することができます。 先ほどと同じステーブルコインの例であれば、200円のステーブルコインを手放すことになるAさんの署名(=承認)は間違いなく必要でしょう。 また、おそらく受け取る側のBさんの署名(=承認)も、必要だということになるでしょう。 Cordaのスマートコントラクトの中では「AさんとBさんの署名があること」という制約をこのTransactionに対してかけることができます。 具体的には、コインを手放す所有者(Input StateにおけるHolderという言い方をします)の署名とコインを受け取る人(Output StateにおけるHolderと言います) の署名が必要である、というスマートコントラクトをCordaは書くことができます。
さて、このようなA,B(そしてNotary)の署名があることで、Transactionは成立(検証に通る)しますが、この署名を集めてくるというプロセスには一つ課題があります。
次にその点について説明していきましょう。
Flowによる署名集め
先ほども書いた通り、CordaのTransactionはネットワーク全体で共有されることはありません。必要な相手にのみ共有されるのですが、その必要な相手にのみ Transactionを送信し、必要に応じてそのTransactionを検証し、署名し、返送するといった動作を定義するプログラムをCordaではFlowと言います。
Flowの中でCordaはTransactionの署名検証(必要な署名が集まっているのかどうか?)を行います。
そのプロセスをもう少し詳しく見てみましょう。
上記①Tx生成・署名の中で、AliceはTransactionの署名検証を行った上で、自己の署名をTransactionに対して行います。Aliceの署名がついたTransactionは①Tx生成・署名の 作業を終えてBobに送られます。受け取ったBobは、②検証・署名を行う中で、Bobは同じくTransactionの署名検証を行い、自己署名をTransactionに対して行います。 さて、ここで示した①や②におけるTransactionの状態、それから、最終的に台帳に書き込まれる時のTransactionの状態を見てみましょう。
①AliceによるTransaction生成&署名時点
②BobによるTransactionへの署名時点
最終的な台帳書き込み時
Signatoriesの活用による2段階の署名検証プロトコル
さて、Cordaのスマートコントラクトでは必要な署名が集まっているかどうかを検証するというロジックを組むことができます。 最終的に台帳に書き込まれるTransactionを検証する場合は、スマートコントラクトが求めるような署名検証を行うことができます。
しかし、その一方で、例えば①AliceがTransactionを生成するタイミングでは、実際のBobの実際の署名が入っていることはありえません。 この問題を解決するのがSignatoriesというCorda5で明示的に導入された仕組みになります。
SignatoriesというのはCorda5で導入されたTransactionの一属性になります。 Signatoriesは、「このTransactionに必要な署名」を意味しており、Corda5ではSignatoriesを介してスマートコントラクトが求める署名検証を2段階で実現します。
署名検証の第一段階(SignedTransaction.verify)
第一段階では、Transactionの署名検証はSignatoriesとTransactionに含まれるその他のデータ(InputState/OutputStateの属性)を比較します。
ここでは、実際の署名は必要なく、あくまでTransactionの内部データだけを使った検証になります。
実際の署名は用いてはいませんが、Signatoriesに記載された署名者一覧だけで、 スマートコントラクトの求める署名検証を実現できるのかを検証します。 例えば、上記の絵はリンゴ(Apple)トークンを新規に発行(issue)することを表現しています。 そこで、リンゴトークンを管理するスマートコントラクトは、リンゴトークンの発行者(Farmer)とトークンの所有者(Holder) の署名が必要と書いておくことができます。すると、第一段階では、SignatoriesにFarmerとHolderが含まれているのか?という検証を行うことが可能です。 この署名検証の内容はスマートコントラクトの中で自由に書くことができます。 今の例なら所有者(Holder)の署名は不要だと思えばそのように定義すればいいです。全然別の例ですが、 Signatoriesには3つの署名が入っている必要がある、と書けばそれはマルチシグ実装が必要ですよ、と定義したスマートコントラクトであるということになります。
署名検証の第二段階(LedgerTransaction.verify)
さて、第一段階ではSignatoriesとの比較を行いましたが、第二段階では、実際に集めた署名との比較がSignatoriesとの間で行われることになります。
ここでは、実署名の検証(Aliceの署名をAliceの公開鍵で復号した結果と、Transactionのハッシュ値が一致すること)をそれぞれの署名に対して行いつつ、実際検証できた 署名のリストがSignatoriesを全て含んでいることを検証します。
Flow上の検証
こうした工夫を一つの絵にしたのがこちらの絵になります。
Flowの初期には、当然ながら実際の署名は集まっていません。その代替手段として、Signatoriesを用いたスマートコントラクトで指定された署名検証を行い、 その結果を受けてAliceやBobはそれぞれの署名を付与します。(実際には署名検証以外の全てのスマートコントラクトの検証やカスタマイズFlowを用意していれば追加の検証も行います) そして、実際に台帳に書き込みを行う直前には、Signatoriesに指定された全ての実署名が確保できることを改めて検証することになります。
まとめ
Corda5におけるTransactionの署名検証の全体像を紹介しました。Corda4と比べて、基本的なプロトコルに差はないのですが、Signatoriesという概念が追加 されたことで、署名検証のプロトコルがよりわかりやすくなったように思います。
<ご質問・ご要望の例>
- Corda Portalの記事について質問したい
- ブロックチェーンを活用した新規事業を相談したい
- 企業でのブロックチェーン活用方法を教えて欲しい 等々
SBI R3 Japan エンジニアリング部長
書籍出してます:https://amzn.asia/d/c0V31Vd
趣味:サッカー、ガンプラ、ドライブ、キャンプ