Here's a story about how blockchain infrastructure eats you alive if you outsource the wrong thing.
Six months ago we shipped libp2p. It's the standard: Filecoin, IPFS, several L1s. Battery-included networking. TCP, QUIC, mesh routing, gossipsub, encrypted transport, peer identity. Sensible defaults everywhere. You install a package and get a working peer-to-peer stack.
For six months it kind of worked. Blocks moved. Votes propagated. Externals joined. And every couple of days, one of our baked validators would silently drop out of the mesh, sit in a corner, and refuse to sign anything until we bounced the service.
What was actually happening
libp2p, our specific problem child, uses a mesh gossip protocol called gossipsub. It maintains a low-latency overlay by pinging peers, evicting slow ones, and adding fresh ones. That mesh management runs on the same event loop as our consensus engine.
Under sustained load — say, a spike of vote broadcasts across 30 external validators — the consensus loop got busy. The libp2p keep-alive tasks starved. Peer connections timed out. The mesh pruned itself down to nothing. And once the mesh was empty, gossipsub couldn't rebuild it without external help. That help was us, restarting the service.
We spent about three weeks trying to fix this the polite way. Moved libp2p into a worker_thread. Tuned the connection manager. Bumped keep-alive intervals. Pinned peer scoring higher. Each fix made the median case better. None fixed the tail.
Then I read the libp2p issue tracker on @chainsafe/libp2p-gossipsub. There's a lot in there. Some of it is our fault. Some of it isn't. Most of it isn't going to be fixed on any timeline we can plan around.
The choice
We had two options.
The first was to invest another month in libp2p, add better observability, learn to live with periodic mesh reboots, and hope the ecosystem stabilised eventually. Every validator would carry a dependency that we couldn't fully reason about.
The second was to write our own.
The scary version of that second option would be "build a general-purpose peer-to-peer stack." Nobody should do that. The interesting version is "build the exact transport that Asentum's BFT consensus needs, and no more."
Our consensus fits in a small envelope. Four to sixteen baked validators talking to each other over persistent TCP. Everyone else talks HTTP to the baked. Vote frames are small. Proposal frames are ~50 KB tops. Nobody needs DHT discovery. Nobody needs relay hole-punching for the mainnet-scale operator population, because pull-mode already handles that.
That's a much smaller thing to build. About 700 lines of TypeScript.
What's actually in ANT
We call it ANT — Asentum Native Transport. packages/node/src/net/ant/.
- One persistent TCP socket per peer. Reconnect with backoff. That's it for transport.
- A framed length-prefixed protocol. Each frame carries a type byte and a payload. Vote, proposal, tx, ping. Five message types.
- Content-fingerprint dedup on inbound. Each peer keeps an LRU of frame hashes it's seen recently. If the same vote arrives twice — once from A, once from B — the second copy is dropped without re-verifying the Dilithium3 signature. Signature verification is the expensive part of consensus; dropping duplicates before verify makes the mesh cheap.
- Swarm snapshot exposed over
/ant/swarmfor observability. You can see who's connected, who's dropping frames, and who's dead in real time.
That's it. No mesh routing. No DHT. No handshake protocol beyond a Dilithium3-signed hello — a placeholder that will grow into a real PQC handshake before mainnet.
What we learned
Consensus infrastructure has different requirements than general-purpose peer-to-peer. Our validators are known ahead of time. Our peer count is small. Our latency budget is tight. Our message shapes are stable. Every one of those facts is a constraint that a general-purpose transport can't take advantage of.
libp2p's design has to work for the case where anyone can join, connections come and go, mesh topology drifts, and peers have wildly different bandwidth. That flexibility is expensive. When you don't need it, you're paying for something you'll never use, and worse, you're paying with your consensus loop's attention budget.
ANT has been in prod for a couple of weeks. Cross-DC mesh between four baked. Zero disconnects. Zero mesh-reboots. Zero silent failures.
The next step is turning the placeholder handshake into a real ML-DSA-signed one. Then we're ready for the mainnet reachability story, which is a different problem for a different post.
If you're using libp2p in production and it's working for you, great — you probably have better tooling around it than we ever built. If you're using libp2p in production and it's fighting you, consider whether you actually need what it offers, or whether you could describe your transport in 700 lines.
We described ours in 706.
