楕円曲線論はじめの一歩 (1)

はじめに

みなさんこんにちは。

VIPPOOL でエンジニアをやっています、星月です。

今回は、暗号通貨で電子署名に使われている、楕円曲線暗号について語ろう...
と思ったのですが、楕円曲線暗号の実装方法や簡単な説明は、イマドキありふれているので、
ここはもう少し踏み込んで、楕円曲線論について語ろうと思います。

このあたりの話になってくると、難しい言葉や難しそうな数式がたくさん出てくる説明なら
WikipediaGoogle で探せば見当たりますが、数学に造詣がないと読み解くのは困難だと思います。
なので、証明や厳密な定義などはそちらにおまかせする方向で、
概念の生まれた背景や考え方のような、ストーリー性に重点を置いて語っていければと思います。

すべてのはじまり、1+1 は?

初っ端から「バカにしてるのか?」と思われそうなタイトルですが、
いたって大真面目です。もちろん、小学一年生でもわかるような 2 という話でも
ないですし、「田んぼの田」みたいななぞなぞでもありません。

注目したいのは以下の点です。

  1. そもそも 1 ってなに?
  2. + ってどういう意味?

どうでしょう?小学校で天下り式に教わった数式ですが、
実はちゃんと説明できる人は多くないのではないでしょうか?

小学校ではどう教わった?

イマドキの学習指導要領でどうなってるかは知りませんが、
私のころは、りんごやおはじきで習いました。

f:id:y-hoshizuki:20181225190936p:plain

りんご1個とりんご1個、あわせるとりんごが2個。

ここで重要な事実が1つ、みんな当たり前に受け入れてきたことですが、
「実はりんごじゃなくてバナナでも同様なことが言える」のです。

つまり、りんごにこだわる必要は特になくて、
りんごとかバナナとか、梨とかみかんが、1個あることを
数式の中では「1」と表記しているのです。

言い方を変えれば、「1」というのは「何か」を示す「ただの記号」でしかなくて、
実は「#」とか好きな文字であっても良かったんです。
ここが混乱の元となるのですが、本文中で「1個」というときの1と、
数式の中で出てくる「1」は意味が違うのです。

f:id:y-hoshizuki:20181225191013p:plain

本文中で「りんごが1個」と言っているの「1」は「具体例の世界」の話、
「1+1」と数式で書いているときの「1」は「記号の世界」の話。

こんな風に、具体例から一旦記号に置き換えて、「計算」と呼ばれる作業をしてから
元の具体例の世界に戻ってくる。
...ということをやっていたのが、小学一年生で習った算数なのです。

どうでしょう?実は意外に複雑なことをやっていましたね?

どうしてそんな面倒な手順を踏むのか?

「記号の世界」つまり「数式の世界」であれば、これまで発明された
いろいろな公式がそのまま使えて便利だから、に他なりません。

言い方を変えれば、記号の世界で考案された公式の方が、より「汎用的」であるわけです。

また、記号の世界には具体的な概念がほとんど登場しなくなります。
これは具体例の要素を可能な限りそぎ落として、本質だけを捉えて扱うということです。

このように、記号の世界に一旦変換して物事を考えることを「抽象化」と呼び、
抽象化して「本質について」だけを考えることこそ、
「数学」という学問の真髄とも言えると思います。

まとめ

今回は 1+1 の数式から始まり、1 とは何か?抽象化とか何か?
というあたりについて語りました。

今回はここまで。
ご質問、ご意見等ありましたらお気軽にリプライください。

暗号通貨のトランザクションを手作りする (8)

今回のおはなし

みなさんこんにちは。

VIPPOOL でエンジニアをやっています、星月です。

前回までで raw トランザクションの作り方は一通り説明し終わりました。
今回はおまけ的な位置づけで、コインアドレスについて説明します。

コインアドレス

コインアドレスは、公開鍵ハッシュと相互に変換可能な文字列なので、
公開鍵ハッシュの代わりにやり取りするときに便利に使えます。

