Erebus

Docs · devnet

Run the mixnet

Three hops on your own machine, in about a minute. For the design behind it, read the paper.

Erebus is two things: a Rust workspace that implements the mixnet, and this site, which documents it. Nothing here talks to a live network yet — the code runs a three-node mixnet on your own machine, and every node, key, and route below is one you created.

Run a mixnet locally

git clone https://github.com/Erebusorg/erebus
cd erebus/mixnet
cargo test
./scripts/local-network.sh "buy 10 AAPL"

The script generates three node keys, writes a registry, starts a node per layer, starts an echo service, sends one request through all three hops, and runs a loop probe back to itself:

echo: buy 10 AAPL
probe returned in 131 ms

Every packet on every link is exactly 32 KB, whether it carries that message, a reply, or cover traffic.

Do it by hand

Each node needs a key and an address:

cargo run -p erebus-node -- keygen --out entry.key
cargo run -p erebus-node -- run \
  --key entry.key --listen 127.0.0.1:9001 --registry registry.json

The registry is a plain JSON file for now, and every client derives the same layer assignment from it, so there is no directory server to trust:

{
  "epoch_seed": "erebus-devnet-1",
  "nodes": [
    {
      "id": "<32-byte public key, hex>",
      "address": "127.0.0.1:9001",
      "stake": 0
    }
  ]
}

Then send something through it:

cargo run -p erebus-client -- sink --registry registry.json --listen 127.0.0.1:9100
cargo run -p erebus-client -- send \
  --registry registry.json --to 127.0.0.1:9100 --message "buy 10 AAPL"
cargo run -p erebus-client -- probe --registry registry.json

The client picks one node per layer, samples an exponential delay for each hop, builds the packet, and attaches a reply block whose return path is chosen independently of the forward path. The service answers into that reply block without ever learning where you are.

Reading the node set off a chain

A file works on one machine, but a node set that participants have to trust each other about is exactly the coordination point Erebus is trying not to have. The same binaries take the registry contract instead:

cargo run -p erebus-node -- run --key entry.key --listen 127.0.0.1:9001 \
  --chain-rpc https://rpc.testnet.robinhood.com --contract 0xREGISTRY
cargo run -p erebus-registry -- fetch --rpc $RPC --contract 0xREGISTRY

The contract is in contracts/: a node registers a public key, an endpoint, and a bond; announcing an exit stops it being selected immediately but keeps the bond slashable for the unbonding period; and one snapshot() call returns the epoch, its seed, and every node clients should be routing through. Nothing after that read differs — layer assignment and path selection already derive from public data alone, so reading the set needs no account and signs nothing.

The whole thing end to end on a local chain, with three nodes that stake and register themselves (foundry required):

cd contracts && forge test
cd ../mixnet && ./scripts/chain-devnet.sh

What each hop learns

HopLearnsCannot learn
EntryYour address, the relay it forwards toThe exit, the destination, the payload
RelayThe entry and the exitYour address, the destination, the payload
ExitThe relay, the destination, the payloadYour address, the entry
DestinationThe request, a reply blockYour address, the path, whether a reply block is reused

No field of a packet survives a hop: the header element, the routing block, and the payload are all re-randomized, so two hops that compare notes see nothing in common except the packet size, which is the same for every packet.

Crates

CrateResponsibility
erebus-sphinxPacket format: header, layered payload, reply blocks
erebus-topologyRegistry, layer assignment, path selection, delay sampling
erebus-wireFixed-size framing between nodes
erebus-nodeThe mix node: peel, delay, forward, reject replays
erebus-clientRequests, reply blocks, cover traffic, loop probes, demo sink

Measure it

cargo run --release -p erebus-sphinx --example bench

Prints the cost of building a packet, of one hop processing it, and of the replay tag. The numbers from this machine are on the benchmarks page.

Not built yet

The registry contract is written and tested but deployed nowhere, so stake is real only on a chain you start yourself. Nobody is paid for running a node, the decision to slash is still a human one made off chain, and there is no key rotation and no node-originated cover traffic. Fees are not shielded, and no public network is running. A browser can already use all of this — see the SDK — but only against a devnet you start yourself. The paper states which of these are engineering work and which are open problems.