HyperLedger Fabric(v1.00) におけるトランザクションの理解

概要が少し長くなりました。
タイトルの内容だけ知りたい方は
「本題 - HyperLedger Fabricのトランザクションについて」から読み進めてください。

元々はFabricにて、十分な間隔を空けずに
同一Keyに対して連続して値の更新をリクエストすると値が変わらないことがある
という事象を説明するためにこの投稿を作成してます。

# 前置 - HyperLedger fabric について簡単に

bitcoinによるブロックチェーン技術を活用すべく生まれた
分散台帳（Distributed Ledger Technology）と呼ばれるもののプラットフォーム。

Linux Foundationのオープン・ソースであり、IBMが中心となって開発しているもので
様々な企業により実証検証が進められている。

# 前置 - HyperLedger fabric の特徴

詳しくは [こちら](https://www.ibm.com/developerworks/jp/cloud/library/cl-top-technical-advantages-of-hyperledger-fabric-for-blockchain-networks/) を参照。
コンソーシアム型（許可型）のブロックチェーン（分散台帳）基盤であり、
パブリック型（非許可型）と比較して以下のような特徴を持つ。

<dl>
  <dt>コンソーシアム型であり、許可制の（広義の）ブロックチェーンである</dt>
  <dd>そのまま。プライベート型でも運用可能だが、意味があるかは議論が分かれるところでしょう。</dd>
  <dd>不特定多数ノードを対象とせず、BFT（ビザンチン障害耐性）をv1.00時点では備えないことから</dd>
  <dd>厳密にはブロックチェーンでないという見解もあるので、「広義の」という表現は必要かな、と。</dd>
  <dd><br></dd>
  <dt>ファイナリティがある</dt>
  <dd>BitCoin等は確率的合意形成（PoW）を行うため、『一時的な』ブロックの分岐を伴う</dd>
  <dd>一方で確定的合意形成を行うfabricではブロックは分岐しない。</dd>
  <dd>v1.00では通常kafkaを用いる。</dd>
  <dd>zoo-keeprアンサンブルで乱暴に言えばノードの多数決でクラッシュ耐性をもつ。</dd>
  <dd>（v0.60ではPBFTがあったが、v1.00時点ではビザンチン障害耐性はない（SBFTは未実装））</dd>
  <dd><br></dd>
  <dt>マルチチャネルコンセンサスなど、秘匿性の高い台帳を構築しやすい</dt>
  <dd>ブロックチェーンの理念云々はともかく、実際のビジネスのニーズを踏まえてのことだろう。</dd>
</dl>

v1.00でTCertなどの実装が外れてる（追いついていない？）ので
現時点で完璧ではないが、CA（認証局）が用意されているのも特徴になる。
(2018.1現在で、CAの役割は初回アクセス時に証明書を払い出すくらいだし
 なお悪いことに実装はその証明書ではなく、サーバ側の秘密鍵を直接みているのでその部分を削る必要がある)

# 本題 - HyperLedger Fabricのトランザクションについて

## 各ノードと用語の役割（前提知識）

### ノード
| 名前 | 役割 | 
|:----:|:----|
|クライアント|SDKを用いてトランザクション(Tx)を発行する| 
|Peer   |台帳を保持し、Txをコミットする。また、エンドースメントのためのTxプローザルを受けて承認・却下を返す。チェインコード（スマートコントラクト）を持つ。  | 
|Orderer   |Txブロックを台帳に追加することを承認し、各Peerに伝える。チェインコードも台帳も持たない。   | 

* Peerは厳密には上記記載どおりの役割をするEndorsing Peerと、エンドースメントをせずチェインコードも持たなくて良いCommiting Peerに分かれる。
* が、ここでは説明を単純化するため、全てのPeerをEndorsing Peerと看做している。

### 用語
| 名前 | 意味 | 
|:----:|:----|
|チェインコード|Fabricの世界ではスマートコントラクトのコードをそう呼ぶ|
|プロポーザル|要求の意味。Txの実行を要求する、承認されるかは別|
|エンドースメント|承認の意味。Tx実行（Txのコミット）を承認するかどうか|
|シミュレーション|承認できるかを判断するため事前にチェインコードを実行する行為。この段階ではTxは台帳にコミットされない|
|台帳|Txの履歴を保持しているブロックチェーン|
|ワールドステート|これまでのTx実行の結果、現在の値がどうなっているかをもつストア|

## トランザクションの流れ

絵にするとかえって分かりづらい気がして、文章主体です。

### １．トランザクション（Tx）のプロポーザル（要求）

クライアントはSDKを通して**Peer[^1]へ対して**Tx要求を投げる。
SDKが、どのPeerにTx要求を投げるかは設定が可能。
例えば、５台に投げて３台から返事があればOKみたいに。

### ２．トランザクション（Tx）のシミュレーション

Tx要求を受けたPeerは実際にチェインコードを動かして、Tx要求を承認できるかを確認する。
（例えば、チェインコードが無限ループしたり例外が発生すると問題なため）

この際、重要な点は以下の２つ。

+ **シミュレーション結果は台帳にコミットされない**
+ **更新前と更新後の両方の値が取得される**

### ３．シミュレーション（検証）の完了

検証が無事に済めば、Txプロポーザルが成功したとみなし
**Peerはクライアント（SDK）に検証時に取得した更新前後の値セットを返却する**

### ４．クライアントから値をOrdererへサブミット

クライアント（SDK）は、再度**Orderer**に向けて更新前後の値セットを送信する。
Ordererは同時にいくつも要求を受信する場合があるので
受けた情報のコミット順序を整理する（整列させる）役割を果たす。

### ５．Ordererから各Peerへのコミット要求を送信

OrdererはTxの実行順序を整理した後で順番にコミット要求を各**Peer**[^2]へ送る。

### ６．各Peerにてトランザクション（Tx）の検証

各PeerはTxの実行を許可するかを判断するため最終的な検証を行う。

**重要なのは、更新前後の値がＮｏ．２の検証時と今回（コミット時）で異なる場合、Txは却下されることだ。**
**よって、同一Keyに対して十分な間隔を空けずに連続したTx要求を送ると、後続のTxはコミットされない事象が発生する。**

+ **Txが承認された場合、台帳に履歴を残し、ワールドステートの値が更新される。**
+ **Txが却下された場合、台帳に無効（失敗）マーク付で履歴は残すが、ワールドステートの値は更新しない。**

## まとめ（所感）

文中では触れなかったが、Fabricのスループットは1000-2000Tx/秒らしい（明確な出典はないが）。
が、恐らく余程理想的な環境でない限りそこまで出ることもまずないんじゃないか、と。
（TCertが実装されれば仕組み上、更にスループットは低下するかもしれない）

加えて、上記のように（あくまで同一Keyに対してだが）
近いタイミングで連続したトランザクション要求を投げれば
後続のトランザクション自体が却下されてしまう。

個人的にはこのあたりが
分散台帳はDBMSとは全然違うものだ、という特徴を表していると思う。
（パブリックなブロックチェーンの場合はファイナリティの違いもあるが）

DBMSをベースに分散台帳やブロックチェーンを比較してしまうと
これはなんなんだ？という話になるのは当たり前のこと。
（特性の違いを理解するための比較自体には意味はある）

分散台帳やブロックチェーンは

+ 非中央集権的な分散ネットワークを持つ（分散台帳の場合はコンソーシアム型になる）
+ 各ノードがブロックチェーンを持ち、高い可用性とデータ保全性（データ同一性）を持つ
+ 改ざん耐性ないし改ざん検出容易性に優れている[^3]

といった特徴を持ち、合意形成（契約履行）の履歴を残すために適しているし
スマートコントラクト（がもらたすビジネス革新）とも相性が非常によいと思う。

# 注釈

[^1]: 厳密には要求を受けられるのはEndosing Peerだけだが、本文中ではPeerはEndosing Peerと同義としている（Commiting Peerはあくまで、Endosing Peerのサブセットなので、それがない構成だと思えばよい）。

[^2]: この場合のPeerはCommiting Peerも含む。また、PeerにはAnchor Peerという特別な役割を与えられたものがあり、Anchor PeerはOrdererから受け取ったコミット要求を、別のPeerへと階層的に中継する役割を果たす。

[^3]: fabricの改ざん耐性は不明。bitcoin等は、PoW（一定期間ごとに難易度を調整可能な方式である先頭nビットが0となるハッシュの生成を求め、それをExtra Nonceへ書き込んでブロックを繋げる）であるから改ざん耐性に優れるのであって、ただのハッシュチェーンの場合はそれほどの労力をかけずに先頭から全てのブロックを書き換えることが論理的に可能なように思える。分散台帳では、悪意のある第３者に侵入されないようにネットワークのセキュリティはしっかり担保しないとならないだろう。