Develop with pleasure!

福岡でCloudとかBlockchainとか。

ECDSA署名のエンコーディング関連のmalleabilityを解消するルールを追加するBIP-146

Segwitのトランザクションで署名が入力から分離されたことで、署名スクリプトに細工してtxidを変更することはできなくなったけど、witnessに移動した署名データの改変自体は可能。依然として可能なECDSA署名のエンコーディング関連の改変を解消するためにトランザクションの有効性を検証する際にルールを追加しようというのがBIP-146↓

https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki

追加のルール自体は以前からCoreのリレーポリシーとして適用されているので実質有効化されているようなものかな。

動機

署名のmalleabilityとは、ネットワーク上のリレーノードが(リレーノード自体はブロードキャストされたトランザクションの署名に使われた秘密鍵にアクセスすることはできない)、トランザクションの署名を改変する能力のことを指す。非Segregated Witnessのトランザクションでは、署名のmalleabilityによりtxidの変更が可能で、もしそのtxidを参照する子トランザクションが存在した場合、その子トランザクションを無効にする。Segregated Witness(BIP-141)のトランザクションであれば第三者がtxidを変更するようなことはできないが、malleabilityによりwtxidを改変することは可能で、Compact Block(BIP-152)のリレーの効率を低下させる可能性がある。

BIP-66で署名のフォーマットに厳密なDER形式を適用して以降、ECDSAの署名には既知の2つのmalleabilityの要因が残っている↓

  1. ECDSA署名固有のmalleability
    ECDSA固有の問題で、署名データ(r, s)があった場合に、sの値をマイナスにし(r, -s(mod n))したデータも署名として有効と判断される。
  2. 失敗した署名のmalleability
    OP_CHECKSIGまたはOP_CHECKMULTISIGで署名の検証に失敗した場合、FALSEがスタックに戻され、スクリプトの評価は続く。失敗した署名でも、BIP-66の規則に従う署名である限りそれには意味がある。

このBIPでは、これらのmalleabilityを解消するための新しいルールを定義する。

仕様

署名エンコーディングのmalleabilityを解消するため、以下の新しいルールをpre-segregated Witness及びsegregated witness scriptに適用する。

LOW_S

ECDSAの署名のSの値は最大でも曲線の位数を2で割った値以下でないといけない。OP_CHECKSIG*1, OP_CHECKSIGVERIFY, OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFYをパスする各ECDSA署名には、このルールが適用され、S0x1から0x7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 5D576E73 57A4501D DFE92F46 681B20A0楕円曲線のベースポイントGの位数を2で割った値)の範囲の値で、厳密なDERフォーマットを適用した署名でなくてはならない。

ECDSAの署名検証の際、署名が空のバイト列ではなく、LOW_Sチェックに合格しない場合、スクリプト全体がfalseと判定される。

署名値にHIGH_Sの値が使われている場合は、以下を計算することで簡単にLOW_Sに置き換えることができる。

S' = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 - S

NULLFAIL

OP_CHECKSIGがスタックにfalseを返す際は、関連する署名は空のバイト配列でなければならない。

OP_CHECKMULTISIGがスタックにfalseを返す際は、OP_CHECKMULTISIGに渡す全ての署名は空のバイト配列でなければならない。この時、マルチシグ内の一部の署名の不正などで署名検証が早期に終了し一部の署名がスキップされたとしても、全署名についてこのNULLFAILチェックをしなければならない。

それ以外の場合は、スクリプト全体がすぐにfalseと判定される。

サンプル

以下の例はLOW_SルールとNULLFAILルールを組み合わせた結果*2

注釈

CO       : 曲線の位数(curve order) = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
HCO      : 曲線の位数を2で割った値(half curve order) = CO / 2 = 0x7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 5D576E73 57A4501D DFE92F46 681B20A0
P1, P2   : シリアライズされた有効な公開鍵
S1L, S2L : P1とP2に対応した有効な low S 値を持つ署名(1 ≤ S ≤ HCO)
S1H, S2H : P1とP2に対応したhigh S 値を持つ署名 (HCO < S < CO)
F        : BIP-66に準拠しているが無効な署名(空ではない)

以下のスクリプトはこれまで通りスタックにTRUEを返す。

S1L P1 CHECKSIG
0 S1L S2L 2 P1 P2 2 CHECKMULTISIG

以下のスクリプトはこれまで通りスタックにFALSEを返す。

0 P1 CHECKSIG
0 0 0 2 P1 P2 2 CHECKMULTISIG

以下のスクリプトはこれまではTRUEだったが、新しいルールではスクリプト自体がすぐに失敗する。

S1H P1 CHECKSIG
0 S1H S2L 2 P1 P2 2 CHECKMULTISIG
0 S1L S2H 2 P1 P2 2 CHECKMULTISIG
0 S1H S2H 2 P1 P2 2 CHECKMULTISIG

以下のスクリプトはこれまではFALSEだったが、新しいルールではスクリプト自体がすぐに失敗する。

F P1 CHECKSIG
0 S2L S1L 2 P1 P2 2 CHECKMULTISIG
0 S1L F   2 P1 P2 2 CHECKMULTISIG
0 F   S2L 2 P1 P2 2 CHECKMULTISIG
0 S1L 0   2 P1 P2 2 CHECKMULTISIG
0 0   S2L 2 P1 P2 2 CHECKMULTISIG
0 F   0   2 P1 P2 2 CHECKMULTISIG
0 0   F   2 P1 P2 2 CHECKMULTISIG

デプロイメント

このBIPはBIP-9のversion bitsを利用してデプロイされるが詳細は未定。

互換性

参照クライアントはv0.9.0以降LOW_S互換の署名を生成しており、LOW_Sのルールはv0.11.0以降の参照クライアントでリレーポリシーとして適用されている。2016年8月時点で、ルールに違反するトランザクションはごくわずかである。実際に使われている全scriptPubKeyにおいて、準拠していない署名を準拠した署名に変換するのは非常に簡単なことであるため、このルールによって機能が損なわれることはない。

OP_CHECKSIGOP_CHECKMULTISIGに失敗するスクリプトがチェーン上に記録されるのは稀で、NULLFAILルールは参照クライアントのv0.13.1以降リレーポリシーとして適用されている。

ただ、ユーザーは変わったスクリプトを設計する際は、このルールに特別な注意を払うこと。

実装

参照クライアントの実装は↓

https://github.com/bitcoin/bitcoin/blob/35fe0393f216aa6020fc929272118eade5628636/src/script/interpreter.cpp#L185

で、そのプルリクは↓

github.com

*1:BIP-141のP2WPKHも含む

*2:参照クライアントv0.13.1の実装により、曲線の位数の半分の値より大きなS値を持つ署名がLOW_Sチェックをパスする可能性があることに注意が必要。ただそのような署名は無効かつ、その後のNULLFAILルールのチェックで失敗する。

ElementsのAsset tagの生成と追加発行の仕組み

ElementsでConfidential Assetsについて、以前ブログを書いた↓

techmedia-think.hatenablog.com

けど、Asset Tagや実際にアセットを追加発行する際のトークンなどがどういうロジックで生成されて、何を持って追加発行が承認されるのか仕組みについてよく分かってなかったので、ホワイトペーパーを読んでみた↓

https://blockstream.com/bitcoin17-final41.pdf

Asset tagを構成する要素

Ricardian contract

アセットの使用条件や償還に関して記載したマシンでパース可能な法的文書で、Elements固有の技術要素ではない。 この文書のハッシュをアセット発行時のエントロピーを生成する際のインプットにすることで、アセットのRicardian contractへのコミットとしてるみたい。

Elementsでは実際にどういうRicardian contractを生成しているのか確認してみたけど、現状のウォレットは空のハッシュ(uint256)を使ってるだけっぽい↓

基本的にRicardian contractの作成は外部レイヤーでやって、今後そのハッシュを引数に取るようになるのかもしれない。

Asset entropy

発行トランザクションに使用するUTXOのOutPointの値をIとし、アセットの発行者が指定したRicardian contract Cがあったとして、asset entropy E

E = Hash(Hash(I)||Hash(C))

として算出される。

Elementsでの実装は↓で、UTXOをRicardian contract をリーフにしたマークルルートを計算してる。

現状のElementsだとRicardian contractが空なので、実質UTXOのOutPointがエントロピーになってる。

Asset tag

↑のasset entropy E(このエントロピーはUTXOとRicardian contractへのコミットメントでもある)を使って、Hash(E||0) を計算しそれを入力としたPedersen commitmentをセットアップする。このPedersen commitment HA ∈ G がasset tagとなる。ランダムオラクルモデルにおいて、asset tagはGまたは他の任意のasset tagについてその離散対数が分からない、ランダムな曲線上のポイントと言える。

アセットの発行

アセットを発行する際のトランザクションの入力は以下の要素で構成される。

  • 使用するUTXO I
  • Ricardian contract C
  • アセットの発行量
    以下のどちらかで指定
    • 発行量を明示的に指定する場合はその量v0
    • 発行量は明示的に指定しない場合は、Pedersen commitment HとBackMaxwellのrangeproof P0
  • 追加発行を許可するかどうかを示すbooleanのフィールド

ICからエントロピーを生成し、エントロピーと追加発行を示すフィールドからasset tagを生成するのだろう。

アセットの追加発行

アセットは初期発行のみで発行量を固定するパターンと、あとでアセットを追加発行できる2つの発行パターンがある。

追加発行する場合は、最初のアセット発行時に、追加発行をすることができるトークンが生成される。

追加発行の有無の設定

アセットを発行する際は、↑にも書いたように、Ricardian contractとUTXOからasset entropy Eを生成し、そのEからHash(E||0) を計算し、それを使って作成したPedersen commitmentがasset tagになる。この時Hash(E||0)の0の部分が追加発行の有無を設定するフィールドになる。0だと発行量を固定するパターンで、これを1にすると追加発行を可能にするPedersen commitment(asset tag)になる。

追加発行が可能なアセットはアセット発行トランザクションの入力でそのことを示し、そのトランザクションにはasset tag HAにコミットするamountが1の追加の出力が作られる。

このようにasset tagはasset entropyと追加発行の有無(0 or 1)に対するコミットメントになっているので、オリジナルのasset entropyとblinding factorを明らかにすることで、再発行する権限を有することを証明できる。

トークンの実態

追加発行をすることができるトークンというのは、Elementsの実装を見るとHash(E||1)の計算結果みたい。

アセットが追加発行を許可しているアセットで、ウォレット内に↑のトークンがあればアセットの追加発行が可能になる。

追加発行時の入力

アセットの追加発行をする際のトランザクションの入力は、以下の要素で構成される。

  • アセットの再発行能力を持つUTXO
    再発行を許可する発行トランザクションにはamountが1の出力が追加されるとあったけど、それを利用する?
  • オリジナルのasset entropy E
  • UTXOのasset commitmentのblinding factor
  • アセットの発行量
    以下のどちらかで指定
    • 発行量を明示的に指定する場合はその量v0
    • 発行量は明示的に指定しない場合は、Pedersen commitment HとBackMaxwellのrangeproof P0

↑のトークンを入手すればアセットの再発行が可能になるんだろうけど、現状のようにRicardian contracが空のままだと発行トランザクションの入力からエントロピーを誰でも計算できてしまうような気がするんだけどそれは問題ないのかな?

Bitcoin Coreのテストコードの実行方法

既存のコードの追加・改修の際に、動作を保証するテストコードがあり、自動テストできる環境があるのは重要で、Bitcoin Coreにももちろんテストコードと自動テストの仕組みがある。

Bitcoin Coreには単体テストと、リグレッション及びインテグレーションテスト用のテストコードがそれぞれ存在する。

単体テストの実行

テストコードはconfigureオプションで無効化していない限り、自動的にコンパイルされる。

実行対象のテストコードは、以下のMakefileに記載されている↓

(他にもウォレットやsecp256k1などのテストが各フォルダにある。)

テストの実行は簡単で make checkを実行すればC++で書かれたテストが実行される。もしくは、コンパイルされたsrc/test/test_bitcoinを実行してもいい。

$ ./src/test/test_bitcoin    
Running 258 test cases...

*** No errors detected

bitcoin-qtの場合はsrc/qt/test/test_bitcoin-qtを実行する。

個別のテストの実行

↑では全テストコードが実行されるので、個別に実行したい場合は、↓のように--run_testオプションで対象のテストを指定して、src/test/test_bitcoinを使って実行する。

$ ./src/test/test_bitcoin --run_test=script_tests --log_level=all

↑はsrc/test/script_tests.cpp のテスト実行。--log_levelオプションでログをコンソールに出力することもできる。

指定可能なオプションは--helpオプションを指定してtest_bitcoinを実行すれば確認できる。

テストコードの追加

単体テストのコードはboostのテストフレームワークを使って書かれてるので、テストコードを追加する際もそれを使用する。

既存のファイルにテストコードを追加する場合は、既存のテストファイルのBOOST_AUTO_TEST_CASE関数内に追加するか、BOOST_AUTO_TEST_CASE関数を追加して実装する。

新規にテストコードのファイルを追加する場合は、そのファイルを↑のMakefile.test.includeに追記する。
基本的にはソースファイルやクラス毎に1つテストファイルを作成することになっており、テストファイルの命名規則<source_filename>_tests.cpp

bitcoin-qtのテストはsrc/qt/test/以下に追加)

リグレッション及びインテグレーションテストの実行

このテストは↓のセットで構成される。

  • functional
    RPCやP2Pインターフェースを介して動作するbitcoind及びbitcoin-qtの機能をテストするコード。
  • util
    Bitcoinのユーティリティのテストコードで、現在の対象はbitcoin-txのみ。

functionalテストの実行

各テストの実行は、それぞれpythonのテストファイルを直接実行すればいい。

$ test/functional/segwit.py 
2017-08-10 06:51:43.129000 TestFramework (INFO): Initializing test directory /tmp/test92n84pq5
2017-08-10 06:51:45.901000 TestFramework (INFO): Verify sigops are counted in GBT with pre-BIP141 rules before the fork
2017-08-10 06:51:50.062000 TestFramework (INFO): Verify default node can't accept any witness format txs before fork
...

もしくは、test_runner.pyの引数に実行対象のテストファイルを指定する方法もある。

$ test/functional/test_runner.py segwit.py net.py
Temporary test directory at /tmp/bitcoin_test_runner_20170810_155359
............
net.py passed, Duration: 6 s
..................................
segwit.py passed, Duration: 24 s

TEST      | STATUS    | DURATION

net.py    | ✓ Passed  | 6 s
segwit.py | ✓ Passed  | 24 s

ALL       | ✓ Passed  | 30 s (accumulated) 
Runtime: 24 s

全テストケースを実行する場合は、テストファイルを指定せずに、test_runner.pyを実行する。

テストコードに記載されているログは、デフォルトではコンソールには出力されず全てtest_framework.logというログファイルに記載され、テスト実行用の一時フォルダ内に格納される。 コンソールに出力する場合は-lオプションを指定。

またPythonで書かれ、実行されているので、任意の場所に↓を入れて、デバッガをアタッチすることも可能。

import pdb; pdb.set_trace()

テストを追加する場合は、↓を参考にする。

https://github.com/bitcoin/bitcoin/blob/master/test/functional/README.md

utilテストの実行

↓のbitcoin-util-test.pyを実行する。-vはverboseオプションで各テストのログが出力される。

$ test/util/bitcoin-util-test.py -v
2017-08-10 15:45:50,726 - INFO - PASSED: Creates a blank v1 transaction
2017-08-10 15:45:50,731 - INFO - PASSED: Creates a blank v1 transaction (output in json)
2017-08-10 15:45:50,735 - INFO - PASSED: Creates a blank transaction when nothing is piped into bitcoin-tx
...

プルーニングピア向けのservice bitを定義したBIP-159

Bitcoinのmainnetのブロックチェーンのデータサイズは現在150GB弱ほどだが、プルーニングモードで動作させると使用済みのTXOを指定サイズ分だけ保持し、古いTXOデータは削除されていくようになり、とても少ないディスクスペースでフルノードを動作させることができる。

ただ、昔の履歴ブロックは消えてしまうため、IBD(Initial Block Download)などでジェネシスブロックからの古いブロックの要求があってもそれに答えることはできない。そのためプルーニングモードを使用している場合は、nServiceFlagsNODE_NETWORKがアンセットされるようになっている。

ただIBDはできないけど、最近リレーされたブロックであれば提供することができるため、プルーニングノード向けに新たにservice bitを定義して、直近のブロックやヘッダ、トランザクションは他のフルノードと同様リレーできるようにしようということでBIP-159が提案された↓

https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki

動機

プルーニングモードで動作しているピアは、全ブロックの歴史を提供することはできないが、それ以外は従来のピアと同じサービスを提供できる。Bitcoinは現在、ピアが全ての履歴ブロックを提供できることを示すNODE_NETWORKのservice bitのみを提供している。

  1. プルーニングされているピアは、ブロック、ヘッダ、トランザクション、アドレスをリレーすることができ、履歴ブロックも限られた数であれば提供できるため、プルーニングピアもそのserviceをアナウンスする方法を持つべきである。
  2. 他のピアが非プルーニングピアからブートストラップできるようにするため、IBDが終わったピアは、プルーニングされたピアへのいくつかのアウトバウンド接続を考慮する必要がある。

仕様

新しいservice bits

このBIPでは2つの新しいservice bitsを定義する↓

