fix(fips): harden companion mesh joins
This commit is contained in:
@@ -156,7 +156,24 @@ pub async fn load(data_dir: &Path) -> Result<Vec<SeedAnchor>> {
|
||||
.with_context(|| format!("read {}", path.display()))?;
|
||||
let anchors: Vec<SeedAnchor> =
|
||||
serde_json::from_slice(&bytes).with_context(|| format!("parse {}", path.display()))?;
|
||||
Ok(anchors)
|
||||
Ok(repair_legacy_anchor_set(anchors))
|
||||
}
|
||||
|
||||
/// Add the newer redundant public TCP anchors to legacy files that only carry
|
||||
/// the Archipelago-operated vps2 anchor. A deliberately custom/private anchor
|
||||
/// list remains authoritative; this only repairs the exact stale shape shipped
|
||||
/// before the join.fips.network anchors became defaults.
|
||||
fn repair_legacy_anchor_set(mut anchors: Vec<SeedAnchor>) -> Vec<SeedAnchor> {
|
||||
let has_archy = anchors.iter().any(|a| a.npub == ARCHY_ANCHOR_NPUB);
|
||||
let has_fips_network = fips_network_anchors()
|
||||
.iter()
|
||||
.any(|default| anchors.iter().any(|a| a.npub == default.npub));
|
||||
if has_archy && !has_fips_network {
|
||||
for anchor in fips_network_anchors() {
|
||||
anchors.push(anchor);
|
||||
}
|
||||
}
|
||||
anchors
|
||||
}
|
||||
|
||||
/// Persist the list. Overwrites atomically via write-then-rename so a
|
||||
@@ -338,6 +355,30 @@ mod tests {
|
||||
assert!(got.iter().all(|a| a.transport == "tcp"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn load_repairs_legacy_archy_only_anchor_file() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
save(dir.path(), &[archy_anchor()]).await.unwrap();
|
||||
|
||||
let got = load(dir.path()).await.unwrap();
|
||||
assert!(got.iter().any(|a| a.npub == ARCHY_ANCHOR_NPUB));
|
||||
for anchor in fips_network_anchors() {
|
||||
assert!(got.iter().any(|a| a.npub == anchor.npub));
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn load_keeps_private_anchor_file_authoritative() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let private = mk("npub1private");
|
||||
save(dir.path(), std::slice::from_ref(&private))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let got = load(dir.path()).await.unwrap();
|
||||
assert_eq!(got, vec![private]);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn removing_one_default_persists_and_keeps_the_other() {
|
||||
// Editing the anchor list (here removing one default) makes the file
|
||||
|
||||
Reference in New Issue
Block a user