doraemon

doraemon

let's go write some rusty code and revolutionize the world!

ビットコインの基本知識

参考:北京大学肖臻老师《区块链技术与应用》公开课

ビットコインにおけるハッシュ関数の三つの特性#

コリジョン耐性#

異なる二つの入力に対して、出力が等しい場合、これをハッシュ衝突と呼びます。

良いハッシュ関数は、ハッシュ衝突をできるだけ避け、コリジョン耐性の特性を持つべきです。

どのハッシュアルゴリズムもコリジョン耐性を証明することはできません。ハッシュ衝突は避けられないもので、入力空間は常に出力空間よりも大きいからです。

  • この特性の役割

メッセージのダイジェストを求めること。

例えば、メッセージのハッシュ値が H (m)=digest である場合、誰かが m の値を改ざんしようとしても H (m) が変わらないようにはできません。

隠蔽性#

ハッシュ関数の計算過程は一方向性であり、逆算できません。(H (x) から x を導き出すことはできません)。

隠蔽性の特性は入力空間が十分に大きいことが前提です。

暗号学において要求されるこの二つの特性に加えて、ビットコインで使用されるハッシュ関数には第三の特性があります。

パズルフレンドリー#

ビットコインのマイニングプロセスは、実際には nonce(number of once)を探すことです。nonce はブロックのヘッダー内の他の情報と一緒に入力として使用され、得られたハッシュ値は指定された目標値以下でなければなりません。H (block header)≤target。block header はブロックのヘッダーを指し、ヘッダーには多くのフィールドがあり、その中の一つが設定可能なランダム数 nonce です。マイニングプロセスは、ブロックヘッダーが指定された範囲内にハッシュされるようにランダム数を試行し続けることです。

パズルフレンドリーとは、マイニングプロセスにショートカットがないことを指します。出力値を指定された範囲に収めるためには、一つずつ試すしかなく、このプロセスは作業証明(proof of work)としても機能します。

ハッシュ値は事前に予測できません。マイニングは難しく、検証は容易です。(difficult to solve, but easy to verify

SHA-256(セキュアハッシュアルゴリズム)#

ビットコインで使用されるハッシュ関数は SHA-256(セキュアハッシュアルゴリズム)であり、上記の三つの特性を満たしています。

あるブロックチェーン取引システムが SHA256 アルゴリズムを使用している場合、$2^{256}$ 通りの出力があり、$2^{256}+1$ 回の入力を行うと必ず一度は衝突が発生します。確率的に見ても、$2^{130}$ 回の入力で 99% の確率で衝突が発生します。

あるコンピュータが毎秒 10000 回の速度でハッシュ計算を行う場合、$10^{27}$ 年かかって $2^{128}$ 回のハッシュを完了することになります。

ビットコインのアカウント#

ローカルで公開鍵と秘密鍵のペア(public key, private key)を作成することがアカウントとなります。公開鍵と秘密鍵のペアは非対称暗号技術(asymmetric encryption algorithm)から生成されます。

BTC 取引では秘密鍵を使用して署名し、他の人は公開鍵で署名を検証します。

公開鍵と秘密鍵を生成する際には良いランダムソース(a good source of randomness)が必要です。公開鍵と秘密鍵はランダムに生成されますが、ランダムソースが悪いと同じ公開鍵と秘密鍵が生成される可能性があります。暗号実装では一般的に物理ノイズソースチップをランダムソースとして使用します。

ビットコインで使用される署名アルゴリズムでは、公開鍵と秘密鍵を生成する際だけでなく、その後の各署名でも良いランダムソースが必要です。一度でも署名に使用するランダムソースが悪ければ、秘密鍵が漏洩する可能性があります。

ランダムに生成された公開鍵と秘密鍵が同じである確率は微々たるもので、無視できるほどです。

ビットコインにおける重要なデータ構造#

ハッシュポインタ#

ビットコインにおける最も基本的な構造はブロックチェーンであり、ブロックチェーンは一つ一つのブロックで構成された連結リストです。ブロックチェーンと通常の連結リストの違いは何でしょうか?

ビットコインは通常のポインタの代わりにハッシュポインタを使用しています(block chain is a linked list using hash pointers)。

ブロックチェーンの最初のブロックは創世ブロック(genesis block)と呼ばれ、最後のブロックは最近生成されたブロック(most recent block)です。各ブロックは前のブロックへのハッシュポインタを含んでいます。

この構造により、** 改ざん検出可能なログ(tamper-evident log)** を実現できます。もし誰かがブロックの内容を変更した場合、次のブロックのハッシュポインタが一致しなくなります。なぜなら、次のブロックのハッシュポインタは前のブロックの内容に基づいて計算されるからです。したがって、次のハッシュポインタも変更しなければならず、これが続きます。したがって、最後のブロックのハッシュを記録しておけば、前のすべてのブロックが改ざんされていないことを保証できます。

ポインタが保存するのはローカルメモリのアドレスであり、ローカルのコンピュータ上でのみ意味があります。他のコンピュータに送信しても意味がありません。では、ブロックを公開する際にハッシュポインタはどのようにネットワークを通じて送信されるのでしょうか?

ハッシュポインタとは、実際のシステムで使用される際にはハッシュのみであり、ポインタは存在しないということです。

マークルツリー#

ブロックヘッダー(block header)にはマークルツリーの根ハッシュ(root hash)が含まれています。マークルツリーの根ハッシュ値を記憶しておけば、ツリー内の任意の部分の変更を検出できます。

取引がマークルツリー内のどこにあるかを見つける(すべての取引は葉ノードにあります)と、そのブロックは根ノードまでのパスをマークル証明(merkle proof)と呼びます。

軽ノードはブロックヘッダーのみを保存します。軽ノードが特定の取引がマークルツリーに含まれているかどうかを知りたい場合、全ノードにリクエストを送信し、その取引が含まれていることを証明するマークル証明を要求します。これには軽ノードが必要とするハッシュが含まれており、軽ノードは自分のローカルで検証します。

マークル証明は何を証明できますか?特定の取引が指定されたブロックに含まれているかどうかを証明します。

例えば、軽ノードが全体のブロック UTXO の内容を維持していない場合、ブロックヘッダーだけを知っているとします。軽ノードが全ノードに尋ねます:その取引はこのブロックにありますか?全ノードは証明としてマークル証明を返し、軽ノードはそれが真実であるかどうかを検証できます。

マークルツリーバイナリツリーの違い:通常のポインタの代わりにハッシュポインタを使用しています。

中央集権的なデジタル通貨が解決すべき問題#

中央集権的でないデジタル通貨は、二つの問題を解決する必要があります。

  • 最初の問題は、誰が通貨を発行する権限を持つのか?
  • 二つ目の問題は、取引の合法性をどうやって検証するのか?

二重支払い問題(double spending)#

二重支払いとは、一つの金銭が二回支払われることを指します。中央集権的な帳簿は二重支払い攻撃を簡単に解決できますが、中央集権的でない方案では、帳簿の正確性を維持するためのデータ構造が必要です。このデータ構造がブロックチェーンです。

ビットコインシステムでは、各取引は入力と出力の二つの部分を含みます。入力部分は通貨の出所を示し、出力部分は受取人の公開鍵のハッシュを示します。

A が B に送金するために必要な情報:A の秘密鍵の署名と B のアドレス(B の受取アドレスは公開鍵から推算されます)。

この部分には二つのハッシュポインタがあります。最初の部分は各ブロックを連結リストとして接続し、取引の詳細には二つ目のハッシュポインタが前の取引を指しています。これは通貨の出所を示すためです(ダブルスパンドを防ぐためです)。

分散型合意(distributed consensus)#

各アカウントは取引を発行できるため、この取引はすべてのノードにブロードキャストされます。いくつかの取引は合法であり、いくつかの取引は違法である可能性があります。では、どの取引が次のブロックに書き込まれるべきか、どの順序で書き込まれるべきかを決定するのは誰でしょうか?

分散型の合意の簡単な例は、分散ハッシュテーブル(distributed hash table)です。たとえば、システム内に多くのマシンがあり、共通のグローバルハッシュテーブルを維持しています。

ここで合意を得るべき内容は何でしょうか?ハッシュテーブルにどのキーと値のペアが含まれているかです。誰かが自分のコンピュータにキーと値のペアを挿入した場合、'xiao' というペアは 12345 に対応し、つまり 'xiao'→12345 です。別の人が別のマシンで読み取るとき、これを読み取れる必要があります。これがグローバルハッシュテーブルです。

不可能結論(impossibility result)#

分散システムに関する多くの ** 不可能結論(impossibility result)があり、その中で最も有名なのがFLP 不可能性結果(FLP impossibility result)** です。この三つの文字は三人の専門家の名前の頭文字を取ったもので、非同期(asynchronous)システムでは、(ネットワーク伝送の遅延に上限がない)たとえ一人のメンバーが問題を抱えていても(faulty)、合意を得ることは不可能です。

CAP 定理(CAP Theorem)#

もう一つの有名な結論は **CAP 定理(CAP Theorem)** です。これは分散システムにおいて、Consistency(一貫性)Availability(可用性)、**Partition tolerance(分割耐性)** の三つを同時に得ることはできないというものです。

ブロックチェーンの不可能三角#

ブロックチェーンの ** 不可能三角(blockchain trilemma)** は、イーサリアムの創設者である Vitalik によって提唱されました。

これはブロックチェーン技術が去中心化性、安全性、高効率性を同時に実現できないことを示しています。

  • 去中心化(Decentralization)
  • スケーラビリティ(Scalability)
  • 安全性(Security)

POW - ビットコインの合意プロトコル(consensus in BitCoin)#

投票に基づく合意方案#

一部のノードは悪意があるかもしれません。システム内の大多数のノードが良いと仮定した場合、合意プロトコルをどのように設計すればよいでしょうか?

一つの方案は投票です。投票に基づく合意方案では、まず誰が投票権を持つかを決定する必要があります。メンバーシップの問題が必要です。このブロックチェーンのメンバーシップは厳密に定義されていると仮定します。たとえば、誰でも参加できるわけではなくコンソーシアムチェーンの Hyperledger Fabric のように、特定の条件を満たす大企業のみが参加できる場合です。この場合、投票に基づく方案は実行可能です。大多数のメンバーが良いと仮定すれば、投票は実行可能です

公有チェーンでは、単純な直接投票は機能しません。

ビットコインシステムはこのようなものではありません。ビットコインシステムでは、アカウントを作成するのは非常に簡単です。あなたはローカルで公開鍵と秘密鍵を生成し、アカウントは誰の承認も必要ありません。他の人は外部で取引を行うまで、そのアカウントが存在することを知りません。もし悪意のあるノードがあれば、スーパーコンピュータを一台用意し、他の何もせずに様々なアカウントを生成し続ければ、生成したアカウントが総数の半分を超えれば、彼は制御権を持ち、投票結果を操作できます。これを ** シビル攻撃(sybil attack)** と呼びます。

ビットコインシステムでは、この問題を解決するために非常に巧妙なメカニズムを使用しています。それも投票ですが、アカウントの数で投票するのではなく、計算力で投票します

記帳権#

各ノードはローカルで候補ブロックを組み立て、合法と考える取引をそのブロックに入れ、さまざまなランダム数 nonce(number of once)値を試し始めます。もしあるノードが要求を満たす nonce(4 バイト)を見つけた場合、H (block header)≤target の条件を満たす場合、私たちはそれを記帳権を得たと見なします。

H(blockheader)targetH( block header )≤target

記帳権とは、ビットコインという去中心化された帳簿に次のブロックを書き込む権利のことです。nonce を見つけて記帳権を得たノードだけが次のブロックを発表する権利を持ちます。

ブロックの合法性を検証する#

他のノードがこのブロックを受け取った後、そのブロックの合法性を検証する必要があります。

例えば、まずこのブロックヘッダーの内容が正しいかどうかを検証します。ブロックヘッダーには nBits というフィールドがあります。実際には、これは目標値のエンコーディングであり、nBits フィールドがビットコインプロトコルで規定された難易度要件に合致しているかどうかを確認します。そして、この nonce が H (block header)≤target の不等式を満たしているかどうかを確認します。

言い換えれば、あなたがブロックを発表する際、本当にブロックを発表する権利があるのか?本当に記帳権を得たのか?すべての要件が満たされていると仮定し、次にブロックボディ内の取引リストを確認し、各取引が合法であるかどうかを検証します。最初に、合法的な署名が必要です。次に、使用された通貨が以前に使われていないことを確認します。もし一つでも要件を満たさない場合、そのブロックは受け入れられません。

分岐攻撃(forking attack)#

すべての条件が満たされていても、そのブロックが受け入れられない場合があります。

どのような状況で条件がすべて満たされていても受け入れられないのでしょうか?ブロック内の取引が合法であっても、それが ** 最長合法チェーン(longest valid chain)上にない場合です。これを分岐攻撃(forking attack)** と呼びます。

分岐攻撃は、ブロックチェーンの中間位置にブロックを挿入して、既に行われた取引を巻き戻すことによって行われます

ブロックチェーンは通常の状況でも分岐が発生する可能性があります。もし二つのノードが同時に記帳権を得た場合、各ノードはローカルで自分が適切だと思うブロックを組み立て、さまざまな nonce を試します。もし二つのノードがほぼ同時に要求を満たす nonce を見つけた場合、両方のブロックを発表することができ、同じ長さの分岐が発生します。どちらのブロックも最長合法チェーンです。

では、どちらを受け入れるべきでしょうか?ビットコインプロトコルでは、デフォルトでは各ノードは最初に受け取ったブロックを受け入れることになっています。したがって、異なるノードはネットワーク上の位置に応じて、あるノードが新しく生成されたブロックの一つを最初に聞いた場合、そのブロックを受け入れます。別のノードが別のブロックを最初に聞いた場合、そのブロックを受け入れます。

どのブロックが受け入れられるかを判断するにはどうすればよいでしょうか? ビットコインプロトコルでは ** 暗黙の委任(implicit consign)** が使用されます。このブロックに沿ってさらに拡張を続けると、その発表されたブロックが認められたことになります。たとえば、新しく生成されたブロックの後にさらにブロックが拡張されると、新しいブロックが認められたことを示します。

では、同時に新しいブロックが生成された二つのチェーンはその後どのように発展するのでしょうか? 同じ長さの一時的な分岐はしばらく維持され、どちらかの分岐が勝利するまで続きます。つまり、どちらのチェーンが新しいブロックを先に生成したかが最長合法チェーンとなります。もう一方は無効なものと呼ばれます。これらの二つの新しいブロックはそれぞれ引き寄せ合う可能性があり、どちらのブロックチェーンが計算力が強いか、時には運が良いかによって勝利します。

ビットコインシステムにおける合意メカニズムが得るべき合意は何か#

分散ハッシュテーブルの例を挙げると、分散システムには多くのサーバーがあり、これらのサーバー間で得るべき合意は何でしょうか?ハッシュテーブルの内容、どのキーと値のペアが含まれているかです。

ビットコインの去中心化された帳簿の内容は得るべき合意であり、記帳権を得たノードだけがそこに書き込むことができます。

なぜみんなが記帳権を争うのか#

なぜみんなが記帳権を争うのでしょうか?まず、記帳権を持つノードは一定の権限を持ち、どの取引が次のブロックに書き込まれるかを決定できます。

しかし、このプロトコルを設計する際には、これを記帳権を争う主な動機にしてはいけません。なぜなら、合法的な取引はすべてブロックチェーンに書き込まれるべきだからです。これにより、** ブロック報酬(block reward)取引手数料(transaction fee)** が導入されます。

誰が通貨の発行を決定するのか#

** コインベース取引(coinbase transaction)** は、ビットコインシステムで新しいビットコインを発行する唯一の方法です。この取引では通貨の出所を示す必要はありません。以降の取引はビットコインの移転に基づいています。

ビットコインの記帳権を争うプロセスはマイニングと呼ばれます。したがって、記帳権を争うノードはマイナーと呼ばれます。もし彼が記帳権を得た場合、私たちは彼がマイニングを行った、またはブロックを掘ったと言います。

どうやって記帳権を得るのか(POW 作業証明)#

さまざまなランダム数 nonce を試すことでパズルを解くことによって

ビットコインの合意メカニズムは計算力で投票します。ビットコインのハッシュ関数の三つの特性の中で、パズルフレンドリーという特性は、パズルを解くプロセスにショートカットがないことを保証し、nonce を一つずつ試すしかありません。

したがって、あるノードの計算力が別のノードの 10 倍であれば、記帳権を得る確率もそのノードの 10 倍になります。これはビットコインにおける投票の特殊性です。それは一人一票でもなく、一台のコンピュータ一票でもなく、あなたが毎秒何個の nonce を試すことができるかによって決まります。これを時々** ハッシュレート(hash rate)** と呼びます。このハッシュレートが投票の重みを決定します。あなたのノードのハッシュレートが高ければ高いほど、記帳権を得てブロック報酬を得る確率も高くなります。

ビットコインではPOW 作業証明がシビル攻撃を防ぎます。計算力で投票し、アカウントをいくら作成しても、計算力を強化することはできません。

ビットコインがパズルを解くプロセスは、計算力を競うこと以外に実際的な意味はありません。ビットコインがますます掘りにくくなっているのは、ブロック報酬が人為的に減少したためであり、ビットコインの希少性は人為的に作り出されたものです。パズルを解くこと自体には実際的な意味はありませんが、マイニングプロセスはビットコインシステムの安全性を維持するために非常に重要です。** ビットコインはマイニングによって保護されています。** マイニングは計算力で投票する効果的な手段を提供し、誠実な人々の手に大部分の計算力が握られていれば、システムの安全性が保証されます。

マイニング中にマイナーが答えを盗むことはあるか#

ありません。発表されたブロックにはコインベース取引があり、その中にはマイニングを行ったマイナーのアドレスが含まれています。もし A がマイニングを行った場合、その中には A の受取アドレスが含まれます。もし答えを盗もうとするなら、A のアドレスを自分のアドレスに変更する必要がありますが、アドレスが一度変わると、コインベース取引の内容も変わります。

これにより、マークルツリーの根ハッシュ値が変わります。なぜなら、この取引とブロックに含まれる他の取引は一緒にマークルツリーを構成しているからです。どこか一つでも変更があれば、根ハッシュ値も変わります。そして nonce はブロックヘッダーの中にあり、根ハッシュ値もブロックヘッダーの中にあります。ブロックヘッダーの内容が変更されると、元々見つけた nonce は無効になります。したがって、答えを盗むことは不可能です。なぜなら、各マイナーが見つけた nonce は彼自身の受取アドレスにバインドされているからです。

ベルヌーイ試験(Bernoulli trial)#

ベルヌーイ試験:二項結果を持つランダム実験。

** ベルヌーイ試験(Bernoulli trial)** は、二つの可能な結果を持つ単一のランダム試験です。

ベルヌーイ過程

ベルヌーイ過程(Bernoulli process):独立したベルヌーイ試験のシーケンス。

マイニングプロセスで毎回 nonce を試すことは、ベルヌーイ試験として考えることができます。各ランダムなベルヌーイ試験はベルヌーイ過程を構成します。

その特性の一つは:無記憶性です。ベルヌーイ過程の特性は ** 無記憶性(memoryless)** であり、大量の試験を行うと、前の結果は後の結果に影響を与えません

各 nonce を試す成功確率は非常に小さく、大量の試験を行う必要があります。この時、ポアソン過程を用いてベルヌーイ過程を代替することができます。

プログレスフリー - マイニングの公平性の保証#

私たちが本当に関心を持っているのは、システムの出力時間です。確率論では、ブロック時間が指数分布に従うことを導出できます(exponential distribution)。

システム全体の平均出力時間は 10 分であり、これはビットコインプロトコルが設計した定期的なマイニング難易度の調整によって、平均出力時間を約 10 分に維持するためです。各マイナーに具体的に言えば、次のブロックを掘ることができる時間は、マイナーの計算力がシステム全体の計算力の何パーセントを占めるかによって決まります。

指数分布も無記憶性を持ち、マイニングの公平性を保証します

指数分布の無記憶性は、確率分布曲線の特性によるもので、どこから切り取っても、残りの部分の曲線は元のものと同じです。たとえば、すでに 10 分待っても誰も合法的なブロックを見つけていない場合、さらにどれくらい待つ必要があるか?平均してまだ 10 分待つ必要があります。将来どれくらいの時間を掘る必要があるかは、過去にどれくらい掘ったかとは関係ありません。このプロセスは ** プログレスフリー(progress free)** とも呼ばれます。

座標軸を描くことができ、縦軸は確率密度を示し、横軸は出力時間を示します(システム全体の出力時間であり、各マイナーの出力時間ではありません)。各マイナーに具体的に言えば、次のブロックを掘ることができる時間は、マイナーの計算力がシステム全体の計算力の何パーセントを占めるかによって決まります。もしある人の計算力がシステム全体の 1% を占めている場合、システムが 100 個のブロックを出力すると、その人が掘ったブロックは 1 個になります。

もしプログレスフリーがなければ、どのような現象が起こるでしょうか? 計算力の強いマイナーは不釣り合いな優位性を持つことになります。なぜなら、計算力の強いマイナーは過去に多くの作業を行っており、過去に多くの失敗した nonce を試した後、後の nonce が成功する確率が高くなります。したがって、プログレスフリーはマイニングの公平性を保証します。

どれだけのコインを無から生み出せるか#

最初の頃、ビットコインが立ち上がったとき、発表された各ブロックは 50 ビットコインのブロック報酬を生成できました。

ビットコインシステムでは、約 10 分ごとに 1 つのブロックが生成され、ビットコインプロトコルでは、21 万ブロック後にブロック報酬が半減することが規定されています。次の 21 万ブロックが経過すると、再び半減します。

ブロック報酬は約 4 年ごとに半減し、こうして生成されるビットコインの数は ** 幾何級数(geometric series)** を構成します。

21000050(1+12+14+...)210000 * 50 (1+\frac{1}{2}+\frac{1}{4}+...)

この計算に基づくと、最大で 2100 万枚のビットコインが存在します。

2022 年までに、ビットコインマイナーは 1 つのブロックを成功裏に採掘するごとに 6.25 ビットコインを獲得します。

ビットコインの安全性分析#

前提として、大部分の計算力が誠実な人々の手に握られていると仮定します。マイニングは確率的な保証を提供するだけであり、次のブロックが誠実なマイナーによって発表される確率が高いと言えるだけであり、記帳権が悪意のある人の手に渡らない保証はありません。

もし悪意のあるノードが記帳権を得た場合、彼が行う可能性のあることは:

1. 不正な取引を偽造する#

たとえば、他人のアカウントから自分のアカウントにお金を移すことですが、他人の秘密鍵を知らないため、これは不正です。したがって、他の誠実なノードはそのブロックを認めず、不正な取引を含むため、前のブロックに続けて拡張されます。最長合法チェーンに従って、そのブロックはブロック報酬を得られず、逆に大量の電力と人力を浪費し、最終的にはブロック報酬を得られません。

2. 二重支払い#

支出したお金を再度支出することです。たとえば、M が A に送金し、M が別の取引を発表してそのお金を自分に戻す(または他の人に戻す)。この場合、二つの状況があります。

  1. 新しいブロックがブロックチェーンに書き込まれた - 分岐攻撃で取引を巻き戻す

悪意のあるノードはブロックチェーンを分岐させ、新しいチェーンを以前のブロックから分岐させる必要があります。この場合、攻撃の難易度は非常に高いです。悪意のあるノードが記帳権を一度得るだけでは不十分であり、誠実なノードは最長合法チェーンのみを認めます。詳細は自己中心的マイニング(selfish mining)を参照してください。

この攻撃を防ぐためには、いくつかのブロック確認(confirmation)を待つ必要があります。デフォルトでは 6 つの確認が必要です。この時点で、前の取引は改ざんされていないと見なされ、待機時間は約1 時間程度です。

  1. 取引が書き込まれていないブロックチェーン内で短時間に複数の取引を発起する

この状況は ** ゼロ確認(zero confirmation)** とも呼ばれ、実際のアプリケーションで非常に一般的です。

各取引にはタイムスタンプが含まれています。ビットコインプロトコルでは、デフォルトで各ノードは最初に受け取った取引を受け入れます。もし正しい取引が最初に受け入れられ、後に発起された重複取引は受け入れられません。そうでなければ、受取人はこの取引を直接拒否できます。

実際には、一定のリスクが依然として存在します。悪意のある攻撃者のノードが非常に小さな確率で記帳権を得る可能性があるため、絶対的な安全を確保するには 6 つの確認(1 時間)を待つ必要があります。

3. 合法的な取引を書き込まない#

問題はありません。合法的な取引は次のブロックに書き込まれることができます。常に誠実なノードが合法的な取引を書き込むことができます。

通常、合法的な取引がブロックに書き込まれないこともあります。なぜなら、ある期間に取引の数が多すぎる可能性があるからです。ビットコインプロトコルでは、各ブロックのサイズに制限があり、ブロックサイズは 1M バイトを超えることはできません。したがって、取引が多すぎる場合、いくつかの取引は次のブロックの発表を待つ必要があります。

4. 自己中心的マイニング(selfish mining)(51% 計算力攻撃に類似)#

通常、ブロックを掘った場合、すぐに発表して、他の人が掘った後に自分のブロックが無効にならないようにします。しかし、自己中心的マイニングでは、悪意のあるノードがブロックを掘った後、発表せずに新しいチェーンを隠し、最長合法チェーンを超えてから発表します。

これは分岐攻撃の一つの手段ですが、悪意のあるノードは通常 51% 以上の計算力を必要とし、実現が難しいです。

** もし単に通常のブロック報酬を多く得るために、最初に掘ったブロックを発表しない場合、他の人は前のブロックを掘り続け、自分は掘ったブロックを延長し、ブロックの競争を減らします。もし自分が二つ目のブロックを掘った場合、他の人が最初のブロックを掘ったと宣言した後、自分は手元の二つを一緒に発表し、最長合法チェーンになります。理論的には非常に実行可能です。** しかし、この方法はリスクが高く、他の人が最初のブロックを掘ったときに、自分が二つ目のブロックを掘ることができなければなりません。そうでなければ、他の人が最初のブロックを発表したとき、手元には一つしかなく、同じ長さのチェーンになり、競争するしかありません。これにより、最初のブロックの報酬を無駄に失う可能性があります。

ビットコインがどのように安全性を保証するか#

二つの側面があります。

  1. 暗号学
  2. 合意メカニズム

他の人があなたの秘密鍵を持っていなければ、あなたの署名を偽造することはできず、あなたのアカウントのお金を移すことはできません。前提として、システム内の大部分の計算力を持つマイナーが良いものであり、プロトコルを遵守し、合法的な署名のない取引を受け入れないことです。これがなければ、暗号学的な保証も役に立ちません。

たとえば、あなたが銀行でお金を引き出す場合、規定に従ってお金を引き出すには合法的な証明書を提示する必要があります。銀行のスタッフはその証明書を見てお金を渡します。合法的な証明書は暗号学的な署名に相当し、暗号学の特性は他の人があなたの署名を偽造できないことを保証します。秘密鍵と署名を生成する際には、良いランダムソースが必要であり、生成されるランダム数は十分にランダムである必要があります。しかし、これだけでは不十分であり、銀行のスタッフは十分に自覚し、合法的な証明書を持たない人にお金を渡さない必要があります。この二つが合わさって初めて、他の人があなたのアカウントのお金を移すことができなくなります。

取引ベースの帳簿モデル(transaction-based ledger)#

一つのブロックには送金取引と発行取引が含まれますが、アカウントの残高は含まれません。どのアカウントにいくらあるかを知るには、取引を通じて推測する必要があります。ブロックチェーンは去中心化された帳簿であり、ビットコインは ** 取引ベースのこの帳簿モデル(transaction-based ledger)** を使用しています。システム内では各アカウントにいくらあるかは表示されません。

ビットコインのこの取引ベースの帳簿モデルに対して、** アカウントベースの帳簿モデル(account-based ledger)** も存在します。たとえば、イーサリアムシステムです。このモデルでは、システムは各アカウントにいくらのコインがあるかを表示する必要があります。

取引ベースの帳簿モデルは、プライバシー保護性が高いですが、欠点はビットコインの送金取引は通貨の出所を示す必要があることです。なぜ出所を示す必要があるのでしょうか?たとえば、あなたが他の人に 10 ビットコインを送金したい場合、誰があなたにその 10 ビットコインを持っているかを知る必要があります。ビットコインシステムにはアカウントの概念がないため、あなたがいくらのビットコインを持っているかを記録する場所はありません。したがって、各取引は必ずどの取引のどの出力から来たのかを明確にする必要があります。

イーサリアムシステムではこの問題は存在しません。アカウントベースのモデルでは通貨の出所を示す必要がありません。銀行口座の残高を知りたい場合、銀行のウェブサイトにログインすれば確認できます。

UTXO(未使用取引出力)#

ビットコインシステムの全ノードは、UTXO(unspent transaction output)と呼ばれるデータ構造を維持する必要があります。これは未使用の取引出力です。

ブロックチェーン上には多くの取引があり、一部の取引の出力は既に使われているかもしれませんし、一部はまだ使われていないかもしれません。すべての未使用の出力の集合を UTXO と呼びます

一つの取引は複数の出力を持つ可能性があります。たとえば、A が B に 5 ビットコインを送金し、B がそれを使った場合、A は C に 3 ビットコインを送金し、C はそれを使わなかったとします。この場合、5 ビットコインは UTXO にはカウントされませんが、3 ビットコインはカウントされます。ビットコインでは各取引は少なくとも一つの入力を消費し、少なくとも一つの出力を生成する必要があります。生成された出力が UTXO(未使用の取引出力)です。B が使った 5 ビットコインは UTXO には含まれていませんが、D に送金された場合、D の UTXO に保存されます。誰かがビットコインの送金取引を受け取った後、そのお金を使わなければ、その情報は UTXO に永遠に保存されます。使いたくない場合もあれば、秘密鍵を失った場合もあります。

UTXO 集合の各要素は、出力を生成した取引のハッシュ値と、その取引内での出力のインデックスを示す必要があります。この二つの情報で UTXO 内の出力を特定できます。

UTXO の役割は、ダブルスパンドを迅速に検出し、時間を節約することです。単純な方法は、全体のチェーンを遡って調べることです。

UTXO 集合は各全ノードが自分のメモリ内で維持するものであり、主に迅速な検索とダブルスパンドの判断のために使用されますが、この集合の内容はブロックチェーンには書き込まれていません

取引手数料(transaction fee)#

各取引は複数の入力を持つことができ、複数の出力を持つこともできます。すべての入力金額の合計は出力金額の合計に等しくなければなりません。すなわち、total inputs=total outputs、しかし実際には取引の total inputs は total outputs よりもわずかに大きいです

たとえば、1 ビットコインの入力があり、0.99 ビットコインの出力がある場合、残りの 0.01 ビットコインは取引手数料として、記帳権を持つノードに渡されます

もしマイニングの報酬がブロック報酬だけであれば、ブロックを発表するノードはなぜあなたの取引をブロックにパッケージ化する必要があるのでしょうか?

彼らはあなたの取引の合法性を検証する必要があります。取引が多すぎると、占有する帯域幅が大きくなり、ネットワークの伝播速度も遅くなります。したがって、ブロック報酬だけでは不十分です。

したがって、ビットコインシステムは第二のインセンティブメカニズムを設計しました:取引手数料(transaction fee)。つまり、あなたが私の取引をブロックにパッケージ化する際に、少しのチップを渡すということです。取引手数料は一般的に非常に小さく、簡単な取引には取引手数料がないこともあります。

取引手数料はどのマイナーに渡すべきかをどう判断するのでしょうか?つまり、事前にどのマイナーがマイニングを行うかをどう知るのでしょうか?

事前にどのマイナーがこの取引手数料を得るかを知る必要はありません。どのマイナーがマイニングを行った場合、そのブロックに含まれる取引の差額を集めて、自分の取引手数料として受け取ることができます。

transaction fee=total inputstotal outputstransaction\ fee = total\ inputs - total\ outputs

あるアドレスのビットコインの残高を計算する方法#

全ノードはこのアカウントが UTXO 内で対応する出力を合計して、アカウントにいくらのコインがあるかを確認します。UTXO を維持していない場合、現在のブロックから最初のブロックまで遡って、すべてのブロックを一通り調べ、メモリ内にすべての取引情報を UTXO として保持します。

ブロックチェーンの保存と受け入れ#

ブロックチェーン取引システムはBerkeley DB(ファイルデータベース)をウォレットデータベースとして使用し、LevelDB(キー値データベース)を使用してブロックのインデックスUTXO(未使用の取引出力)を保存します。ノードが起動すると、全ブロックチェーンのインデックスを LevelDB からメモリにロードします。新しいブロックを受け取ると、ノードは新しいブロック内のすべての取引を検証し、取引形式、取引サイズ、取引署名、UTXO の一致、取引署名、スクリプトの準拠などを確認します。

もし検証が成功すれば、前のブロックヘッダーとチェーンヘッダーブロックのハッシュ値が一致するかどうかを確認します一致すれば、UTXO データベースとロールバック取引データベースを更新します;一致しなければ(つまり分岐)、そのブロックを孤児ブロックプールに置きます。ノードがネットワーク内に別のより長いブロックチェーンが存在することを発見した場合、現在のブロックを切断し、ブロックチェーンを再構築する必要があります。

もし検証が成功しなければ、そのブロックは捨てられ、新しいブロックの到来を待ち続けます(マイナーは新しいブロックの数学的問題を計算し続けます)。

ビットコインの具体的な実装#

参考:Block Chain — Bitcoin

ブロックの基本構造#

ブロックの基本構造は4 つの部分から構成されています

  1. ブロック区切り(4 バイト)
  2. ブロックサイズ(4 バイト)
  3. ブロックヘッダー(80 バイト)
  4. ブロックボディ(不確定)

ビットコインプロトコルではブロックのサイズに 1M バイトの制限があります。ビットコインシステムが採用する伝播方式は非常に帯域幅を消費し、帯域幅がボトルネックです。1M のブロックサイズ制限に基づくと、新しく発表されたブロックがネットワークの大部分に伝達されるまでに数十秒かかる可能性があり、これはかなり長い時間です。このため、この制限値は小さくありません。

ブロックヘッダー#

ブロックヘッダーは6 つの部分から構成されています

  1. ブロックバージョン(4 バイト)
  2. 前のブロックヘッダーのハッシュ値(32 バイト)
  3. マークルツリーの根ハッシュ値(32 バイト)
  4. タイムスタンプ(4 バイト)
  5. 目標値(4 バイト)
  6. ランダム数(4 バイト)

ブロックボディ#

ここにはブロックの取引記録各取引記録の詳細が記録されています。

ブロックボディ内のすべての取引記録を二分木の形式で反復的に二つずつ結合し、ハッシュ操作を行うことで、マークルツリーの根ハッシュ値を得ることができます。

特定のブロックの状況#

Blockchain.com Explorer | BCH | ETH | BCH

image-20230226170039708

左側

最初の行は:このブロックには 686 の取引が含まれています。
二行目:総出力 XXX ビットコイン
四行目:総取引手数料(686 の取引の取引手数料の合計)
最下行:ブロック報酬(マイナーの主要な動機)
五行目:ブロックのシリアル番号
六行目:ブロックのタイムスタンプ
九行目:マイニングの難易度(2016 ブロックごとにマイニングの難易度を調整し、出力時間を約 10 分に維持します
倒数第二行:マイニング中に試行されたランダム数

右側

最初の行:このブロックヘッダーのハッシュ値
二行目:前のブロックヘッダーのハッシュ値
(注意:ハッシュ値の計算はブロックヘッダーのみを考慮します)
二つのハッシュ値の共通点:前に一連の 0 があります。これは設定された目標値を 16 進数で表したもので、前に長い一連の 0 があります。したがって、難易度要件を満たすブロックは、ブロックヘッダーのハッシュ値が長い一連の 0 を持つ必要があります。
四行目:マークルルートは、このブロックに含まれる取引から構成されるマークルツリーの根ハッシュ値です。

ビットコインブロック構造体#

image-20230226170233323

フィールドの説明

image-20230226170939750

image-20230226171347701

nonce が足りなくなったらどうする?

nonce は 32 ビットの符号なし整数です。nonce には 2 の 32 乗個の可能な値があります。ビットコインの現在のマイニング状況を考えると、2 の 32 乗個の値をすべて検証しても適切なものが見つからない可能性が高いです。では、ブロックヘッダーのデータ構造内にはどのフィールドを調整できるのでしょうか?

ブロックヘッダー内の各フィールドの説明
最初の行:ビットコインプロトコルのバージョン番号(変更できません)
二行目:前のブロックのブロックヘッダーのハッシュ値(変更できません)
三行目:マークルツリーの根ハッシュ値(変更可能
四行目:ブロック生成の時間(調整可能)ビットコインシステムは特に正確な時間を要求せず、一定の範囲内で調整できます。
五行目:目標値(エンコードされたバージョン)(プロトコルの要求に従って定期的に調整する必要があります)
六行目:ランダム数

マイニング時にランダム数だけを変更するのが不十分であれば、根ハッシュ値も変更できます
コインベース取引には入力がなく、コインベース取引には任意の内容を書き込むことができます。デジタルコミットメント内の commit のハッシュ値をそこに書き込むこともできます。第一節で説明した株式市場の予測内容をそこに書き込むこともできます。コインベースの内容は誰もチェックしないので、何を書いても問題ありません。

このフィールドは私たちにどのような利点をもたらすのでしょうか?

最後のブロックヘッダー内の根ハッシュ値は、左下の取引がコインベースであり、そのフィールドを変更すると、上のハッシュ値が変わります。そして、マークルツリーの構造に沿って上に伝わります。最終的にブロックヘッダー内の根ハッシュ値も変わります(マークルルートはブロックヘッダーの一部です)。ブロックヘッダー内の 4 バイトの nonce が足りなくなった場合、他のバイトを使用することができます。たとえば、コインベースフィールドの最初の 8 バイトを extra nonce として使用することができ、これにより検索空間が 2 の 96 乗に増加します。

したがって、実際のマイニング時には二層のループしかありません。外側のループでコインベースフィールドの extra nonce を調整します。ブロックヘッダー内の根ハッシュ値を算出した後、内側のループでヘッダー内の nonce を調整します。

このように、通常の送金取引の例

image-20230226172236697この取引には二つの入力と二つの出力があります。
左上:ここでの output は実際には入力であり、以前の取引の output を指します。
右上:ここでの output はすべて未使用であり、使用されていません。UTXO に保存されます。
右側の表の最初の行:入力の総額。
以下:出力の総額、入力と出力の差額(取引手数料)

二つの表の下:入力と出力はスクリプト形式で指定されています

ビットコインシステムで取引の合法性を検証するには、input scripts と output script をペアにして実行する必要があります。注意:図中の input scripts と output scripts をペアにするのではなく、これら二つのスクリプトは一つの取引内のスクリプトです。

ここでの入力スクリプトと前の取引の出力スクリプトをペアにします。もし入力出力スクリプトが結合され、正常に実行され、エラーが発生しなければ、その取引は合法です。

ビットコインネットワーク#

ビットコインはアプリケーション層(application layer block chain)で動作し、その下層はネットワーク層(network layer overlay network)です。

ビットコインの P2P ネットワークは非常にシンプルで、すべてのノードは対等です。一部の P2P ネットワークには、いわゆるスーパー ノード(super node)やマスターノード(master node)が存在します。

P2P ネットワークに参加するには、まず少なくとも一つのシードノードを知る必要があり、その後シードノードに連絡を取ります。シードノードは、ネットワーク内の他のノードを知っていることを教えてくれます。ノード間は TCP 通信を介して行われ、ファイアウォールを突破するのに役立ちます。離れるときは、何の操作も必要なく、他のノードに通知する必要もなく、アプリケーションを終了するだけで済みます。他のノードはあなたの情報を聞いていないため、しばらくするとあなたを削除します。

ビットコインネットワークの設計原則
シンプル(simple)、堅牢(robust)、しかし効率的ではない(but not efficient)。

各ノードは隣接ノードの集合を維持し、メッセージの伝播はネットワーク内でフラッディング方式を採用します。ノードがあるメッセージ(取引)を最初に聞いたとき、それをすべての隣接ノードに伝播し、同時にこのメッセージをすでに受け取ったことを記録します。次回このメッセージを受け取ったときは、隣接ノードに再度転送する必要はありません。これにより、メッセージの洪水を避けることができます。

隣接ノードの選択はランダムであり、下層のトポロジー構造は考慮されていません。たとえば、カリフォルニアにいるノードが選ぶ隣接ノードはアルゼンチンにいる可能性があります。この設計の利点は、ロバスト性(robustness)を強化することです。下層のトポロジー構造を考慮していないため、効率が犠牲になっています。近くの人に送金するのとアメリカの人に送金するのでは、速度はほぼ同じです。

ビットコインプロトコルではブロックのサイズに 1M バイトの制限があります。ビットコインシステムが採用する伝播方式は非常に帯域幅を消費し、帯域幅がボトルネックです。1M のブロックサイズ制限に基づくと、新しく発表されたブロックがネットワークの大部分に伝達されるまでに数十秒かかる可能性があり、これはかなり長い時間です。このため、この制限値は小さくありません。

ビットコインネットワークの伝播は ** 最大努力(best effort)** です。取引がビットコインネットワークに発表されると、必ずしもすべてのノードが受け取るわけではなく、異なるノードがこの取引を受け取る順序も必ずしも同じではありません。

マイニングの難易度#

マイニングの難易度を調整することは、目標空間が全出力空間に占める割合を調整することです。ビットコインが使用するハッシュアルゴリズムは SHA-256 であり、生成されるハッシュ値は 256 ビットです。したがって、全出力空間は 2 の 256 乗です。この割合を調整する、つまり目標空間が出力空間に占める割合を調整することは、一般的にはハッシュ値の前にいくつの 0 が必要かということです。たとえば、256 ビットのハッシュ値がある場合、合法的なブロックは、算出されたハッシュの前に少なくとも 70 個の 0 が必要です。もちろん、これは一般的な言い方に過ぎません。

難易度係数 - 目標値 target の計算#

マイニングは nonce を探し続けるプロセスです。条件を満たすハッシュのみがブロックチェーンに受け入れられます。

H(blockheader)targetH( block header )≤target

ブロックヘッダーには難易度係数(Difficulty)が含まれています。この値はハッシュ計算の難易度を決定します。

ブロックチェーンプロトコルでは、難易度係数で定数を除算することで目標値(Target)を得ることができます

target=targetMaxdifficultytarget = \frac{targetMax}{difficulty}

明らかに、目標値が小さければ小さいほど、マイニングの難易度は高くなります

なぜマイニングの難易度を調整するのか#

なぜ平均出力時間を 10 分に設定する必要があるのでしょうか?

システム内の総計算力が強化されると、マイニングの難易度が変わらなければ、出力時間はどんどん短くなります

出力時間が短くなると、ブロックの分岐が常態化します。さらに、二分岐だけでなく、多くの分岐が発生する可能性があります。たとえば、10 個のブロックが同時に掘られ、システムに 10 分岐が発生する可能性があります。分岐が多すぎると、システムが合意に達するのに役立たず、システムの安全性を脅かします

ビットコインプロトコルは、大部分の計算力が誠実なマイナーの手に握られていると仮定しています。システム内の総計算力が強化されると、安全性が向上します。なぜなら、悪意のあるノードが 51% の計算力を掌握することがますます難しくなるからです。もし 51% の計算力を掌握すれば、悪事を働くことができます。たとえば、分岐攻撃を行うことができます。

もし後の分岐が多い場合、前のブロック内の取引は、分岐攻撃を受ける可能性が高くなります。悪意のあるノードは巻き戻しを試みます。

後の分岐が多いと、計算力が分散されるため、悪意のあるノードが成功する確率が高くなります。この場合、悪意のあるノードは 51% の計算力を必要とせず、10% の計算力で十分かもしれません。したがって、出力時間は短くなればなるほど良いわけではありません。

10 分の出力時間は最適なのか#

必ずしもそうではありません。他の値に変更することもできますが、間隔があるということは、一定の範囲の定数が必要であることを示しています。イーサリアムシステムでは出力時間が 15 秒に短縮されており、イーサリアムの出力速度はビットコインの 40 倍です。

出力時間が大幅に短縮されると、イーサリアムは新しいプロトコルを設計する必要があります。これをゴースト(ghost)と呼びます。このプロトコルでは、これらの分岐から生成された孤児ブロック(orphan block)(たとえば、同時に掘られた 10 個のブロック)は捨てられず、報酬を与えられる必要があります。イーサリアムは出力時間を 15 秒に維持するためにマイニングの難易度を調整する必要があります。

難易度係数の動的調整#

マイニングはランダム性を持ち、正確に 10 分で 1 つのブロックを生成することは保証できません。時には 1 分で算出されることもあれば、数時間かかっても結果が得られないこともあります。全体的に見れば、ハードウェアの向上とマイニング機器の増加に伴い、計算速度は確実に向上します

出力率を 10 分に一定に保つために、中本聡は難易度係数の動的調整メカニズムを設計しました。

難易度係数は約 2 週間(2016 ブロック)ごとに調整されます。この 2 週間の間に、ブロックの平均生成速度が 9 分であれば、法定速度よりも 10% 速いことを意味し、次回の難易度係数は 10% 上昇します。平均生成速度が 11 分であれば、法定速度よりも 10% 遅いことを意味し、次回の難易度係数は 10% 低下します。難易度係数が上昇し続け、目標値が小さくなると、マイニングがますます難しくなります。

difficulty=difficultyexpected  timeactual  timedifficulty = difficulty* \frac{expected\ \ time}{actual\ \ time}

actual time は 2016 ブロックを生成するのに実際にかかった時間を指し、expected time は 2016 ブロックを生成するのに必要な時間、すなわち 2016×10 分です

実際には、上昇と下降には 4 倍の制限があります。実際の時間が 8 週間を超えた場合、計算式では 4 倍として計算され、目標値の増加は最大で 4 倍に制限されます。

すべてのマイナーが同時に目標閾値 target を調整する方法#

target の計算方法はビットコインシステムのコードに書かれており、2016 ブロックを掘るたびに自動的に調整されます

もしあるノードが調整しなければ、そのブロックを発表しても、大部分の誠実なノードはそれを認めません

nBits は target のエンコーディングバージョンであり、ブロックヘッダーには target を直接保存するフィールドはありません。なぜなら、target のフィールドは 256 ビットであり、target を直接保存すると 32 バイトが必要になるからです。nBits はヘッダー内でわずか 4 バイトしかないため、圧縮エンコーディングと見なすことができます。悪意のあるマイナーが調整すべき時に調整しない場合、ブロックの合法性をチェックするときに通過しません。チェック内容には nBits、目標閾値が正しく設定されているかどうかが含まれます。

image-20230303230815659

Bitcoin Difficulty Chart

上記は難易度調整曲線であり、非常に明確に段階的に上昇していることがわかります。2 週間ごとに難易度が一段階上昇し、マイニングを行う人が増え、使用する機器が進化していることを示しています。ビットコインに対する熱意が高まっていることを反映しています。

逆の状況が発生した場合、たとえば、ある暗号通貨のマイニング難易度がどんどん下がっている場合、マイニングがますます簡単になっていることを示しています。しかし、これは良いことではなく、通貨に対する熱意が徐々に減少していることを示しています。この状態が続くと、その通貨

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。