前回、手作りしたトランザクション
TXID 661b7e85f863232aff7344acd268bb9eaab306fc8b806d3e6101244c6d06c373
ですが、その直前のトランザクションとなる
TXID c37ab04631eef5813077fbbaae44e01bf26f9cab86426316ba81f99e2c9e8282
はどうやって作ったと思いますか?

実は、公開鍵ハッシュからコインアドレスを生成して、そこに送金しただけです。

ではコインアドレスの作成方法を見ていきましょう。

公開鍵ハッシュは db2e054bb576dc63283c0060abd46df14057c2de でしたね。
まずは先頭にモナコインのテストネットを表すプレフィックス、6f をつけます。

そして、sha256 を 2 回計算して、チェックサムを作ります。

$ printf "%b" "\x6f\xdb\x2e\x05\x4b\xb5\x76\xdc\x63\x28\x3c\x00\x60\xab\xd4\x6d\xf1\x40\x57\xc2\xde" | openssl sha -sha256 -binary | openssl sha -sha256
(stdin)= 1320a8f11585dd4764f6c8ffe4bd8824585d737b821b4b928a40be5e483e4f36

この先頭 4 Byte の「1320a8f1」がチェックサムです。

プレフィックス、公開鍵ハッシュ、チェックサムの 3 つをつなげると
6fdb2e054bb576dc63283c0060abd46df14057c2de1320a8f1
となります。

これを、Base58 エンコードすればコインアドレスの完成です。
Bass58 エンコードといっても、要はただの 58 進数なので、多倍長整数が扱える言語なら
簡単なコードで変換できます。

例えば python で書いてみましょう。

# util.py

def b58encode( src ):
	mapping = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

	r = ''
	n = long( src, 16 )
	for i in range( 0, 34 ):
		r = mapping[n % 58] + r
		n = n / 58

	return r

実行してみます。

$ python
>>> import util
>>> util.b58encode( '6fdb2e054bb576dc63283c0060abd46df14057c2de1320a8f1' )
'n1VsQdyHFc15HzZMxfGgEC2zRQKWqu4XSQ'

はい、できました。

あとは、このコインアドレスに送金すれば、
TXID c37ab04631eef5813077fbbaae44e01bf26f9cab86426316ba81f99e2c9e8282
が作られます。

今回の連載はこれで終了となります。
みなさん、お付き合いいただき、ありがとうございました。
ご質問、ご意見等ありましたらお気軽にリプライください。

暗号通貨のトランザクションを手作りする (7)

今回のおはなし

みなさんこんにちは。

VIPPOOL でエンジニアをやっています、星月です。

前回までで、P2PKH で必要な「電子署名」「公開鍵」「公開鍵のハッシュ値」ができました。
今回は raw トランザクションを完成させてブロックチェーンに取り込んでもらいましょう。

scriptSig の組み立て

P2PKH の scriptSig は以下の形式でした。

PUSH 電子署名
PUSH 公開鍵

これにあわせて scriptSig を組み立てます。
1点注意、openssl dgst で作った電子書名は DER 形式というフォーマットになっているため、
そのまま使えますが、OP_CHECKSIG はその後ろに 01 をつけたものを PUSH する必要があります。

47                        ... 前回作った電子署名の長さ + 1 (PUSH 命令)
30 44 02 20 5C 66 D2 C6 F1 AE 9D 91 D4 10 3F 4F
40 B7 26 CC 9C 27 21 42 B1 A1 7F CE B5 23 74 45
FD BD 95 63 02 20 21 F1 2C 9D A7 7E AC 95 35 31
61 6E E6 73 DC 19 69 A0 48 C3 C1 6A EB 60 22 E0
D2 E8 CA D3 E6 4F         ... 前回作った電子署名
01                        ... 後ろにくっつける

21                        ... 公開鍵の長さ (PUSH 命令)
02 B4 EE A1 4B 61 45 A8 97 F8 75 61 3C 80 FE 3B
3F 50 D4 69 A5 B2 88 6B 50 5F 55 F6 A3 08 B9 E8
74                        ... 第5回で作った公開鍵

本番用 raw トランザクションの組み立て

前回仮組みしたのと同じ構成にする必要があります。
scriptSig は今回は正しく電子署名の入ったものを使います。

02 00 00 00      ... バージョン 2
01               ... 入力は 1 つ

入力データ
 82 82 9E 2C 9E F9 81 BA 16 63 42 86 AB 9C 6F F2
 1B E0 44 AE BA FB 77 30 81 F5 EE 31 46 B0 7A C3
                  ... 前 TXID: c37ab04631eef5813077fbbaae44e01bf26f9cab86426316ba81f99e2c9e8282
 00 00 00 00      ... 前 TX の第0出力を使用する
 6A               ... scriptSig の長さ 106 Byte
 47
 30 44 02 20 5C 66 D2 C6 F1 AE 9D 91 D4 10 3F 4F
 40 B7 26 CC 9C 27 21 42 B1 A1 7F CE B5 23 74 45
 FD BD 95 63 02 20 21 F1 2C 9D A7 7E AC 95 35 31
 61 6E E6 73 DC 19 69 A0 48 C3 C1 6A EB 60 22 E0
 D2 E8 CA D3 E6 4F
 01
 21
 02 B4 EE A1 4B 61 45 A8 97 F8 75 61 3C 80 FE 3B
 3F 50 D4 69 A5 B2 88 6B 50 5F 55 F6 A3 08 B9 E8
 74               ... 正しい scriptSig
 00 00 00 00      ... シーケンス番号はとりあえず 0

01               ... 出力は 1 つ

出力データ
 C0 9E E6 05 00 00 00 00 ... 0.99 tMONA
 19               ... scriptPubKey は 25 Byte
 76 A9 14
 DB 2E 05 4B B5 76 DC 63 28 3C 00 60 AB D4 6D F1 40 57 C2 DE
 88 AC            ... scriptPubKey 本体

00 00 00 00      ... ロックタイムはとりあえず 0

これで P2PKH の raw トランザクションが完成しました。


後はこの16進文字列を、

$ monacoin-cli sendrawtransaction "0200000001...00000000"

とコインノードに送りつければ、ブロードキャストされてブロックチェーンに取り込まれます。

こうしてできたのが、
TXID 661b7e85f863232aff7344acd268bb9eaab306fc8b806d3e6101244c6d06c373
です。

今回はここまで。あと 1 回だけ続きます。
ご質問、ご意見等ありましたらお気軽にリプライください。

暗号通貨のトランザクションを手作りする (6)

今回のおはなし

みなさんこんにちは。

VIPPOOL でエンジニアをやっています、星月です。

前回は秘密鍵と公開鍵のペアを作って、公開鍵のハッシュ値を求めました。
今回は電子署名を作ってみましょう。

OP_CHECKSIG の仕様

電子署名を作るには、OP_CHECKSIG の仕様を知る必要があります。

...とはいえ、実際に使われているパターンは1つしかないので、
それだけ覚えてもらえれば十分です。

bitcoin wiki の OP_CHECKSIG
ページに図と共に詳細な説明がありますが、もう少し噛み砕いて説明します。

  1. まず、UTXO の scriptPubKey を取り出します。
  2. 新規トランザクションの scriptPubKey を設計します。
  3. 次に、新規トランザクションの scriptSig を全部空っぽ、長さは 0 にしたデータを作ります。
  4. 電子署名を作る対象の入力データだけ、scriptSig の部分に、取り出した scriptPubKey を挿入します。
  5. この状態のデータの SHA256 ハッシュを2度計算して、電子署名を作成します。

具体的には図のように作ります。

f:id:y-hoshizuki:20181022130426p:plain

