Skip to content

Addresses

By now we already know that Bitcoin wallets are based on public-key cryptography. But there’s an important nuance worth clarifying right from the start: in Bitcoin there is no balance record tied to an account or identity. What exists are unspent transaction outputs (UTXOs) locked behind cryptographic conditions. Ownership of those bitcoins comes down to one thing: holding the private key that lets you create a valid signature to spend them.

There is no server storing your balance. No account you can recover with an email. If you have the private key, you have the bitcoins. If you lose it, the bitcoins are gone forever. If someone else obtains it, they can spend them and there’s nothing you can do about it.

That’s why it’s essential to understand how private keys work and how they turn into the addresses we use every day. In this chapter we’ll focus on Bitcoin addresses and wallets.

Private Keys

A private key in Bitcoin is simply a 256-bit number generated with the highest degree of randomness a computer can provide. This means there are approximately 2²⁵⁶ possible private keys — almost as many as there are atoms in the universe — a number so large that it’s practically impossible to guess or brute-force (we’ll ignore quantum computing for now).

transaction

To generate that number, Bitcoin requires a cryptographically secure random number generator (CSPRNG). You can’t just use your programming language’s normal random number generator, because those aren’t cryptographically secure and can end up with patterns that might be exploitable. A private key must come from a high-quality source of entropy; for this purpose things like hardware noise, mouse movements, system events, etc. are used.

Nowadays wallets don’t generate independent private keys. Almost all modern implementations are deterministic: all keys are mathematically derived from a single seed. We’ll look at this in more depth in the wallets section.

Bitcoin uses elliptic curve cryptography, specifically the secp256k1 curve. This means that for a 256-bit private key to be valid, it must be a number between 1 and n − 1, where n is the order of the elliptic curve:

\[ 1 ≤ p < n, n = 1.1578 × 10⁷⁷ \]

In this chapter we won’t go deep into elliptic curve cryptography. We’ll cover it when we explain how public keys are derived from private keys. One day I’ll write an article about the math behind Bitcoin 🫡

Private Key Representation Formats

A private key is a number. But a raw 256-bit number isn’t practical: it’s easy to copy incorrectly, it doesn’t indicate what kind of data it is, and it has no error-detection mechanism. That’s why there are different representation formats, each designed to solve a specific problem.

Hexadecimal

Simply the private key encoded in hexadecimal. This is the format the software handles internally. You should never have to see or copy this format manually: a single mistyped character and the key becomes something completely different, with no way to detect the error.

hex → 1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd

WIF (Wallet Import Format)

WIF is a format designed for a very specific use case: exporting a private key from one wallet and importing it into another. Nowadays it’s practically never used — modern wallets are deterministic and don’t need to export individual keys — but understanding it is useful because it introduces concepts that reappear elsewhere in the protocol.

The problem it solved was twofold. First: raw hexadecimal has no error-detection mechanism. If you copy a character wrong, the resulting key is completely different yet still valid, with no warning. Second: a wallet receiving a string has no way to know whether it’s a private key, an address, or some other type of data.

WIF solves both problems by using Base58Check, an encoding we’ll look at in detail later. For now, it’s enough to know that it adds two things to the original number: a version byte at the beginning that identifies the type of data, and a checksum at the end that lets you detect transcription errors. If you enter a character wrong, the checksum won’t match and the wallet will reject it before trying to use it.

The version byte 0x80 makes the resulting string always start with 5:

WIF → 5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn

WIF-compressed

When Bitcoin evolved and compressed public keys appeared, a new problem arose: the same private key can generate two different addresses depending on whether you derive a 65-byte or a 33-byte public key. The wallet importing the key needs to know which one to look for on the blockchain, because if it looks in the wrong address it won’t find the funds.

The solution was WIF-compressed: exactly the same as WIF, but with an extra byte (0x01) appended to the end of the number before encoding it. That byte doesn’t compress anything — in fact the representation is one byte longer — it’s simply a signal: "derive compressed public keys from this private key". The extra byte changes the Base58 prefix from 5 to K or L:

WIF-compressed → KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ

The term “compressed private key” is technically incorrect but is still used out of habit: the private key itself cannot be compressed. What is being signaled is that the public keys derived from it should be compressed. A wallet that imports the key in the wrong format won’t find the funds when scanning the blockchain, because it will be looking in the wrong addresses.


Public Keys

Let’s remember once again:

private key → signs a transaction
public key → verifies that the signature is valid

