Compact size
Compact size в биткойн, или компактен размер, записва брой или дължина с размер от 1 до 9 байта. Стойностите от 253 нагоре ползват префикс FD, FE или FF.
От Dimitar Zurnov · Обновено на 4 ноември 2026
Адаптирано от Learn Me a Bitcoin на Greg Walker.
Compact size е цяло число с променлива дължина. Биткойн го ползва за броеве и дължини, например за броя входове в трансакция или за размера на скрипт. Малките стойности заемат един байт. По-големите започват с префиксен байт, FD, FE или FF, последван от 2, 4 или 8 байта. Хората често го наричат VarInt, но VarInt в базата данни chainstate работи различно.
Колко байта заема?
Първият байт определя размера. Стойност от 0 до 252 се записва с един байт, а този байт е самата стойност. Трите префикса маркират по-големи стойности, а байтовете след префикса държат числото в little-endian ред.
| Първи байт | Диапазон от стойности | Байтове след префикса | Общ размер | Пример |
|---|---|---|---|---|
00 до FC |
От 0 до 252 | Няма, байтът е самата стойност | 1 байт | 64 е 100 |
FD |
От 253 до 65,535 | 2 | 3 байта | FDE803 е 1,000 |
FE |
От 65,536 до 4,294,967,295 | 4 | 5 байта | FEA0860100 е 100,000 |
FF |
От 4,294,967,296 до 18,446,744,073,709,551,615 | 8 | 9 байта | FF00E40B5402000000 е 10,000,000,000 |
В трансакцията това поле пази броевете и променливите дължини. Ще срещате най-често формата с един байт.
Защо 253 заема три байта?
Защото FD, FE и FF са префикси, стойностите 253, 254 и 255 не могат да се запишат с един байт. Най-голямата стойност, която се записва сама по себе си, е 252. Затова 253 се записва FDFD00, а 254 се записва FDFE00. Префиксът казва на четящия, че следващите два байта държат числото.
Реални трансакции показват това. Трансакция 3454605a…e936 има 254 изхода, така че броят им е FDFE00. Трансакция e411dbeb…a455 има изходен скрипт от 4,026 байта, така че дължината на този скрипт е FDBA0F.
Какви са някои примери?
Таблицата показва кодирането на стойности в четирите размера.
| Стойност | Compact size | Байтове |
|---|---|---|
| 100 | 64 |
1 |
| 252 | fc |
1 |
| 253 | fdfd00 |
3 |
| 1,000 | fde803 |
3 |
| 65,535 | fdffff |
3 |
| 65,536 | fe00000100 |
5 |
| 100,000 | fea0860100 |
5 |
| 4,294,967,295 | feffffffff |
5 |
| 4,294,967,296 | ff0000000001000000 |
9 |
| 10,000,000,000 | ff00e40b5402000000 |
9 |
| 18,446,744,073,709,551,615 | ffffffffffffffffff |
9 |
Най-голямата стойност, която може да съхрани всяко compact size поле, е 18,446,744,073,709,551,615, което е 2⁶⁴ − 1. Тя изисква префикса FF, последван от осем байта FF.
Защо изобщо променлив размер?
Повечето броеве са малки, но някои трансакции имат хиляди изхода. Фиксирано поле от 2 байта би ги побрало всичките, но би изхабило място за останалите.
Вземете броевете на изходите на десет трансакции: 2, 2, 1, 2, 27, 3, 3,000, 2, 1 и 2. Фиксирано 2-байтово поле струва 20 байта за тези десет. Compact size струва 12 байта. Девет от стойностите заемат по един байт, а 3,000 заема три байта: FDB80B, с младшия байт първи.
Всеки спестен байт е малък. Но ако го умножите по дневните трансакции в мрежата, спестените байтове се натрупват.
Как се чете реален пример?
Броят входове на една трансакция във веригата е записан като FDC503. Префиксът FD казва, че следват два байта. Тези байтове са C5 03 в little-endian ред, така че числото е 0x03C5, което е 965. Можете да проверите тази трансакция в нашия експлорър, където са изброени входовете ѝ.
Сега пример с един байт. Трансакцията за пицата, с която са били купени две пици за 10,000 BTC, има 131 входа. Броят на входовете му е единственият байт 83, което е 131 в hex.
Къде се срещат compact size полетата?
- Трансакции: броят на входовете и изходите и дължината на всеки scriptSig и scriptPubKey. SegWit трансакциите пазят и броя на witness елементите, както и дължината на всеки от тях.
- Блокове: броят трансакции. Идва веднага след 80-байтовото заглавие и е единственият compact size в блока извън трансакциите.
- Мрежови съобщения: броят елементи в съобщение като
invи дължината на полезния товар в много съобщения.
Тази трансакция в стария формат (legacy), 414719d5…a492, показва полетата по ред. Нейните compact size полета са броят на входовете, размерът на scriptSig, броят на изходите и размерът на scriptPubKey.
01000000 version
01 брой входове: 1
79fe…7dae предишен TXID, естествен ред
00000000 vout: 0
6b размер на scriptSig: 107 байта
483045…2270 scriptSig, съкратен тук
ffffffff sequence
01 брой изходи: 1
72c9000000000000 сума: 51,570 сатоши
19 размер на scriptPubKey: 25 байта
76a914…88ac scriptPubKey, съкратен тук
00000000 locktime
Блокът започва така: първо заглавието, после броят.
[80-байтово заглавие на блока]
01 <- брой трансакции: една трансакция
01000000 ... <- първата трансакция започва тук
В полезния товар на мрежовото съобщение inv се вижда същата идея. Байтът 01 казва, че следва един елемент. Всеки елемент е 4-байтов тип, 01000000 за трансакция, и след него 32-байтов хеш.
Защо FE и FF са редки?
Няколко ограничения обясняват това, а те са различни за всяко поле.
Скриптовете преди tapscript са ограничени до 10,000 байта, така че дължината им се побира във формата FD. Ограничението е MAX_SCRIPT_SIZE в script.h на Bitcoin Core.
Броят входове никога не се нуждае от FE. Всеки вход заема поне 41 байта, или 164 weight units, а блокът е ограничен до 4,000,000 weight units. Така блок би побрал най-много около 24,390 входа с минимален размер. Това е далеч под 65,536.
Броят изходи теоретично може да достигне този размер. Минималният изход е 9 байта, или 36 weight units, така че 65,536 от тях биха се събрали в един блок. Реалните изходи са по-големи, а трансакцията dd9f6bbf…a1ab3 има 13,107 изхода, далеч под 65,535.
Witness данните са мястото, където най-вероятно ще срещнете FE и FF. BIP 342 премахна ограничението от 10,000 байта за tapscript. Witness елемент от 65,536 байта или повече се нуждае от префикса FE за дължината си.
Как Bitcoin Core проверява кодирането?
Четецът в serialize.h на Bitcoin Core е по-строг от описаното по-горе. Той отхвърля стойност, която ползва по-дълъг префикс от необходимия, с грешката „non-canonical ReadCompactSize()“. Така FD 01 00 за числото 1 е грешка, а правилната форма е 01. По подразбиране той отхвърля и всяка дължина над 0x02000000, което е 32 MiB. Парсър, който пропуска тези проверки, може да приеме данни, които Bitcoin Core отказва.
Как се кодира и декодира в код?
Функциите по-долу следват горните правила. Декодерът не отхвърля по-дълъг префикс от необходимия, затова го ползвайте само върху данни, които вече сте проверили.
def encode(n):
if n <= 252:
return bytes([n])
if n <= 0xFFFF:
size, prefix = 2, b"\xfd"
elif n <= 0xFFFFFFFF:
size, prefix = 4, b"\xfe"
else:
size, prefix = 8, b"\xff"
body = n.to_bytes(size, "little")
return prefix + body
def decode(data):
"""Връща (стойност, използвани байтове)."""
first = data[0]
if first < 0xFD:
return first, 1
size = {0xFD: 2, 0xFE: 4, 0xFF: 8}[first]
value = int.from_bytes(data[1:1 + size], "little")
return value, 1 + size
# fdc503
print(encode(965).hex())
# (965, 3)
print(decode(bytes.fromhex("fdc503")))
Същото ли е compact size и VarInt?
Не, макар че имената често се бъркат. BIP 141 в текста си нарича compact size var_int. VarInt в базата данни chainstate на Bitcoin Core работи различно. Той чете байтовете един по един, докато намери байт, чийто най-старши бит е нулев. Compact size чете префикса си първо и знае дължината само от него.
В този раздел: Данни
Целият курс „Биткойн от нулата“
Нещо не изглежда наред? Кажете ни