§ 04

§ 04 · Keys & addresses

Address

A locking script, written for humans

An address is a locking script written so that a person can copy it, read it aloud or put it in a QR code.

Under the text there are only two things: a witness version (which kind of lock) and 32 bytes of witness program (whose lock). Bech32m wraps them in a network prefix and a checksum. Paste an address into a wallet and the wallet unwraps it back into the locking script it puts in a transaction output.

Try it

This address received 2 PRL in block 130,825. Decode it, then change one character.

Bech32m explorer

Every part of a prl1 address, and the checksum that catches typos

Valid Pearl mainnet address

Taproot (P2TR) · the checksum matches

Prefix (HRP)
prl mainnet
Witness version
p = 1 Taproot (P2TR)
Checksum
euhn70 matches (bech32m)
Program
62e9da3682aab288392cf7218bafc36287288abb3ce200c5d1a50aa234073b2b
Locking script
51 20 62e9da3682aab288392cf7218bafc36287288abb3ce200c5d1a50aa234073b2b
See the 5-bit → 8-bit regrouping

The 52 program letters carry 260 bits. Read them as bytes (8 bits each) and you get 32 bytes, with 4 zero bits of padding left over.

01100010111010011101101000110110100000101010101010110010100010000011100100101100111101110010000110001011101011111100001101100010100001110010100010001010101110110011110011100010000000001100010111010001101001010000101010100010001101000000011100111011001010110000

0110001011101001110110100011011010000010101010101011001010001000001110010010110011110111001000011000101110101111110000110110001010000111001010001000101010111011001111001110001000000000110001011101000110100101000010101010001000110100000001110011101100101011

Show every step
  1. Check the letter case

    All lower case, as expected.

  2. Split at the last '1'

    Everything before the last '1' is the human-readable part; the 59 characters after it are the data part.

  3. Read the prefix

    "prl" means Pearl mainnet.

  4. Turn each character into a 5-bit number

    Each character is its position in the alphabet qpzry9x8gf2tvdw0s3jn54khce6mua7l (q=0 … l=31). The first is the witness version, the last 6 are the checksum.

  5. Verify the checksum

    Running the BCH polymod over the expanded prefix and all data gives the bech32m constant 0x2bc830a3, so the checksum is valid.

  6. Read the witness version

    "p" = 1: a Taproot (P2TR) address.

  7. Regroup 5-bit numbers into bytes

    52 characters × 5 bits = 260 bits; the last 4 padding bits are zero, leaving 256 bits = 32 bytes: the tweaked public key Q.

  8. Build the locking script

    OP_1 OP_PUSHBYTES_32 <program>: the scriptPubKey a transaction output uses to pay this address.

Runs in your browser · nothing is sent src/lib/bech32m.ts · BIP-350 + Pearl’s rules

What are the parts of an address?

A mainnet Taproot address: 63 characters
Field Size Description
prefix (HRP) 3 chars prl: the network. Test networks use tprl, regtest rprl.
separator 1 char 1: the last 1 in the string ends the prefix.
version 1 char p = 1, Taproot. z = 2, P2MR. Nothing else is accepted.
program 52 chars 32 bytes, five bits per character: the tweaked key Q (Taproot) or the script tree root (P2MR).
checksum 6 chars Computed from everything before it. Catches typos. See bech32m.

The human-readable part is the only part you can read. Everything after the separator uses a 32-character alphabet, qpzry9x8gf2tvdw0s3jn54khce6mua7l, where each character stands for a number from 0 to 31. It leaves out 1, b, i and o, which are easy to confuse.

Size
63 characters (mainnet), 64 (test networks)
Type
bech32m text
Format
prefix ‖ 1 ‖ version ‖ program ‖ checksum

Which prefixes does Pearl use?

The prefix says which network an address is for. Wallets refuse an address from the wrong network.

Network Prefix Taproot address of private key 1 Length
mainnet prl prl1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5sse9xfq3 63
testnet, testnet2 tprl tprl1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5ssj2zhly 64
regtest rprl rprl1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5ssgn706v 64
Bitcoin, for comparison bc bc1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5sspknck9 62