Generating a Public Key from the Private Key

The public key is derived from the private key through a mathematical operation on an elliptic curve. The secp256k1 curve is the set of points that satisfy the equation:

\[y² = x³ + 7\]

The operation performed is:

\[K = k × G\]

where: - k is the private key (the random 256-bit number) - G is the generator point — a fixed, public point defined in the secp256k1 standard, the same for all Bitcoin users - K is the resulting public key: a point on the elliptic curve with coordinates (x, y)

This operation is known as elliptic curve scalar multiplication. It is easy to compute in one direction (from private to public), but extremely difficult to reverse (compute k from K). This is called a trapdoor function.

For example, for the private key k:

k = 1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD

The resulting public key would be:

x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A
y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB

Uncompressed vs. Compressed Public Key

Originally the public key was represented by prefixing 0x04 to the concatenation of the X and Y coordinates:

04 || x (32 bytes) || y (32 bytes)  =  65 bytes

Later it was discovered that transmitting both coordinates is redundant. The secp256k1 curve is symmetric with respect to the X axis, which means that for every value of x there are exactly two possible values of y: one even and one odd. If you know x and whether y is even or odd, you can fully recalculate y.

This allows representing the public key using only the x coordinate plus one byte that indicates the parity of y:

  • Prefix 02 if y is even
  • Prefix 03 if y is odd

The result is a 33-byte compressed public key instead of 65:

K = 03F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A

Same point on the curve, same private key behind it, almost half the space. Multiplied by the number of transactions on the blockchain, the savings are enormous. Today all modern implementations use compressed public keys by default.

A private key in WIF format generates different addresses than one in WIF-compressed format because each format signals a different type of public key. The private key is the same number, but the serialized public key is different in size and prefix, which produces a different hash and therefore a different address.


Bitcoin Addresses

As Bitcoin has evolved, improvements have been implemented in the protocol, many of them changing the address format. Each type of address represents a different way of locking and unlocking UTXOs.

Before diving into the types of addresses, you need to understand hash functions: they take an input of any size and produce a fixed-size output. They are deterministic — the same input always produces the same output — and one-way: given the output, you cannot reconstruct the input.

In Bitcoin, an address is nothing more than a compact, human-readable, and secure way to represent a cryptographic commitment (a hash) of a public key or a script. Instead of sharing the full public key, the recipient shares an address. The sender uses it to create a scriptPubKey that locks the funds until the recipient proves they control the corresponding private key.

P2PK — Pay to Public Key

P2PK is the oldest and simplest type of output in Bitcoin. It locks a UTXO directly to a public key. To spend it, the recipient only needs to provide a valid signature with the corresponding private key.

Output script:

<public key> OP_CHECKSIG

Input script:

<signature>

When a node validates the transaction, it combines both scripts and executes them in order:

<signature> <public key> OP_CHECKSIG

The Bitcoin Script interpreter works like a stack. Each element is pushed onto it, and when an opcode appears it consumes elements from the top of the stack:

<signature>       → pushed
<public key> → pushed on top
OP_CHECKSIG   → consumes the two top elements (public key and signature),
                verifies that the signature is valid for that public key and the hash
                of the transaction. If correct, pushes 1. If not, pushes 0.

If at the end of execution the top of the stack is a non-zero value, the script is valid and the transaction can be processed.

P2PK doesn’t have an address format as such: the public key was included directly in the output script. Nowadays P2PK practically doesn’t exist in new transactions; Satoshi’s early transactions used this format, including the genesis block coinbase, but nodes are still able to validate them.

P2PKH — Pay to Public Key Hash

P2PKH is the first modern-style Bitcoin address: instead of locking the UTXO to a full public key, it locks it to a hash of the public key. It’s the format that generates addresses starting with 1.

The reasons for the change from P2PK are twofold: uncompressed public keys took up 65 bytes, which was long and heavy data; and revealing the public key before spending the UTXO exposed unnecessary information. With P2PKH, the public key is only revealed at the moment of spending.

To build the address, HASH160 is applied to the public key K:

A = RIPEMD160(SHA256(K))

Output script:

OP_DUP OP_HASH160 <public key hash> OP_EQUALVERIFY OP_CHECKSIG

Input script:

<signature> <public key>

Execution:

