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.
|
||||
/// - wss://relay.nostr.band currently hangs the WebSocket handshake; it is
|
||||
/// also pay-to-read. Dropped from the pairing set.
|
||||
/// - wss://nos.lol and wss://relay.snort.social accept ephemeral 24133 and
|
||||
/// serve it live (snort does not persist ephemeral kinds, which is fine —
|
||||
/// pairing only needs the live push).
|
||||
/// - wss://nos.lol and wss://relay.primal.net are the two relays with
|
||||
/// PROVEN bidirectional ephemeral-24133 traffic in the live Sep 23 scans
|
||||
/// (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> {
|
||||
vec![
|
||||
"wss://relay.damus.io".to_string(),
|
||||
"wss://relay.primal.net".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.
|
||||
let identity = self
|
||||
.send_rpc("get_public_key", vec![], REQUEST_TIMEOUT, false)
|
||||
.await
|
||||
.map_err(|e| format!("The signer would not reveal its public key: {e}"))?;
|
||||
//
|
||||
// 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)
|
||||
.await
|
||||
{
|
||||
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())
|
||||
.map_err(|e| format!("The signer returned an unreadable public key: {e}"))?;
|
||||
let identity_npub = identity
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue