Skip to content

feat: add z-base-32 encoder for iroh EndpointId hex form#145

Merged
zachsmith1 merged 2 commits intomainfrom
feat/iroh-z32-helper
Apr 30, 2026
Merged

feat: add z-base-32 encoder for iroh EndpointId hex form#145
zachsmith1 merged 2 commits intomainfrom
feat/iroh-z32-helper

Conversation

@zachsmith1
Copy link
Copy Markdown
Contributor

@zachsmith1 zachsmith1 commented Apr 30, 2026

Summary

  • New internal/iroh.EndpointHexToZ32 helper: parses the lowercase-hex EndpointId form that desktop clients write to Connector.Status.ConnectionDetails.PublicKey.Id and re-encodes the 32 raw bytes as z-base-32, the form iroh's DNS resolver uses for _iroh.<z32>.<origin> discovery lookups.
  • Implemented with stdlib encoding/base32 configured with the Zooko alphabet and no padding — z-base-32 is RFC 4648 base32 bit-packing with a different alphabet, so stdlib produces byte-identical output. No external dependency.
  • No behavior change. Groundwork for an upcoming controller that will write iroh-format TXT records into a downstream DNSRecordSet.

Why hex→z32 lives here

  • iroh's EndpointId::Display is lowercase hex (iroh-base/src/key.rs:199-203), so the desktop agent writes hex into the Connector's Id field.
  • iroh-gateway's dial path calls EndpointId::from_str which accepts hex or base32 — so the gateway works with whatever string form is on disk.
  • iroh's DNS discovery, by contrast, always calls EndpointId::to_z32() to construct the lookup name (iroh-0.95.1/src/discovery/dns.rs:22-25, test_utils.rs:510). z-base-32 uses a distinct alphabet (ybndrfg8ejkmcpqxot1uwisza345h769) from RFC 4648 base32.
  • This helper is the boundary between the two encodings; future controller code converts at write-time to TXT.

Verification

  • TestZ32EncodingMatchesIrohUpstream runs every (bytes, z32) pair from iroh's own z32 crate test table (z32-1.3.0/src/lib.rs TEST_DATA + the 32-byte public_key test) through the stdlib-based encoder. All ten vectors agree byte-for-byte across input lengths 0–32, confirming alphabet, bit-packing, and trailing-bit handling match.
  • TestEndpointHexToZ32 covers the wrapper: known-good vector, invalid hex, odd length, too few/many bytes, empty input.
  • go build ./... compiles.

zachsmith1 and others added 2 commits April 30, 2026 15:04
Adds internal/iroh.EndpointHexToZ32, the encoding boundary between the
hex form iroh exposes via Display (and that desktop agents write to
Connector.Status.ConnectionDetails.PublicKey.Id) and the z-base-32
form iroh's DNS resolver uses to construct "_iroh.<z32>.<origin>"
discovery lookup names.

Verified against iroh's own z32 crate test vector
(z32-1.3.0/src/lib.rs public_key test): the 32-byte public key
[241, 32, 213, 46, ...] encodes to
"6ropkm1nz98qqwnotqz1tryk3mrfiw9u16iwzp1usci6kbqdfwho".

This is the first PR in the iroh DNS discovery controller series; no
behavior change yet.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the tv42/zbase32 dependency with encoding/base32 configured
with the Zooko z-base-32 alphabet and no padding — the bit-packing is
identical to RFC 4648 base32, so the stdlib encoder produces
byte-identical output. Drops one third-party dep.

TestZ32EncodingMatchesIrohUpstream runs every (bytes, z32) pair from
iroh's z32 crate test table (z32-1.3.0/src/lib.rs TEST_DATA +
public_key) through the new stdlib-based encoder, spanning input
lengths 0–32. All ten vectors agree, confirming alphabet, bit-packing,
and trailing-bit handling match the Rust implementation iroh actually
uses.
@zachsmith1 zachsmith1 requested a review from scotwells April 30, 2026 22:12
@zachsmith1 zachsmith1 merged commit 97155b5 into main Apr 30, 2026
11 checks passed
@zachsmith1 zachsmith1 deleted the feat/iroh-z32-helper branch April 30, 2026 23:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants