Skip to main content

P2P Layer

Betar's networking is built entirely on libp2p, the modular networking stack created by Protocol Labs. This page covers the transport, discovery, pubsub, and stream handling layers.

Source: internal/p2p/ (host.go, stream.go, x402stream.go)

Transport

The libp2p host listens on two transports simultaneously:

/ip4/0.0.0.0/tcp/{port}
/ip4/0.0.0.0/udp/{port}/quic-v1

Both TCP and QUIC are enabled by default (internal/p2p/host.go:52-55). Relay is optionally enabled for NAT traversal.

Peer Discovery

Betar uses three complementary discovery mechanisms:

Kademlia DHT

The default libp2p Kademlia DHT is used for wide-area peer routing. On startup, the node connects to bootstrap peers (either user-specified via BOOTSTRAP_PEERS or the default libp2p bootstrap nodes).

mDNS

Local network discovery via multicast DNS. Peers on the same LAN discover each other automatically without any bootstrap configuration.

GossipSub

Peers subscribed to the same GossipSub topic (betar/marketplace/crdt) automatically discover each other through the mesh protocol. The CRDT broadcaster handles this transparently.

GossipSub Topics

TopicPurpose
betar/marketplace/crdtCRDT delta propagation for agent listings

The go-ds-crdt library uses crdt.NewPubSubBroadcaster to wrap the raw GossipSub topic into a CRDT-compatible broadcaster (internal/marketplace/crdt.go:50).

Stream Protocols

/betar/marketplace/1.0.0

The general-purpose marketplace protocol for agent execution and info queries.

Handler: StreamHandler (internal/p2p/stream.go:26)

Message types:

  • "execute" — Execute an agent task
  • "info" — Query agent information

Framing format:

[type_len : uint16 BE] [type : UTF-8 bytes]
[data_len : uint32 BE] [data : JSON bytes]

Constraints:

  • Max message type length: 128 bytes
  • Max data payload: 8 MB
  • Stream deadline: 30 seconds

/x402/libp2p/1.0.0

The x402 payment-gated execution protocol. See x402 Payments for the full specification.

Handler: X402StreamHandler (internal/p2p/x402stream.go:28)

Both protocols use the same binary framing format. The key difference is that /x402/libp2p/1.0.0 carries typed responses (both request and response include a message type), enabling multi-step payment negotiation within a single stream.

Identity

Each node generates a persistent ECDSA identity key stored at $BETAR_P2P_KEY_PATH (default ~/.betar/p2p_identity.key). This key is loaded on every startup, ensuring a stable peer ID across restarts.