Upgrade Iroh integration to 1.0
This commit is contained in:
parent
b0768999db
commit
32580749d6
9 changed files with 912 additions and 930 deletions
1672
Cargo.lock
generated
1672
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
16
Cargo.toml
16
Cargo.toml
|
|
@ -32,7 +32,7 @@ resolver = "3"
|
|||
edition = "2024"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://example.invalid/local/geth"
|
||||
rust-version = "1.85"
|
||||
rust-version = "1.91"
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1"
|
||||
|
|
@ -44,24 +44,22 @@ bytes = "1"
|
|||
clap = { version = "4", features = ["derive", "env"] }
|
||||
clap_complete = "4"
|
||||
directories = "5"
|
||||
# Compatibility pins for iroh 0.95's ed25519-dalek prerelease dependency.
|
||||
ed25519 = "=3.0.0-rc.1"
|
||||
ed25519-dalek = { version = "2", features = ["rand_core"] }
|
||||
pkcs8 = "=0.11.0-rc.11"
|
||||
futures = "0.3"
|
||||
hex = "0.4"
|
||||
hexane = "=0.1.5"
|
||||
iroh = { version = "0.95.1", features = ["discovery-local-network"] }
|
||||
iroh-blobs = "0.97.0"
|
||||
iroh-docs = "0.95.0"
|
||||
iroh-gossip = "0.95.0"
|
||||
iroh = "1.0.0"
|
||||
iroh-blobs = "0.103.0"
|
||||
iroh-docs = "0.101.0"
|
||||
iroh-gossip = "0.101.0"
|
||||
iroh-mdns-address-lookup = "0.4.0"
|
||||
postcard = { version = "1", features = ["alloc"] }
|
||||
rand = "0.9"
|
||||
rand_core = { version = "0.6", features = ["getrandom"] }
|
||||
rusqlite = { version = "0.32", features = ["bundled"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
swarm-discovery = "0.4.1"
|
||||
swarm-discovery = "0.6.0"
|
||||
tempfile = "3"
|
||||
thiserror = "2"
|
||||
time = { version = "0.3", features = ["formatting", "serde"] }
|
||||
|
|
|
|||
|
|
@ -231,8 +231,8 @@ card against the observed Iroh EndpointID and requires `cas.fetch` on
|
|||
blob payload over native `iroh-blobs` (`/iroh-bytes/4`) on the same daemon-owned
|
||||
Iroh endpoint, verifies the BLAKE3 hash, stores it in local CAS, and records the
|
||||
serving peer as a provider visible with `geth cas providers <hash>`.
|
||||
`geth-iroh` is pinned to `iroh 0.95.1` and compiles the native backend
|
||||
libraries `iroh-blobs 0.97.0`, `iroh-docs 0.95.0`, and `iroh-gossip 0.95.0`
|
||||
`geth-iroh` is pinned to `iroh 1.0.0` and compiles the native backend
|
||||
libraries `iroh-blobs 0.103.0`, `iroh-docs 0.101.0`, and `iroh-gossip 0.101.0`
|
||||
against the same daemon-owned endpoint generation. KV stores are mirrored into
|
||||
native `iroh-docs` namespaces and peers receive read-only document tickets only
|
||||
after geth authorization succeeds. Pubsub joins native `iroh-gossip` topics
|
||||
|
|
|
|||
|
|
@ -7,13 +7,11 @@ license.workspace = true
|
|||
|
||||
[dependencies]
|
||||
hex.workspace = true
|
||||
ed25519.workspace = true
|
||||
pkcs8.workspace = true
|
||||
iroh.workspace = true
|
||||
iroh-blobs.workspace = true
|
||||
iroh-docs.workspace = true
|
||||
iroh-gossip.workspace = true
|
||||
rand.workspace = true
|
||||
iroh-mdns-address-lookup.workspace = true
|
||||
serde.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ pub const ALPN_DOCUMENT: &[u8] = b"/geth/document/1";
|
|||
pub const ALPN_SSH_PROXY: &[u8] = b"/geth/ssh-proxy/1";
|
||||
pub const ALPN_OVERLAY: &[u8] = b"/geth/overlay/1";
|
||||
|
||||
pub const IROH_VERSION: &str = "0.95.1";
|
||||
pub const IROH_BLOBS_VERSION: &str = "0.97.0";
|
||||
pub const IROH_DOCS_VERSION: &str = "0.95.0";
|
||||
pub const IROH_GOSSIP_VERSION: &str = "0.95.0";
|
||||
pub const IROH_VERSION: &str = "1.0.0";
|
||||
pub const IROH_BLOBS_VERSION: &str = "0.103.0";
|
||||
pub const IROH_DOCS_VERSION: &str = "0.101.0";
|
||||
pub const IROH_GOSSIP_VERSION: &str = "0.101.0";
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct GethIrohConfig {
|
||||
|
|
@ -348,20 +348,20 @@ fn is_loopback_socket_addr(addr: &str) -> bool {
|
|||
|
||||
pub async fn start_endpoint(config: &GethIrohConfig) -> Result<GethIrohEndpoint, IrohError> {
|
||||
let secret_key = load_or_create_secret_key(&config.secret_key_path)?;
|
||||
let mut builder = iroh::Endpoint::builder()
|
||||
let mut builder = iroh::Endpoint::builder(iroh::endpoint::presets::N0)
|
||||
.secret_key(secret_key)
|
||||
.relay_mode(config.relay_mode.to_iroh()?)
|
||||
.alpns(config.alpns.clone());
|
||||
|
||||
if config.local_discovery {
|
||||
builder = builder.discovery(iroh::discovery::mdns::MdnsDiscovery::builder());
|
||||
builder = builder.address_lookup(iroh_mdns_address_lookup::MdnsAddressLookup::builder());
|
||||
}
|
||||
|
||||
if let Some(bind_ipv4) = config.bind_ipv4 {
|
||||
builder = builder.bind_addr_v4(bind_ipv4);
|
||||
builder = builder.bind_addr(bind_ipv4)?;
|
||||
}
|
||||
if let Some(bind_ipv6) = config.bind_ipv6 {
|
||||
builder = builder.bind_addr_v6(bind_ipv6);
|
||||
builder = builder.bind_addr(bind_ipv6)?;
|
||||
}
|
||||
|
||||
let endpoint = builder.bind().await.map_err(IrohError::from)?;
|
||||
|
|
@ -391,7 +391,7 @@ pub fn load_or_create_secret_key(path: &Path) -> Result<iroh::SecretKey, IrohErr
|
|||
if let Some(parent) = path.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
let secret_key = iroh::SecretKey::generate(&mut rand::rng());
|
||||
let secret_key = iroh::SecretKey::generate();
|
||||
let tmp = path.with_extension("tmp");
|
||||
std::fs::write(&tmp, hex::encode(secret_key.to_bytes()))?;
|
||||
std::fs::rename(tmp, path)?;
|
||||
|
|
@ -444,6 +444,8 @@ pub enum IrohError {
|
|||
InvalidSecretKeyLength,
|
||||
#[error("invalid iroh relay URL `{url}`: {message}")]
|
||||
InvalidRelayUrl { url: String, message: String },
|
||||
#[error("invalid iroh bind address: {0}")]
|
||||
InvalidBindAddr(iroh::endpoint::InvalidSocketAddr),
|
||||
#[error("failed to bind iroh endpoint: {0}")]
|
||||
Bind(Box<iroh::endpoint::BindError>),
|
||||
#[error("timed out waiting for iroh node address")]
|
||||
|
|
@ -460,6 +462,12 @@ pub enum RouterError {
|
|||
UnknownAlpn { alpn: String },
|
||||
}
|
||||
|
||||
impl From<iroh::endpoint::InvalidSocketAddr> for IrohError {
|
||||
fn from(error: iroh::endpoint::InvalidSocketAddr) -> Self {
|
||||
Self::InvalidBindAddr(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<iroh::endpoint::BindError> for IrohError {
|
||||
fn from(error: iroh::endpoint::BindError) -> Self {
|
||||
Self::Bind(Box::new(error))
|
||||
|
|
|
|||
|
|
@ -238,15 +238,13 @@ fn geth_status_against_running_daemon() {
|
|||
assert!(stdout.contains("iroh relay: disabled"));
|
||||
assert!(stdout.contains("iroh discovery: local-network disabled"));
|
||||
assert!(stdout.contains(
|
||||
"native backend cas: shared-iroh-endpoint-ready target iroh-blobs 0.97.0 (wired)"
|
||||
"native backend cas: shared-iroh-endpoint-ready target iroh-blobs 0.103.0 (wired)"
|
||||
));
|
||||
assert!(
|
||||
stdout.contains(
|
||||
"native backend kv: shared-iroh-endpoint-ready target iroh-docs 0.95.0 (wired)"
|
||||
)
|
||||
);
|
||||
assert!(stdout.contains(
|
||||
"native backend pubsub: shared-iroh-endpoint-ready target iroh-gossip 0.95.0 (wired)"
|
||||
"native backend kv: shared-iroh-endpoint-ready target iroh-docs 0.101.0 (wired)"
|
||||
));
|
||||
assert!(stdout.contains(
|
||||
"native backend pubsub: shared-iroh-endpoint-ready target iroh-gossip 0.101.0 (wired)"
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ prefix-scoped capabilities.
|
|||
## Consequences
|
||||
|
||||
The prototype keeps SQLite as the durable local KV index and mirrors each named
|
||||
KV store into an Iroh Documents namespace on the daemon-owned `iroh 0.95.1`
|
||||
KV store into an Iroh Documents namespace on the daemon-owned `iroh 1.0.0`
|
||||
endpoint. Remote `geth kv sync` still uses geth control as the authorization
|
||||
preflight. If the caller has `kv.read` on the remote `resource:kv:<name>`, the
|
||||
remote daemon returns a read-only Iroh Documents ticket and the requester imports
|
||||
entries through `iroh-docs 0.95.0`.
|
||||
entries through `iroh-docs 0.101.0`.
|
||||
|
||||
The daemon must not hand out Iroh Documents write capabilities as a substitute
|
||||
for geth authorization. Write authority remains modeled through geth resource
|
||||
|
|
|
|||
|
|
@ -19,9 +19,11 @@ shared Iroh endpoint and register module protocols on ALPNs such as
|
|||
`/geth/cas/1`, `/geth/kv/1`, `/geth/pipe/1`, `/geth/ssh-proxy/1`, and
|
||||
`/geth/overlay/1`.
|
||||
|
||||
The pinned Iroh integration uses `iroh = 0.95.1`. `geth-iroh` wraps
|
||||
`iroh::Endpoint::builder()`, configures geth ALPNs with `Builder::alpns`, uses
|
||||
`Builder::relay_mode`, persists an `iroh::SecretKey` as hex-encoded 32-byte key
|
||||
The pinned Iroh integration uses `iroh = 1.0.0`. `geth-iroh` wraps
|
||||
`iroh::Endpoint::builder(iroh::endpoint::presets::N0)`, configures geth
|
||||
ALPNs with `Builder::alpns`, uses `Builder::relay_mode`, adds
|
||||
`iroh-mdns-address-lookup` when local discovery is enabled, persists an
|
||||
`iroh::SecretKey` as hex-encoded 32-byte key
|
||||
material, and shuts down through `Endpoint::close().await`. The default config
|
||||
uses Iroh's default relay policy; local-only/offline development can set
|
||||
`[iroh].relay_mode = "disabled"`. Named custom relay maps are configured under
|
||||
|
|
@ -31,7 +33,7 @@ uses Iroh's default relay policy; local-only/offline development can set
|
|||
|
||||
The native module-backend crates for the intended CAS, KV, and pubsub
|
||||
replacements now compile against the same endpoint generation:
|
||||
`iroh-blobs 0.97.0`, `iroh-docs 0.95.0`, and `iroh-gossip 0.95.0`. `geth-iroh`
|
||||
`iroh-blobs 0.103.0`, `iroh-docs 0.101.0`, and `iroh-gossip 0.101.0`. `geth-iroh`
|
||||
exposes their native ALPNs without creating a second daemon endpoint. CAS now
|
||||
registers an `iroh-blobs` provider handler on `/iroh-bytes/4`; local CAS writes
|
||||
are mirrored into the native blob store, and remote `geth cas fetch` performs a
|
||||
|
|
|
|||
|
|
@ -191,9 +191,9 @@ Implementation order:
|
|||
equivalent.
|
||||
- `[x]` Fallback/stub behavior remains clearly marked where APIs are not yet
|
||||
pinned.
|
||||
- `[x]` Upgrade `geth-iroh` from `iroh 0.90.0` to an endpoint version
|
||||
compatible with `iroh-blobs`, `iroh-docs`, and `iroh-gossip` without
|
||||
introducing a second daemon endpoint.
|
||||
- `[x]` Upgrade `geth-iroh` to stable `iroh 1.0.0` with matching `iroh-blobs 0.103.0`,
|
||||
`iroh-docs 0.101.0`, and `iroh-gossip 0.101.0` without introducing a
|
||||
second daemon endpoint.
|
||||
|
||||
- `[x]` File sync reconciliation polish.
|
||||
Acceptance criteria:
|
||||
|
|
@ -620,8 +620,8 @@ authorization and durable-state boundaries clear.
|
|||
- `[x]` `geth cas providers <hash>` lists locally known providers.
|
||||
- `[x]` Tests cover local provider metadata storage.
|
||||
- `[x]` Replace the bootstrap control-ALPN byte transfer with `iroh-blobs`
|
||||
provider/fetch behavior using the daemon-owned `iroh 0.95.1` endpoint and
|
||||
pinned `iroh-blobs 0.97.0`.
|
||||
provider/fetch behavior using the daemon-owned `iroh 1.0.0` endpoint and
|
||||
pinned `iroh-blobs 0.103.0`.
|
||||
- `[x]` CAS fetch keeps the geth control-ALPN authorization preflight before
|
||||
opening the native `iroh-blobs` payload transfer.
|
||||
- `[x]` Local CAS adds and daemon startup mirror available blobs into the
|
||||
|
|
|
|||
Loading…
Reference in a new issue