CTransactionにあったvinとvoutの中身をみていきましょう。
これがCTxInとCTxOutです。それでは、Serializeの実装について見ていきましょう。しかし、Serializeが見当たらないようです。実は、ビットコインのコードベースには統一された書き方がありません。そのため、場所によってコードの書き方が大きく異なり、全体像を把握していないと正確に読み取るのが難しい状況です。この問題を解決するために、CTxInとCTxOutにSerializeを復活させると、以下のようにコードを書き換えることができます。
このように、入力 (CTxIn) と出力 (CTxOut) の二つのクラスで構成されています。これらは、ビットコインの移動を管理するためのスクリプトを含みます。
CTxInのscriptSig
- scriptSig: 署名スクリプト。このスクリプトには、トランザクションの入力が所有者によって正当に使用されることを証明するための署名が含まれています。scriptSigは、対応するCTxOutのscriptPubKeyと組み合わせて実行され、正当性を検証します。なお、SegWitはscriptSigではなく、別に割り当てられたフィールドを利用します。そこを利用すると、CTxInのGetSerializesizeから、scriptSigとして計上されていたはずのサイズが除外され、トランザクション手数料が安くなります。また、トランザクションID(txid)の計算から署名の情報が除外されるため、txidの変動がなくなります。このtxidの変動は、ECDSAの署名過程に乱数を利用することから起きておりました。つまり、署名としては有効ですが、同じ秘密鍵から得られる署名自体は乱数によりいつも変わるということです。ちなみにこの乱数は非常に重要で、第三者にばれてはいけない値です。
CTxOutのscriptPubKey
CTxOutは、特定のアドレスにコインを送信するためのスクリプトが含まれています。
- scriptPubKey: 公開鍵スクリプト。これは、コインを受け取るアドレスや条件を指定するスクリプトです。このスクリプトは、新しいトランザクションの入力として使用される際にscriptSigと組み合わせて実行されます。
トランザクションの結合
CTxInとCTxOutを組み合わせることで、トランザクションが形成されます。
- 入力の参照: CTxInは、以前のトランザクションの出力(UTXO:未使用トランザクション出力)を参照します。このUTXOは、コインの現在の所有者が利用可能な資産を示します。
- 署名の検証: scriptSig(CTxIn内)とscriptPubKey(CTxOut内)を組み合わせてからEvalScriptで実行し、トランザクションの正当性を検証します。
トランザクションとブロックチェーン、そして同期までをみていきましょう
このようなトランザクションは、これらのCTxInとCTxOutを含むデータ構造としてブロックチェーンに取り込まれ、取り込まれると全ノードに伝播するためのinvがネットワーク全体に拡散します。
このinvを受け取り次第、そのノードはそのinvの送付先にこのトランザクションの情報の送信を要求するようになります。それにより交互に接続され、ブロックチェーンの同期が進んでいくという仕組みになっております。なぜなら、これで同期が完了したノードもまたinvを拡散して他のノードに情報伝播を試みる仕組みにより、そこで情報伝播の連鎖が起きるためです。
重要な部分だけ、軽く説明した感じになりました。つまり、トランザクションの詳細はブロックチェーンにすべて書き込まれ、第三者に公開される性質があります。
また流出事故が起きてしまいました。ところが、それは本当にセキュリティの問題でしょうか?
実は確率の問題も絡んでおり、そのような場合からの流出(ハッキング)を確実に防ぐ効果的な方法があります。なぜその方法で防げるのか。理論的な側面を詳しく説明し、考察(その7)の最後に解決策をお教えします。