Pular para o conteúdo
buybitcoinsmart

Glossário / Referência do desenvolvedor

CompactSize

Outros nomes: Compact size unsigned integer, VarInt.

O que é CompactSize?
CompactSize é o inteiro de tamanho variável que o bitcoin usa para prefixar contagens e comprimentos em dados serializados, custando um byte para valores abaixo de 253 e até nove para o restante.

Os formatos binários do Bitcoin não carregam nomes de campos, então é preciso dizer a um analisador quantas entradas vêm a seguir e qual é o comprimento de cada script. O CompactSize responde com apenas um byte: de 0 a 252 é esse byte sozinho, e valores maiores ocupam um marcador mais dois, quatro ou oito bytes adicionais. Todo pagamento que você envia contém pelo menos quatro deles.

Como funciona

O CompactSize lê seu próprio primeiro byte para decidir quanto de si mesmo resta.

Um primeiro byte abaixo de 0xfd é o próprio valor, então contagens de 0 a 252 ocupam um byte e nada mais. Um primeiro byte 0xfd significa que o valor está nos dois bytes seguintes, 0xfe significa os quatro seguintes e 0xff significa os oito seguintes. Todos esses números seguintes são little endian. A codificação mais longa possível tem nove bytes e pode expressar um valor acima de 18 quintilhões, algo que nenhuma estrutura real chega perto de precisar.

As codificações precisam ser mínimas. Escrever o número 5 como 0xfd 0x05 0x00 é aritmeticamente idêntico a escrever 0x05, e o Bitcoin Core rejeita isso, gerando um erro de codificação não canônica durante a desserialização. Sem essa regra, a mesma transação poderia ser escrita de várias formas, cada uma com um identificador diferente, o que é um problema de maleabilidade, não de organização.

Há um teto prático muito abaixo do aritmético. O Bitcoin Core se recusa a alocar memória para qualquer objeto desserializado que afirme ser maior que 0x02000000 bytes, cerca de 33,5 megabytes, e o protocolo entre pares limita separadamente uma mensagem a 4.000.000 bytes. Um par hostil, portanto, não pode fazer seu nó reservar gigabytes de memória anunciando uma transação com um quintilhão de entradas.

Vale destacar uma armadilha de nomenclatura. A documentação do formato de rede chama isso de var_int, as bibliotecas de carteiras costumam chamá-lo de VarInt, e o próprio código-fonte do Bitcoin Core usa o nome VarInt para uma codificação completamente diferente e sem relação, que aparece apenas em seus arquivos de banco de dados e de desfazer. Ao ler código, verifique qual dos dois você está vendo.

Onde você o encontra

O CompactSize é a estrutura mais encontrada no bitcoin que não tem nenhum nome voltado ao usuário.

Em uma transação bruta, ele aparece logo após os quatro bytes de versão, ou após o marcador e o sinalizador do segwit quando eles estão presentes, carregando a contagem de entradas. Ele aparece de novo antes de cada script para informar seu comprimento, e outra vez antes da contagem de saídas. Em um bloco serializado, ele carrega a contagem de transações. No protocolo entre pares, ele abre a carga útil das mensagens inv, getdata, addr e headers.

A mensagem headers mostra a codificação em sua forma mais estranha. Cada cabeçalho de 80 bytes é seguido por uma contagem de transações CompactSize igual a zero, então uma entrada ocupa 81 bytes em vez de 80, e um lote completo de 2.000 cabeçalhos chega a 162.000 bytes na rede. A contagem é sempre zero porque uma mensagem headers nunca carrega transações. O campo existe para que o mesmo código de análise possa ler um cabeçalho com ou sem um corpo de bloco depois dele.

Se você decodificar uma transação bruta à mão e os campos pararem de fazer sentido no meio, um CompactSize mal lido é quase sempre a causa. Consuma um byte a menos e tudo depois dele fica deslocado.

Perguntas frequentes

Por que o bitcoin usa um inteiro de tamanho variável?

Porque quase toda contagem no bitcoin é pequena. Uma transação geralmente tem uma ou duas entradas, e gastar quatro ou oito bytes para dizer isso em cada campo de cada transação já feita teria adicionado um grande volume de peso permanente para nada.

O CompactSize é o mesmo que o VarInt do Bitcoin Core?

Não, apesar do apelido compartilhado. O CompactSize é o formato de rede e de disco descrito aqui, enquanto a classe chamada VarInt no Bitcoin Core é uma codificação compacta separada, usada apenas dentro de seus próprios arquivos de banco de dados e de desfazer.

Termos relacionados

Mais em Referência do desenvolvedor

Ler esta página em inglês