This document describes the version bytes used in Electrum for master keys.
BIP32 defines a serialization format for extended keys. This serialization includes four bytes allocated as version bytes. We use these version bytes to encode the type of output scripts (scriptPubKeys) a wallet should derive along this HD subtree.
Among other changes, the activation of SegWit (BIP141) introduced new output script templates usable on Bitcoin mainnet. This poses a new problem for HD wallets in terms of what type of scripts they should derive from master keys. Previously most wallets offered deriving either P2PKH or multi-signature embedded in BIP16 P2SH outputs, and it was usually deduced from context which of the two should be used. We believe it would be better to have this knowledge explicitly.
Encoding the script type in BIP32 extended keys is beneficial for wallets. For example, a watch-only wallet constructed from an extended public key would otherwise have to either (1) derive all possible scripts in the subtree [1], or (2) prompt the user to enter the script type in a side-channel.
Deriving all possible scripts (1)
- Potentially wastes resources. Wallets have to monitor more output scripts for incoming transactions.
- Introduces key-reuse. Public keys are reused for each script type.
- Becomes an ever-growing barrier for developers of new wallet software to implement detecting and spending from every type of UTXO. Otherwise, if they choose not to implement legacy script types that can lead to not discovering funds.
Prompting the user to enter the script type (2) as additional information besides the extended public key just leads to more complex user interfaces and suboptimal experience.
Users directly interact with master public keys, for watch-only wallets, or when specifying cosigners for HD multisig. These keys are commonly serialized as BIP32 extended keys, hence it makes sense to make the encoding of the script type user-visible. As version bytes are already used to encode the network in such a way, this document introduces new constants for version bytes to further encode the script type.
Without explicit knowledge of the output script type, wallets have no clear way to communicate to users whether the type of script the user would expect to be derived is supported/implemented. Casual users would simply notice funds missing, if they have prior knowledge of funds at all.
The version byte values defined in BIP32 do not distinguish P2PKH and P2SH-multisig outputs, and to remain backwards compatible, this will not be changed. However, this has already resulted in loss of funds in some cases, where e.g. a user restored and received transactions on a watch-only P2PKH wallet from a master public key participating in P2SH-multisig that he had no control over (it was a key of a different cosigner). To try to prevent this kind of situation, e.g. P2WPKH and P2WSH-multisig is distinguished in this document.
In the table below,
- P2SH stands for a BIP11 multi-signature script embedded in a BIP16 pay-to-script-hash output
- P2WPKH stands for pay-to-witness-public-key-hash (witness version 0), as in BIP141
- P2WPKH-P2SH stands for a P2WPKH script (witness version 0) nested in a BIP16 P2SH output, as in BIP141
- P2WSH stands for a BIP11 multi-signature pay-to-witness-script-hash (witness version 0) script, as in BIP141
- P2WSH-P2SH stands for a BIP11 multi-signature pay-to-witness-script-hash (witness version 0) script nested in a BIP16 P2SH output, as in BIP141
Note that an M-of-N multi-signature script is usually constructed from N extended keys (and M is provided in a side-channel). Hence in most cases more than one extended key is needed to create such scripts; this is out of scope of this document.
network | script type | pub/priv | version bytes | human-readable
prefix
|
---|---|---|---|---|
mainnet | p2pkh or p2sh | public | 0x0488b21e | xpub |
mainnet | p2pkh or p2sh | private | 0x0488ade4 | xprv |
mainnet | p2wpkh-p2sh | public | 0x049d7cb2 | ypub |
mainnet | p2wpkh-p2sh | private | 0x049d7878 | yprv |
mainnet | p2wsh-p2sh | public | 0x0295b43f | Ypub |
mainnet | p2wsh-p2sh | private | 0x0295b005 | Yprv |
mainnet | p2wpkh | public | 0x04b24746 | zpub |
mainnet | p2wpkh | private | 0x04b2430c | zprv |
mainnet | p2wsh | public | 0x02aa7ed3 | Zpub |
mainnet | p2wsh | private | 0x02aa7a99 | Zprv |
testnet | p2pkh or p2sh | public | 0x043587cf | tpub |
testnet | p2pkh or p2sh | private | 0x04358394 | tprv |
testnet | p2wpkh-p2sh | public | 0x044a5262 | upub |
testnet | p2wpkh-p2sh | private | 0x044a4e28 | uprv |
testnet | p2wsh-p2sh | public | 0x024289ef | Upub |
testnet | p2wsh-p2sh | private | 0x024285b5 | Uprv |
testnet | p2wpkh | public | 0x045f1cf6 | vpub |
testnet | p2wpkh | private | 0x045f18bc | vprv |
testnet | p2wsh | public | 0x02575483 | Vpub |
testnet | p2wsh | private | 0x02575048 | Vprv |
This document is backwards compatible with BIP32; existing extended keys will keep working. Compatibility is intentionally broken in the sense that extended keys derived for newer script types will not have valid BIP32 version bytes.
[1] | Which is not even possible, given there are an effectively infinite number of possible scripts. A wallet could however derive scripts for all standard templates. |