How the BitChat Favorites System Influences Courier Selection

BitChat treats mutual favorites as highest-tier couriers, preferring them over standard verified peers when routing messages through intermediate nodes.

BitChat, an open-source mesh messaging application from permissionlesstech/bitchat, uses a sophisticated favorites mechanism to establish trust hierarchies in peer-to-peer networks. When direct delivery fails, the BitChat favorites system determines which connected peers may act as trusted couriers for your encrypted messages, creating a user-controlled priority lane through the mesh.

The Courier Directory and Noise Key Resolution

At the heart of courier selection lies the CourierDirectory struct defined in bitchat/Services/MessageRouter.swift. This router component relies on two critical closures that interface directly with the favorites store.

First, the noiseKey closure resolves a peer’s static Noise protocol key. The implementation checks the peer object directly, then falls back to querying the favorites database:

// MessageRouter.swift (lines 15-24)
let noiseKey: (PeerID) -> Data? = { peerID in
    // First check active peer connections
    if let peer = meshTransport.connectedPeers.first(where: { $0.id == peerID }) {
        return peer.noisePublicKey
    }
    // Fallback to favorites store for offline but favored peers
    return FavoritesPersistenceService.shared.getFavoriteStatus(forPeerID: peerID)?.noisePublicKey
}

This design ensures that even if a favorite peer is temporarily offline, their cryptographic identity remains available for routing decisions.

Mutual Favorite Detection Logic

Trust is not granted unilaterally. In bitchat/Services/FavoritesPersistenceService.swift, the service determines mutual favorite status by verifying a reciprocal relationship:

// FavoritesPersistenceService.swift (lines 21-23)
var isMutualFavorite: Bool {
    return isFavorite && theyFavoritedUs
}

A peer only achieves mutual favorite status when both sides have explicitly marked each other as favorites. This bidirectional verification prevents asymmetric trust exploits where one user could force another to carry their traffic without consent.

Courier Eligibility and Selection

When the router assembles candidate couriers for a sealed message envelope, it builds an eligibleCouriers list subject to strict validation rules found in bitchat/Services/MessageRouter.swift (lines 46-54). Each candidate must satisfy three criteria:

  • Currently connected to the local mesh transport
  • Not the intended message recipient
  • Trusted according to the directory’s verification logic

The trust evaluation occurs through the isTrustedCourier closure:

// MessageRouter.swift (lines 25-27)
let isTrustedCourier: (Data) -> Bool = { noiseKey in
    FavoritesPersistenceService.shared.isMutualFavorite(noiseKey: noiseKey)
}

If the peer is a mutual favorite, the router accepts them immediately. Non-favorite peers must instead prove they are signature-verified mesh participants, representing a lower tier of trust.

Sorting Preferences

After filtering candidates, the router applies a deterministic sort to prioritize mutual favorites. As implemented in lines 56-58 of MessageRouter.swift, the sorting places mutual favorites at the head of the candidate list, ensuring they receive message envelopes first when courier slots are limited.

Dynamic Updates and Real-Time Adjustments

The BitChat favorites system responds immediately to social graph changes. The MessageRouter subscribes to .favoriteStatusChanged notifications (lines 56-69), triggering an outbox flush whenever users add or remove favorites. This reactive architecture ensures that:

  • Newly established mutual favorites instantly become eligible for pending messages
  • Removed favorites are excluded from future courier selection without requiring app restart
  • The routing layer always reflects the current trust state of the social graph

Implementation Example

To leverage the favorites system programmatically, you first establish a mutual favorite relationship, then observe the automatic courier preference:

// 1️⃣ Establish mutual favorite status
// (Typically triggered when both users "star" each other)
FavoritesPersistenceService.shared.addFavorite(
    peerNoisePublicKey: courierNoiseKey,
    peerNickname: "TrustedCourier"
)

// 2️⃣ Verify courier eligibility
let directory = CourierDirectory.favoritesBacked()
let isTrusted = directory.isTrustedCourier(courierNoiseKey)   // Returns true for mutual favorites

// 3️⃣ Route message with automatic favorite priority
let candidates = router.eligibleCouriers(
    on: meshTransport,
    recipientKey: recipientNoiseKey,
    excluding: [],               // No previously attempted couriers
    limit: MessageRouter.maxCouriersPerMessage
)
// Mutual favorites appear first in the candidates array

According to the BitChat source code in bitchat/Services/MessageRouter.swift, this pattern ensures that your messages physically travel through nodes you have explicitly endorsed, falling back to the general mesh population only when trusted couriers are unavailable.

Summary

  • Mutual favorites receive highest priority when the router selects intermediate couriers for message delivery
  • Bidirectional verification (isFavorite && theyFavoritedUs) prevents unilateral trust exploitation
  • Automatic key resolution allows offline favorites to remain eligible for courier selection via FavoritesPersistenceService.shared.getFavoriteStatus(forPeerID:)
  • Real-time updates via .favoriteStatusChanged notifications ensure the router always uses current trust relationships
  • Graceful degradation falls back to signature-verified mesh peers when mutual favorites are unavailable

Frequently Asked Questions

How does BitChat define a "mutual favorite"?

A mutual favorite exists when two peers have both marked each other as favorites in their respective FavoritesPersistenceService instances. The code explicitly checks isFavorite && theyFavoritedUs in bitchat/Services/FavoritesPersistenceService.swift, ensuring that courier trust requires reciprocal consent from both parties.

Can a user become a courier without being a mutual favorite?

Yes, but with lower priority. The isTrustedCourier closure in MessageRouter.swift accepts two categories of couriers: mutual favorites (always trusted) and signature-verified mesh peers. While non-favorite verified peers can carry messages, the router sorts them after mutual favorites in the candidate list.

What happens when I add a new favorite while messages are pending?

The MessageRouter subscribes to .favoriteStatusChanged notifications and automatically flushes the outbox when favorite relationships change. This means newly established mutual favorites immediately become eligible to carry any queued messages, without requiring manual intervention or app restart.

Where is the courier selection logic implemented in the BitChat codebase?

The primary courier selection algorithm resides in bitchat/Services/MessageRouter.swift, specifically within the eligibleCouriers method (lines 46-58). Supporting logic for favorite relationship management exists in bitchat/Services/FavoritesPersistenceService.swift, particularly the isMutualFavorite computed property and getFavoriteStatus(forPeerID:) method.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →