Enable Iroh local network discovery
This commit is contained in:
parent
280472cecb
commit
bfc5df698c
12 changed files with 136 additions and 16 deletions
11
AGENTS.md
11
AGENTS.md
|
|
@ -105,8 +105,9 @@ Roadmap items should be actionable and checkable:
|
||||||
daemon-owned Iroh endpoint startup, built-in relay-mode config, SSH
|
daemon-owned Iroh endpoint startup, built-in relay-mode config, SSH
|
||||||
certificate metadata, revocation metadata, user service definitions, and a
|
certificate metadata, revocation metadata, user service definitions, and a
|
||||||
pinned `geth-iroh` endpoint wrapper with protocol-router scaffold, peer-card
|
pinned `geth-iroh` endpoint wrapper with protocol-router scaffold, peer-card
|
||||||
types, untrusted discovery-backend trait, and custom relay-map config exist.
|
types, untrusted discovery-backend trait, custom relay-map config, and Iroh
|
||||||
- mDNS discovery transport, peer auth over Iroh, cr-sqlite, iroh-docs,
|
local-network discovery toggle exist.
|
||||||
iroh-gossip, iroh-blobs, Automerge sync, real auth enforcement, OpenSSH KRL
|
- Signed peer-card LAN discovery payloads, peer auth over Iroh, cr-sqlite,
|
||||||
generation, and Keyhive/BeeKEM-style authorization are future roadmap items
|
iroh-docs, iroh-gossip, iroh-blobs, Automerge sync, real auth enforcement,
|
||||||
unless implemented later.
|
OpenSSH KRL generation, and Keyhive/BeeKEM-style authorization are future
|
||||||
|
roadmap items unless implemented later.
|
||||||
|
|
|
||||||
36
Cargo.lock
generated
36
Cargo.lock
generated
|
|
@ -2,6 +2,20 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "acto"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a026259da4f1a13b4af60cda453c392de64c58c12d239c560923e0382f42f2b9"
|
||||||
|
dependencies = [
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project-lite",
|
||||||
|
"rustc_version",
|
||||||
|
"smol_str",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.25.1"
|
version = "0.25.1"
|
||||||
|
|
@ -1871,6 +1885,7 @@ dependencies = [
|
||||||
"strum",
|
"strum",
|
||||||
"stun-rs",
|
"stun-rs",
|
||||||
"surge-ping",
|
"surge-ping",
|
||||||
|
"swarm-discovery",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
|
|
@ -3428,6 +3443,12 @@ version = "1.15.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smol_str"
|
||||||
|
version = "0.1.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "snafu"
|
name = "snafu"
|
||||||
version = "0.8.9"
|
version = "0.8.9"
|
||||||
|
|
@ -3575,6 +3596,21 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "swarm-discovery"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "790d8444f7db1e88f70aed3234cab8e42c48e05360bfc86ca7dce0d9a5d95d26"
|
||||||
|
dependencies = [
|
||||||
|
"acto",
|
||||||
|
"hickory-proto",
|
||||||
|
"rand 0.9.4",
|
||||||
|
"socket2 0.5.10",
|
||||||
|
"thiserror 2.0.18",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.117"
|
version = "2.0.117"
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ directories = "5"
|
||||||
ed25519-dalek = { version = "2", features = ["rand_core"] }
|
ed25519-dalek = { version = "2", features = ["rand_core"] }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
iroh = "0.90.0"
|
iroh = { version = "0.90.0", features = ["discovery-local-network"] }
|
||||||
postcard = { version = "1", features = ["alloc"] }
|
postcard = { version = "1", features = ["alloc"] }
|
||||||
rand_core = { version = "0.6", features = ["getrandom"] }
|
rand_core = { version = "0.6", features = ["getrandom"] }
|
||||||
rusqlite = { version = "0.32", features = ["bundled"] }
|
rusqlite = { version = "0.32", features = ["bundled"] }
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ SSH is not a geth transport backend, and there is no SSH fallback transport.
|
||||||
The default node config uses Iroh's default relay policy for practical
|
The default node config uses Iroh's default relay policy for practical
|
||||||
connectivity; set `[iroh].relay_mode = "disabled"` for local-only/offline
|
connectivity; set `[iroh].relay_mode = "disabled"` for local-only/offline
|
||||||
development. Named custom relay maps can be selected with
|
development. Named custom relay maps can be selected with
|
||||||
`relay_mode = "custom"` and `relay_map = "<name>"`.
|
`relay_mode = "custom"` and `relay_map = "<name>"`. Iroh local-network
|
||||||
|
discovery is enabled by default with `[iroh].local_discovery = true`.
|
||||||
|
|
||||||
SSH keys are used as admin trust anchors and ecosystem integration points.
|
SSH keys are used as admin trust anchors and ecosystem integration points.
|
||||||
OpenSSH, FIDO, and YubiKey-backed keys can sign geth trust objects through
|
OpenSSH, FIDO, and YubiKey-backed keys can sign geth trust objects through
|
||||||
|
|
|
||||||
|
|
@ -508,6 +508,14 @@ fn print_response(response: ControlResponse, json: bool) -> Result<()> {
|
||||||
status.endpoint_id.as_deref().unwrap_or("not started")
|
status.endpoint_id.as_deref().unwrap_or("not started")
|
||||||
);
|
);
|
||||||
println!("iroh relay: {}", status.iroh_relay_mode);
|
println!("iroh relay: {}", status.iroh_relay_mode);
|
||||||
|
println!(
|
||||||
|
"iroh discovery: {}",
|
||||||
|
if status.iroh_local_discovery {
|
||||||
|
"local-network enabled"
|
||||||
|
} else {
|
||||||
|
"local-network disabled"
|
||||||
|
}
|
||||||
|
);
|
||||||
println!("iroh: {}", status.iroh);
|
println!("iroh: {}", status.iroh);
|
||||||
}
|
}
|
||||||
ControlResponse::NodeId(node) => {
|
ControlResponse::NodeId(node) => {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ pub const DEFAULT_CONFIG_TOML: &str = r#"# geth local node config
|
||||||
# Values: "default", "staging", "disabled", "custom".
|
# Values: "default", "staging", "disabled", "custom".
|
||||||
[iroh]
|
[iroh]
|
||||||
relay_mode = "default"
|
relay_mode = "default"
|
||||||
|
local_discovery = true
|
||||||
# relay_map = "home"
|
# relay_map = "home"
|
||||||
#
|
#
|
||||||
# [iroh.relay_maps.home]
|
# [iroh.relay_maps.home]
|
||||||
|
|
@ -101,6 +102,8 @@ pub enum ConfigError {
|
||||||
TomlParse(#[from] toml_edit::TomlError),
|
TomlParse(#[from] toml_edit::TomlError),
|
||||||
#[error("invalid iroh relay_mode: {0}")]
|
#[error("invalid iroh relay_mode: {0}")]
|
||||||
InvalidRelayMode(String),
|
InvalidRelayMode(String),
|
||||||
|
#[error("invalid iroh local_discovery value: {0}")]
|
||||||
|
InvalidLocalDiscovery(String),
|
||||||
#[error("custom iroh relay_mode requires iroh.relay_map")]
|
#[error("custom iroh relay_mode requires iroh.relay_map")]
|
||||||
MissingRelayMapSelection,
|
MissingRelayMapSelection,
|
||||||
#[error("selected iroh relay map does not exist: {0}")]
|
#[error("selected iroh relay map does not exist: {0}")]
|
||||||
|
|
@ -136,6 +139,7 @@ impl GethConfig {
|
||||||
pub fn parse(text: &str) -> Result<Self, ConfigError> {
|
pub fn parse(text: &str) -> Result<Self, ConfigError> {
|
||||||
let document = text.parse::<toml_edit::DocumentMut>()?;
|
let document = text.parse::<toml_edit::DocumentMut>()?;
|
||||||
let relay_maps = parse_relay_maps(&document)?;
|
let relay_maps = parse_relay_maps(&document)?;
|
||||||
|
let local_discovery = parse_local_discovery(&document)?;
|
||||||
let relay_mode = match document.get("iroh").and_then(|iroh| iroh.get("relay_mode")) {
|
let relay_mode = match document.get("iroh").and_then(|iroh| iroh.get("relay_mode")) {
|
||||||
Some(item) => {
|
Some(item) => {
|
||||||
let value = item
|
let value = item
|
||||||
|
|
@ -150,15 +154,27 @@ impl GethConfig {
|
||||||
iroh: IrohConfig {
|
iroh: IrohConfig {
|
||||||
relay_mode,
|
relay_mode,
|
||||||
relay_maps,
|
relay_maps,
|
||||||
|
local_discovery,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct IrohConfig {
|
pub struct IrohConfig {
|
||||||
pub relay_mode: RelayMode,
|
pub relay_mode: RelayMode,
|
||||||
pub relay_maps: BTreeMap<String, RelayMapConfig>,
|
pub relay_maps: BTreeMap<String, RelayMapConfig>,
|
||||||
|
pub local_discovery: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for IrohConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
relay_mode: RelayMode::Default,
|
||||||
|
relay_maps: BTreeMap::new(),
|
||||||
|
local_discovery: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
|
@ -269,6 +285,18 @@ fn validate_relay_url(map: &str, relay_url: &str) -> Result<(), ConfigError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_local_discovery(document: &toml_edit::DocumentMut) -> Result<bool, ConfigError> {
|
||||||
|
match document
|
||||||
|
.get("iroh")
|
||||||
|
.and_then(|iroh| iroh.get("local_discovery"))
|
||||||
|
{
|
||||||
|
Some(item) => item
|
||||||
|
.as_bool()
|
||||||
|
.ok_or_else(|| ConfigError::InvalidLocalDiscovery(item.to_string())),
|
||||||
|
None => Ok(true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -277,6 +305,7 @@ mod tests {
|
||||||
fn default_config_uses_iroh_relays() {
|
fn default_config_uses_iroh_relays() {
|
||||||
let config = GethConfig::parse(GethConfig::default_toml()).expect("parse config");
|
let config = GethConfig::parse(GethConfig::default_toml()).expect("parse config");
|
||||||
assert_eq!(config.iroh.relay_mode, RelayMode::Default);
|
assert_eq!(config.iroh.relay_mode, RelayMode::Default);
|
||||||
|
assert!(config.iroh.local_discovery);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -345,4 +374,16 @@ mod tests {
|
||||||
.expect_err("error");
|
.expect_err("error");
|
||||||
assert!(matches!(error, ConfigError::UnknownRelayMap(map) if map == "home"));
|
assert!(matches!(error, ConfigError::UnknownRelayMap(map) if map == "home"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_parses_local_discovery_toggle() {
|
||||||
|
let config = GethConfig::parse("[iroh]\nlocal_discovery = false\n").expect("parse");
|
||||||
|
assert!(!config.iroh.local_discovery);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_rejects_non_bool_local_discovery() {
|
||||||
|
let error = GethConfig::parse("[iroh]\nlocal_discovery = \"yes\"\n").expect_err("error");
|
||||||
|
assert!(matches!(error, ConfigError::InvalidLocalDiscovery(_)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,7 @@ pub struct StatusResponse {
|
||||||
pub iroh_enabled: bool,
|
pub iroh_enabled: bool,
|
||||||
pub endpoint_id: Option<String>,
|
pub endpoint_id: Option<String>,
|
||||||
pub iroh_relay_mode: String,
|
pub iroh_relay_mode: String,
|
||||||
|
pub iroh_local_discovery: bool,
|
||||||
pub iroh: String,
|
pub iroh: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ pub const ALPN_SSH_PROXY: &[u8] = b"/geth/ssh-proxy/1";
|
||||||
pub struct GethIrohConfig {
|
pub struct GethIrohConfig {
|
||||||
pub secret_key_path: PathBuf,
|
pub secret_key_path: PathBuf,
|
||||||
pub relay_mode: GethRelayMode,
|
pub relay_mode: GethRelayMode,
|
||||||
|
pub local_discovery: bool,
|
||||||
pub bind_ipv4: Option<SocketAddrV4>,
|
pub bind_ipv4: Option<SocketAddrV4>,
|
||||||
pub bind_ipv6: Option<SocketAddrV6>,
|
pub bind_ipv6: Option<SocketAddrV6>,
|
||||||
pub alpns: Vec<Vec<u8>>,
|
pub alpns: Vec<Vec<u8>>,
|
||||||
|
|
@ -35,6 +36,7 @@ impl GethIrohConfig {
|
||||||
Self {
|
Self {
|
||||||
secret_key_path: secret_key_path.into(),
|
secret_key_path: secret_key_path.into(),
|
||||||
relay_mode,
|
relay_mode,
|
||||||
|
local_discovery: true,
|
||||||
bind_ipv4: None,
|
bind_ipv4: None,
|
||||||
bind_ipv6: None,
|
bind_ipv6: None,
|
||||||
alpns: default_protocol_router().alpns(),
|
alpns: default_protocol_router().alpns(),
|
||||||
|
|
@ -229,6 +231,10 @@ pub async fn start_endpoint(config: &GethIrohConfig) -> Result<GethIrohEndpoint,
|
||||||
.relay_mode(config.relay_mode.to_iroh()?)
|
.relay_mode(config.relay_mode.to_iroh()?)
|
||||||
.alpns(config.alpns.clone());
|
.alpns(config.alpns.clone());
|
||||||
|
|
||||||
|
if config.local_discovery {
|
||||||
|
builder = builder.discovery_local_network();
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(bind_ipv4) = config.bind_ipv4 {
|
if let Some(bind_ipv4) = config.bind_ipv4 {
|
||||||
builder = builder.bind_addr_v4(bind_ipv4);
|
builder = builder.bind_addr_v4(bind_ipv4);
|
||||||
}
|
}
|
||||||
|
|
@ -241,9 +247,10 @@ pub async fn start_endpoint(config: &GethIrohConfig) -> Result<GethIrohEndpoint,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
endpoint_id: Some(endpoint.node_id().to_string()),
|
endpoint_id: Some(endpoint.node_id().to_string()),
|
||||||
relay_mode: config.relay_mode.label(),
|
relay_mode: config.relay_mode.label(),
|
||||||
|
local_discovery: config.local_discovery,
|
||||||
note: format!(
|
note: format!(
|
||||||
"Iroh endpoint started with iroh 0.90.0; relay mode: {:?}",
|
"Iroh endpoint started with iroh 0.90.0; relay mode: {:?}; local discovery: {}",
|
||||||
config.relay_mode
|
config.relay_mode, config.local_discovery
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
Ok(GethIrohEndpoint { endpoint, status })
|
Ok(GethIrohEndpoint { endpoint, status })
|
||||||
|
|
@ -283,6 +290,7 @@ pub struct EndpointStatus {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub endpoint_id: Option<String>,
|
pub endpoint_id: Option<String>,
|
||||||
pub relay_mode: String,
|
pub relay_mode: String,
|
||||||
|
pub local_discovery: bool,
|
||||||
pub note: String,
|
pub note: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,6 +301,7 @@ impl EndpointStatus {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
endpoint_id: None,
|
endpoint_id: None,
|
||||||
relay_mode: "not-started".to_owned(),
|
relay_mode: "not-started".to_owned(),
|
||||||
|
local_discovery: false,
|
||||||
note: "Iroh endpoint is not running outside daemon mode".to_owned(),
|
note: "Iroh endpoint is not running outside daemon mode".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -416,16 +425,18 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn endpoint_status_tracks_node_id_when_bind_is_available() {
|
async fn endpoint_status_tracks_node_id_when_bind_is_available() {
|
||||||
let dir = tempfile::tempdir().expect("tempdir");
|
let dir = tempfile::tempdir().expect("tempdir");
|
||||||
let config = GethIrohConfig::local_with_relay(
|
let mut config = GethIrohConfig::local_with_relay(
|
||||||
dir.path().join("iroh.ed25519"),
|
dir.path().join("iroh.ed25519"),
|
||||||
GethRelayMode::Disabled,
|
GethRelayMode::Disabled,
|
||||||
);
|
);
|
||||||
|
config.local_discovery = false;
|
||||||
match start_endpoint(&config).await {
|
match start_endpoint(&config).await {
|
||||||
Ok(endpoint) => {
|
Ok(endpoint) => {
|
||||||
let status = endpoint.status();
|
let status = endpoint.status();
|
||||||
assert!(status.enabled);
|
assert!(status.enabled);
|
||||||
assert_eq!(status.endpoint_id, Some(endpoint.node_id()));
|
assert_eq!(status.endpoint_id, Some(endpoint.node_id()));
|
||||||
assert_eq!(status.relay_mode, "disabled");
|
assert_eq!(status.relay_mode, "disabled");
|
||||||
|
assert!(!status.local_discovery);
|
||||||
endpoint.shutdown().await;
|
endpoint.shutdown().await;
|
||||||
}
|
}
|
||||||
Err(IrohError::Bind(error)) => {
|
Err(IrohError::Bind(error)) => {
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ pub fn handle_request(
|
||||||
iroh_enabled: node.iroh_status.enabled,
|
iroh_enabled: node.iroh_status.enabled,
|
||||||
endpoint_id: node.iroh_status.endpoint_id.clone(),
|
endpoint_id: node.iroh_status.endpoint_id.clone(),
|
||||||
iroh_relay_mode: node.iroh_status.relay_mode.clone(),
|
iroh_relay_mode: node.iroh_status.relay_mode.clone(),
|
||||||
|
iroh_local_discovery: node.iroh_status.local_discovery,
|
||||||
iroh: node.iroh_status.note.clone(),
|
iroh: node.iroh_status.note.clone(),
|
||||||
})),
|
})),
|
||||||
ControlRequest::NodeId => Ok(ControlResponse::NodeId(NodeIdResponse {
|
ControlRequest::NodeId => Ok(ControlResponse::NodeId(NodeIdResponse {
|
||||||
|
|
@ -456,8 +457,10 @@ async fn start_daemon_iroh_endpoint(
|
||||||
let node_config = GethConfig::load(&node.paths.config_file())?;
|
let node_config = GethConfig::load(&node.paths.config_file())?;
|
||||||
let relay_mode = node_config.iroh.relay_mode.clone();
|
let relay_mode = node_config.iroh.relay_mode.clone();
|
||||||
let relay_mode_label = relay_mode.label();
|
let relay_mode_label = relay_mode.label();
|
||||||
|
let local_discovery = node_config.iroh.local_discovery;
|
||||||
let iroh_relay_mode = config_relay_mode_to_iroh(&relay_mode, &node_config.iroh.relay_maps);
|
let iroh_relay_mode = config_relay_mode_to_iroh(&relay_mode, &node_config.iroh.relay_maps);
|
||||||
let config = GethIrohConfig::local_with_relay(node.paths.iroh_key(), iroh_relay_mode);
|
let mut config = GethIrohConfig::local_with_relay(node.paths.iroh_key(), iroh_relay_mode);
|
||||||
|
config.local_discovery = local_discovery;
|
||||||
match geth_iroh::start_endpoint(&config).await {
|
match geth_iroh::start_endpoint(&config).await {
|
||||||
Ok(endpoint) => {
|
Ok(endpoint) => {
|
||||||
let status = endpoint.status();
|
let status = endpoint.status();
|
||||||
|
|
@ -473,6 +476,7 @@ async fn start_daemon_iroh_endpoint(
|
||||||
enabled: false,
|
enabled: false,
|
||||||
endpoint_id: None,
|
endpoint_id: None,
|
||||||
relay_mode: relay_mode_label,
|
relay_mode: relay_mode_label,
|
||||||
|
local_discovery,
|
||||||
note: format!("Iroh endpoint failed to start: {error}"),
|
note: format!("Iroh endpoint failed to start: {error}"),
|
||||||
};
|
};
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,11 @@ fn geth_init_in_temp_home() {
|
||||||
.expect("read config")
|
.expect("read config")
|
||||||
.contains("relay_mode = \"default\"")
|
.contains("relay_mode = \"default\"")
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
std::fs::read_to_string(home.path().join("config.toml"))
|
||||||
|
.expect("read config")
|
||||||
|
.contains("local_discovery = true")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -75,7 +80,7 @@ fn geth_status_against_running_daemon() {
|
||||||
assert!(run_geth(home.path(), &["init"]).status.success());
|
assert!(run_geth(home.path(), &["init"]).status.success());
|
||||||
std::fs::write(
|
std::fs::write(
|
||||||
home.path().join("config.toml"),
|
home.path().join("config.toml"),
|
||||||
"[iroh]\nrelay_mode = \"disabled\"\n",
|
"[iroh]\nrelay_mode = \"disabled\"\nlocal_discovery = false\n",
|
||||||
)
|
)
|
||||||
.expect("write config");
|
.expect("write config");
|
||||||
let mut daemon = spawn_daemon(home.path());
|
let mut daemon = spawn_daemon(home.path());
|
||||||
|
|
@ -95,6 +100,7 @@ fn geth_status_against_running_daemon() {
|
||||||
assert!(stdout.contains("agent:"));
|
assert!(stdout.contains("agent:"));
|
||||||
assert!(stdout.contains("endpoint:"));
|
assert!(stdout.contains("endpoint:"));
|
||||||
assert!(stdout.contains("iroh relay: disabled"));
|
assert!(stdout.contains("iroh relay: disabled"));
|
||||||
|
assert!(stdout.contains("iroh discovery: local-network disabled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,10 @@ The target product should use Iroh relay support for practical internet
|
||||||
connectivity and mDNS/LAN discovery for local networks. These are connectivity
|
connectivity and mDNS/LAN discovery for local networks. These are connectivity
|
||||||
and candidate-discovery mechanisms only. They do not grant trust, mutate
|
and candidate-discovery mechanisms only. They do not grant trust, mutate
|
||||||
authorization state, or make EndpointID knowledge sufficient for access.
|
authorization state, or make EndpointID knowledge sufficient for access.
|
||||||
|
The current daemon can enable Iroh's local-network discovery service through
|
||||||
|
`[iroh].local_discovery = true`, which is the default. This publishes and
|
||||||
|
discovers Iroh node addressing. Signed geth peer-card payloads over LAN
|
||||||
|
discovery remain separate future work.
|
||||||
|
|
||||||
Peer cards are the discovery payload. A peer card carries node ID, agent ID,
|
Peer cards are the discovery payload. A peer card carries node ID, agent ID,
|
||||||
endpoint candidates, timestamp, and signature metadata. The current scaffold
|
endpoint candidates, timestamp, and signature metadata. The current scaffold
|
||||||
|
|
|
||||||
|
|
@ -88,10 +88,17 @@ geth-to-geth connections without granting trust from discovery alone.
|
||||||
- Status output identifies the selected custom relay map without exposing
|
- Status output identifies the selected custom relay map without exposing
|
||||||
unrelated config.
|
unrelated config.
|
||||||
|
|
||||||
- `[ ]` LAN mDNS discovery.
|
- `[x]` Iroh LAN address discovery.
|
||||||
Acceptance criteria:
|
Acceptance criteria:
|
||||||
- The daemon can advertise and discover local geth peer cards over mDNS.
|
- Config can enable or disable Iroh local-network discovery.
|
||||||
- mDNS results are stored only as untrusted peer candidates.
|
- The daemon registers Iroh's local mDNS-like discovery service when enabled.
|
||||||
|
- `geth status --json` reports whether local-network discovery is enabled.
|
||||||
|
|
||||||
|
- `[ ]` Signed peer-card LAN discovery payloads.
|
||||||
|
Acceptance criteria:
|
||||||
|
- The daemon can advertise and discover signed geth peer cards over LAN
|
||||||
|
discovery.
|
||||||
|
- LAN-discovered peer cards are stored only as untrusted peer candidates.
|
||||||
- Discovered EndpointIDs do not grant module access without keychain/auth
|
- Discovered EndpointIDs do not grant module access without keychain/auth
|
||||||
validation.
|
validation.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue