Skip to content

Commit bb139de

Browse files
JSKittyclaude
andcommitted
perf(concord): Volley Sync — boot paint for every community in seconds, not minutes
Boot-to-messages on a 72-channel account: 95-112s of serial per-channel chains down to ~8s total, with the hottest channels painting in 1-4s. Chat planes are flat, linear, non-authoritative data — they paint from stored state immediately; the control plane verifies behind the paint and retro-hide revokes anything a ban invalidates. - Volley Sync (community/v2/volley.rs): every v2 channel's latest page in mass-batched multi-filter REQs on the shared warm client, most recently active channels fired first. One plane per channel at the MAX HELD epoch (the community row's epoch fields can lag a rotation); per-filter since = the chat's last held message. Per-relay-set pipelines gate on their own first live socket. Auth-gating relays refuse batches by protocol, so a bounded per-plane authed fallback covers exactly the channels whose live relays all gate (learned durably from NIP-42 challenges via the auth_gate KV), plus a recency confirmation for active channels when a flaky open relay may hold holes. Ingest reuses the backfill pipeline (v2_ingest_chat_page). - v1 hot lane: the 12 most recently active v1 channels run their full probe-cheapened chain 12-wide, ahead of the sweep; the sweep skips the lane's successes. - Evidence doctrine enforced in transport: the until→Full floor is gone — chat reads ride their declared tier. Every completeness- sensitive conclusion requests Full at its own call site (v1 history-start latch, join-verify genesis anchor, refound compaction, guestbook folds); tolerant control reads declare Quorum explicitly. - Boot order: chat paint first (volley ∥ control probe, then hot lane), consensus follows and the verification sweep behind it — boot exists to deliver message data. A reconnect landing mid-sweep queues one follow-up run instead of being dropped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 3638ed2 commit bb139de

8 files changed

Lines changed: 682 additions & 53 deletions

File tree

crates/vector-core/src/community/send.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,11 @@ pub async fn fetch_channel_page<T: Transport + ?Sized>(
215215
// z_tags, above), and back-pagination passes `None` here.
216216
since,
217217
limit: Some(limit),
218-
// Latest pages are positive-data reads. Older pages (`until` set) are
219-
// force-promoted to Full by the transport — the history-start latch
220-
// needs the completest union the reachable relays allow.
221-
evidence: Evidence::Fast,
218+
// Latest pages are positive-data reads and ride Fast. Older pages
219+
// request Full HERE (no transport floor does it anymore): this is the
220+
// one fetch whose short result latches "history starts here", and an
221+
// absence verdict trusts only the completest reachable union.
222+
evidence: if until.is_some() { Evidence::Full } else { Evidence::Fast },
222223
..Default::default()
223224
};
224225
transport.fetch(&query, &community.relays).await

crates/vector-core/src/community/transport.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -411,15 +411,13 @@ fn breaker_record_at(generation: u64, url: &str, success: bool, full_budget: boo
411411
})
412412
}
413413

414-
/// `until` forces Full — a back-page verdict (the history-start latch) trusts
415-
/// "nothing older than the cursor" only against the completest union the
416-
/// reachable relay set allows. A floor in the transport, not trust in callers.
414+
/// Callers own their evidence tier. The chat plane is flat, linear data — an
415+
/// event exists or it doesn't — so no transport floor promotes its reads.
416+
/// Every site that draws a completeness-sensitive conclusion from an `until`
417+
/// walk (the v1 history-start latch, join-verify's genesis anchor, refound
418+
/// compaction, guestbook folds) REQUESTS Full explicitly at its own Query.
417419
fn effective_evidence(query: &Query) -> Evidence {
418-
if query.until.is_some() {
419-
Evidence::Full
420-
} else {
421-
query.evidence
422-
}
420+
query.evidence
423421
}
424422

425423
// ── Plane connection pool (fetch_plane) ─────────────────────────────────────
@@ -783,7 +781,7 @@ impl LiveTransport {
783781
/// the pool doesn't hold yet is added idempotently (mirrors what the realtime subscription does), then
784782
/// `connect()` kicks it without disturbing the already-connected majority. Never shut this client down:
785783
/// it is shared. Errors only if there is no client yet or every relay url was invalid.
786-
async fn warm_client(relays: &[String], connect_timeout: std::time::Duration) -> Result<Client, String> {
784+
pub(crate) async fn warm_client(relays: &[String], connect_timeout: std::time::Duration) -> Result<Client, String> {
787785
if relays.is_empty() {
788786
return Err("community has no relays configured".to_string());
789787
}
@@ -1915,12 +1913,12 @@ mod tests {
19151913
// ── The evidence floor ───────────────────────────────────────────────────
19161914

19171915
#[test]
1918-
fn until_forces_full_evidence_and_default_is_quorum() {
1916+
fn declared_evidence_stands_and_default_is_quorum() {
19191917
assert_eq!(Query::default().evidence, Evidence::Quorum, "unclassified sites get Quorum");
19201918
assert_eq!(
19211919
effective_evidence(&Query { until: Some(1), evidence: Evidence::Fast, ..Default::default() }),
1922-
Evidence::Full,
1923-
"a back-page can never ride Fastthe history-start latch needs the full union"
1920+
Evidence::Fast,
1921+
"chat pagination rides its declared tierabsence verdicts request Full themselves"
19241922
);
19251923
assert_eq!(
19261924
effective_evidence(&Query { evidence: Evidence::Fast, ..Default::default() }),

crates/vector-core/src/community/v2/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub mod inbound;
2525
pub mod invite;
2626
pub mod list;
2727
pub mod realtime;
28+
pub mod volley;
2829
pub mod rekey;
2930
pub mod roles;
3031
pub mod service;

crates/vector-core/src/community/v2/service.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ pub async fn fetch_channel<T: Transport + ?Sized>(
535535
channel_id: &ChannelId,
536536
limit: usize,
537537
) -> Result<Vec<FetchedEvent>, String> {
538-
fetch_channel_history(transport, community, channel_id, limit, 1, |_| true).await
538+
fetch_channel_history(transport, community, channel_id, limit, 1, None, crate::community::transport::Evidence::Quorum, |_| true).await
539539
}
540540

541541
/// Walk a channel's history newest-first (CORD-03 §3 "clients load a Channel
@@ -557,6 +557,8 @@ pub async fn fetch_channel_history<T: Transport + ?Sized>(
557557
channel_id: &ChannelId,
558558
page: usize,
559559
max_pages: usize,
560+
since: Option<u64>,
561+
evidence: crate::community::transport::Evidence,
560562
mut keep_paging: impl FnMut(&[FetchedEvent]) -> bool,
561563
) -> Result<Vec<FetchedEvent>, String> {
562564
// Guards the opportunistic scrub-key heals below — the fetch loop straddles
@@ -609,8 +611,10 @@ pub async fn fetch_channel_history<T: Transport + ?Sized>(
609611
let q = Query {
610612
kinds: vec![stream::KIND_WRAP],
611613
authors: vec![plane.pk_hex()],
614+
since,
612615
until,
613616
limit: Some(page),
617+
evidence,
614618
..Default::default()
615619
};
616620
if let Ok(evs) = transport.fetch_plane(plane.keys(), &q, &community.relays).await {
@@ -1049,11 +1053,15 @@ pub async fn community_is_public<T: Transport + ?Sized>(transport: &T, community
10491053
let mut oldest: Option<u64> = None;
10501054
let mut until: Option<u64> = None;
10511055
for page in 0..COMPACT_MAX_PAGES {
1056+
// Quorum, DECLARED (the until→Full transport floor is gone): these
1057+
// control reads tolerate a partial union — their fold semantics are
1058+
// fail-safe on gaps (seeded banlists, withheld roster cache).
10521059
let query = Query {
10531060
kinds: vec![stream::KIND_WRAP],
10541061
authors: vec![control.pk_hex()],
10551062
until,
10561063
limit: Some(FOLLOW_PAGE),
1064+
evidence: crate::community::transport::Evidence::Quorum,
10571065
..Default::default()
10581066
};
10591067
let Ok(wraps) = transport.fetch(&query, &community.relays).await else { return true };
@@ -1282,10 +1290,11 @@ async fn verify_owner_root_and_reconcile<T: Transport + ?Sized>(
12821290
// T's genesis onto a fake root to MITM another T-joiner — is closed only by
12831291
// binding the root into community_id (protocol, deferred).
12841292
//
1285-
// Seed `until` with a FAR-FUTURE constant (NOT now-based): `until.is_some()` takes
1286-
// the transport's AUTHORITATIVE drain-ALL-relays path (an open `until` returns only
1287-
// a fast relay's partial window and misses a genesis on a lagging relay — routine
1288-
// over Tor), while a constant beyond any real created_at clips NOTHING — so neither
1293+
// Seed `until` with a FAR-FUTURE constant (NOT now-based), and request
1294+
// Evidence::Full EXPLICITLY below: this walk draws an ABSENCE verdict (no
1295+
// owner-signed genesis ⇒ reject), which trusts only the completest union —
1296+
// an open partial window misses a genesis on a lagging relay (routine over
1297+
// Tor). A constant beyond any real created_at clips NOTHING — so neither
12891298
// a clock-skewed future-dated genesis nor a >1h-slow-clock joiner is excluded (a
12901299
// now-based bound could clip either). Break on an EMPTY page (a short page is a
12911300
// relay cap). A forged root walks to exhaustion and rejects; a flood/deep plane
@@ -1323,6 +1332,7 @@ async fn verify_owner_root_and_reconcile<T: Transport + ?Sized>(
13231332
authors: vec![control_pk.clone()],
13241333
until,
13251334
limit: Some(PAGE),
1335+
evidence: crate::community::transport::Evidence::Full,
13261336
..Default::default()
13271337
};
13281338
let wraps = transport.fetch(&query, &community.relays).await?;
@@ -1720,11 +1730,15 @@ pub async fn fetch_authority<T: Transport + ?Sized>(transport: &T, community: &C
17201730
// silently un-ban on withheld data.
17211731
let mut a = fold_authority(community, &[], &floors);
17221732
for _ in 0..FOLLOW_MAX_PAGES {
1733+
// Quorum, DECLARED (the until→Full transport floor is gone): these
1734+
// control reads tolerate a partial union — their fold semantics are
1735+
// fail-safe on gaps (seeded banlists, withheld roster cache).
17231736
let query = Query {
17241737
kinds: vec![stream::KIND_WRAP],
17251738
authors: vec![control.pk_hex()],
17261739
until,
17271740
limit: Some(FOLLOW_PAGE),
1741+
evidence: crate::community::transport::Evidence::Quorum,
17281742
..Default::default()
17291743
};
17301744
let Ok(wraps) = transport.fetch(&query, &community.relays).await else { break };
@@ -1785,7 +1799,9 @@ async fn fetch_guestbook_events<T: Transport + ?Sized>(
17851799
let mut until: Option<u64> = None;
17861800
let mut oldest: Option<u64> = None;
17871801
for _ in 0..GB_MAX_PAGES {
1788-
let query = Query { kinds: vec![stream::KIND_WRAP], authors: vec![gb_group.pk_hex()], until, limit: Some(GB_PAGE), ..Default::default() };
1802+
// Full: this set becomes the refound's recipient list — a member's
1803+
// Join visible only on a minority relay must not be severed.
1804+
let query = Query { kinds: vec![stream::KIND_WRAP], authors: vec![gb_group.pk_hex()], until, limit: Some(GB_PAGE), evidence: crate::community::transport::Evidence::Full, ..Default::default() };
17891805
let wraps = transport.fetch(&query, &community.relays).await?;
17901806
let mut fresh = 0usize;
17911807
for wrap in &wraps {
@@ -2155,11 +2171,15 @@ pub async fn refound_community<T: Transport + ?Sized>(transport: &T, community:
21552171
// coverage test, so stopping there could compact it away.
21562172
let mut truncated = false;
21572173
for page in 0..COMPACT_MAX_PAGES {
2174+
// Full: compaction re-wraps the head set it can SEE — a control
2175+
// edition (a ban head) reachable only on a minority relay must not be
2176+
// compacted away by a partial union.
21582177
let query = Query {
21592178
kinds: vec![stream::KIND_WRAP],
21602179
authors: vec![current_control.pk_hex()],
21612180
until,
21622181
limit: Some(FOLLOW_PAGE),
2182+
evidence: crate::community::transport::Evidence::Full,
21632183
..Default::default()
21642184
};
21652185
let wraps = transport.fetch(&query, &community.relays).await?;
@@ -2444,7 +2464,7 @@ pub async fn refound_at_birth<T: Transport + ?Sized>(
24442464
// Exhaustion, not coverage — see the sibling read in `refound_community`.
24452465
let mut truncated = false;
24462466
for page in 0..COMPACT_MAX_PAGES {
2447-
let query = Query { kinds: vec![stream::KIND_WRAP], authors: vec![current_control.pk_hex()], until, limit: Some(FOLLOW_PAGE), ..Default::default() };
2467+
let query = Query { kinds: vec![stream::KIND_WRAP], authors: vec![current_control.pk_hex()], until, limit: Some(FOLLOW_PAGE), evidence: crate::community::transport::Evidence::Full, ..Default::default() };
24482468
let wraps = transport.fetch(&query, &community.relays).await?;
24492469
let mut fresh = 0usize;
24502470
for w in &wraps {
@@ -3541,11 +3561,15 @@ pub async fn follow_control<T: Transport + ?Sized>(
35413561
// device's baseline is the one step that outlives the round.
35423562
let mut truncated = true;
35433563
for _ in 0..FOLLOW_MAX_PAGES {
3564+
// Quorum, DECLARED (the until→Full transport floor is gone): these
3565+
// control reads tolerate a partial union — their fold semantics are
3566+
// fail-safe on gaps (seeded banlists, withheld roster cache).
35443567
let query = Query {
35453568
kinds: vec![stream::KIND_WRAP],
35463569
authors: vec![control.pk_hex()],
35473570
until,
35483571
limit: Some(FOLLOW_PAGE),
3572+
evidence: crate::community::transport::Evidence::Quorum,
35493573
..Default::default()
35503574
};
35513575
let wraps = transport.fetch(&query, &community.relays).await?;
@@ -8139,7 +8163,7 @@ mod tests {
81398163
let general = community.channels[0].id;
81408164
flood_general(&relay, &community, &owner, 120, 10_000).await;
81418165

8142-
let all = fetch_channel_history(&relay, &community, &general, 50, 8, |_| true).await.unwrap();
8166+
let all = fetch_channel_history(&relay, &community, &general, 50, 8, None, crate::community::transport::Evidence::Quorum, |_| true).await.unwrap();
81438167
assert_eq!(all.len(), 120, "the walk pages the whole burst");
81448168
// Oldest→newest, no duplicates.
81458169
let contents: Vec<String> = all.iter().map(|f| f.event.opened().rumor.content.clone()).collect();
@@ -8164,7 +8188,7 @@ mod tests {
81648188

81658189
// The caller says "I hold everything" after the first page — no deeper fetch.
81668190
let mut pages = 0usize;
8167-
let got = fetch_channel_history(&relay, &community, &general, 50, 8, |_| {
8191+
let got = fetch_channel_history(&relay, &community, &general, 50, 8, None, crate::community::transport::Evidence::Quorum, |_| {
81688192
pages += 1;
81698193
false
81708194
})
@@ -8190,7 +8214,7 @@ mod tests {
81908214
let (wrap, _) = chat::seal_chat_rumor(&rumor, &group, &owner, Timestamp::from_secs(5_000), false).unwrap();
81918215
relay.publish(&wrap, &community.relays).await.unwrap();
81928216
}
8193-
let got = fetch_channel_history(&relay, &community, &general, 25, 8, |_| true).await.unwrap();
8217+
let got = fetch_channel_history(&relay, &community, &general, 25, 8, None, crate::community::transport::Evidence::Quorum, |_| true).await.unwrap();
81948218
assert!(got.len() >= 25, "at least the relay page is read");
81958219
assert!(got.len() <= 60, "sane bound");
81968220
// Termination is the assertion: reaching here means the wall didn't loop.

crates/vector-core/src/community/v2/streamauth.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,15 @@ pub fn ensure_responder(client: &Client) {
205205
if let ClientNotification::Message { relay_url, message } = n {
206206
if let nostr_sdk::prelude::RelayMessage::Auth { challenge } = *message {
207207
let challenge = challenge.into_owned();
208+
// Durable capability fact: this relay gates reads behind
209+
// NIP-42 (the boot volley routes fallbacks by it). Write
210+
// once — a challenge-spamming relay must not drive DB
211+
// writes at frame rate on the notification loop.
212+
let gate_key =
213+
format!("auth_gate:{}", relay_url.as_str().trim_end_matches('/'));
214+
if crate::db::get_sql_setting(gate_key.clone()).ok().flatten().is_none() {
215+
let _ = crate::db::set_sql_setting(gate_key, "1".to_string());
216+
}
208217
let fresh_connection = remember_challenge(&relay_url, &challenge);
209218
if !is_empty() {
210219
authenticate_streams(&client, &relay_url, &challenge).await;

0 commit comments

Comments
 (0)