1. Magic-bytes table
| Chain | b3chain magic | Bitcoin magic |
|---|---|---|
| mainnet | b3 c0 01 0d | f9 be b4 d9 |
| testnet | b3 c1 02 0e | 0b 11 09 07 |
| testnet4 | 1c 16 3f 28 | 1c 16 3f 28 (intentionally identical — testnet4 is rarely used) |
| regtest | b3 c2 03 0f | fa bf b5 da |
The audit accepts the testnet4 collision (testnet4 is a developer network that doesn't autoconnect to public peers). Mainnet, testnet, and regtest must all be unique vs Bitcoin.
2. What is being audited
- Static. Every
pchMessageStart[*] = 0x..;block insrc/kernel/chainparams.cppis parsed and checked against the Bitcoin magics table. - Static. The DNS seed list contains zero forbidden hosts
(
seed.bitcoin.sipa.be,dnsseed.bluematt.me, etc.). - Static. Mainnet's
CMainParamsbody explicitly callsvFixedSeeds.clear()andvSeeds.clear()— preventing accidentally inheriting Bitcoin's seed lists. - Functional. A live regtest node must drop / ignore a connection that opens with the Bitcoin mainnet magic, and accept one that opens with the b3chain regtest magic.
3. Why it matters
Two kinds of disasters this prevents:
- Cross-chain peering. If b3chain accepted Bitcoin magic, the first b3chain mainnet node we deploy would be flooded with connections from honest Bitcoin nodes. They would then receive unparseable b3chain data, log errors, and (depending on the version) disconnect us — or, worse, accept our headers.
- Address collisions. If users could mistake b3chain
addresses for Bitcoin addresses, they would lose money. Distinct
bech32 HRPs (
b3,tb3,b3rt) and base58 prefixes prevent that. See also W-1.
4. How to run
cd b3chain python3 contrib/testing/audit/audit-network-isolation.py
5. Expected output
[N-1] Network isolation (magic, DNS seeds) ======================================================================== PASS [N-1] found 4 explicit magic-start declarations PASS [N-1] magic b3c0010d != Bitcoin mainnet magic PASS [N-1] magic b3c0010d not a Bitcoin mainnet/regtest/signet magic PASS [N-1] magic b3c1020e != Bitcoin mainnet magic PASS [N-1] magic b3c1020e not a Bitcoin mainnet/regtest/signet magic PASS [N-1] magic 1c163f28 != Bitcoin mainnet magic PASS [N-1] magic 1c163f28 not a Bitcoin mainnet/regtest/signet magic PASS [N-1] magic b3c2030f != Bitcoin mainnet magic PASS [N-1] magic b3c2030f not a Bitcoin mainnet/regtest/signet magic PASS [N-1] no forbidden Bitcoin DNS seeds present PASS [N-1] mainnet calls vFixedSeeds.clear() PASS [N-1] mainnet calls vSeeds.clear() Spawning regtest node and probing P2P port with Bitcoin magic... PASS [N-1] node disconnects/ignores Bitcoin mainnet magic on P2P port PASS [N-1] sanity: correct b3chain regtest magic gets a reply PASS [N-1] getnetworkinfo responds with networkactive flag ------------------------------------------------------------------------ 15/15 checks passed in 3.2s AUDIT RESULT: PASS [N-1]
6. Source files
- contrib/testing/audit/audit-network-isolation.py
- src/kernel/chainparams.cpp — magic bytes, DNS seed lists
The problem in one sentence
If a B3Chain node accidentally peers with a Bitcoin node, the Bitcoin node's headers can poison the B3Chain node's view of the chain — even though the chains will never converge — wasting bandwidth and confusing operators.
The theory
Two pieces of data make a node a B3Chain node rather than a Bitcoin node:
- Magic bytes — the four-byte network identifier sent at the start
of every P2P message. Bitcoin mainnet uses f9beb4d9. Anything else, B3Chain ignores.
- DNS seeds — the bootstrap addresses a node uses on first start.
Bitcoin's seeds (e.g. seed.bitcoin.sipa.be) return Bitcoin nodes; B3Chain's seeds (when set) must return B3Chain nodes only.
Both are constants in src/kernel/chainparams.cpp. A copy-paste error that left a Bitcoin seed in the B3Chain mainnet vSeeds list would silently funnel new nodes into trying to talk to the Bitcoin network on every start.
Hands-on demo
python3 contrib/testing/audit/audit-network-isolation.py
The script:
- Spawns a regtest node, sends a Bitcoin mainnet
versionmessage
with magic f9beb4d9. Expects the connection to be dropped without acknowledgment.
- Reads
chainparams.cppand verifies that the mainnetvSeeds
vector contains zero hostnames matching the Bitcoin seed pattern (bitcoin, bluematt, dashjr, etc.) and zero entries from Bitcoin's chainparams.cpp directly.
Exercise
Edit src/kernel/chainparams.cpp, in the MAIN chain branch, add a line:
vSeeds.emplace_back("seed.bitcoin.sipa.be");
Rebuild and re-run the audit. Expected output:
FAIL [N-1] mainnet vSeeds contains 'seed.bitcoin.sipa.be' (Bitcoin seed) AUDIT RESULT: FAIL [N-1]
Why magic bytes alone don't save you
Even if your node correctly rejects Bitcoin's magic bytes at the wire protocol, you still want it to never try to connect to a Bitcoin node, because:
- Many port scanners flag the connection attempt and your IP gets on
block lists.
- The Bitcoin node may waste CPU on the handshake before disconnecting.
- Your operator sees noise in their logs and starts to mistrust the
software.
So the audit checks both layers.
Further reading
- Bitcoin Core network constants:
src/kernel/chainparams.cpp
- BIP-37 connection-bloom filter (early example of cross-chain
protocol-level confusion concerns): github.com/bitcoin/bips/blob/master/bip-0037.mediawiki
- Tor exit-node policy notes — same principle: networks should refuse
to forward traffic that doesn't belong to them.