Pebble Coding

ソフトウェアエンジニアによるIT技術、数学の備忘録

bitcoinのgenesis blockの情報を見てみる

ビットコインのgenesis blockつまり、最初のブロックの情報を見てみます。
まず、0番めつまり、genesis block のブロックハッシュを取得します。

$ bitcoin-cli getblockhash 0  
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f  

指定ブロックの情報を取得する。

$ bitcoin-cli getblock 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f  
{
  "hash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
  "confirmations": 1,
  "strippedsize": 285,
  "size": 285,
  "weight": 1140,
  "height": 0,
  "version": 1,
  "versionHex": "00000001",
  "merkleroot": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
  "tx": [
    "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
  ],
  "time": 1231006505,
  "mediantime": 1231006505,
  "nonce": 2083236893,
  "bits": "1d00ffff",
  "difficulty": 1,
  "chainwork": "0000000000000000000000000000000000000000000000000000000100010001",
  "nTx": 1
}

1231006505 はUNIXタイムスタンプなので以下のサイトで 2009-01-04 03:15:05 であることが分かります。
Unixtime相互変換ツール - konisimple tools

"nTx": 1
はこのブロックに含まれるトランザクションが1つであることを表し、そのトランザクションIDは
"tx": [
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
],
です。

トランザクションIDを指定して、生のトランザクションを取得してみます。

$ bitcoin-cli getrawtransaction 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
error code: -5
error message:
The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved

なんかエラーが出ました。
genesis blockに含まれるトランザクションは通常のトランザクションではないので、これは意図した動作だそうです。
仕方ないので、次のブロックに含まれるトランザクションをみていきます。

$ bitcoin-cli getblockhash 1
00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
$ bitcoin-cli getblock 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
{
  "hash": "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048",
  "confirmations": 129290,
  "strippedsize": 215,
  "size": 215,
  "weight": 860,
  "height": 1,
  "version": 1,
  "versionHex": "00000001",
  "merkleroot": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
  "tx": [
    "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
  ],
  "time": 1231469665,
  "mediantime": 1231469665,
  "nonce": 2573394689,
  "bits": "1d00ffff",
  "difficulty": 1,
  "chainwork": "0000000000000000000000000000000000000000000000000000000200020002",
  "nTx": 1,
  "previousblockhash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
  "nextblockhash": "000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da3fdcc99ddbd"

2つめのブロックもトランザクションが一つですが、ちゃんとpreviousblockhashとnextblockhashが付いていますね。
トランザクションが一つしかないので、これをみていきます。

bitcoin-cli getrawtransaction 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098
error code: -5
error message:
No such mempool transaction. Use -txindex or provide a block hash to enable blockchain transaction queries. Use gettransaction for wallet transactions.

今度は別のエラーです。
このエラーを解消するにはトランザクションをインデックスしたデータベースを構築する必要がありそうです。
そのため、bitcoin.confに以下を追加してbitcoindを再起動します。
txindex=1
ちなみに、再起動後、ブロックのダウンロード中であっても先頭近くのトランザクションなので、取得に成功します。

$ bitcoin-cli getrawtransaction 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098
01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000

さて、人間が読める形にしていきます。

$ bitcoin-cli decoderawtransaction 01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000
{
  "txid": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
  "hash": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
  "version": 1,
  "size": 134,
  "vsize": 134,
  "weight": 536,
  "locktime": 0,
  "vin": [
    {
      "coinbase": "04ffff001d0104",
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 50.00000000,
      "n": 0,
      "scriptPubKey": {
        "asm": "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee OP_CHECKSIG",
        "hex": "410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac",
        "type": "pubkey"
      }
    }
  ]
}

vinがインプット、voutがアウトプットです。
vinの所にあるcoinbaseというのはマイナーがブロックを生成した時にマイナーに支払われたビットコインであることを意味します。
"coinbase"の部分の値はマイナーがnonceの拡張領域として任意のデータをセットするようです。
voutの"value": 50.0となっているので、このトランザクションはこのブロックを生成したマイナーのビットコインアドレスに50.0BTCが送金されたことを意味します。
マイナーはおそらくSatoshi Nakamotoでしょう。
この50.0BTCが利用できるのはvoutに設定された問題を解くことができる人物だけなので、50.0BTCの所有者はSatoshi Nakamotoということになります。

"0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee"
の部分をみていきます。
65バイトあります。これは1バイト+32バイト(256ビット)+32バイト(256ビット)に分けます。
"04"
"96b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52"
"da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee"
これは非圧縮形式の公開鍵です。
$ python3
>>> x = int.from_bytes(bytes.fromhex('96b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52'), byteorder='big')
>>> y = int.from_bytes(bytes.fromhex('da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee'), byteorder='big')
>>> x
68167119367492385946477614127391411699187587739043560034303210379772692937810
>>> y
98811869135478233071017892877157889966923567543651789733849964475999540762862
>>> p = 2 ** 256 - 2 ** 32 - 977
>>> (x ** 3 + 7 - y ** 2) % p
0
であり、確かに楕円曲線上の点であることが確かめられます。
ベースポイントを秘密鍵であるスカラー倍した点がこの点になりますが、何倍したらこの点になるかは秘密鍵の所有者にしか分かりません。
楕円曲線離散対数問題に守られています。
現状、楕円曲線離散対数問題が破られているレコードは128ビット程度なので、256ビットあれば余裕なのです。

"scriptPubKey"とありますが、ビットコインの初期に用いられたスクリプトタイプでP2PK(Pay-to-pubkey)と呼ばれています。
上で見た通り、離散対数問題だけに守られているので、現在はほぼ使われていないと言っていいでしょう。

UTXOを確認してみる

P2PKの場合はビットコインアドレスに相当するのが"scriptPubKey"の"4104...eeac"の部分になります。
このP2PKの所有者が現在誰の者かを示すのがUTXOです。
ビットコインは常に取引され続けているので、所有者が誰かを表すのがUTXOですが、特定のアドレスの現在の所有者を知るには、
過去の全てのトランザクションを検索する必要があります。
これらは元のデータはブロックチェーン上にありますが、検索しやすい形でフルノードのデータベース上に構築されているらしいです。
(確認はしていません。)
自分のウォレットのアドレスのUTXOを調べるには bitcoin-cli listunspentというコマンドを使いますが、
任意のアドレスのUTXOを調べたい場合はbitcoin-cli scantxoutsetというコマンドを使います。
2番めのブロックでマイニングされたsatoshi nakamotoの50BTCの現在の所有者を調べて見ましょう。

$ bitcoin-cli  scantxoutset start "[  \"pk(0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee)\" ]"
{
  "success": true,
  "txouts": 1907663,
  "height": 191737,
  "bestblock": "000000000000057135622b503adc6463ffb6f70da8fa8832e08369afcbd2f831",
  "unspents": [
    {
      "txid": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
      "vout": 0,
      "scriptPubKey": "410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac",
      "desc": "pk([119b098e]0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee)#886589wh",
      "amount": 50.00000000,
      "height": 1
    }
  ],
  "total_amount": 50.00000000
}

トランザクションID(txid)が変わっていないので所有者は変わっていないようです。
初期のsatoshi nakamotoがマイニングしたコインは一度も使われたことがないと言われています。
今後も使われることはなさそうなので、Burnされたような状態になっているようなものです。


bitcoin-cli scantxoutsetコマンドについてはこちらに解説がありました。

Output Descriptorとscantxoutsetを使ってUTXOセットをスキャンする - Develop with pleasure!