<signature>         → pushed
<public key> → pushed
OP_DUP          → duplicates the top of the stack. Now there are two copies of the public key
OP_HASH160      → consumes the top copy and replaces it with its HASH160
<hash>          → pushed (the hash that was in the output script)
OP_EQUALVERIFY  → consumes the two top elements (the calculated hash and the hash from the output),
                  verifies they are equal. If they don’t match, the script fails here
OP_CHECKSIG     → consumes signature and public key, verifies the signature. If valid, pushes 1

If the public key provided by the recipient produces the same hash as the one in the output, and the signature is valid for that key, the spend is legitimate.

Base58Check: the address format

A 20-byte hash in hexadecimal isn’t practical for users either: it’s long, doesn’t indicate what kind of data it is, and any transcription error means the funds are lost forever. To solve this, Bitcoin uses Base58Check.

Base58 is an encoding similar to Base64 but without the characters that cause visual confusion: no 0 (zero), no O (uppercase o), no l (lowercase L), and no I (uppercase i). The resulting alphabet has 58 characters, hence the name.

Base58Check adds two things on top of Base58:

  • A version byte at the beginning, which identifies the type of data. For P2PKH it is 0x00, which makes the encoded address always start with 1.
  • A 4-byte checksum at the end, calculated as the first 4 bytes of SHA256(SHA256(version || data)). If you transcribe a character wrong, the checksum won’t match and the wallet rejects the address before sending anything.

Constructing a P2PKH address:

public key (33 bytes, compressed)
    → SHA256
    → RIPEMD160                          [20 bytes]
    → add version byte 0x00           [21 bytes]
    → SHA256(SHA256(...))  → take the first 4 bytes as checksum
    → concatenate: version + hash + checksum  [25 bytes]
    → encode in Base58
    → address starting with 1

P2PKH was the dominant standard during Bitcoin’s early years and remains valid today. Its limitations — no native multisig support and higher transaction size — led to the following formats.

P2SH — Pay to Script Hash

P2SH, introduced in 2012 via BIP16, generalizes the P2PKH concept: instead of locking to a public key hash, it locks to the hash of an arbitrary script, called the redeem script. It generates addresses starting with 3.

Imagine Bob wants to receive payments that require two signatures to spend — for example, one from his computer and one from his hardware wallet. The script expressing that condition can be large. Without P2SH, Alice would have to include that entire script in her output, paying the corresponding fees and needing to know Bob’s internal scheme details.

With P2SH, Bob summarizes his script in a 20-byte hash. Alice only needs that hash to pay. Bob reveals the full script only when he’s ready to spend, and he is the one who pays the fees associated with its complexity.

Bob’s redeem script could be, for example, a 2-of-2 multisig:

<pubkey1> OP_CHECKSIGVERIFY <pubkey2> OP_CHECKSIG

Its HASH160 is calculated:

hash = RIPEMD160(SHA256(redeem script))

Output script:

OP_HASH160 <redeem script hash> OP_EQUAL

Input script:

OP_0 <signature1> <signature2> <serialized redeem script>

Validation happens in two phases. First it verifies that the provided redeem script produces the correct hash. If it matches, the redeem script is deserialized and executed as a normal script, verifying the signatures.

P2SH also uses Base58Check, but with version byte 0x05, which produces addresses starting with 3.

P2SH was an important leap because it separated script complexity from the act of paying: the payer doesn’t need to know anything about the recipient’s spending conditions. However, P2SH inherited a security limitation: its hashes are 160 bits, which makes them theoretically vulnerable to collision attacks in certain multisig scenarios. Later formats solved this.

P2WPKH — Pay to Witness Public Key Hash

P2WPKH is the native SegWit version of P2PKH. Introduced in 2017 with BIP141, it moves the signature and public key out of the traditional input field and places them in a separate field called the witness.

SegWit (Segregated Witness) solved two problems:

  1. Transaction malleability: before SegWit, it was possible to slightly modify the signature data without invalidating it, which changed the transaction’s txid. This blocked building contracts and payment channels on top of Bitcoin. By separating the signature from the transaction body, the txid no longer depends on it.
  2. Efficiency: witness data receives a discount in the transaction weight calculation, which reduces the effective fees for anyone using SegWit.

In P2WPKH the witness does not contain a hash — it contains the signature and public key directly. In other words, the same data that used to go in the P2PKH input script is now moved to the witness field, and the input script is left empty.

The address is built the same way as in P2PKH: applying HASH160 to the compressed public key. What changes is how that hash is packaged in the transaction and how the address is encoded.

Output script:

OP_0 <20-byte public key hash>

OP_0 is the SegWit version number. An output script starting with OP_0 followed by 20 bytes is recognized by nodes as P2WPKH.

Input script:

(empty)

Witness:

<signature> <public key>

Execution:

The node detects the OP_0 <20 bytes> pattern in the output script
    → recognizes P2WPKH, witness version 0
    → takes the signature and public key from the witness field
    → verifies that HASH160(public key) == the 20 bytes in the output script
    → if it matches, verifies the signature against the public key
    → if both verifications pass, the spend is legitimate

The logic is identical to P2PKH — public key hash plus signature — but the sensitive data travels in a separate field that old nodes ignore and new nodes validate.

Bech32: the SegWit address format

P2WPKH does not use Base58Check. It uses Bech32 (BIP173), a format designed specifically for SegWit addresses that solves several problems that Base58 carried.

Base58Check mixed uppercase and lowercase, which made it hard to read aloud and generated errors when transcribing visually similar characters. Bech32 uses only lowercase and a 32-character alphabet designed to minimize visual confusion: no 1, b, i, or o.

A Bech32 address has three parts:

  • A human-readable part (HRP): bc for mainnet, tb for testnet
  • A separator: always the character 1
  • The data: witness version (encoded as a single character) followed by the witness program (the 20-byte hash) in Base32, plus a 6-character checksum

Constructing a P2WPKH address:

public key (33 bytes, compressed)
    → SHA256
    → RIPEMD160                          [20 bytes → witness program]
    → add witness version 0
    → encode in Base32
    → calculate Bech32 checksum
    → concatenate: "bc" + "1" + version + data + checksum
    → address starting with bc1q

The prefix bc1q is consistent across all P2WPKH mainnet addresses: bc is the HRP, 1 is the separator, and q is the Base32 encoding of witness version 0.

Bech32 → bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4

Bech32’s checksum is more robust than Base58Check’s: it detects up to four substitution errors in any position. In addition, if you make an error, Bech32 can tell you exactly which position the incorrect character is in — something Base58Check cannot do.

P2WPKH is today the recommended format for standard single-signature payments. It reduces transaction size compared to P2PKH — because witness data gets a discount in the weight calculation — and its address is more resistant to transcription errors. Its limitations appear when more flexibility in spending conditions is needed, territory covered by P2TR.

P2SH-P2WPKH

P2SH-P2WPKH introduces no new logic: it is a P2WPKH wrapped inside a P2SH. Its only purpose was backward compatibility. When SegWit activated in 2017, many wallets and exchanges still didn’t know how to generate or send to Bech32 addresses. P2SH-P2WPKH solved that problem: it produces an address starting with 3, indistinguishable from any other P2SH, so any wallet that could pay to P2SH could pay to this address without knowing that SegWit was inside.

The mechanism is simple. A redeem script is built that is exactly the output script of a P2WPKH:

redeem script = OP_0 <HASH160 of the public key>

And that redeem script is treated like any other in P2SH: it is hashed and locked to its hash.

hash = RIPEMD160(SHA256(redeem script))

Output script:

OP_HASH160 <redeem script hash> OP_EQUAL

Input script:

<serialized redeem script>

Witness:

<signature> <public key>

Execution:

First phase — P2SH validation:
    the node verifies that HASH160(redeem script) == hash in the output script
    if it matches, the redeem script is deserialized

Second phase — SegWit validation:
    the node reads the redeem script: OP_0 <20 bytes>
    → recognizes the P2WPKH pattern, witness version 0
    → takes signature and public key from the witness field
    → verifies that HASH160(public key) == the 20 bytes in the redeem script
    → verifies the signature against the public key

The address uses Base58Check with version byte 0x05, the same as P2SH, so it also starts with 3. There is no way to distinguish a P2SH-P2WPKH address from a regular P2SH at a glance.

Base58Check → 3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN

P2SH-P2WPKH is a transitional format. It gets the SegWit discount in the witness field, but it carries the cost of including the redeem script in the input, making it somewhat heavier than native P2WPKH. Today it has little justification compared to P2WPKH or P2TR, except for compatibility with legacy systems that haven’t migrated yet.

P2TR — Pay to Taproot

P2TR, introduced in 2021 with BIP340, BIP341 and BIP342, is the deepest change in Bitcoin since SegWit. It generates addresses starting with bc1p.

To understand it we have to start from the problem it solves, because all previous formats share a structural limitation: they reveal information they don’t need to reveal.

