fix(pairing): retry identity RPC; pairing set to proven relays only
The 09:44 live scan proved the failure with the new accepted_by trace: our get_public_key was published and accepted, but Amber's own connect echo was created one second LATER — Amber's subscription to our client key opens milliseconds after we publish, so the first identity request is already in the relays' past when its listener starts (relays never replay history to a fresh subscription). The signer-side race is structural and unfixable from our subscription ordering; adopt_identity now retries get_public_key up to 4x with 3/8/15s backoff (non-timeout errors still fail fast), so a later attempt lands while the signer is listening. pairing_relays() narrowed to primal + nos.lol — the only two relays with proven bidirectional ephemeral-24133 traffic in today's scans. damus.io 503'd reads and silently dropped events; snort persists nothing; user settings switched to the two proven relays as well.
This commit is contained in:
parent
be51f67797
commit
2bc6321d58
2 changed files with 44 additions and 9 deletions
|
|
@ -27,15 +27,18 @@ pub fn default_relays() -> Vec<RelayConfig> {
|
||||||
/// connect event is thrown away, so it must never be in the pairing URI.
|
/// connect event is thrown away, so it must never be in the pairing URI.
|
||||||
/// - wss://relay.nostr.band currently hangs the WebSocket handshake; it is
|
/// - wss://relay.nostr.band currently hangs the WebSocket handshake; it is
|
||||||
/// also pay-to-read. Dropped from the pairing set.
|
/// also pay-to-read. Dropped from the pairing set.
|
||||||
/// - wss://nos.lol and wss://relay.snort.social accept ephemeral 24133 and
|
/// - wss://nos.lol and wss://relay.primal.net are the two relays with
|
||||||
/// serve it live (snort does not persist ephemeral kinds, which is fine —
|
/// PROVEN bidirectional ephemeral-24133 traffic in the live Sep 23 scans
|
||||||
/// pairing only needs the live push).
|
/// (both stored Amber's connect reply AND our identity RPC).
|
||||||
|
/// - wss://relay.damus.io returned HTTP 503 to reads and answered connects
|
||||||
|
/// inconsistently during the same scans; while flapping it splits the
|
||||||
|
/// conversation across relays the signer never reads.
|
||||||
|
/// - wss://relay.snort.social accepts ephemeral 24133 publishes but does
|
||||||
|
/// not persist them; with damus out it adds no shared ground.
|
||||||
pub fn pairing_relays() -> Vec<String> {
|
pub fn pairing_relays() -> Vec<String> {
|
||||||
vec![
|
vec![
|
||||||
"wss://relay.damus.io".to_string(),
|
|
||||||
"wss://relay.primal.net".to_string(),
|
"wss://relay.primal.net".to_string(),
|
||||||
"wss://nos.lol".to_string(),
|
"wss://nos.lol".to_string(),
|
||||||
"wss://relay.snort.social".to_string(),
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1714,10 +1714,42 @@ impl Nip46ClientSigner {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Learn the REAL signing identity from the signer itself.
|
// Learn the REAL signing identity from the signer itself.
|
||||||
let identity = self
|
//
|
||||||
|
// RETRIED with backoff on timeout. The live Sep 23 scans proved a
|
||||||
|
// structural race on the SIGNER side: our first `get_public_key`
|
||||||
|
// publishes the instant the connect echo is verified, but Amber's
|
||||||
|
// own subscription to our client key opens milliseconds later, so
|
||||||
|
// the request is already in the relays' past when its listener
|
||||||
|
// starts — relays never replay history to a fresh subscription and
|
||||||
|
// the answer never comes. A retry lands while the signer is
|
||||||
|
// listening. Non-timeout failures (refusal, bad payload) still fail
|
||||||
|
// fast.
|
||||||
|
let mut attempt = 0u32;
|
||||||
|
let identity = loop {
|
||||||
|
attempt += 1;
|
||||||
|
match self
|
||||||
.send_rpc("get_public_key", vec![], REQUEST_TIMEOUT, false)
|
.send_rpc("get_public_key", vec![], REQUEST_TIMEOUT, false)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("The signer would not reveal its public key: {e}"))?;
|
{
|
||||||
|
Ok(identity) => break identity,
|
||||||
|
Err(e) => {
|
||||||
|
if !matches!(e, SigningError::Timeout) || attempt >= 4 {
|
||||||
|
return Err(format!("The signer would not reveal its public key: {e}"));
|
||||||
|
}
|
||||||
|
if live_relays(&connection.relays) {
|
||||||
|
pairing_trace(&format!(
|
||||||
|
"identity attempt {attempt} timed out; retrying get_public_key"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
tokio::time::sleep(Duration::from_secs(match attempt {
|
||||||
|
1 => 3,
|
||||||
|
2 => 8,
|
||||||
|
_ => 15,
|
||||||
|
}))
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
let identity = PublicKey::from_hex(identity.trim())
|
let identity = PublicKey::from_hex(identity.trim())
|
||||||
.map_err(|e| format!("The signer returned an unreadable public key: {e}"))?;
|
.map_err(|e| format!("The signer returned an unreadable public key: {e}"))?;
|
||||||
let identity_npub = identity
|
let identity_npub = identity
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue