Bitcoinのトランザクションについて


Mastering Bitcoinを読んでいるので個人的メモ

トランザクションとは

トランザクションはビットコインシステムに参加している者たちの間での価値の移転を表現したもの

トランザクションのライフサイクル

  1. トランザクションを組む
  2. トランザクションに署名する
  3. トランザクションをビットコインネットワーク内にブロードキャスト
  4. 各ノードにおいて検証されながら伝搬していく
  5. Proof of Workによって検証されたらブロックチェーンに組み込まれる
  6. 十分な個数のブロックの生成によってトランザクションが承認される
  7. 新たなトランザクションの生成

トランザクションを組む

トランザクションは小切手に似ている。送金の意思を表明するのがトランザクション。

トランザクションのブロードキャスト

トランザクションはどんな手段でも構わないのでとりあえずビットコインネットワークを構成しているどっかのノード一つに届く必要がある。手段はWifiでもBluetoothでもNFCでもなんでも構わない。

ビットコインネットワーク内でのトランザクションの伝搬

トランザクションがあるノードに届くと、そのノードは届いたトランザクションが有効な者であるかを検証する。有効なものだと認められればそのノードが自分のお隣さんにそのトランザクションをブロードキャストする。この様子をfloodingという。洪水のようにトランザクションが伝搬していく様。不正なトランザクションだと判明したらそこで棄却される。ビットコインネットワークはP2Pネットワークで、緩やかなメッシュ構造になっている。固定したトポロジーを保っているのではなくて、常にネットワークを構成するノードの参加・脱退が可能。ネットワークの形状は時々刻々と変化していく。

トランザクションの構造

トランザクションはinputとoutputによって構成される。トランザクションは資金の移動を表現している。inputからoutputへ資金が移動する。トランザクションインプットに書くことができるのは未使用トランザクションアウトプットUTXOで、これはある特定の所有者にロックされたビットコインの塊みたいなもの。全ての所有者の全てのUTXOはブロックチェーン上に記録されていて、正真正銘誰でもそれを見ることが出来る。ビットコインには口座ごとの残高という概念が存在しない。特定の人物が所有しているビットコインはUTXOという形でビットコインネットワーク内で共有しているブロックチェーン内にバラバラに存在している。ウォレットではブロックチェーンを全てスキャンしてそのウォレットのユーザーに紐づけられているUTXOを全て弾き出しているに過ぎない。ビットコインではユーザーに紐づけられた口座ごとに残高が保有されているという形で資金を記述するのではない。

トランザクションアウトプット

ほとんど全てのトランザクションアウトプットはUTXOである。UTXOは全てのビットコインクライアントによって追跡され、それぞれのメモリ内でUTXOプールという名前のデータベースに保存されている。トランザクションアウトプットは①satoshi単位で記述されたビットコイン金額と②アウトプットを使用する際に解除することが求められる条件を表現したlocking scriptからなる。locking scriptはScript言語によって記述されている。locking scriptに対応するのがunlocking scriptでこれを特定のトランザクションのアウトプットであるUTXOに対して提示することでそのUTXOに記述してあるだけのビットコインを使用することが出来るようになる。

トランザクション手数料

トランザクションはビットコインネットワークを構成するノードによってマイニングという作業を通じてその信頼性が保証される。この時マイニングを行うノードには手数料が支払われる。手数料がないと誰もめんどくさい作業をしたくない。トランザクション手数料はトランザクションごとに発生するが、それは明示的にトランザクション内に表現されるのではなくて、トランザクションインプットとトランザクションアウトプット内の差異によって暗黙的に表現される。トランザクション手数料の大きさはマイナーが処理しなければならないトランザクションのデータ量の大きさによって決まる。トランザクションで扱われるビットコインの総量によって変化するのではない。トランザクション手数料は必須ではないが、手数料が大きいトランザクションほどマイナーによって処理される期待値が高い。マイナーはボランティアじゃない。トランザクション手数料の決定には市場競争の原理などを反映する。プロトコルの改定によって今後変わる可能性がある。

オーファントランザクション

トランザクションは鎖を形成しながら伸びていく。トランザクションの親子関係が逆転してノードの届いてしまうことがある。こんな時はやってきた子トランザクションを捨てないで、オーファントランザクションとしてプールしておく。親トランザクションが届いた時点で、オーファントランザクションプールから対象の子トランザクションを引っ張り出してきて再帰的に処理する。オーファントランザクションプールがあることで正しい順番でトランザクションを処理できるようになる。オーファントランザクションプールに保存しておく子トランザクション数には上限がMAX_ORPHAN_TRANSACTIONとして定められている。これはビットコインネットワークに対するDOS攻撃を防ぐため。オーファントランザクションプールが溢れそうになった時はランダムに孤児が捨てられる。

Script言語

トランザクションの有効性の検証はScript言語によって記述されたscriptを実行することによって行われる。
scriptの形式は

  • Pay-To-Public-Key-Hash
  • Pay-To-Public-Key
  • Multi-Signiture
  • OP_RETURN
  • Pay-To-Script-Hash

など。Script言語は多くのオペレータを持っているが、意図的にチューリング不完全になっている。つまりScript言語ではループや分岐がかけないように制限されている。チューリング不完全であることからScript言語によって記述されたscriptの処理回数が予測できるようになっている。チューリング不完全であることから、無限ループなどが書けないのでDOS攻撃などのネットワークの脆弱性を発生させずに済む。Ethereumとの違い。
Script言語はステートレスな検証を可能にする。これによってscriptを実行するために必要な情報が全てscript内に存在するということになるから、いかなるシステム上でもトランザクションの検証が可能になる。
逆ポーランド記法の言語。頭からスタックマシンに突っ込みながら処理していくことで、最後にTRUEが残れば検証完了。雰囲気は2 7 OP_ADD 3 OP_SUB 1 OP_ADD 7 OP_EQUALな感じ。

Pay-To-Public-Key-Hash

よくあるやつ。AliceがBobの運営しているCafeに支払う時を想定する。このトランザクションのアウトプットに対するlocking scriptは

OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUAL OP_CHECKSIG

で、このUTXOを使用するためのunlocking scriptは

<Cafe Signature> <Cafe Public Key>

Aliceの支払ったビットコインをBobが使おうとした時にはこれらをくっつけて、Bobが今から使おうとしているやつが本当にBobに対する支払いで、Bobが使っていいのかを検証する

<Cafe Signature> <Cafe Public Key> OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUAL OP_CHECKSIG

はCafeの秘密鍵を知っていないと生成できないから、上のスクリプトが実行できてTRUEが返ってきたら検証が成功してBobはAliceからの支払いとして受け取ったビットコインを他のトランザクションのインプットとして使用することができるようになる。

Pay-To-Public-Key

Pay-To-Public-Key-Hashでは公開鍵のハッシュ値と等しいことが検証されたが、Pay-To-Public-Keyでは生の公開鍵に対して検証がなされる。

locking scriptは

<Public Key A> OP_CHECKSIG

unlocking scriptは

<Signature from Private Key A>

結合して

<Signature from Private Key A> <Public Key A> OP_CHECKSIG

Multi-Signiture

M-of-Nスキームとも呼ばれる。上の二つでは一つの公開鍵と秘密鍵に対して検証が行われトランザクションの正当性が確認されていたが、Multi-Signitureでは事前に登録されていたN本の公開鍵に対してそれらに対応するM個の署名があって初めてトランザクションが検証されるというもの。安全性高まる。

locking scriptは

M <Public Key 1> <Public Key 2> <Public Key 3> ... <Public Key N> N OP_CHECKMULTISIG

でunlocking scriptは

OP_0 <Signature 1> <<Signature 2> ... <Signature M>

結合して

OP_0 <Signature 1> <<Signature 2> ... <Signature M> M <Public Key 1> <Public Key 2> <Public Key 3> ... <Public Key N> N OP_CHECKMULTISIG

OP_0OP_CHECKMULTISIGの実装上のバグ(余分に一個ポップしてしまう)から必要となった。特に意味はない。空き箱。

OP_RETURN

データアウトプット。支払い以外の情報にビットコインシステムを使えないだろうかという考えのもと様々なサービスが開発されているがそのために使うオペレーション。ただ、ビットコインの支払いとは無関係なデータをブロックチェーン上に乗せることに対する論争が巻き起こった。反対した人たちはブロックサイズがいたずらに肥大化してしまうことに対して懸念を表明した。ディスクストレージコストが増大してしまい、フルノードを動かしている人の負担が増加して、ビットコインネットワークに参加するインセンティブが損なわれてしまうのではないか、という不安。
OP_RETURNは明示的に使用不可能なアウトプットを作るオペレーション。

Pay-To-Script-Hash

新しいやつ。Multi-Signatureって使いづらいというところからきている。Multi-Signatureは公開鍵を複数登録する必要がある。Multi-Signatureのlocking scriptは

M <Public Key 1> <Public Key 2> <Public Key 3> ... <Public Key N> N OP_CHECKMULTISIG

でunlocking scriptは

OP_0 <Signature 1> <<Signature 2> ... <Signature M>

で、Multi-Signatureのlocking scriptは長くなりがち。こうなると、トランザクション手数料が高くついてしまう。そのトランザクション手数料の負担は送金側が払うことになる。
そこで、Pay-To-Script-Hashの登場。Pay-To-Script-HashではMulti-Signatureでのlocking Scriptのハッシュ値をとって、それに対して支払うという体を取り、Multi-Signatureでの取引によって支払われたビットコインを利用したい側が使いたいときに同じハッシュ値を与えるunlocking scriptを使って資金を解錠する。これによって高くつくトランザクション手数料を支払い側ではなく支払われる側が受け持つことになり、手数料の支払いも時間的にずれることになる。Pay-To-Script-Hashでは、支払い側のlock scriptは

OP_HASH160 <Hash Value Of "M <Public Key 1> <Public Key 2> <Public Key 3> ... <Public Key N> N OP_CHECKMULTISIG"> OP_EQUAL

支払われる側は、この取引によって得られた資金を使用したい時に

<Signature 1> <<Signature 2> ... <Signature M> M <Public Key 1> <Public Key 2> <Public Key 3> ... <Public Key N> N OP_CHECKMULTISIG

というunlocking scriptを提示する。検証する時には、結合して、

<<Signature 1> <<Signature 2> ... <Signature M> M <Public Key 1> <Public Key 2> <Public Key 3> ... <Public Key N> N OP_CHECKMULTISIG> OP_HASH160 <Hash Value Of "M <Public Key 1> <Public Key 2> <Public Key 3> ... <Public Key N> N OP_CHECKMULTISIG"> OP_EQUAL

が実行される。
これは実はPay-To-Script-Hashにおける支払先のハッシュ値があたかもアドレスかのように振舞っている。ということで、BIP0013にてPay-To-Script-Hashアドレスが提案され、実際に組み込まれている。これはscriptのハッシュ値をBase58Checkでエンコードしたもの。これでアドレスと区別することなくウォレット内で扱うことができるようになった。Pay-To-Script-Hashの注意点としては、誤ったハッシュ値を含んでしまうとそのトランザクションに紐づけられたビットコインは永遠に使用できなくなってしまうということ。ハッシュ値の持つ不可逆性から、Pay-To-Script-Hashのハッシュ値はPay-To-Script-Hashについてどんなヒントもくれない。つまり誤ったハッシュ値をPay-To-Script-Hashのlocking scriptに加えてしまってもそれが誤ったハッシュ値であることを検出する機構はないということ。