今回のおはなし
みなさんこんにちは。
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 リトルエンディアンで記述 |
トランザクションの構造
トランザクションの構造自体は単純で、ヘッダ+入力データ+出力データの構成となっています。
内容 | 型 |
---|---|
バージョン (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 で問題ありません。
例えばこんな接続の場合。
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
出力が複数ある場合は、この形式を連続して並べます。