§ 12 · Networking
Magic bytes and ports
PRLM: a network name that never crosses the wire in the clear
On this page 6 sections
Pearl isn’t one network but several: the real one, mainnet, plus test networks whose coins are worthless. They run the same software. Something has to keep them from mixing, so that a test block never ends up on the real chain.
In Bitcoin, that something is the magic bytesMagic bytes: Four bytes that name a network: “PRLM” on Pearl's mainnet. Because Pearl encrypts all traffic between nodes, they never appear in plain view on the wire.: four bytes that open every message, saying which network it belongs to. Pearl has magic bytes too, “PRLM” for mainnet. But you will never see them on the wire. Pearl encrypts every connection, so the magic does its job in a quieter place.
Try it
Type 50524C4D as hex and flip the byte order. You get 4D4C5250: the same number, stored the way pearld stores it.
What are Pearl’s magic bytes?
Each network has a 4-byte number, chosen so that its hex spells letters:
| Network | Magic (number) | As text | Bytes on disk | P2P port | RPC port |
|---|---|---|---|---|---|
| Mainnet | 0x50524C4D |
PRLM | 4d 4c 52 50 |
44108 | 44107 |
| Testnet | 0x50524C31 |
PRL1 | 31 4c 52 50 |
44110 | 44109 |
| Testnet2 | 0x50524C32 |
PRL2 | 32 4c 52 50 |
44112 | 44111 |
| Regtest | 0x50524C52 |
PRLR | 52 4c 52 50 |
18444 | 18334 |
| Simnet | 0x50524C53 |
PRLS | 53 4c 52 50 |
18555 | 18556 |
| Signet | 0x40CF030A |
(none) | 0a 03 cf 40 |
38333 | 38332 |
0x50 0x52 0x4C is ASCII for “PRL”, and the last byte names the network: M for mainnet, 1 and 2 for the testnets, R for regtest, S for simnet. Signet’s magic is derived from a hash of its challenge script instead, as in Bitcoin.
Why are the bytes backwards?
Because pearld writes the magic as a 4-byte little-endianLittle-endian: Storing a number that spans several bytes with its smallest byte first. Pearl, like Bitcoin, stores numbers this way, and shows hashes with their bytes reversed. number, smallest byte first, exactly as Bitcoin does with its own magic (0xD9B4BEF9, written f9 be b4 d9). So 0x50524C4D becomes 4d 4c 52 50, which as ASCII reads “MLRP”. Byte order is explained on byte order.
Where do the magic bytes appear?
Not on the network. Pearl peers only speak BIP-324 encrypted transport, and BIP-324 messages have no plaintext header at all: no magic, no command name, no checksum. To anyone watching, a Pearl connection is a stream of random-looking bytes.
The magic shows up in two places instead:
- In the key derivation. When two nodes set up encryption, they turn their shared secret into keys with HKDFHKDF: A standard recipe, built on HMAC, for turning one shared secret into several independent keys. Pearl’s encrypted transport salts it with "pearl_v2_shared_secret" plus the network’s magic bytes., salted with the text
pearl_v2_shared_secretfollowed by the magic’s four bytes. - On disk. pearld’s block files store each block after the network’s magic, as Bitcoin nodes do.
Here is mainnet’s salt, as pearld builds it:
| Field | Bytes | Value |
|---|---|---|
| "pearl_v2_shared_secret" | 22 @0 | 22 bytes of ASCII text |
| Magic, little-endian | 4 @22 | 0x50524C4D, "PRLM" |
Then how are networks kept apart?
By that salt. A mainnet node and a testnet node that connect by mistake each derive their encryption keys with their own magic in the salt: 4d4c5250 against 314c5250. Their keys don’t match, so neither can decrypt the other, and the connection fails before a single real message. In Bitcoin’s old v1 protocol the same job is done by checking the magic at the start of each message; in Pearl it is done by cryptography.
Each network also has its own ports, its own genesis block and its own address prefix (prl1… on mainnet, tprl1… on testnet), so even outside the wire protocol the networks rarely look alike.
Which ports does Pearl use?
On mainnet:
- Peer-to-peer
- 44108
- open to the internet for incoming peers
- pearld RPC
- 44107
- local commands; keep it private
- Oyster wallet RPC
- 44207
- the wallet daemon
A node only needs the P2P port open to accept incoming peers. It can run perfectly well with only outgoing connections; it just won’t be listed by the DNS seeds, which only hand out nodes reachable on 44108.
Make a guess
A firewall vendor wants to block Bitcoin and Pearl traffic by spotting magic bytes in packets. Which one can it catch that way?
Think of your answer first, then check it.
Answer Only Bitcoin's v1 connections.
Bitcoin’s unencrypted v1 messages start with f9 be b4 d9. Pearl never sends v1 messages, and its encrypted stream
contains no fixed bytes to match. A firewall could still block port 44108, or guess from traffic
patterns, but not from the magic.
Code: magic values and the salt
From protocol.go (node/wire/protocol.go:133-152 at v1.5.2, on GitHub):
MainNet PearlNet = 0x50524C4D // "PRLM" in ASCII
RegTest PearlNet = 0x50524C52 // "PRLR" in ASCII
TestNet PearlNet = 0x50524C31 // "PRL1" in ASCII
TestNet2 PearlNet = 0x50524C32 // "PRL2" in ASCII
SigNet PearlNet = 0x40CF030A
SimNet PearlNet = 0x50524C53 // "PRLS" in ASCII And the salt, from transport.go (node/v2transport/transport.go:194-200 at v1.5.2, on GitHub):
salt := []byte("pearl_v2_shared_secret")
var magic [4]byte
binary.LittleEndian.PutUint32(magic[:], uint32(net))
salt = append(salt, magic[:]...)