Comprimi la stringa esadecimale della transazione

Sep 06 2020

Mi sono reso conto che l'esadecimale della transazione può essere molto lungo e ne hai bisogno per trasmettere un tx usando l'API blockstream.info:

https://blockstream.info/testnet/api/tx

https://github.com/Blockstream/esplora/blob/master/API.md

Se l'utente desidera inviare questo esadecimale utilizzando un messaggio di testo che consente 160 caratteri in un messaggio, quale dovrebbe essere il modo migliore per risolvere questo problema? Ho provato a cercare come comprimerlo, inviare a un numero che inoltra al server web che esegue un codice PHP, la stringa esadecimale viene decompressa e inviata a blockstream.info per la trasmissione in tx. La codifica Base64 dopo gzcompress()non è riuscita a ridurre il numero di caratteri a meno di 160.

Esempio:

Esadecimale:

02000000000101e939fb23e9991ebbc75fd08c736da32ca12d98a4ff1b8e970e97f5661927ee410100000000fdffffff02b0a90a000000000016001421e2f997b3bd36e273eaca365da8515a389444ae40420f0000000000160014829e2dbcf6b7f31bc93633971f71f6f6b9b5f89e0247304402200f8e3e573be749caf1964a85707bf540de2e7b367ae46c23bd4f21932ff82346022062dc3007072cd5a19b45e479525f4829bc48be4fd3c21b5a9ae34bcf9a3a3ccf0121020f88c7db36cbb492e80d3062fc19db55bed82687498f8cfe6d0cf47adf6687aa49f31b00

Compresso e codificato Base64:

eNpdkNmJBEAIRFPyarsNxzP/ENZZGBZW9Eew6pVA8C0EbGObIG4zw47Ie6bg5WUtZ0pHKnsuMxiv7cLOHFU0ut2yCl+xqfktoAA3cPiz0R0hbBqzGxzF2nS5PZ31lL+Dx/mZiHgLCMH8v35kTRU5GncYI42V2S7Otu7W4syzBpLLIAK0Mec197kcfcXSB01lzS7cmCNQTb04etdUk5ZLhtCYZh6x6EdDqZIB9oSyjqOFnJZrh858oCLlRcsUJ2EcN2+WxTRn58wBJITN8/altV4ZIUb9oHi1J9EqzomuR/qW8s3LaS3Ikes1ult3sU9mgB8sW3Vy

Risposte

2 RedGrittyBrick Sep 06 2020 at 23:44

Comprimere un numero casuale più o meno è inutile. La tua migliore opzione è semplicemente usare una codifica più compatta. Base64 è migliore di Hex ma esistono altre codifiche che funzionano meglio

Wikipedia ne elenca molti e li classifica in ordine di efficienza

Encoding            Data type                    Efficiency
yEnc                Arbitrary, mostly non-text   ~98%
Ascii85             Arbitrary                     80%
Base85 (RFC 1924)   Arbitrary                     80%
Base64              Arbitrary                     75%
...

Ovviamente puoi fare di meglio se usi 8 bit (ad esempio punti di codice stampabili Unicode che hanno codifiche a byte singolo in UTF-8) ma poiché SMS utilizza un set di caratteri a 7 bit (per quanto ne so) non farai molto meglio

CodingEnthusiast Sep 07 2020 at 13:50

Se l'utente desidera inviare questo esadecimale utilizzando un messaggio di testo che consente 160 caratteri in un messaggio, quale dovrebbe essere il modo migliore per risolvere questo problema?

Trasformare 222 byte in 160 caratteri sarà molto impegnativo, quindi il nostro focus non può essere solo sulla codifica, ma dovrebbe essere diretto al 222 byte stesso. Poiché non è esattamente byte casuali e la struttura delle transazioni bitcoin non è esattamente la struttura più efficiente, ci sono opportunità per comprimere questi byte (o più accuratamente per sbarazzarsi di alcuni byte "inutili").
Analizziamolo prima e vediamo di quali byte possiamo sbarazzarci:

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
  1. La versione
    potrebbe trasformarsi in 1 byte codificato come CompactInt ->02
  2. La bandiera del testimone
    può essere saltata -> (funziona modificando # 6)
  3. Conteggio input
    Nessuna modifica ->01
  4. Hash della transazione di input
    Nessuna modifica ->e939fb23e9991ebbc75fd08c736da32ca12d98a4ff1b8e970e97f5661927ee41
  5. Indice di input
    Un altro CompactInt ->01
  6. Script di firma
    Di norma tutti gli script potrebbero iniziare con un flag 1 = P2PKH, 2 = P2WPKH, 3 = P2SH, ... 255 = non definito, e quando non sono definiti lo script esatto viene posizionato qui con la dimensione e tutto il resto. Come ogni altra parte, il destinatario deve costruire lo script correttamente (impostare il flag del testimone n. 2, spostarli sugli elementi del testimone n. 14 e # 15, aggiungere lunghezze per ogni push push, firma della codifica DER) Il
    testimone diventa: <flag di 1 byte > <32-byte-r> <32-byte-s> <33-byte-pubkey>
    <02><0f8e3e573be749caf1964a85707bf540de2e7b367ae46c23bd4f21932ff82346><62dc3007072cd5a19b45e479525f4829bc48be4fd3c21b5a9ae34bcf9a3a3ccf><01><020f88c7db36cbb492e80d3062fc19db55bed82687498f8cfe6d0cf47adf6687aa>
    Se pubkey non è stato compresso, il primo byte viene modificato in 0x82=0b10000010(set di bit più significativo) per indicare che è necessario costruire pubkey non compresso.
  7. La sequenza
    può essere codificata come "StackInt" (un numero che viene inserito nello stack che può essere negativo)
    1 = OP_1, 2 = OP_2 -1 = OP_NegativeOne -2 = 0x82, 321321 = 0x4e29e70400
    Poiché 0xfdffffff è UInt32.Max-2 - >82
  8. Conteggio output
    Nessuna modifica ->02
  9. Importo
    come CompactInt->feb0a90a00
  10. Script Pubkey
    Simile allo script di firma potremmo usare flag per script standard, ad es. 0x03 potrebbe essere script P2WPKH ->0321e2f997b3bd36e273eaca365da8515a389444ae
  11. Importo
    come CompactInt->fe40420f00
  12. Script Pubkey
    Come prima03829e2dbcf6b7f31bc93633971f71f6f6b9b5f89e
  13. Conteggio elementi testimone
    rimosso ->
  14. Testimone
    rimosso (è già posizionato in # 6) ->
  15. Testimone
    rimosso (è già posizionato in # 6) ->
  16. Locktime
    Nessuna modifica ->49f31b00

Ora i 222 byte vengono compressi in 192 byte (13,5%) che possono quindi essere codificati con una codifica più efficiente per ottenere il miglior risultato possibile.
Questo potrebbe anche essere più compresso se stai inviando questa transazione al destinatario effettivo dei fondi saltando i loro output. Ad esempio, quando avresti dovuto pagare 698800satoshi a bc1qy830n9anh5mwyul2egm9m2z3tgufg39wk4g0eu, il destinatario lo sa già e non devi dirglielo di nuovo. Ciò significa che 26 byte in # 11 e # 12 possono essere saltati riducendo la dimensione a 166 byte (25,2%) . Ma si deve concordare che l'uscita ricevente è la prima, ad esempio.
Questo potrebbe essere ulteriormente compresso elaborando più accordi:

  • La versione Tx dovrebbe sempre essere 2 -> 165 byte
  • SigHashType dovrebbe sempre essere SigHashAll -> 164 byte (rimuovere da ogni input # 6 qui)
  • Ogni sequenza di input deve essere impostata su int predefinito -> 163 byte (salta # 7)
  • Tx dovrebbe sempre avere 2 uscite -> 162 byte (salta # 8)
  • Il tempo di blocco dovrebbe sempre essere 0 -> 158 byte (ignora # 16) ( 28,8% )