電子署名は scriptSig ごとに作る必要があるため、
入力が複数ある場合はこのようになります。

f:id:y-hoshizuki:20181022130435p:plain

さて、それでは実際に作ってみましょう。
今回は monacoin のテストネットで実験してみます。
自分から自分に送る単純なトランザクションです。

UTXO の scriptPubKey

P2PKH を使っているなら以下の形式で固定です。

76   ... OP_DUP
A9   ... OP_HASH160
14   ... 公開鍵のハッシュの長さ (PUSH 命令)
DB 2E 05 4B B5 76 DC 63 28 3C 00 60 AB D4 6D F1 40 57 C2 DE ... 公開鍵のハッシュ
88   ... OP_EQUALVERIFY
AC   ... OP_CHECKSIG

長さは 25Byte です。

新規トランザクションの scriptPubKey

P2PKH で出力するなら先ほどと同じです。

76   ... OP_DUP
A9   ... OP_HASH160
14   ... 公開鍵のハッシュの長さ (PUSH 命令)
DB 2E 05 4B B5 76 DC 63 28 3C 00 60 AB D4 6D F1 40 57 C2 DE ... 公開鍵のハッシュ
88   ... OP_EQUALVERIFY
AC   ... OP_CHECKSIG

長さも同じく 25Byte です。

新規トランザクションの準備

第3回で説明した通りに scriptSig を空っぽの状態で raw トランザクションを作ります。

02 00 00 00      ... バージョン 2
01               ... 入力は 1 つ

入力データ
 82 82 9E 2C 9E F9 81 BA 16 63 42 86 AB 9C 6F F2
 1B E0 44 AE BA FB 77 30 81 F5 EE 31 46 B0 7A C3
                  ... 前 TXID: c37ab04631eef5813077fbbaae44e01bf26f9cab86426316ba81f99e2c9e8282
 00 00 00 00      ... 前 TX の第0出力を使用する
 00               ... scriptSig は 0 Byte
 00 00 00 00      ... シーケンス番号はとりあえず 0

01               ... 出力は 1 つ

出力データ
 C0 9E E6 05 00 00 00 00 ... 0.99 tMONA
 19               ... scriptPubKey は 25 Byte
 76 A9 14
 DB 2E 05 4B B5 76 DC 63 28 3C 00 60 AB D4 6D F1 40 57 C2 DE
 88 AC            ... scriptPubKey 本体

00 00 00 00      ... ロックタイムはとりあえず 0

電子署名対象となる入力だけ、scriptSig を埋める

同じなので区別がつきづらいですが、
トランザクションから抽出した scriptPubKey を、
scriptSig を埋めるべき場所に配置します。

そして末尾に 01 00 00 00 をくっつけます。

02 00 00 00      ... バージョン 2
01               ... 入力は 1 つ

入力データ
 82 82 9E 2C 9E F9 81 BA 16 63 42 86 AB 9C 6F F2
 1B E0 44 AE BA FB 77 30 81 F5 EE 31 46 B0 7A C3
                  ... 前 TXID: c37ab04631eef5813077fbbaae44e01bf26f9cab86426316ba81f99e2c9e8282
 00 00 00 00      ... 前 TX の第0出力を使用する
 19               ... scriptSig ではなく前トランザクションの scriptPubKey の長さは 25 Byte
 76 A9 14
 DB 2E 05 4B B5 76 DC 63 28 3C 00 60 AB D4 6D F1 40 57 C2 DE
 88 AC            ... 前トランザクションの scriptPubKey 本体
 00 00 00 00      ... シーケンス番号はとりあえず 0

01               ... 出力は 1 つ

出力データ
 C0 9E E6 05 00 00 00 00 ... 0.99 tMONA
 19               ... scriptPubKey は 25 Byte
 76 A9 14
 DB 2E 05 4B B5 76 DC 63 28 3C 00 60 AB D4 6D F1 40 57 C2 DE
 88 AC            ... scriptPubKey 本体

00 00 00 00      ... ロックタイムはとりあえず 0

01 00 00 00      ... くっつける

SHA256 ハッシュを2度計算して電子署名を作成する

うまく整形してバイナリ形式で openssl に流し込みます。
openssl dgst で1回 sha256 を計算するので、先に一度 sha256 を計算しておく必要があることに注意してください。

$ printf "%b" "\x02\x00\x00\x00\x01\x82\x82\x9E\x2C\x9E\xF9\x81\xBA\x16\x63\x42\x86\xAB\x9C\x6F\xF2\x1B\xE0\x44\xAE\xBA\xFB\x77\x30\x81\xF5\xEE\x31\x46\xB0\x7A\xC3\x00\x00\x00\x00\x19\x76\xA9\x14\xDB\x2E\x05\x4B\xB5\x76\xDC\x63\x28\x3C\x00\x60\xAB\xD4\x6D\xF1\x40\x57\xC2\xDE\x88\xAC\x00\x00\x00\x00\x01\xC0\x9E\xE6\x05\x00\x00\x00\x00\x19\x76\xA9\x14\xDB\x2E\x05\x4B\xB5\x76\xDC\x63\x28\x3C\x00\x60\xAB\xD4\x6D\xF1\x40\x57\xC2\xDE\x88\xAC\x00\x00\x00\x00\x01\x00\x00\x00" | openssl sha -sha256 -binary | openssl dgst -sha256 -sign wallet.pem -hex
(stdin)= 304402205c66d2c6f1ae9d91d4103f4f40b726cc9c272142b1a17fceb5237445fdbd9563022021f12c9da77eac953531616ee673dc1969a048c3c16aeb6022e0d2e8cad3e64f

これで、電子署名は完成です。

電子署名は乱数を使用するため毎回異なる署名が出力されます。
今は詳しく説明しませんが、正規化ルールの都合があるので、
何度か実行して 3044 から始まるものを選んでください。

今回はここまで。
ご質問、ご意見等ありましたらお気軽にリプライください。

暗号通貨のトランザクションを手作りする (5)

今回のおはなし

みなさんこんにちは。

VIPPOOL でエンジニアをやっています、星月です。

前回は P2PKH の動作原理について解説しました。
それでは実際にテンプレートを埋める方法について説明していきます。

各要素とコインアドレスの関係

まずは各要素の関係について確認しておきましょう。

f:id:y-hoshizuki:20181022130337p:plain

基本的に一方通行ですが、コインアドレスと公開鍵のハッシュだけ、
相互に変換可能なところに注意してください。

秘密鍵と公開鍵のペアを作成する

openssl を使うと簡単に作れます。
secp256k1 という名前の曲線を使いますが、比較的新しいバージョンの openssl でないと
使えないので注意してください。

$ openssl ecparam -genkey -name secp256k1 -out wallet.pem
$ openssl ec -in wallet.pem -conv_form compressed -text
Private-Key: (256 bit)
priv:
    00:8d:6a:af:b3:37:d6:e3:dd:5a:96:c1:54:95:c6:
    cd:4b:65:1e:52:d0:82:e3:e2:a7:89:28:35:bb:94:
    9c:e1:07
pub:
    02:b4:ee:a1:4b:61:45:a8:97:f8:75:61:3c:80:fe:
    3b:3f:50:d4:69:a5:b2:88:6b:50:5f:55:f6:a3:08:
    b9:e8:74

priv が秘密鍵 256bit、pub が compressed 形式の公開鍵です。

公開鍵のハッシュを求める

次は公開鍵のハッシュを求めます。
公開鍵の : を \x に置換して繋げてから、
openssl で sha256, ripemd160 の順でハッシュを計算します。

$ printf "%b" "\x02\xb4\xee\xa1\x4b\x61\x45\xa8\x97\xf8\x75\x61\x3c\x80\xfe\x3b\x3f\x50\xd4\x69\xa5\xb2\x88\x6b\x50\x5f\x55\xf6\xa3\x08\xb9\xe8\x74" | openssl sha -sha256 -binary | openssl sha -ripemd160
(stdin)= db2e054bb576dc63283c0060abd46df14057c2de

これが公開鍵のハッシュです。

今回はここまで。
ご質問、ご意見等ありましたらお気軽にリプライください。

暗号通貨のトランザクションを手作りする (4)

今回のおはなし

みなさんこんにちは。

VIPPOOL でエンジニアをやっています、星月です。

前回までで簡単な raw トランザクションの手作りができるようになりました。
今回からは本格的に、実際に使える raw トランザクションを作る方法について解説していきます。

前回までの解説で抜けているところといえば、Script で使われる P2PKH についてです。
あとは P2PKH のスクリプトを書けるようになれば、raw トランザクションについては完璧です。

P2PKH の仕組み

第2回ではさらっと流しましたが、もう一度、P2PKH は以下の形式のプログラムです。

scriptSig:
 PUSH 電子署名
 PUSH 公開鍵
scriptPubKey:
 OP_DUP
 OP_HASH160
 PUSH 公開鍵のハッシュ値
 OP_EQUALVERIFY
 OP_CHECKSIG

ここで、「電子署名」「公開鍵」「公開鍵のハッシュ値」の埋め方がわかれば、
このテンプレートどおりに書くだけで OK です。

ですが、先にこのプログラムの動作原理を理解しておきましょう。

まず、scriptSig を実行し終わった段階で、スタックは以下の状態になっています。

公開鍵   <- スタックトップ
電子署名

次に OP_DUP はスタックトップをコピーします。

公開鍵   <- スタックトップ
公開鍵
電子署名

OP_HASH160 は、スタックトップの SHA-256 ハッシュを計算してから、RIPEMD-160 ハッシュを計算します。

RIPEMD165(SHA256(公開鍵)) <- スタックトップ
公開鍵
電子署名

さらに公開鍵のハッシュ値を PUSH します。

公開鍵のハッシュ値 <- スタックトップ
RIPEMD165(SHA256(公開鍵))
公開鍵
電子署名

次の OP_EQUALVERIFY は、OP_EQUAL と OP_VERIFY をまとめて実行する命令で、
要するにスタックの先頭2つが一致しなければプログラムの実行を FAIL させる命令です。
つまり、「公開鍵のハッシュ値=RIPEMD165(SHA256(公開鍵))」が、続きを実行する条件です。
実行後はスタックの先頭2つが消えます。

公開鍵 <- スタックトップ
電子署名

最後に OP_CHECKSIG は、スタックに積まれた公開鍵と電子署名を使って、
「正しい持ち主が持つ秘密鍵によって作られたトランザクションである」ことを確認します。

成功したら 1 True, 失敗したら 0 False <- スタックトップ

要するに

  1. 公開鍵のハッシュ値=RIPEMD165(SHA256(公開鍵)) であること
  2. トランザクションデータが正しい秘密鍵によって電子署名を付与されていること

の2点を確認するプログラムとなっているわけです。

今回はここまで。
次回からはテンプレートの埋め方について解説していきます。
ご質問、ご意見等ありましたらお気軽にリプライください。

暗号通貨のトランザクションを手作りする (3)

今回のおはなし

みなさんこんにちは。

VIPPOOL でエンジニアをやっています、星月です。

前回までで、トランザクションの概念と Script について解説しました。

今回は raw トランザクションの構造について説明します。
これで簡単なトランザクションが手作りできるようになります。

raw トランザクションとは、トランザクションの実データのことで、
可変長のバイナリ列で表現されます。
今回はこれを手作りすることを目指します。

var_int 型

トランザクションのデータで、数値を格納するために多用されている形式です。

格納したい値 x を、以下のルールで可変長のバイナリ列にします。