When you spend a P2PKH you expose your public key. When you spend a P2SH multisig you expose how many keys there were, which ones they were, and how many signed. When you spend a P2WSH with a complex script, that script is permanently recorded on the blockchain, including all the conditions that were not executed. Any analyst can reconstruct your wallet’s security scheme just by looking at the transaction.

P2TR inverts this model. In the most common case, a Taproot spend is indistinguishable on the blockchain from any other: a 32-byte point and a 64-byte signature, nothing more. No public key hash, no visible script, no trace of the number of participants. A simple one-person payment looks exactly the same as an institutional 20-signer multisig, or a contract with timelocks and emergency recovery conditions.

To achieve this, Taproot combines three pieces: Schnorr signatures, key aggregation, and cryptographically committed script trees.

Schnorr Signatures

Until Taproot, Bitcoin used ECDSA to sign transactions. Schnorr (BIP340) is a different scheme, mathematically simpler, with a property ECDSA does not have: linearity.

In ECDSA, combining multiple signatures into one requires complex protocols. In Schnorr, linearity arises from the scheme’s own structure. If you have two private keys a and b, with their respective public keys A = a×G and B = b×G, the sum of the public keys A + B is the public key corresponding to the private key a + b. The math of the signature behaves the same way: signing with a and signing with b can be combined into a single valid signature against A + B.

This has an enormous consequence: a 5-of-5 multisig can produce a single 64-byte signature that is valid against a single aggregated public key. From the blockchain’s perspective, it is impossible to distinguish it from an individual signature. There is no trace that there were five people, or which keys they were.

The concrete implementation of this in Bitcoin is called MuSig2 (BIP327). Key aggregation is not as trivial as adding two points — that would be vulnerable to key cancellation attacks — but the practical result is the same: multiple participants produce a single on-chain signature.

Schnorr signatures are also smaller than ECDSA: 64 bytes versus an average of 71–72 bytes for DER-encoded ECDSA. And unlike ECDSA, they do not require an independent random nonce per signature, which eliminates a historical source of catastrophic failures. Bitcoin’s Schnorr scheme also has a formal security proof in the random oracle model, something ECDSA does not have.

The Tweaked Key: How to Embed Scripts in a Key

The central piece of Taproot is a construction called the tweaked key. The idea is subtle but elegant: the public key that appears in the output is not just the recipient’s key. It is a key that cryptographically carries, in a mathematically verifiable way, a commitment to a set of alternative spending scripts.

The mechanism works like this. You have an internal public key P. You also have a set of alternative spending conditions represented as a tree — we’ll see the details later — whose root hash we call m. The tweak is calculated as:

t = hash(P || m)
Q = P + t×G

Q is the tweaked key that gets published in the output. There are two important things about this construction:

The first: anyone who knows P and m can verify that Q was constructed honestly, because they can recalculate t and check that P + t×G gives exactly Q. This means you cannot publish a fraudulent Q that claims to have scripts it doesn’t have.

The second: anyone who only sees Q on the blockchain cannot tell whether it carries embedded scripts or not. Q looks like a random point on the curve. There is no visible marker.

If there are no alternative scripts — simple single-key spend — m is an empty string and the tweak is hash(P). The tweaked key is still a valid key, and the spend looks identical to the case with scripts.

Key Path: the Most Efficient Spend Possible

If the key holder can sign directly — whether a single person or a group using MuSig2 — the spend is immediate and minimal.

Output script:

OP_1 <32-byte tweaked key Q>

OP_1 is witness version 1. A node that sees OP_1 followed by 32 bytes knows it is looking at a P2TR output.

An important detail: P2TR uses x-only keys, that is, only the 32-byte x coordinate, without the prefix byte used by compressed P2WPKH keys. Because the curve is symmetric with respect to the x-axis, given x there are always two possible points, and by convention Taproot chooses the one with even y coordinate. This saves one byte and simplifies the verification arithmetic.

Input script:

(empty)

Witness:

<64-byte Schnorr signature>

Execution:

the node reads OP_1 <32 bytes> → recognizes P2TR, witness version 1
    → takes the Schnorr signature from the witness field
    → verifies the signature against the tweaked key Q
    → if valid, the spend is legitimate

That’s it. No intermediate hashes, no explicit public key in the input, no exposed scripts. It is the most compact and most private spend that exists in Bitcoin.

Script Path: MAST and the Tree of Conditions

