Comprimir string hexadecimal de transação
Percebi que a transação hexadecimal pode ser muito longa e você precisa dela para transmitir um tx usando a API blockstream.info:
https://blockstream.info/testnet/api/tx
https://github.com/Blockstream/esplora/blob/master/API.md
Se o usuário deseja enviar este hex através de mensagem de texto que permite 160 caracteres em uma mensagem, qual a melhor forma de solucionar este problema? Tentei pesquisar sobre como compactá-lo, enviar para um número que encaminha para o servidor web executando um código PHP, a string hexadecimal é descompactada e enviada para blockstream.info para transmissão tx. A codificação Base64 posterior gzcompress()não conseguiu reduzir o número de caracteres para menos de 160.
Exemplo:
Hex:
02000000000101e939fb23e9991ebbc75fd08c736da32ca12d98a4ff1b8e970e97f5661927ee410100000000fdffffff02b0a90a000000000016001421e2f997b3bd36e273eaca365da8515a389444ae40420f0000000000160014829e2dbcf6b7f31bc93633971f71f6f6b9b5f89e0247304402200f8e3e573be749caf1964a85707bf540de2e7b367ae46c23bd4f21932ff82346022062dc3007072cd5a19b45e479525f4829bc48be4fd3c21b5a9ae34bcf9a3a3ccf0121020f88c7db36cbb492e80d3062fc19db55bed82687498f8cfe6d0cf47adf6687aa49f31b00
Compactado e codificado em Base64:
eNpdkNmJBEAIRFPyarsNxzP/ENZZGBZW9Eew6pVA8C0EbGObIG4zw47Ie6bg5WUtZ0pHKnsuMxiv7cLOHFU0ut2yCl+xqfktoAA3cPiz0R0hbBqzGxzF2nS5PZ31lL+Dx/mZiHgLCMH8v35kTRU5GncYI42V2S7Otu7W4syzBpLLIAK0Mec197kcfcXSB01lzS7cmCNQTb04etdUk5ZLhtCYZh6x6EdDqZIB9oSyjqOFnJZrh858oCLlRcsUJ2EcN2+WxTRn58wBJITN8/altV4ZIUb9oHi1J9EqzomuR/qW8s3LaS3Ikes1ult3sU9mgB8sW3Vy
Respostas
Comprimir um número mais ou menos aleatório é inútil. Sua melhor opção é simplesmente usar uma codificação mais compacta. Base64 é melhor do que Hex, mas existem muitas outras codificações que funcionam melhor
A Wikipedia lista muitos e os classifica em ordem de eficiência
Encoding Data type Efficiency
yEnc Arbitrary, mostly non-text ~98%
Ascii85 Arbitrary 80%
Base85 (RFC 1924) Arbitrary 80%
Base64 Arbitrary 75%
...
Obviamente, você pode fazer melhor se usar 8 bits (por exemplo, pontos de código para impressão Unicode que têm codificações de byte único em UTF-8), mas como o SMS usa um conjunto de caracteres de 7 bits (até onde eu sei), você não fará muito melhorar
Se o usuário deseja enviar este hex através de mensagem de texto que permite 160 caracteres em uma mensagem, qual a melhor forma de solucionar este problema?
Transformar 222 bytes em 160 caracteres será muito desafiador, então nosso foco não pode ser apenas na codificação, mas deve ser direcionado ao próprio 222 byte. Como não são bytes exatamente aleatórios e a estrutura de transação de bitcoin não é exatamente a estrutura mais eficiente, há oportunidades para compactar esses bytes (ou, mais precisamente, para se livrar de alguns bytes "inúteis").
Vamos primeiro decompô-lo e ver de quais bytes podemos nos livrar:
1) 02000000
2) 0001
3) 01
4) e939fb23e9991ebbc75fd08c736da32ca12d98a4ff1b8e970e97f5661927ee41
5) 01000000
6) 00
7) fdffffff
8) 02
9) b0a90a0000000000
10) 16001421e2f997b3bd36e273eaca365da8515a389444ae
11) 40420f0000000000
12) 160014829e2dbcf6b7f31bc93633971f71f6f6b9b5f89e
13) 02
14) 47304402200f8e3e573be749caf1964a85707bf540de2e7b367ae46c23bd4f21932ff82346022062dc3007072cd5a19b45e479525f4829bc48be4fd3c21b5a9ae34bcf9a3a3ccf01
15) 21020f88c7db36cbb492e80d3062fc19db55bed82687498f8cfe6d0cf47adf6687aa
16) 49f31b00
- A versão
pode se transformar em 1 byte codificado como CompactInt ->02 - Sinalizador de testemunha
pode ser ignorado ->(funciona modificando # 6) - Contagem de entrada
Sem alteração ->01 - Hash da transação de entrada
Sem alteração ->e939fb23e9991ebbc75fd08c736da32ca12d98a4ff1b8e970e97f5661927ee41 - Índice de entrada
Outro CompactInt ->01 - Script de assinatura
Como regra, todos os scripts podem começar com um sinalizador 1 = P2PKH, 2 = P2WPKH, 3 = P2SH, ... 255 = não definido, e quando eles não são definidos, o script exato é colocado aqui com o tamanho e tudo mais. Como todas as outras partes, o receptor deve construir o script corretamente (definir o sinalizador de testemunha # 2, movê-los para os itens de testemunha # 14 e # 15, adicionar comprimentos para cada push push, assinatura de codificação DER) A
testemunha torna-se: <sinalizador de 1 byte > <32-byte-r> <32-byte-s> <33-byte-pubkey>
<02><0f8e3e573be749caf1964a85707bf540de2e7b367ae46c23bd4f21932ff82346><62dc3007072cd5a19b45e479525f4829bc48be4fd3c21b5a9ae34bcf9a3a3ccf><01><020f88c7db36cbb492e80d3062fc19db55bed82687498f8cfe6d0cf47adf6687aa>
Se pubkey foi descompactado, o primeiro byte é alterado para0x82=0b10000010(conjunto de bits mais significativo) para indicar que pubkey descompactado deve ser construído. - A sequência
pode ser codificada como "StackInt" (um número que é colocado na pilha que pode ser negativo)
1 = OP_1, 2 = OP_2 -1 = OP_NegativeOne -2 = 0x82, 321321 = 0x4e29e70400
Visto que 0xfdffffff é UInt32.Max-2 - >82 - Contagem de saída
Sem alteração ->02 - Quantidade
como umCompactInt->feb0a90a00 - Script Pubkey
Semelhante ao script de assinatura, podemos usar sinalizadores para scripts padrão, por exemplo. 0x03 podem ser scripts P2WPKH ->0321e2f997b3bd36e273eaca365da8515a389444ae - Quantidade
como umCompactInt->fe40420f00 - Script Pubkey O
mesmo de antes03829e2dbcf6b7f31bc93633971f71f6f6b9b5f89e - Contagem de itens de testemunhas
removida -> - Testemunha
removida (já está colocada em # 6) -> - Testemunha
removida (já está colocada em # 6) -> - Tempo de bloqueio
sem alteração ->49f31b00
Agora, os 222 bytes são compactados em 192 bytes (13,5%), que podem ser codificados com uma codificação mais eficiente para obter o melhor resultado possível.
Isso também pode ser mais compactado se você enviar esta transação para o destinatário real dos fundos, ignorando sua (s) produção (ões). Por exemplo, quando você deveria pagar 698800satoshi para bc1qy830n9anh5mwyul2egm9m2z3tgufg39wk4g0eu, o receptor já sabe disso e você não precisa dizer a ele novamente. Isso significa que 26 bytes em # 11 e # 12 podem ser ignorados, reduzindo o tamanho para 166 bytes (25,2%) . Mas deve-se concordar que a saída de recebimento é a primeira, por exemplo.
Isso poderia ser compactado ainda mais com mais acordos:
- A versão Tx deve ser sempre 2 -> 165 bytes
- SigHashType deve ser sempre SigHashAll -> 164 bytes (remova de cada entrada # 6 aqui)
- Cada sequência de entrada deve ser definida para int predefinido -> 163 bytes (pular # 7)
- Tx deve sempre ter 2 saídas -> 162 bytes (pular # 8)
- O tempo de bloqueio deve ser sempre 0 -> 158 bytes (pular # 16) ( 28,8% )