zipnet — anonymous submission
audience: contributors
Proposed source: not in this repo. The lattice consumes the existing flashbots/zipnet crate unchanged at whatever version the lattice pins. This page documents only the lattice-specific wrapping.
What the lattice consumes
zipnet::Zipnet::<D>as the external SDK surface for wallets and searchers submitting into the lattice.zipnet::UNIVERSEwhich is identical tobuilder::UNIVERSE(both resolve tounique_id!("mosaik.universe")).zipnet::Configas one field of theLatticeConfig.zipnet::Broadcastsas the only upstream input tounseal(see unseal).
Authoritative docs for everything above live in the zipnet book:
Lattice wrapping
Three wrapping facts that matter at the builder level and do not appear in the zipnet book because zipnet does not know it is in a lattice.
1. Instance name derivation
A zipnet deployment that is part of a lattice takes its
zipnet::Config.name directly from the lattice’s instance
name. The builder meta-crate’s LatticeConfig constructor
enforces this:
impl LatticeConfig {
pub const fn new(name: &'static str, chain_id: u64) -> Self {
Self {
name,
chain_id,
// zipnet's own content + intent addressing folds the
// lattice name in as the zipnet instance name.
zipnet: zipnet::Config::new(name),
unseal: unseal::Config::new(name),
offer: offer::Config::new(name),
atelier: atelier::Config::new(name),
relay: relay::Config::new(name),
tally: tally::Config::new(name),
}
}
}
Two lattices under different names get disjoint zipnet
GroupIds by the zipnet content + intent addressing rules,
exactly as intended. A lattice cannot share a zipnet committee
with another lattice; a zipnet committee belongs to exactly one
lattice.
2. Sealed payload convention
Zipnet shuffles opaque D: ShuffleDatum values. The lattice’s
convention is that D carries an unseal-sealed payload:
the application-level transaction (e.g. an EIP-2718 RLP) is
first encrypted to the unseal committee’s threshold public
key, then right-padded to D::WIRE_SIZE, then submitted.
The reference datum is Tx2718; its WIRE_SIZE is set by the
lattice such that
unseal::seal(max_app_payload).len() <= Tx2718::WIRE_SIZE
with enough slack for the AEAD overhead. The exact constant
ships in the lattice’s datum crate.
This convention is enforced at the integrator layer (see
integrators/submitting.md);
zipnet itself does not know or care what is inside D. A
lattice that fails to seal payloads before submission is still
a valid zipnet deployment; it is just not a lattice whose
anonymity holds beyond zipnet’s own guarantee.
3. Consumer: the unseal organism
The lattice’s only downstream consumer of
zipnet::Broadcasts is the unseal organism. Every other
organism reads from unseal::UnsealedPool instead — the
cleartext side — because they need to reason about the actual
transactions, not the ciphertext.
This means in operational terms: if unseal is down but
zipnet is up, zipnet continues to commit Broadcasts (no
back-pressure from unseal); those broadcasts simply accumulate
without producing downstream effect until unseal recovers.
See composition.md — failure table.
State machine
Unchanged from zipnet. CommitteeMachine as specified in the
zipnet book’s committee state
machine page. signature() folds in the zipnet
wire version plus its round parameters; the lattice does not
add further inputs.
Cryptography
Unchanged from zipnet. X25519 ECDH + HKDF-SHA256 + AES-128-CTR for pads, keyed blake3 for the falsification tag. See Cryptography — zipnet in this book for the summary and zipnet cryptography for the full derivation.
ACL composition
zipnet::Config carries its own TicketValidator composition.
In a TDX-gated lattice it stacks with the lattice-level
tee-tdx feature:
// In the integrator agent's Cargo.toml, when tee-tdx is enabled:
zipnet = { version = "...", features = ["tee-tdx"] }
The validator chain pins atelier’s MR_TD for committee
admission (so zipnet committee members are TDX-attested
peers). Writer-side admission of external submitters is gated
by the lattice operator’s JWT issuer key — same mechanism
zipnet ships.
Trust shape
Any-trust on anonymity; crash-fault on liveness. See threat-model.md — zipnet. No change from the zipnet book.
Open questions specific to the lattice
- v2 receipts stream. Zipnet defers
Receipts<D>to its v2. The lattice’stallyorganism is a partial replacement at the attribution layer but does not restore the per-submitter receipt shape zipnet’s design contemplates. Does the lattice want to push for zipnet’s receipts to land, or istallyenough? Open. - Cover traffic rate. Lattices targeting public L1 PBS
have different anonymity-set cadences from lattices targeting
a fast L2 sequencer. The zipnet
ShuffleWindowpreset (interactive,archival) covers the common cases; lattices with unusual chain cadences ship a custom window, which folds into the zipnet fingerprint as usual. - Multi-lattice zipnet sharing? Not supported. A zipnet
committee belongs to exactly one lattice. Proposals to share
one zipnet across lattices would need a new zipnet shape
(higher-dimensional
Config) and are out of scope.
Cross-references
- The six organisms — the index that lives one level up.
- unseal spec — the immediate downstream.
- composition.md — the subscription graph zipnet feeds into.
- threat-model.md — trust composition.