Look at the middle: the 52 program characters are identical on every row. Same key, same program. Only the prefix and the checksum change, because the checksum covers the prefix too.

Two test networks share tprl, and regtest shares rprl with simnet, so an address tells you “mainnet, test or regtest”, not which testnet. (Pearl’s code also reserves tprl for a signet, but no Pearl signet runs.)

Which versions are there?

The version character picks the kind of lock. Pearl accepts exactly two.

Character Version Type Program Status
q 0 segwit v0 (Bitcoin’s bc1q) Rejected: “unsupported witness version: 0”
p 1 Taproot (P2TR) tweaked public key Q What wallets make
z 2 P2MR Merkle root of scripts Valid; wallets never make one
r, y, … 3–16 Rejected

The program must also be exactly 32 bytes. Bech32m itself could carry 2 to 40, but Pearl’s decoder insists on 32 for both versions.

How does an address become a locking script?

Directly. Decode the version and the program, then write OP_n (0x50 + version), a push of 32 bytes (0x20) and the program:

Address starts Locking script (34 bytes)
prl1p… 51 20 ‖ 32-byte Q
prl1z… 52 20 ‖ 32-byte root

Here is the real payment that sent 2 PRL to the address in the “Try it” box. Its second output’s locking script is 5120 followed by the 32 bytes behind vt5a5d5…:

A typical payment: 1 input, 2 outputs 205 bytes
01000000 00 01 01 5939557091bae792be66f26cbd83fc78f16a690a854109e8a1d115e253812133 ab020000 00 ffffffff 02 b0359f1100000000 22 5120d7ab02c96a342bdddb5d07b9f3ebd6c04e077ff41418110b9a1e5997439416b2 00c2eb0b00000000 22 512062e9da3682aab288392cf7218bafc36287288abb3ce200c5d1a50aa234073b2b 01 40 4686c7014749649b25555874c7772ecb7a44e85454893ed5888db11ebcdc82a22d74ce1a1671d02810f5ba1dca3277409e95a653ba9644099f7da26be7a86ba2 00000000
Field Bytes Value
Version version 4 @0 1 int32 little-endian. Pearl wallets and pearld coinbases use version 1; relay policy accepts 1-2.
Marker marker 1 @4 0x00 Segwit marker (BIP-144): says witness data follows the outputs.
Flag flag 1 @5 0x01 Witness flag; 0x01 is the only value Pearl accepts.
Input count vin.length 1 @6 1 CompactSize number of inputs.
Previous txid vin[0].txid 32 @7 33218153e215d1a1e80941850a696af178fc83bd6cf266be92e7ba9170553959 The transaction being spent, stored byte-reversed (internal order); shown here in normal display order.
Output index vin[0].vout 4 @39 683 Which output of that transaction is spent (uint32 LE).
scriptSig length vin[0].scriptSig.length 1 @43 0 Always 0 for non-coinbase inputs in Pearl: every spend uses the witness instead.
Sequence vin[0].sequence 4 @44 0xffffffff Final (0xffffffff): no RBF signal, no relative locktime, and locktime is ignored for this input. Pearl wallets use this.
Output count vout.length 1 @48 2 CompactSize number of outputs.
Amount vout[0].value 8 @49 295,646,640 grains (2.95646640 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains).
Script length vout[0].scriptPubKey.length 1 @57 34 CompactSize length of the locking script.
Locking script vout[0].scriptPubKey 34 @58 prl1p674s9jt2xs4amk6aq7ul867kcp8qwll5zsvpzzu6revewsu5z6eqv9d5z4 OP_1 OP_PUSHBYTES_32 <output key Q>: a Taproot output.
Amount vout[1].value 8 @92 200,000,000 grains (2.00000000 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains).
Script length vout[1].scriptPubKey.length 1 @100 34 CompactSize length of the locking script.
Locking script vout[1].scriptPubKey 34 @101 prl1pvt5a5d5z42egswfv7uscht7rv2rj3z4m8n3qp3w35592ydq88v4seuhn70 OP_1 OP_PUSHBYTES_32 <output key Q>: a Taproot output.
Witness items witness[0].length 1 @135 1 Number of witness stack items for input 0.
Schnorr signature length witness[0][0].length 1 @136 64 CompactSize length of this witness item.
Schnorr signature witness[0][0] 64 @137 4686c7014749649b25555874c7772ecb7a44e85454893ed5888db11ebcdc82a22d74ce1a1671d02810f5ba1dca3277409e95a653ba9644099f7da26be7a86ba2 64-byte BIP-340 signature (R.x ‖ s) with SIGHASH_DEFAULT: a Taproot key-path spend.
Locktime locktime 4 @201 0 0: no time lock.
txid
d919e02a4adfd739ceef31d98803f0ddd24e1b1fa67b0fe572cdec42c1b384c9
Size
205 bytes · 154 vbytes
Block
130,825
Fee
7,915 grains

