aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/swarm/bootstrap.rs1
-rw-r--r--src/swarm/roots.rs24
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 {