# How the BitChat Favorites System Influences Courier Selection

> Discover how the BitChat favorites system prioritizes trusted couriers for message routing, enhancing security and efficiency in decentralized communication. Learn more about this key feature.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: deep-dive
- Published: 2026-08-08

---

**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`](https://github.com/permissionlesstech/bitchat/blob/main/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:

```swift
// 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`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/FavoritesPersistenceService.swift), the service determines mutual favorite status by verifying a reciprocal relationship:

```swift
// 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`](https://github.com/permissionlesstech/bitchat/blob/main/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:

```swift
// 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`](https://github.com/permissionlesstech/bitchat/blob/main/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:

```swift
// 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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/MessageRouter.swift), specifically within the `eligibleCouriers` method (lines 46-58). Supporting logic for favorite relationship management exists in [`bitchat/Services/FavoritesPersistenceService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/FavoritesPersistenceService.swift), particularly the `isMutualFavorite` computed property and `getFavoriteStatus(forPeerID:)` method.