1

Could anyone provide me a link to the specification of segwit raw transactions such as provided in https://developer.bitcoin.org/reference/transactions.html#raw-transaction-format ? (This url explains it perfectly, but only for legacy transactions) I could only find documents (such as BIPs) that don't explain bit by bit how to build one.

2

BIP144 details the exact format.

The idea is that every transaction input has a witness stack (consisting of 0 or more byte arrays, each of variable length). For pre-segwit transactions, all witness stacks are empty.

There are two distinct serialization formats for transactions, the basic and the extended one. Whenever all witness stacks in a transaction are empty, the basic serialization format (equal to the pre-segwit transaction format) must be used. Whenever at least one witness stack is non-empty, the extended format must be used.

Common formats

I'll first introduce a few names for common serializations that are used further:

  • LE16: serialization of an unsigned integer in range [0,0xFFFF] as 2 bytes, with the least significant byte first.

  • LE32: serialization of an unsigned integer in range [0,0xFFFFFFFF] as 4 bytes, with the least significant byte first.

  • LE64: serialization of an unsigned integer in range [0,0xFFFFFFFFFFFFFFFF] as 8 bytes, with the least significant byte first.

  • CompactSize: serialization of an unsigned integer in a variable number of bytes:

    • 0 ≤ n ≤ 0xFC: serialized as [n] directly (one byte).
    • 0xFD ≤ n ≤ 0xFFFF: serialized as [0xFD] + LE16(n) (3 bytes).
    • 0x10000 ≤ n ≤ 0xFFFFFFFF: serialized as [0xFE] + LE32(n) (5 bytes).
    • 0x100000000 ≤ n ≤ 0xFFFFFFFFFFFFFFFF: serialized as [0xFF] + LE64(n) (9 bytes). This isn't actually used, as no structure this big would fit in a block.
  • Vector of T: serialization of a variable-length list of items of type T. The serialization consists of first CompactSize(n), where n is the number of list elements, followed by the serialization of each element itself.

Basic serialization

For transactions without witnesses.

The serialization is as follows:

  • LE32: version number: the transaction version number (typically 1 or 2 for now, see BIP68 for the meaning of version 2).
  • Vector of TxIns to specify the transaction inputs. Each TxIn is:
    • 32-byte: prevout hash: the txid of a previous transaction whose output is being spent by this input.
    • LE32: prevout index: the position in the previous transaction's TxOut vector of the output being spent by this input.
    • Vector of bytes: scriptSig, or unlocking script. This script is supposed to push onto the stack the arguments needed to satisfy the program in the spent output's scriptPubKey.
    • LE32: nSequence: the sequence number, or relative locktime, of the transaction input. See BIP125 and BIP68 for details.
  • Vector of TxOuts to specify the transaction outputs. Each TxOut is:
    • LE64: amount: the value of the transaction output in sats (1/100000000th of a BTC).
    • Vector of bytes: scriptPubKey, or locking script. This script specifies the conditions under which the output can be spent.
  • LE32: nLockTime: the absolute locktime (in height, if < 500000000, or in UNIX timestamp if laster) of the transaction. The transaction cannot be included in a block until this time/height has passed.
Extended serialization

For transactions with witness.

  • LE32: nVersion: same as above
  • Fixed byte 0x00: indicates extended format
  • Fixed byte 0x01: indicates witness extension is present
  • Vector of TxIn: same as above
  • Vector of TxOut: same as above
  • For each input, a Witnessstack. There is no length indicator for the number of witness stacks; their number is implicitly equal to the number of TxIns. Each WitnessStack is:
    • Vector of StackItems. Each StackItem is:
      • Vector of bytes.
  • LE32: nLockTime: same as above

So each transaction input has a corresponding witness stack, consisting of zero of more byte vectors each. For pre-witness spends, the witness stack is empty. For segwit inputs, the stack items are the equivalent of the scriptSig, unlocking the spend. For example:

  • For P2WPKH spends (BIP141], the witness stack contains two items; first a public key, and then a signature.
  • For P2WSH spends (BIP141), the witness stack contains one or more items. The last item is the witness script, and all the items before that are inputs to it.
  • For P2TR key-path spends (BIP341), the witness stack contains exactly one item: the signature.
  • For P2TR script-path spends (BIP341, and BIP342), the witness stack contains 2 or more items: the last one is the control block (proving this script was permitted), the penultimate one is the script itself, and all items before that are the inputs to the script.

For native witness spends, the scriptSigs themselves will be (and must be) empty. P2WPKH and P2WSH can also be embedded in P2SH (BIP16). In that case the scriptSig will contain a dummy redeemscript, which "redirects" execution to the witness.

5
  • I didn't understand the script_witnesses[] structure ... Nov 17 '21 at 21:06
  • 1
    I'll try to elaborate later, if nobody beats me to it. Nov 17 '21 at 21:11
  • Btw, I'm developing something similar to a wallet actually. But really I just need to be able to build 1 kind of transaction. Should I just go straight into P2TR? Nov 17 '21 at 23:27
  • 1
    You may find that a lot of other network participants still using older wallet software or whose software doesn't support sending to bech32m addresses would be unable to send to you if you were only able to receive to P2TR outputs.
    – Murch
    Nov 18 '21 at 21:35
  • 1
    Updated my answer. Nov 18 '21 at 22:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.