The key path covers the common case. But sometimes the key holder cannot or does not want to sign directly: it might be a contract with a timelock, a multisig whose participants are not available to coordinate MuSig2, or an emergency recovery condition. For this the script path exists.

The idea is that when building the output, the recipient can define a set of alternative scripts and organize them into a binary Merkle tree. This tree is called MAST (Merkelized Alternative Script Trees).

Imagine a company that wants to receive funds with the following spending conditions:

Script A: 3-of-5 multisig of the board of directors
Script B: 2-of-3 multisig + 6-month timelock (for recovery)
Script C: single signature of the CEO + 1-year timelock (extreme emergency case)

These three scripts become the leaves of the tree. Each leaf is hashed, and the hashes are combined in pairs upward until reaching a single root hash:

                    root
                   /    \
              H(A,B)    H(C)
             /      \
           H(A)    H(B)

H(A) = hash(Script A)
H(B) = hash(Script B)
H(C) = hash(Script C)
H(A,B) = hash(H(A) || H(B))
root   = hash(H(A,B) || H(C))

This root m is what gets embedded in the tweak when building Q. The output only contains Q; nobody knows how many scripts there are or what they are.

When the company wants to spend using Script B, it reveals in the witness only Script B plus the sibling hashes that allow reconstructing the path to the root — in this case, H(A) and H(C). The node can verify that those data produce the same root that is embedded in Q, without Scripts A and C ever having been revealed.

Input script:

(empty)

Witness:

<data that satisfies the script> <script to execute> <control block>

The control block contains the internal key P, a version byte, and the sibling hashes needed to reconstruct the path from the leaf to the root of the tree.

Execution:

the node extracts the script and the control block from the witness
    → reconstructs the tree root from the script and the sibling hashes
    → verifies that Q == P + hash(P || reconstructed root) × G
    → if the commitment is valid, executes the script with the witness data
    → if the script returns true, the spend is legitimate

Two practical consequences of MAST. First: if you have ten possible spending conditions and only use one, the other nine never appear on the blockchain. Second: for a tree with n leaves, the control block only needs log₂(n) hashes for the proof. A tree with a thousand scripts only exposes ten hashes when spent.

Tapscript

The scripts executed in the script path are not conventional Bitcoin Script, but Tapscript (BIP342), an updated version with some important differences.

The most relevant is that OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY are disabled in Tapscript and replaced by OP_CHECKSIGADD. The reason is that OP_CHECKMULTISIG has legacy behavior with an old protocol bug — it consumes an extra stack element for historical reasons — and is incompatible with batch verification of Schnorr signatures. OP_CHECKSIGADD is cleaner: it receives a signature, a public key, and a counter, and if the signature is valid it increments the counter. This allows building multisigs with more explicit and efficient logic.

Tapscript also opens the door to future upgrades of the scripting language through reserved opcodes (OP_SUCCESS), without needing an additional soft fork: if the node encounters an OP_SUCCESS opcode, the script is considered valid unconditionally, which allows activating new semantics in future versions.

Bech32m: the Bech32 correction

P2TR does not use Bech32 but Bech32m (BIP350). After SegWit was deployed, a flaw was discovered in Bech32’s checksum function: inserting or deleting the character q at the end of the data part was not always detected. This didn’t affect P2WPKH or P2WSH — their lengths are fixed and the error would be detected anyway — but it could affect future witness versions with variable lengths. Bech32m fixes the flaw by changing a constant in the checksum algorithm. The visual format is identical.

Constructing a P2TR address:

internal public key P (32 bytes, x-coordinate only)
    → calculate script tree root (or empty string if no scripts)
    → t = hash("TapTweak" || P || root)
    → Q = P + t×G                          [tweaked key, 32 bytes, x only]
    → add witness version 1
    → encode in Base32
    → calculate Bech32m checksum
    → concatenate: "bc" + "1" + "p" + data + checksum
    → address starting with bc1p
Bech32m → bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297

P2TR is today Bitcoin’s most efficient, most private, and most flexible format. The key path — a 64-byte signature, no hashes, no explicit public key — is the most compact spend possible. The script path with MAST allows arbitrary conditions without revealing the ones that aren’t used. And the indistinguishability between a simple key path and a MuSig2 multisig is a real privacy improvement at the protocol level, not just good practice. The only friction is that support in exchanges and wallets is still uneven, although adoption is growing consistently.

support with btc <3

wallet-qr