Към съдържанието
ДаретеEN

Данни

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
Префиксите на compact size: FC или по-малко е един байт, FD три, FE пет и FF девет. Първият байт определя размера До FC 1 байт, от 0 до 252 64 е 100 обичайният случай FD 3 байта: FD, после 2 байта FDE803 е 1,000 от 253 до 65,535 FE 5 байта: FE, после 4 байта FEA0860100 е 100,000 от 65,536 до 4,294,967,295 FF 9 байта: FF, после 8 байта 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. Можете да проверите тази трансакция в нашия експлорър, където са изброени входовете ѝ.

FD C5 03: префиксът FD означава, че следват два байта. C5 03 в little-endian е 0x03C5, което е 965. Четем FDC503 като 965 FD префикс C5 младши байт 03 старши байт като little-endian обърнати, байтовете се четат 03 C5 като число 0x03C5 в десетична система 965 входа
Двата байта след FD държат числото, като младшият е първи.

Сега пример с един байт. Трансакцията за пицата, с която са били купени две пици за 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 чете префикса си първо и знае дължината само от него.

В този раздел: Данни

Целият курс „Биткойн от нулата“

Нещо не изглежда наред? Кажете ни