値の表現
目次
最終更新日:2024/12/11
数値は 2の補数の little endian で表す。
固定長の場合はそのバイト数のデータ型、可変長は Compact Size型が使われている。
Compact Size型はあまり見慣れないと思う。
例えば 0xfc までなら 1バイトでそのまま表現できるが、0xfd は 0xfdfd00(little endian)になる。
データ長を表すのに使われることがほとんどだと思う。
0x00 - 0xfc- 長さ:
0x00-0xfc - 変換: そのまま
uint8_tにする
- 長さ:
0xfdfd00 - 0xfdffff- 長さ:
0xfd-0xffff - 変換: 先頭の
fdは捨て、残り 2byte をuint16_tにする
- 長さ:
0xfe00000100 - 0xfeffffffff- 長さ:
0x010000-0xffffffff - 変換: 先頭の
feは捨て、残り 4byte をuint32_tにする
- 長さ:
0xff0000000001000000 - 0xffffffffffffffffff- 長さ:
0x0100000000-0xffffffffffffffff - 変換: 先頭の
ffは捨て、残り 8byte をuint64_tにする
- 長さ:
uint64_t varint(const uint8_t *p_varint)
{
uint64_t val;
if (p_varint[0] < 0xfd) {
val = p_varint[0];
} else if (p_varint[0] == 0xfd) {
val = ((uint16_t)p_varint[2] << 8) | (uint16_t)p_varint[1];
} else if (p_varint[0] == 0xfe) {
val = ((uint32_t)p_varint[4] << 24) |
((uint32_t)p_varint[3] << 16) |
((uint32_t)p_varint[2] << 8) |
(uint32_t)p_varint[1];
} else {
val = ((uint64_t)p_varint[8] << 56) |
((uint64_t)p_varint[7] << 48) |
((uint64_t)p_varint[6] << 40) |
((uint64_t)p_varint[5] << 32) |
((uint64_t)p_varint[4] << 24) |
((uint64_t)p_varint[3] << 16) |
((uint64_t)p_varint[2] << 8) |
(uint64_t)p_varint[1];
}
return val;
}
VarInt, varint, var_int
Compact Size型という名称だが、BIP には VarInt や varint もあれば var_int として書かれているところもある。
GitHub の BIP を検索したところこういう状況だった。
あまり区別されていないようなので、Bitcoin 関連でこれらの型が出てきたらだいたい Compact Size型だと思ってよいのではなかろうか。
var_intが使われている BIPVarInt/varintが使われている BIP- BIP-10
- BIP-23
- BIP-37
- BIP-98
- BIP-154
- BIP-180
- BIP-337
スクリプトの中に数値が使われる場合は命令と組み合わせて使うため Compact Size型とは別の表現になる(Constants)。
LevelDBにVarIntがあるが、あれとは関係ない。
関連ページ
writer: hiro99ma