名称 bit 内容
NODE_NETWORK_LIMITED_LOW bit 10 (0x400) このservice bitが通知された場合、ピアは少なくとも最新の288ブロック(現在のBitcoin Coreの最小値で約2日分のブロック)に対応できなければならない。
NODE_NETWORK_LIMITED_HIGH bit 11 (0x800) このservice bitが通知された場合、ピアは最新の1152ブロック(約8日分)に対応できなければならない。

NODE_NETWORK_LIMITED_*のservice bitをシグナリングしているピアに接続する際は、チェーンの再編成を処理するため144ブロックのセーフティバッファを考慮する必要がある。

アドレスのリレー

このBIPに従うフルノードは、(NODE_NETWORK_LIMITED_*のservice bitをシグナリングしているピアを含む)接続中のピアから(addrメッセージ等で送られる)address/servicesをリレーする必要がある。

ピアのフィンガープリント対策

(ディスク容量など各ピアの構成は違うので)プルーニングしいてるピアがどれだけのブロック数を保持しているかはピアによって異なり、それがフィンガープリンティングの弱点につながるかもしれない(getdataメッセージでピアがプルーニングしている深さを知ることができる)。NODE_NETWORK_LIMITEDをサポートするピアは、プルーニングしている深さを漏らさないようにしなければならない。そのため、通知されたNODE_NETWORK_LIMITED_*閾値(↑よりそれぞれ288ブロックと1152ブロック)より深いブロックを要求するメッセージが来ても処理してはならない。

リスク

このBIPに従うプルーニングピアは、より多くのアウトバウンドの帯域幅を消費する可能性がある。

リレーされたaddrメッセージのnServiceFlags(service bits) をチェックしていない軽量クライアントは、意図せずプルーニングピアに接続し、プルーニング済みのブロックを要求する可能性がある。この場合プルーニングピアは対象のブロックデータを返せないので、そういう事態を避けるために軽量クライアントはservice bitsをチェックしなければならない。DNSシードを介してピアのIPを取得する軽量クライアントは、DNSフィルタリングオプションを使う必要がある。

互換性

この提案は後方互換性がある。

参照実装

github.com

2017年8月8時点ではまだマージはされてない。

所感

  • 接続先のノードがプルーニングノードかどうかは、今までNODE_NETWORKがセットされてないノードという識別方法だったけど、上記のservice bitsが追加されたことで明示的にプルーニングノードが識別できるようになる。
  • プルーニングピアにプルーニングされたブロックを要求した場合、そのピアの挙動としては何も応答を返さない?

Bitcoinの高速リレーネットワークFIBRE

ブロックサイズを拡張について、データ量が多くなるためデータを転送する際により高いネットワーク帯域が求められるようになり、ハッシュパワーの集中が促進するのではないかという懸念がある。 より高速なリレーネットワークを活用することで、この問題を解消できるのではないかということで、Matt CoralloによりFIBRE(Fast Internet Bitcoin Relay Engine)というパブリックに利用可能なBitcoinの高速リレーネットワークが2016年7月に発表されている↓

http://bitcoinfibre.org/

簡単に言うと、TCPだと長距離伝送する際のパケットロスが発生し、パケットの再送が必要になりネットワークの往復によるスパイクが発生するので、FEC(前方誤り訂正)のあるUDPを使って受信側のピアがロスしたパケットについて送信元に再度リクエストするのではなく、受信済みのデータから欠落したデータを再構築できるようにし、余分な往復をさせないようにし、Compact Blockと組み合わせて高速なリレーネットワークを実現しようというもの。

FIBREがどういうコンセプトで作られたのかは、Matt Coralloのブログにまとめられている↓ので見てみる。

The Future of The Bitcoin Relay Network(s) · BlueMatt's Blog

FIBREの設計

オリジナルのリレーネットワークにおいて、ブロックを1つまたは2つのパケットで送信することが出来なかった。この結果、TCPの長距離伝送の処理が不十分になり、リレー時間が著しく急上昇する(元は100ミリ秒〜300ミリ秒だったのが1秒以上に)。FIBREはオリジナルのリレーネットワークの設計を以下の2つの点で改善している。

  • FEC(前方誤り訂正)のあるUDPを使用して、最初に余分なデータを送信することで、パケットロスによるリレー時間のスパイクを排除する。
  • Bitcoin CoreのCompact Blockを使った圧縮

