fix(pairing): widen pairing relay set so signer-chosen relays are covered
Amber picks whichever relay it likes from the nostrconnect:// URI and some relays drop ephemeral kind-24133 traffic, so pairing could appear successful on the signer while nothing reached us. The pairing set is now the user's relays UNION a curated fallback of well-known relays; loopback-only sets (e2e harness) skip widening to keep tests isolated.
This commit is contained in:
parent
937fcc67cb
commit
f59c2b1b45
3 changed files with 45 additions and 7 deletions
|
|
@ -14,6 +14,21 @@ pub fn default_relays() -> Vec<RelayConfig> {
|
|||
]
|
||||
}
|
||||
|
||||
/// Extra relays always included in the NIP-46 *pairing* set (on top of the
|
||||
/// user's enabled relays). Signer apps (Amber et al.) are free to pick any
|
||||
/// relay listed in the nostrconnect:// URI, and relays differ wildly in
|
||||
/// reliability for ephemeral kind-24133 traffic; listening on a few extra
|
||||
/// well-known relays costs nothing and makes pairing robust whichever one
|
||||
/// the signer happens to choose.
|
||||
pub fn pairing_relays() -> Vec<String> {
|
||||
vec![
|
||||
"wss://relay.damus.io".to_string(),
|
||||
"wss://relay.primal.net".to_string(),
|
||||
"wss://purplepag.es".to_string(),
|
||||
"wss://relay.nostr.band".to_string(),
|
||||
]
|
||||
}
|
||||
|
||||
/// Validate that a string is a well-formed relay URL.
|
||||
pub fn validate_url(raw: &str) -> Result<(), AppError> {
|
||||
let cleaned = raw.trim().trim_end_matches('/');
|
||||
|
|
|
|||
|
|
@ -430,8 +430,13 @@ impl Nip46ClientSigner {
|
|||
}
|
||||
}
|
||||
|
||||
// Pair over the user's enabled relays; fall back to the app defaults
|
||||
// when none are configured.
|
||||
// Pair over the user's enabled relays UNION a curated fallback set:
|
||||
// signer apps (Amber et al.) pick whichever relay they like from the
|
||||
// nostrconnect:// URI, and relays vary wildly in reliability for
|
||||
// ephemeral kind-24133 traffic. Listening on a few extra well-known
|
||||
// relays costs nothing and covers whichever one the signer chooses.
|
||||
// Loopback-only relay sets (the e2e harness) skip widening so test
|
||||
// pairing traffic never touches the real network.
|
||||
let relays: Vec<RelayUrl> = {
|
||||
let app = self.app.lock().await;
|
||||
let mut urls: Vec<String> = app
|
||||
|
|
@ -441,11 +446,17 @@ impl Nip46ClientSigner {
|
|||
.filter(|r| r.enabled)
|
||||
.map(|r| r.url.clone())
|
||||
.collect();
|
||||
if urls.is_empty() {
|
||||
urls = crate::relays::default_relays()
|
||||
.into_iter()
|
||||
.map(|r| r.url)
|
||||
.collect();
|
||||
let loopback_only = !urls.is_empty()
|
||||
&& urls.iter().all(|u| {
|
||||
let u = u.to_lowercase();
|
||||
u.contains("127.0.0.1") || u.contains("localhost") || u.contains("[::1]")
|
||||
});
|
||||
if !loopback_only {
|
||||
for extra in crate::relays::pairing_relays() {
|
||||
if !urls.contains(&extra) {
|
||||
urls.push(extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
urls
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,11 @@ async fn start_relay() -> String {
|
|||
])
|
||||
.to_string();
|
||||
if let Some(sess) = s.sessions.get(session_idx) {
|
||||
eprintln!(
|
||||
"[relay] replay {} to new sub {}",
|
||||
&ev.id.to_hex()[..16],
|
||||
sub_id
|
||||
);
|
||||
let _ = sess.tx.send(out);
|
||||
}
|
||||
break;
|
||||
|
|
@ -526,8 +531,13 @@ async fn run_fake_scanner(
|
|||
continue;
|
||||
}
|
||||
let Some(plain) = nip44_dec(&conversation, &ev.content) else {
|
||||
eprintln!(
|
||||
"[scanner] event from {} not decryptable",
|
||||
&ev.pubkey.to_hex()[..16]
|
||||
);
|
||||
continue;
|
||||
};
|
||||
eprintln!("[scanner] decrypted: {}", &plain[..plain.len().min(120)]);
|
||||
let Ok(req) = serde_json::from_str::<Value>(&plain) else {
|
||||
continue;
|
||||
};
|
||||
|
|
@ -641,6 +651,8 @@ async fn nip46_qr_pairing_handshake_and_sign() {
|
|||
else {
|
||||
panic!("pairing URI must be the client variant");
|
||||
};
|
||||
// The e2e relay set is loopback-only, and loopback sets skip the curated
|
||||
// pairing-relay widening, so the token carries exactly our relay.
|
||||
assert_eq!(relays.len(), 1);
|
||||
assert!(!secret.is_empty());
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue