wif -> private key
- Use base58-decode to convert the base58 string to bytes
- Strip the first byte (network byte) and the last 4 bytes (checksum). The remainder is the key
- Verify that the first 4 bytes of the sha256(sha256(network byte || key)) are equal to the checksum
- If the key ends with
0x01
(compressed) remove the last byte. You are left with the private key
private key -> public key
- Cast the private key as an integer
Multiply with the secp256k1 generator point to get a Point(x,y) on the curve. This is your public key
Encode your public key in a compressed format. Byte 0x03
(if y is odd) or 0x02
(if y even) followed by x as 256-bit integer
Public key -> P2WPKH address
- Create the witness program = ripemd160(sha256(public key))
- Encode into bech32 by providing the witness program,
bc
as the human readable part and 0
as witness version
Public key -> P2SH-P2WPKH address
- Create the witness program = ripemd160(sha256(public key))
- Create the redeem script =
0x0014<witness program>
= witness version + push20 + witness program
- Calculate the hash160 = ripemd160(sha256(script))
- Prepend the hash with the version byte
0x05
- Calculate the checksum = sha256(sha256(version byte || scripthash ))
- Base58-encode(version byte || scripthash || first 4 bytes of checksum)
How do these two formats differ and why are there two? I've seen that
the P2SH version is compatible with older clients, are native Segwit
addresses not?
Old clients cannot send to segwit addresses but they can send to P2SH addresses and by extension to P2SH-P2WPKH