Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

API reference

audience: users

A compact reference of the surface the zipnet facade crate exposes. Link-in-book pages cover the “how”; this page is the “what”.

The whole import story

Almost every user-side agent pulls from exactly one module:

use zipnet::{
    // The universe constant.
    UNIVERSE,

    // The typed facade + handle types.
    Zipnet, Submitter, Receipts, Reader,

    // Deployment fingerprint.
    Config, ShuffleWindow,

    // Datum contract.
    ShuffleDatum, DecodeError,

    // Identifier types and macros.
    UniqueId, NetworkId, Tag, unique_id,

    // Value types.
    Receipt, Outcome, SubmissionId, RoundId,

    // Error model.
    Error, Result,
};

Constants

ItemTypeRole
zipnet::UNIVERSENetworkIdThe shared mosaik universe every zipnet deployment lives on. Build your Network against it.

Deployment fingerprint

pub struct Config { /* opaque, const-constructible */ }

impl Config {
    pub const fn new(name: &'static str) -> Self;
    pub const fn with_window(self, window: ShuffleWindow) -> Self;
    pub const fn with_init(self, init: [u8; 32]) -> Self;

    pub const fn name(&self) -> &'static str;
    pub const fn window(&self) -> &ShuffleWindow;
    pub const fn init(&self) -> &[u8; 32];
}

pub struct ShuffleWindow { /* opaque */ }

impl ShuffleWindow {
    pub const fn interactive() -> Self; // 1s rounds, up to 64
    pub const fn archival()    -> Self; // 30s rounds, up to 1024
    pub const fn custom(
        round_period:     std::time::Duration,
        min_participants: u32,
        max_participants: u32,
        fold_deadline:    std::time::Duration,
        round_deadline:   std::time::Duration,
    ) -> Self;
}

Every field folds into the deployment id — see Quickstart — Pin the deployment in a const.

Datum contract

pub trait ShuffleDatum: Send + Sync + Sized + 'static {
    const TYPE_TAG: UniqueId;
    const WIRE_SIZE: usize;

    fn encode(&self) -> Vec<u8>;
    fn decode(bytes: &[u8]) -> Result<Self, DecodeError>;
}

pub struct DecodeError(pub String);

Every value of D MUST encode to exactly D::WIRE_SIZE bytes. TYPE_TAG and WIRE_SIZE both fold into the deployment identity; schema bumps produce a different id and fail to bond cleanly rather than silently garble.

The typed façade

pub struct Zipnet<D: ShuffleDatum>(/* marker */);

impl<D: ShuffleDatum> Zipnet<D> {
    pub async fn submit  (network: &Arc<Network>, config: &Config) -> Result<Submitter<D>>;
    pub async fn receipts(network: &Arc<Network>, config: &Config) -> Result<Receipts<D>>;
    pub async fn read    (network: &Arc<Network>, config: &Config) -> Result<Reader<D>>;

    pub fn deployment_id(config: &Config) -> UniqueId;
}

Zipnet<D> is a marker — there is no instance to hold. The three constructors open the writer, encrypted-receipt watcher, and read-side streams for the deployment described by Config and the datum type D. All three reach the same on-wire identity derived from Config + D’s TYPE_TAG/WIRE_SIZE.

deployment_id is a pure function useful for handshake diagnostics — print it on both sides to confirm you and the operator compute the same fingerprint.

Handle types

#[derive(Clone)]
pub struct Submitter<D: ShuffleDatum> { /* opaque */ }

impl<D: ShuffleDatum> Submitter<D> {
    pub async fn send(&self, datum: D) -> Result<SubmissionId>;
}

pub struct Receipts<D: ShuffleDatum> { /* opaque */ }
impl<D: ShuffleDatum> futures::Stream for Receipts<D> {
    type Item = Receipt;
}

pub struct Reader<D: ShuffleDatum> { /* opaque */ }
impl<D: ShuffleDatum> futures::Stream for Reader<D> {
    type Item = D;
}

Submitter<D> is Clone; all clones share one driver task. Drop every clone to tear down the writer. Receipts<D> and Reader<D> are independent stream handles; drop them individually.

Value types

pub struct SubmissionId(pub u64);

pub struct Receipt {
    pub submission_id: SubmissionId,
    pub round:         RoundId,
    pub slot:          usize,
    pub outcome:       Outcome,
}

pub enum Outcome {
    Landed,   // happy path
    Collided, // slot collision; retry next round
    Dropped,  // aggregator never forwarded; retry
}

Receipts arrive on the Receipts<D> stream, one per past submission; the SubmissionId correlates back to the send call that produced the payload.

Errors

pub type Result<T, E = Error> = core::result::Result<T, E>;

#[derive(Debug, thiserror::Error)]
pub enum Error {
    WrongUniverse { expected: NetworkId, actual: NetworkId },
    ConnectTimeout,
    Attestation(String),
    Shutdown,
    Protocol(String),
}

See Troubleshooting for a per-variant diagnostic checklist.

Re-exports from mosaik

ItemFromUse
UniqueIdmosaik::UniqueIdAlias for 32-byte intent-addressed identifiers.
NetworkIdmosaik::NetworkIdType of UNIVERSE and WrongUniverse fields.
Tagmosaik::TagPeer-catalog tag type. Rarely needed directly.
unique_id!mosaik::unique_id!Compile-time UniqueId construction.

Re-exports from zipnet-proto

ItemRole
RoundIdMonotonic round counter; appears on Receipt.

What you do NOT import

  • zipnet_node::* — committee and role internals. Users do not construct CommitteeMachines or run committee Raft groups.
  • mosaik::groups::GroupKey — you do not have committee secrets.
  • Any raw StreamId / StoreId / GroupId — the SDK derives them from Config + D. Do not try to pin them yourself.

If you find yourself reaching for these, you are probably writing an operator or contributor concern. Revisit What you need from the operator.

Version compatibility

DependencyVersionNote
mosaik=0.3.17Pin exactly; minor versions change wire formats.
zipnetfollow the deployment’s release notesKeep in lockstep with the operator’s version.
tokio1.xAny compatible minor.
futures0.3For StreamExt::next on Receipts<D> / Reader<D>.

When the operator announces a deployment upgrade, they should publish the zipnet version to use. Users rebuild and redeploy in lockstep.