diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/swarm/bootstrap.rs | 1 | ||||
| -rw-r--r-- | src/swarm/roots.rs | 24 |
2 files changed, 22 insertions, 3 deletions
diff --git a/src/swarm/bootstrap.rs b/src/swarm/bootstrap.rs index 6d3a4ad..d2a593b 100644 --- a/src/swarm/bootstrap.rs +++ b/src/swarm/bootstrap.rs @@ -409,6 +409,7 @@ async fn resolve_seeds( debug!(seed = %seed, peer = %peer, "Resolved seed"); } remember_peer(state, &peer).await; + crate::swarm::roots::seed_found(state, &peer); if let Err(error) = send_hello_once(state, &peer).await { warn!(peer = %peer, error = %format!("{error:#}"), "Initial HELLO failed; will retry"); } diff --git a/src/swarm/roots.rs b/src/swarm/roots.rs index d12f089..930c190 100644 --- a/src/swarm/roots.rs +++ b/src/swarm/roots.rs @@ -11,8 +11,10 @@ //! * a joining node takes as its root only the one given (`--genesis-root`), or else the //! one its peers name, and none while they name different ones (`RootPin`); and none //! before each of its seeds named one, or `ROOT_WAIT` passed since the first did, so -//! the seed that answers first doesn't decide alone. One peer hands a joiner another -//! root only if it is all the joiner hears within the wait. +//! the seed that answers first doesn't decide alone. Seeds are the nodes proven at +//! the seeds' addresses (`seed_found`): a peer answering under identities of its own +//! neither ends the wait nor starts its clock, only disputes. One seed hands a joiner +//! another root only if it is all the joiner hears of its seeds within the wait. use std::collections::{HashMap, HashSet}; use std::time::Duration; @@ -35,6 +37,9 @@ pub(crate) const ROOT_WAIT: Duration = Duration::from_secs(10); pub(crate) struct Roots { /// Of the first epoch, as each peer named it. named: HashMap<String, ChangeHash>, + /// The nodes proven at the seeds' addresses (`seed_found`): only theirs count + /// toward the wait (`repin`). + seeds: HashSet<String>, /// Joining with an empty document: how many seeds it waits for, and until when once /// the first named a root. awaiting: Option<(usize, Option<tokio::time::Instant>)>, @@ -156,6 +161,14 @@ pub(crate) fn await_seeds(state: &AppState, seeds: usize) { repin(state); } +/// `node` is the one at a seed's address (`bootstrap::resolve_seeds`): its root counts +/// toward the wait for the seeds (`repin`). +pub(crate) fn seed_found(state: &AppState, node: &str) { + if state.roots.lock_or_recover().seeds.insert(node.to_owned()) { + repin(state); + } +} + /// Until when a joining node still waits for its seeds to name the swarm's root, if it /// waits on a clock (`await_seeds`): then `repin`. pub(crate) fn waiting_until(state: &AppState) -> Option<tokio::time::Instant> { @@ -172,7 +185,12 @@ pub(crate) fn repin(state: &AppState) { let now = tokio::time::Instant::now(); let pin = { let mut roots = state.roots.lock_or_recover(); - let named = roots.named.len(); + // Seeds only: others' roots dispute, but neither end the wait nor start it. + let named = roots + .named + .keys() + .filter(|peer| roots.seeds.contains(*peer)) + .count(); let awaiting = match &mut roots.awaiting { Some((seeds, until)) => { if until.is_none() && named > 0 { |
