Bitcoinの仕組みをエンジニア向けに解説してみる(その1)

Bitcoinの解説記事は多数ありますが、どれも抽象的でエンジニアにとっては逆に分かりづらくなっています。エンジニアならコードで語れよ!と思ったので、ここではコードを出しながら解説していきます。

今回は、Bitcoinを理解する上で最も重要なTransactionを解説します。

Transactionと証明書

まず、Transactionを大雑把に説明すると、図のような取引証明書に例えられます。

f:id:caspitra:20140406194647p:plain

取引証明書は以下の構成になっています。

  • (1)この証明書の番号
  • (2)譲渡する取引証明書の番号
  • (3)いくら渡すか
  • (4)誰へ渡すか
  • (5)自分のハンコ


Bitcoinの世界では、この取引証明書は、全世界の人に公開され、一度公開されると取り消すことはできなくなります。ここでは、あるコルクボードに取引証明書を貼り付けると、全世界に公開されるものとします。

例えば、アリスからボブへ1000円を渡す場合を考えてみましょう。最初、全世界に公開されているコルクボードの内容は図のようになっています。

f:id:caspitra:20140406194917p:plain

このコルクボードを見ると、2つの証明書が貼り付けられています。

No.001の証明書は特殊で、上で説明したものとは異なっています。Bitcoinでは、最初の証明書の発行は「採掘」と呼ばれ、かなり特殊なものです。今は、銀行によって発行された特殊な証明書と考えてください。これは、解説その2で説明します。

証明書No.002を見ると、これはキャロルからアリスへ渡された証明書であることを確認できます。キャロル以外の第3者は、キャロルのハンコを入手できないため、この取引証明書を偽造することはできません。この証明書では、名前の上からハンコを押していますが、証明書Noや金額の上からもハンコを押すべきです(今回は見やすさのために名前だけになっています)。

この証明書で入手した1000円をボブへ渡す場合、アリスは、取引証明書に譲渡する証明書の番号(2)、金額(3)、ボブの名前(4)を書き込み、アリスのハンコ(5)を押します。これで、ボブは1000円の権利を得たことになります。

f:id:caspitra:20140406195026p:plain

この操作を続けていくことで、証明書の権利を別の人へ権利を渡すことができます。これがBitcoinにおけるお金の流れになります。

ここで理解してほしいことは、「Bitcoinを持っている=証明書の権利を保有している」ということです。一般的なオンライン口座での1000円の受け渡しであれば、アリスの口座から1000円をマイナスし、ボブの口座に1000円をプラスするというイメージを持っている人が多いと思います。Bitcoinではこのイメージではなく、実際のお金(証明書)をやりとりするイメージに近いと思ってください。とにかく、Bitcoinではこの証明書が大事になります。現在、Bitocoinの証明書は15GB*1ものデータ量があります。

Bitcoinで重要なのは、この取引証明書が全ての人に公開されていて、不正が無いことを保証しなければならないことです。不正の例としては、証明書No.002の二重利用が考えられます。もし、コルクボードから証明書を剥がすことができるのであれば、アリスはNo.003の証明書をボブに渡した後、それを剥がし、別の人にNo.002の権利を渡すことが出来てしまいます。不正を防止する方法については、解説その2に回します。

ここまでの説明で、ある証明書の権利を別の人へ渡すことができました。数学的帰納法で言えば、n=k からk+1の説明をしたことになります。ただし、n=1(採掘)の解説はしていません。また、取引の不正を防止する方法についてもまだ解説していません。普通であれば、それらの解説に移るところですが、これはエンジニア向けの解説ですので、証明書(Transaction)をより具体的に解説していきます。Transactionの構造をしっかりと理解することで、後々の理解も深まっていくはずと考えています。

Transactionに使われる暗号技術

ここまでは、証明書やハンコなどの現実世界の物を使用して説明してきましたが、ここからは、暗号用語を使って説明していきます。これまでの解説と対応する暗号用語は以下のようになります。

f:id:caspitra:20140406195457p:plain

  • 証明書→Transaction
  • (1)(2)証明書No→Transactionハッシュ
  • (4)の名前→譲渡したい人のパブリックキー
  • (5)ハンコ→電子署名

ここでキャロルの電子署名は以下のように作られます。

f:id:caspitra:20140406195628p:plain

電子署名はキャロルのpublic keyで検証することができるため、Transactionの作成者がキャロルであることを保証できます。

先ほどのアリスとボブの取引を、もう一度説明すると以下の図のようになります。

f:id:caspitra:20140406195717p:plain

実は、ここまでの説明が、中本 哲史氏が書いた論文の「2. 取引」の内容に当たります。もし、興味があればそちらを御覧ください。

Transactionの実装

Transactionの内容の詳細に入っていきます。実は、今までの証明書はかなり簡素化したものになっていて、実際のTransactionに合わせると図のようになります。

f:id:caspitra:20140406200001p:plain

1つの証明書にはに複数の証明書を含めることができます。また、複数の人に分け与えることができます。この時、最小単位は1円ではなく、0.00000001円まで分割できます。Bitcoinでは0.00000001 Bitcoinのことを1 satoshi といいます。さらに、渡す人には自分を含めて良いので、「お釣り」が可能です。例えば、1000円の証明書しか持っていない時に、500円を他人に渡し、500円を自分へ渡すことができます。

この構造を押さえることができたら、実際のコードを見てみましょう。

Bitocionのソースコード中では、TransactionはCTransactionというクラスになっています。

https://github.com/bitcoin/bitcoin/blob/master/src/core.h

class CTransaction
{
public:
    static int64_t nMinTxFee;
    static int64_t nMinRelayTxFee;
    static const int CURRENT_VERSION=1;
    int nVersion;
    std::vector<CTxIn> vin;
    std::vector<CTxOut> vout;
    unsigned int nLockTime;
    ...
}

ここで重要なものは、std::vector<CTxIn>とstd::vector<CTxOut>です。これが少し前に説明した、複数の証明書と複数の人に分け与えるコードとなります。

class CTxIn {
    COutPoint prevout;
    CScript scriptSig;
    unsigned int nSequence;
    ...
};

class COutPoint {
    uint256 hash;
    unsigned int n;
    ...
};

class CTxOut {
    int64_t nValue;
    CScript scriptPubKey;
    ...
};

CTxIn.prevoutには、取引に使用する証明書のハッシュ(COutPoint.hash)とその証明書の何番のvoutを使用するか(COutPoint.n)を入れます。CTxIn.scriptSigには電子署名を入れます*2。CTxIn.nSequenceは理解していません。ごめんなさい。

CTxOut.nValueには取引する金額を入れます。CTxOut.scriptPubKeyには取引相手のpublic keyを入れます*3

最初に示したアリスとボブのやりとりを、Cのコードに当てはめると以下のようになります。

f:id:caspitra:20140406204709p:plain

Transactionのまとめ

最後にTransactionについてまとめます。

  • Bitcoinのお金の概念は、一連のTransactionからなる
  • Transactionの内部構造は、複数の入力TransactionとそのTransactionを誰に渡すかという情報によって構成される
  • 電子署名によって、Transactionの権利者がだれかを確認することができる

まだ説明していないものは以下の2点です。今後解説します。

  • 最初の証明書はどこから生まれるのか
  • 一連の証明書が正しいことはどうやって保証するのか

最後になりますが、Bitcoinに対する私の理解はまだまだ甘いところがあります。もし、間違いを見つけましたら、指摘をお願いします。

コルクボード画像は以下からお借りしました。
http://www.pixiv.net/member_illust.php?mode=medium&illust_id=28386285

*1:http://freesoft.tvbok.com/bitcoin/monacoin_wallet_qt.html

*2:CScriptはBitcoin内部で使用できるスクリプトになっていて、単純に電子署名を入れれば良いものではない

*3:実際にはpublic keyをハッシュ化したアドレスと呼ばれるものを入れる?