That’s all a “payment to an address” is on chain: an output whose locking script is the address, unwrapped. A Taproot address holds the key itself, not a hash of it, so there is nothing to look up.

What does the decoder reject?

These are the results of feeding strings to Pearl’s own DecodeAddress on mainnet settings:

Input Result
bc1pmfr3p9…sspknck9 (Bitcoin) rejected: only Taproot and P2MR addresses are supported
1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH (base58) rejected, same message
prl1qw508d6qejxtdg4y5r3zarvary0c5xw7k34d768 (version 0) rejected: unsupported witness version: 0
prl1rmfr3p9…sswn0rny (version 3) rejected: unsupported witness version: 3
prl1p…hf5ssvek99n (old bech32 checksum) rejected: expected bech32m encoding
prl1pqqqq…xfau6t (20-byte program) rejected: witness program must be 32 bytes
PRL1PMFR3P9J00…HF5SSE9XFQ3 (all capitals) accepted
prl1pmfr3p9…sse9xFq3 (mixed case) rejected

All-capital addresses are allowed because QR codes store capitals more compactly. Mixing cases is not.

Why exactly 63 characters?

Count the pieces: 3 (prl) + 1 (separator) + 1 (version) + 52 (program) + 6 (checksum) = 63.

The 52 comes from the 32 bytes: 256 bits, cut into 5-bit characters, needs 52 characters (260 bits), with 4 zero bits of padding at the end. Since every Pearl program is 32 bytes, no Pearl address is ever shorter or longer. Test addresses add one letter for the t or r: 64.

Make a guess

Someone sends you a 62-character address that starts prl1p. Is it valid?

Think of your answer first, then check it.

Answer No.

Every valid mainnet address is exactly 63 characters. A 62-character prl1p string is missing a character somewhere, and the checksum will fail. (Bitcoin’s bc1p addresses are 62 characters because their prefix is one letter shorter.)

What do Pearl wallets hand out?

  • Taproot, always. Oyster and the Pearl Desktop Wallet give out prl1p… addresses from the BIP-86 path, a fresh one each time you ask, so payments aren’t trivially linked.
  • Never P2MR. P2MR outputs are valid and do appear on chain (rarely: 5 in 200 recent blocks, against 62,638 Taproot outputs), but a search of Pearl’s v1.5.2 code finds nothing outside tests that creates a P2MR address.
  • Quantum-safe on request only. getnewaddress … pq=true gives a prl1p… address whose tweak commits to an XMSS script. It looks like any other Taproot address.
Code: address to locking script

With this site’s library (the same code the tools use):

JavaScript
import { decodeAddress } from '~/lib/bech32m';

const a = decodeAddress('prl1pvt5a5d5z42egswfv7uscht7rv2rj3z4m8n3qp3w35592ydq88v4seuhn70');
a.network;  // 'mainnet'
a.version;  // 1
a.type;     // 'p2tr'
a.script;   // Uint8Array(34): 51 20 62e9da3682aab288392cf7218bafc36287288abb3ce200c5d1a50aa234073b2b

Pearl’s own Go code does the same in btcutil.DecodeAddress and txscript.PayToAddrScript.

The codex

Suggested

Up and down arrows move through the results, Enter opens one, Escape closes. Anywhere on the site, slash or Command K opens this search, and the square brackets [ and ] go to the previous and next page.