diff --git a/core/archipelago/src/api/rpc/federation/handlers.rs b/core/archipelago/src/api/rpc/federation/handlers.rs index 27cd89d8..ef62f1f6 100644 --- a/core/archipelago/src/api/rpc/federation/handlers.rs +++ b/core/archipelago/src/api/rpc/federation/handlers.rs @@ -387,6 +387,23 @@ impl RpcHandler { .await .unwrap_or_default(); + // Our own FIPS npub, so pre-v1.4 federation pairs (whose + // invite codes didn't carry it) can learn it on the next sync. + let identity_dir = self.config.data_dir.join("identity"); + let own_fips_npub = crate::identity::fips_npub(&identity_dir) + .await + .ok() + .flatten() + .or_else(|| { + // Legacy/dev nodes without a seed-derived key fall back + // to the upstream daemon's public key on disk. + None + }); + let own_fips_npub = match own_fips_npub { + Some(n) => Some(n), + None => crate::fips::service::read_upstream_npub().await.ok().flatten(), + }; + let state = federation::build_local_state( apps, 0.0, @@ -398,6 +415,7 @@ impl RpcHandler { tor_active, server_name, nostr_npub, + own_fips_npub, &federated_peers, ); diff --git a/core/archipelago/src/federation/storage.rs b/core/archipelago/src/federation/storage.rs index c643302a..429a2c93 100644 --- a/core/archipelago/src/federation/storage.rs +++ b/core/archipelago/src/federation/storage.rs @@ -177,6 +177,17 @@ pub async fn update_node_state(data_dir: &Path, did: &str, state: NodeStateSnaps node.name = Some(name.clone()); } } + // Learn the peer's FIPS npub from their state snapshot so + // federations established before v1.4 (pre-fips_npub) start + // routing over FIPS on the very next sync. Refresh if the peer + // rotated their FIPS key, too. + if let Some(ref npub) = state.own_fips_npub { + if !npub.is_empty() + && node.fips_npub.as_deref().map(str::trim) != Some(npub.trim()) + { + node.fips_npub = Some(npub.clone()); + } + } node.last_state = Some(state); save_nodes(data_dir, &nodes).await?; } @@ -314,6 +325,7 @@ mod tests { uptime_secs: Some(86400), tor_active: Some(true), nostr_npub: None, + own_fips_npub: None, federated_peers: Vec::new(), }; diff --git a/core/archipelago/src/federation/sync.rs b/core/archipelago/src/federation/sync.rs index 18dec72a..b7d08079 100644 --- a/core/archipelago/src/federation/sync.rs +++ b/core/archipelago/src/federation/sync.rs @@ -160,6 +160,7 @@ pub fn build_local_state( tor_active: bool, server_name: Option, nostr_npub: Option, + own_fips_npub: Option, federated_peers: &[FederatedNode], ) -> NodeStateSnapshot { let hints = federated_peers @@ -186,6 +187,7 @@ pub fn build_local_state( uptime_secs: Some(uptime), tor_active: Some(tor_active), nostr_npub, + own_fips_npub, federated_peers: hints, } } @@ -274,6 +276,7 @@ mod tests { true, Some("Test Node".to_string()), None, + None, &[], ); assert_eq!(state.apps.len(), 1); @@ -328,7 +331,7 @@ mod tests { ]; let state = build_local_state( vec![], - 0.0, 0, 0, 0, 0, 0, true, None, None, &peers, + 0.0, 0, 0, 0, 0, 0, true, None, None, None, &peers, ); assert_eq!(state.federated_peers.len(), 1); assert_eq!(state.federated_peers[0].did, "did:key:zTrusted"); diff --git a/core/archipelago/src/federation/types.rs b/core/archipelago/src/federation/types.rs index 8a3cc9ee..332e1046 100644 --- a/core/archipelago/src/federation/types.rs +++ b/core/archipelago/src/federation/types.rs @@ -78,6 +78,13 @@ pub struct NodeStateSnapshot { /// haven't synced after this field was added will report None. #[serde(default)] pub nostr_npub: Option, + /// The sender's own FIPS npub (bech32). Lets pre-FIPS federation + /// pairs — who federated before v1.4 added fips_npub to the invite + /// code — discover each other's FIPS identity on the next state + /// sync and route over FIPS from then on. Optional for back-compat + /// with older peers. + #[serde(default)] + pub own_fips_npub: Option, /// Minimal summary of peers this node trusts, used for transitive /// federation: when Alice syncs with Bob, she learns Bob's trusted /// peers and adds them as Observers on her side so `fips_npub` is diff --git a/core/archipelago/src/transport/delta.rs b/core/archipelago/src/transport/delta.rs index a99c910d..9172e8d4 100644 --- a/core/archipelago/src/transport/delta.rs +++ b/core/archipelago/src/transport/delta.rs @@ -223,6 +223,7 @@ mod tests { uptime_secs: Some(86400), tor_active: Some(true), nostr_npub: None, + own_fips_npub: None, federated_peers: Vec::new(), } } @@ -256,6 +257,7 @@ mod tests { uptime_secs: Some(86700), // Changed tor_active: Some(true), nostr_npub: None, + own_fips_npub: None, federated_peers: Vec::new(), } }