Add capability bits to announce TLV (#1375)

Announces now carry an optional capabilities TLV (0x05): a little-endian
bitfield with named bits for upcoming features (prekeys, wifiBulk,
gateway, groups, board, vouch, meshDiagnostics). Old clients skip the
unknown TLV; peers without it decode as nil so features can distinguish
"legacy peer" from "advertises nothing".

PeerCapabilities lives in BitFoundation with a minimal-length encoding
that preserves unknown bits for forward compatibility. Peer capabilities
are stored in the BLE peer registry on verified announce and exposed via
BLEService.peerCapabilities(_:). The local advertisement set is empty
until each feature ships its bit.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jack
2026-07-07 14:07:52 +02:00
committed by GitHub
co-authored by jack Claude Fable 5
parent c2a5668569
commit 5fdc15d5af
7 changed files with 182 additions and 5 deletions
+9 -2
View File
@@ -9,6 +9,7 @@ struct BLEPeerInfo: Equatable {
var signingPublicKey: Data?
var isVerifiedNickname: Bool
var lastSeen: Date
var capabilities: PeerCapabilities = []
}
struct BLEPeerAnnounceUpdate: Equatable {
@@ -107,6 +108,10 @@ struct BLEPeerRegistry {
peers[peerID]?.noisePublicKey?.sha256Fingerprint()
}
func capabilities(for peerID: PeerID) -> PeerCapabilities {
peers[peerID.toShort()]?.capabilities ?? []
}
func displayNicknames(selfNickname: String) -> [PeerID: String] {
let connected = peers.filter { $0.value.isConnected }
let tuples = connected.map { ($0.key, $0.value.nickname, true) }
@@ -157,7 +162,8 @@ struct BLEPeerRegistry {
noisePublicKey: Data,
signingPublicKey: Data?,
isConnected: Bool,
now: Date
now: Date,
capabilities: PeerCapabilities = []
) -> BLEPeerAnnounceUpdate {
let existing = peers[peerID]
let update = BLEPeerAnnounceUpdate(
@@ -173,7 +179,8 @@ struct BLEPeerRegistry {
noisePublicKey: noisePublicKey,
signingPublicKey: signingPublicKey,
isVerifiedNickname: true,
lastSeen: now
lastSeen: now,
capabilities: capabilities
)
return update
+10 -2
View File
@@ -619,6 +619,12 @@ final class BLEService: NSObject {
}
}
/// Capabilities the peer advertised in its last verified announce.
/// Empty for peers that predate the capabilities TLV.
func peerCapabilities(_ peerID: PeerID) -> PeerCapabilities {
collectionsQueue.sync { peerRegistry.capabilities(for: peerID) }
}
func getPeerNicknames() -> [PeerID: String] {
return collectionsQueue.sync {
peerRegistry.displayNicknames(selfNickname: myNickname)
@@ -1261,7 +1267,8 @@ final class BLEService: NSObject {
nickname: myNickname,
noisePublicKey: noisePub,
signingPublicKey: signingPub,
directNeighbors: connectedPeerIDs
directNeighbors: connectedPeerIDs,
capabilities: PeerCapabilities.localSupported
)
guard let payload = announcement.encode() else {
@@ -3315,7 +3322,8 @@ extension BLEService {
noisePublicKey: announcement.noisePublicKey,
signingPublicKey: announcement.signingPublicKey,
isConnected: isConnected,
now: now
now: now,
capabilities: announcement.capabilities ?? []
) ?? BLEPeerAnnounceUpdate(isNewPeer: false, wasDisconnected: false, previousNickname: nil)
},
shouldEmitReconnectLog: { [weak self] peerID, now in