値域 形式
0≦x<0xFD x をそのまま 1 Byte で記述
0xFD≦x≦0xFFFF 0xFD に続けて x を 2 Byte リトルエンディアンで記述
0x10000≦x≦0xFFFFFFFF 0xFE に続けて x を 4 Byte リトルエンディアンで記述
0x100000000≦x 0xFF に続けて x を 8 Byte リトルエンディアンで記述

var_int に限らず、raw トランザクションではすべてリトルエンディアンを使用します。

トランザクションの構造

トランザクションの構造自体は単純で、ヘッダ+入力データ+出力データの構成となっています。

内容
バージョン (1か2を入れておく) int32_t
入力の個数 var_int
入力データの配列 後述
出力の個数 var_int
出力のデータ配列 後述
ロックタイム uint32_t

ロックタイムというのが初出ですが、ここは通常 0 を入れておけば問題ありません。

ざっくりこんなイメージです。

02 00 00 00      ... バージョン 2
03               ... 入力は 3 つ
入力データ1
入力データ2
入力データ3
02               ... 出力は 2 つ
出力データ1
出力データ2
00 00 00 00      ... ロックタイムはとりあえず 0

トランザクションの入力データ

トランザクションの入力データは以下の形式です。

内容
TXID uint256_t
出力インデックス uint32_t
scriptSig の長さ var_int
scriptSig 本体 可変長バイナリ
シーケンス番号 uint32_t

TXID はトランザクション ID のことで、256bit の整数をリトルエンディアンで書きます。

出力インデックスは、入力として接続する相手のトランザクションの出力の、
何番目か、というインデックスです。

シーケンス番号は普段使うことはないので 0 で問題ありません。

例えばこんな接続の場合。

f:id:y-hoshizuki:20181022130135p:plain

scriptSig には以下のプログラムを含めるとします。

02 CD AB         ... OP_PUSH 0xABCD

こうなります。

EC F2 65 AF 3E 30 B4 44 BC 14 1E EB 95 60 DD E8
34 DD 1B E2 CD 5D 2D BE 2F 84 75 01 00 A8 02 3F
                 ... 前 TXID: 3f02a8000175842fbe2d5dcde21bdd34e8dd6095eb1e14bc44b4303eaf65f2ec
02 00 00 00      ... 前 TX の第2出力を接続する
03               ... scriptSig の長さ
02 CD AB         ... scriptSig 本体
00 00 00 00      ... シーケンス番号はとりあえず 0

入力が複数ある場合は、この形式を連続して並べます。

トランザクションの出力データ

トランザクションの出力データは以下の形式です。

内容
出力金額 int64_t
scriptPubKey の長さ var_int
scriptPubKey 本体 可変長バイナリ

出力金額はコインではなく satoshi 単位の整数で書きます。
100,000,000 satoshi = 1.0 BTC です。
MONA の場合は特に呼び名は決まっていないそうですが、
同じ単位で書きます。

scriptPubKey には以下のプログラムを含めるとします。

02 CD AB         ... OP_PUSH 0xABCD
87               ... OP_EQUAL

こうなります。

00 E1 F5 05 00 00 00 00 ... 1BTC (100000000 satoshi)
04               ... scriptPubKey の長さ
02 CD AB 87      ... scriptPubKey

出力が複数ある場合は、この形式を連続して並べます。

まとめ

いかがでしたでしょうか。
raw トランザクション、意外に簡単な構造ではないでしょうか。

既にお気づきの方もいるとは思いますが、
TXID をプライマリキーとして見ると、
トランザクションのリンクは過去に向かう単方向リストの構造になっています。

よくよく考えれば当然の仕様で、
ブロックチェーンは追記はできても変更はできない分散型データベースですので、
トランザクションのリンクも必然的に過去に向かう単方向リストにせざるを得ないんですね。

今回はここまで。
ご質問、ご意見等ありましたらお気軽にリプライください。