TCPは大量のデータを送信する際に適切な帯域幅で信頼性の高い伝送ができるよう設計されているが、小中規模のデータを確実に低いレイテンシーでリレーするのには向いていない。TCPでは、それぞれ1500バイト以下に調整されたパケットを一度だけ送信し、相手側から応答があって初めて一部のパケットが失われたことが検出できる。パケットロスが発生したことを検知した送信側は、再度ロストしたパケットを相手に再送信し、相手は受け取ったパケットから元の送信を再構築する。この余分な往復の時間は、オリジナルのネットワーク上のリレー時間に大きなスパイクを発生させる。

インターネットにおける長距離伝送では平均して1%のパケットロスが確認された。この場合、余計な往復なく完全な非圧縮のブロックを送信する可能性はだいたい0.991000000/1500 = 0.1%となる。さらにパケットロスはより多くのデータを送信するにつれて増える。(約10パケットで)15KBのデータを送信するだけでも、平均的なホスティングプロバイダでは成功する確率は90%である。往復のレイテンシーが100〜200ミリ秒の1Gbpsもしくは100Mbpsのリンクについて言えば、1回の往復のコストは、送信可能なデータ量から考えると大幅なコスト高になる。

従って、最大限に低遅延なブロック送信を行なうためには、再送の必要性がないようにする必要がある。再送を必要としないようにするためには、途中でパケットが失われても送信側に再度データを尋ねること無く受信ピアがブロック全体を再構築できるだけの充分なデータを送信する必要がある。こういうった分野は、同じ要件を持つビデオ会議のおかげで、よく研究がされている分野になる。一般的な解決策は、失われたパケットの隙間を埋めることができるデータを送信する、比較的単純な線形代数を用いた(=FEC(前方誤り訂正)のある)UDPベースの送信である。

このようにしてパケットロスの問題を解消しても、1Gbpsのリンクで1MBのデータを送信するのは数ミリ秒だが、FECデータの構築と送信によるオーバーヘッドの時間は2倍以上になる。そのためできるだけデータを圧縮するという意味で、Bitcoin CoreのCompact Blockの仕組みはパフォーマンスにとって重要になる。

Compact Blockの設計はFIBREの作業を進めていた時に同時に進められていたので、cmpctblockメッセージのフォーマットはUDP-FECベースのリレーメカニズムに収まるよう設計されている。Compact BlockとFIBREの唯一の違いは、FIBREではデータをFEC付きのUDPで送信し、mempoolに欠落しているトランザクションを要求するために往復するのではなくブロックのトランザクションがすぐにFEC付きで送信する。

FIBREのもう1つの改善点として、サーバに個々のパケットが到着するとすぐにそのパケットをピアにリレーする。残念ながらFIBREのFECエンコーディングの性質上、個々のパケットが正当なブロックの一部かどうかを知ることはできず、同じグループによって実行されているノード間でのみ、この最適化が可能になる。

Bitcoinのリレーとリレーネットワークの集中化

Bitcoinのリレーネットワークの集中化の苦情の多くは、その存在がブロックの検閲する立場にあるという点にある。より効果的なP2Pネットワークであればそういった攻撃の影響を減らすことができるが、完全には解決できない。慎重に選択されたネットワークトポロジーが確実にP2Pネットワークのレイテンシーを上回るため、この問題を唯一解決するには、パブリックなリレーネットワークを追加することである。残念ながらソフトウェアがオープンであるにも関らず、設置された唯一の他のリレーネットワークは個々のマイナーによって運営されるプライベートなものであった。半公式のFalconというリレーネットワークが登場した時、その設計者はスクラッチでスタートし過去数年間のBitcoinのブロックリレーに関する知識を取り入れていないものだった。

FIBREがBitcoinの中継の分散化をさらに促進するためには、FIBREネットワークを設定するのが明らかに簡単である必要がある。そのためFIBREソフトウェアはBitcoin Coreをフォークしアドオンモジュールとして設計されており、Bitcoin Coreを含めた形でリリースされるので、既存のマイナーのシステムにも簡単に組み込むことができる。さらに、ソフトウェアの構成から世界中のレイテンシーを最小限に抑えるためのホスティングプロバイダーの選択方法まで全てを網羅したガイドが以下の記事でまとめられている↓

FIBRE Fast Internet Bitcoin Relay Engine

2017年8月現在は、Bitcoin Core 0.14.1をベースにしたFIBREが公開されている↓

github.com

あまり話題にならないけど、ブロックサイズの拡大が叫ばれる裏ではこういったリレーネットワークやUTXOのサイズ削減など地道なリサーチが続けられているので、その辺も追っていきたい。