MultiversX Tracker is Live!

P2SH raw tx undestanding

Bitcoin Stack Exchange

Bitcoin News / Bitcoin Stack Exchange 190 Views

That transaction has a P2SH input (but no outputs are P2SH)

If we look at the network format of the input section of a transaction message we see

FieldDescriptionSize
Previous Transaction hashdoubled SHA256-hashed of a (previous) to-be-used > transaction32 bytes
Previous Txout-indexnon negative integer indexing an output of the to-> be-used transaction4 bytes
Txin-script lengthnon negative integer VI = VarInt1 - 9 bytes
Txin-script / scriptSigScript<in-script length>-many bytes
sequence_nonormally 0xFFFFFFFF; irrelevant unless transaction's lock_time is > 04 bytes

So the Txin-script length is of type Varint.

Variable length integer

Integer can be encoded depending on the represented value to save space. Variable length integers always precede an array/vector of a type of data that may vary in length. Longer numbers are encoded in little endian.

ValueStorage lengthFormat
< 0xFD1uint8_t
<= 0xFFFF30xFD followed by the length as uint16_t
<= 0xFFFF FFFF50xFE followed by the length as uint32_t
-90xFF followed by the length as uint64_t

(my emphasis)

So for script-lengths longer than 0xFD and less than 0xffff the script-length is represented as a Varint with three bytes, the first byte of which must be 0xfe so that the format can be unambiguously differentiated from other lengths of Varint.

  • If the first byte we read is lower than 253 (0xFD) we know the Varint is one byte long and the value we just read is the length of the script.

  • If the first byte we read is 253 (0xFD) we know the Varint is three bytes long and we need to discard this byte and read the next two bytes as the length of the script.

  • Ditto 254 (0xFE), five bytes, next four.

  • Ditto 255 (0xFF), nine bytes, next eight.

So we can't represent a script length of 254 in a one-byte Varint because 254 (0xFE) is a special marker byte-value for a five-byte Varint. Instead of using a one-byte Varint, we have to go to the next size up of Varint - a three-byte Varint, and use it's special marker byte value to prefix a two-byte (Uint16_t) length value.

The endianness of the Uint16_t is why the first byte of the last two is the lowest part of the Uint16_t value. 254 is 0x00FE but in little-endian byte-order that is 0xFE00.


What this teaches us is that the developers of this network protocol prioritised compactness of message size over clarity and simplicity.

Given the prevalence of other protocols that take the opposite approach to message size (consider SNMP with XML payloads like DOCX etc or HTTP with HTML payloads) it must be debateable whether this was a necessary or good choice. Maybe a simpler, less confusing choice could have been used, optionally wrapped in a compression envelope. But the choice was made and I guess it is one that Bitcoin developers must live with.


Get BONUS $200 for FREE!

You can get bonuses upto $100 FREE BONUS when you:
πŸ’° Install these recommended apps:
πŸ’² SocialGood - 100% Crypto Back on Everyday Shopping
πŸ’² xPortal - The DeFi For The Next Billion
πŸ’² CryptoTab Browser - Lightweight, fast, and ready to mine!
πŸ’° Register on these recommended exchanges:
🟑 Binance🟑 Bitfinex🟑 Bitmart🟑 Bittrex🟑 Bitget
🟑 CoinEx🟑 Crypto.com🟑 Gate.io🟑 Huobi🟑 Kucoin.



Comments