Nén chuỗi hex giao dịch

Sep 06 2020

Tôi nhận ra rằng giao dịch hex có thể rất dài và bạn cần nó để phát tx bằng cách sử dụng API blockstream.info:

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

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

Nếu người dùng muốn gửi hex này bằng tin nhắn văn bản cho phép 160 ký tự trong một tin nhắn, cách tốt nhất để giải quyết vấn đề này là gì? Tôi đã thử nghiên cứu về cách nén nó, gửi đến một số chuyển tiếp đến máy chủ web chạy mã PHP, chuỗi hex được giải nén và gửi đến blockstream.info để phát tx. Mã hóa Base64 sau khi gzcompress()không thể giảm số ký tự xuống dưới 160.

Thí dụ:

Hex:

02000000000101e939fb23e9991ebbc75fd08c736da32ca12d98a4ff1b8e970e97f5661927ee410100000000fdffffff02b0a90a000000000016001421e2f997b3bd36e273eaca365da8515a389444ae40420f0000000000160014829e2dbcf6b7f31bc93633971f71f6f6b9b5f89e0247304402200f8e3e573be749caf1964a85707bf540de2e7b367ae46c23bd4f21932ff82346022062dc3007072cd5a19b45e479525f4829bc48be4fd3c21b5a9ae34bcf9a3a3ccf0121020f88c7db36cbb492e80d3062fc19db55bed82687498f8cfe6d0cf47adf6687aa49f31b00

Được nén và mã hóa Base64:

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

Trả lời

2 RedGrittyBrick Sep 06 2020 at 23:44

Nén một số ngẫu nhiên nhiều hơn hoặc ít hơn là vô ích. Lựa chọn tốt nhất của bạn chỉ đơn giản là sử dụng một mã hóa nhỏ gọn hơn. Base64 tốt hơn Hex nhưng có thể tồn tại các mã hóa khác hoạt động tốt hơn

Wikipedia liệt kê nhiều và xếp hạng chúng theo thứ tự hiệu quả

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

Rõ ràng bạn có thể làm tốt hơn nếu bạn sử dụng 8-bit (ví dụ: các điểm mã có thể in Unicode có mã hóa byte đơn trong UTF-8) nhưng vì SMS sử dụng bộ ký tự 7 bit (theo tôi biết) nên bạn sẽ không làm được gì nhiều tốt hơn

CodingEnthusiast Sep 07 2020 at 13:50

Nếu người dùng muốn gửi hex này bằng tin nhắn văn bản cho phép 160 ký tự trong một tin nhắn, cách tốt nhất để giải quyết vấn đề này là gì?

Việc chuyển 222 byte thành 160 ký tự sẽ rất khó khăn vì vậy sự tập trung của chúng tôi không chỉ tập trung vào mã hóa mà nó phải hướng vào chính byte 222. Vì nó không chính xác là các byte ngẫu nhiên và cấu trúc giao dịch bitcoin không chính xác là cấu trúc hiệu quả nhất nên có nhiều cơ hội để nén các byte này (hoặc chính xác hơn là để loại bỏ một số byte "vô dụng").
Trước tiên, hãy chia nhỏ nó và xem chúng ta có thể loại bỏ những byte nào:

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. Phiên bản
    có thể chuyển thành 1 byte được mã hóa dưới dạng CompactInt ->02
  2. Cờ nhân chứng
    Có thể được bỏ qua -> (nó hoạt động bằng cách sửa đổi # 6)
  3. Số lượng đầu vào
    Không thay đổi ->01
  4. Nhập mã băm giao dịch
    Không thay đổi ->e939fb23e9991ebbc75fd08c736da32ca12d98a4ff1b8e970e97f5661927ee41
  5. Chỉ mục đầu vào
    Một CompactInt khác ->01
  6. Tập lệnh chữ ký
    Theo quy tắc, tất cả các tập lệnh có thể bắt đầu bằng cờ 1 = P2PKH, 2 = P2WPKH, 3 = P2SH, ... 255 = notdefined, và khi chúng không được xác định, tập lệnh chính xác được đặt ở đây với kích thước và mọi thứ khác. Giống như mọi phần khác, người nhận phải xây dựng tập lệnh một cách chính xác (đặt cờ nhân chứng # 2, di chuyển chúng để chứng kiến ​​các mục # 14 & # 15, thêm độ dài cho mỗi lần đẩy đẩy, chữ ký mã hóa DER)
    Nhân chứng trở thành: <1-byte-flag > <32-byte-r> <32-byte-s> <33-byte-pubkey>
    <02><0f8e3e573be749caf1964a85707bf540de2e7b367ae46c23bd4f21932ff82346><62dc3007072cd5a19b45e479525f4829bc48be4fd3c21b5a9ae34bcf9a3a3ccf><01><020f88c7db36cbb492e80d3062fc19db55bed82687498f8cfe6d0cf47adf6687aa>
    Nếu pubkey không được nén, byte đầu tiên được đổi thành 0x82=0b10000010(tập hợp bit quan trọng nhất) để chỉ ra rằng nên xây dựng pubkey không nén.
  7. Chuỗi
    có thể được mã hóa dưới dạng "StackInt" (một số được đẩy vào ngăn xếp có thể là số âm)
    1 = OP_1, 2 = OP_2 -1 = OP_NegativeOne -2 = 0x82, 321321 = 0x4e29e70400
    Vì 0xfdffffff là UInt32.Max-2 - >82
  8. Số lượng đầu ra
    Không thay đổi ->02
  9. Số lượng
    Như một CompactInt->feb0a90a00
  10. Tập lệnh Pubkey
    Tương tự như tập lệnh chữ ký, chúng ta có thể sử dụng cờ cho các tập lệnh chuẩn, ví dụ. 0x03 có thể là tập lệnh P2WPKH ->0321e2f997b3bd36e273eaca365da8515a389444ae
  11. Số lượng
    Như một CompactInt->fe40420f00
  12. Tập lệnh Pubkey
    Giống như trước03829e2dbcf6b7f31bc93633971f71f6f6b9b5f89e
  13. Số lượng mục nhân chứng
    Đã xóa ->
  14. Nhân chứng đã
    bị loại bỏ (nó đã được đặt ở vị trí số 6) ->
  15. Nhân chứng đã
    bị loại bỏ (nó đã được đặt ở vị trí số 6) ->
  16. Thời gian khóa
    Không thay đổi ->49f31b00

Bây giờ 222 byte được nén thành 192 byte (13,5%) , sau đó có thể được mã hóa bằng mã hóa hiệu quả hơn để có được kết quả tốt nhất có thể.
Điều này cũng có thể được nén nhiều hơn nếu bạn đang gửi giao dịch này đến người nhận tiền thực sự bằng cách bỏ qua (các) đầu ra của họ. Ví dụ: khi bạn phải trả 698800satoshi cho bc1qy830n9anh5mwyul2egm9m2z3tgufg39wk4g0eu, người nhận đã biết điều này và bạn không cần phải nói lại với họ. Điều đó có nghĩa là có thể bỏ qua 26 byte trong # 11 và # 12, giảm kích thước xuống 166 byte (25,2%) . Nhưng phải thống nhất rằng đầu ra nhận là đầu ra đầu tiên chẳng hạn.
Điều này có thể được nén nhiều hơn bằng cách đưa ra nhiều thỏa thuận hơn:

  • Phiên bản Tx phải luôn là 2 -> 165 byte
  • SigHashType phải luôn là SigHashAll -> 164 byte (xóa khỏi mỗi đầu vào # 6 tại đây)
  • Mỗi chuỗi đầu vào phải được đặt thành int xác định trước -> 163 byte (bỏ qua # 7)
  • Tx phải luôn có 2 đầu ra -> 162 byte (bỏ qua # 8)
  • Thời gian khóa phải luôn là 0 -> 158 byte (bỏ qua # 16) ( 28,8% )