0

I don't fully understand the meaning of the witness version byte. I am not sure if I confuse the address format prefix bc1 with the witness version.

My understanding: The extra byte reserved for the witness version indicates what opcodes are used for evaluating the spending script (scriptPubKey).

  • P2WPKH, P2WSH have witness version 0 indicated by the yellow part shown below. If witness version is 0, a SegWit node looks at the size of the byte-key-hash to determine if it is a P2WPKH (20B) or P2WSH(32B).

enter image description here

  • P2WPKH wrapped in P2SH and P2WSH wrapped in P2SH does not have a witness version byte in the scriptPubKey. Why is that?

enter image description here

  • According to BIP350, bech32 has witness version 0 and bech32m has witness version. Does the 1 in bc1... indicate the witness version? If so, why are there are no bc0 addresses? Where is my thought process wrong? Do I mix address prefixes with witness versions?

  • P2TR introduces new opcodes and therefore, it should introduce a new witness version, is that correct? But P2TP addresses start with bc1...

1 Answer 1

1

I am not sure if I confuse the address format prefix bc1 with the witness version.

You are confusing them. "bc1" is the prefix. The witness version is part of the bech32/bech32m payload; specifically, the next character after the "1" encodes the witness version.

P2WPKH, P2WSH have witness version 0 indicated by the yellow part shown below. If witness version is 0, a SegWit node looks at the size of the byte-key-hash to determine if it is a P2WPKH (20B) or P2WSH(32B).

This is correct.

P2WPKH wrapped in P2SH and P2WSH wrapped in P2SH does not have a witness version byte in the scriptPubKey. Why is that?

In P2SH-wrapped P2WPKH/P2WSH the scriptPubKey encodes only a hash of the witness program (the OP_(version) + data push). The actual witness program (including the witness version) is only revealed at spending time.

According to BIP350, bech32 has witness version 0 and bech32m has witness version.

Almost. You cannot tell bech32 from bech32m strings by just looking at them. However, in the context of native segwit addresses, bech32 has to be used for witness 0, and bech32m has to be used for witness 1 and higher.

So in general the strategy is to try decoding every address as both bech32 and bech32m, see if either is valid, then check if the payload encodes a valid segwit address, find its version, and finally check that the version matches the address encoding (bech32 for 0, bech32m for other versions).

This is mostly unrelated to your question though. The encoding is structured as follows (for both bech32 and bech32m; the only difference between the two is the checksum):

  • First there is the human readable part.
    • For mainnet native segwit addresses (v0 or later), the human readable part is "bc".
  • Then there is the separator. The separator is always exactly "1".
  • Then there is the payload, consisting of a variable number of base32 characters.
    • For native segwit addresses (v0 or later), the payload consists of one character that encodes the witness version (v0 = "p", v1 = "q", v2 = "z", ...), followed by 4 to 64 characters that encode the 2 to 40 byte push in the witness program (the data pushed after the OP_(version)).
  • Lastly there are 6 base32 characters that form a checksum over the whole thing.

P2TR introduces new opcodes and therefore, it should introduce a new witness version, is that correct?

Indeed, P2TR uses witness programs that consist of OP_1 + a 32-byte push, and are thus witness version 1. In BIP350 addresses, that translates to a "p" after the separator (as opposed to version 0 P2WPKH/P2WSH, which have a "q" after the sepatator).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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