Skip to content

feat(primitives)!: typed Swarm spec primitives + signing layout#40

Merged
mfw78 merged 1 commit into
mainfrom
feat/swarm-spec-primitives
Jun 2, 2026
Merged

feat(primitives)!: typed Swarm spec primitives + signing layout#40
mfw78 merged 1 commit into
mainfrom
feat/swarm-spec-primitives

Conversation

@mfw78

@mfw78 mfw78 commented Jun 2, 2026

Copy link
Copy Markdown
Member

Summary

Migrates the canonical Swarm spec / wire primitives into nectar so vertex, apiarist, and future Swarm implementations consume one source of truth instead of duplicating consts.

Bundles

  • Typed newtypes: Nonce(B256), NetworkId(u64), Timestamp(i64), ProximityOrder(u8), Bin(u8). Range-validated. NetworkId::{MAINNET, TESTNET} consts.
  • compute_overlay(eth, net, nonce) in overlay.rs: canonical keccak256(eth || net.to_le || nonce) per bee crypto/crypto.go:45-57. Network ID is little-endian here; tests pin the LE-vs-BE distinction.
  • SwarmAddress proximity API typed: proximity() now returns ProximityOrder (was u8). New xor() and bin(&anchor) -> Bin. Breaking change to the primitives crate public API.
  • SwarmSpec trait in spec.rs with default methods sourcing bee's canonical knobs (saturation_peers=8, over_saturation=18, bootnode_over_saturation=20, neighborhood_low_watermark=2, clock_skew_tolerance=6h). StaticSpec, MAINNET, TESTNET.
  • recompute_neighborhood_depth: pure function port of bee kademlia.go:896-920. Routing-layer wrappers stay with each downstream impl; nectar owns the math.
  • signing.rs: SIGN_DATA_PREFIX and sign_data(...) builder for the canonical BzzAddress sign-data byte layout per bee bzz/address.go:138-160. Transport-agnostic (caller passes underlay_bytes as raw bytes; no libp2p dep). Signing and recovery are not wrapped, callers use alloy's signer.sign_message_sync / Signature::recover_address_from_msg directly.

Design notes

  • Errors via thiserror enums (not unit structs), even for single-variant errors, for forward extensibility.
  • No trivial wrappers: redundant named ctors / accessors replaced by From/Into/AsRef where possible. Nonce::random() lives unconditionally (alloy's getrandom feature added to non-wasm primitives deps).
  • SwarmAddress::proximity() return type change is the only breaking surface; primitives version should bump.

Test plan

  • cargo test -p nectar-primitives --all-features --no-fail-fast: 196 passed (180 lib + 16 doc + new module tests for nonce, network_id, timestamp, proximity_order, bin, overlay, spec, neighborhood_depth, signing).
  • cargo clippy -p nectar-primitives --all-features --lib: no new lints from new modules (pre-existing generic_array deprecation in bmt remains; will be fixed in a separate deps-bump PR that this one rebases on).
  • Vertex side: PRs #101, #102, #107 will be revised in follow-up to consume this surface and drop the local duplicates.

@mfw78 mfw78 force-pushed the feat/swarm-spec-primitives branch 3 times, most recently from 5eadcac to d6ef3ba Compare June 2, 2026 02:18
@mfw78 mfw78 changed the base branch from main to chore/bump-deps June 2, 2026 02:18
@mfw78 mfw78 force-pushed the chore/bump-deps branch from 3bc958f to beeb879 Compare June 2, 2026 03:07
@mfw78 mfw78 force-pushed the feat/swarm-spec-primitives branch from d6ef3ba to c7ce2d8 Compare June 2, 2026 03:07
Base automatically changed from chore/bump-deps to main June 2, 2026 03:38
@mfw78 mfw78 force-pushed the feat/swarm-spec-primitives branch 2 times, most recently from c0aecfa to ad1563a Compare June 2, 2026 04:05
Adds the canonical Swarm spec/wire primitives so vertex, apiarist, and
future Swarm implementations consume them from one place instead of
duplicating consts.

Bundles:

- Typed newtypes (nonce, network_id, timestamp, proximity_order, bin):
  Nonce(B256), NetworkId(u64), Timestamp(i64), ProximityOrder(u8), Bin(u8).
  NetworkId::{MAINNET, TESTNET} consts; Timestamp::now + skew_check;
  range-validated ProximityOrder/Bin with named thiserror enums.

- compute_overlay(eth, net, nonce) -> SwarmAddress in overlay.rs:
  canonical keccak256(eth || net.to_le || nonce) per bee
  crypto/crypto.go:45-57. Network ID is little-endian here; tests pin
  the LE-vs-BE distinction.

- SwarmAddress proximity API typed: proximity() now returns
  ProximityOrder (was u8). Adds xor() and bin(&anchor) -> Bin.
  Breaking change to the primitives crate.

- SwarmSpec trait in spec.rs with default methods sourcing bee's
  canonical knobs (saturation_peers=8, over_saturation=18,
  bootnode_over_saturation=20, neighborhood_low_watermark=2,
  clock_skew_tolerance=6h). StaticSpec, MAINNET, TESTNET.

- recompute_neighborhood_depth in neighborhood_depth.rs: pure function
  port of bee kademlia.go:896-920. Routing-layer wrappers stay with
  each downstream impl; nectar owns just the math.

- signing.rs: SIGN_DATA_PREFIX and sign_data(...) builder for the
  canonical BzzAddress sign-data byte layout per bee
  bzz/address.go:138-160. Transport-agnostic, caller passes
  underlay_bytes as raw wire bytes. Signing and recovery are NOT wrapped;
  callers use alloy's signer.sign_message_sync /
  Signature::recover_address_from_msg directly.
@mfw78 mfw78 force-pushed the feat/swarm-spec-primitives branch from ad1563a to b08e09d Compare June 2, 2026 04:08
@mfw78 mfw78 merged commit 3c99edc into main Jun 2, 2026
5 checks passed
@mfw78 mfw78 deleted the feat/swarm-spec-primitives branch June 2, 2026 04:23
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 2, 2026
@mfw78

mfw78 commented Jun 2, 2026

Copy link
Copy Markdown
Member Author

Follow-up: #42 tracks consolidating the bee source citations introduced here into a single reference doc.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant