Built for ZECATHON · Shielded Payments

Pay and talk when the network won't.

Murmur carries a real shielded Zcash transaction and a sealed note from device to device with no internet. Whoever reconnects first broadcasts it.

Verified on the Zcash testnet
txid 5110a458bd641e54…48a4c8fd43See the proof

Payer writes:

Paid. Two bags, pickup at 5.

A relay sees:

9F3A C71E 04B2 E8D1 5A60 B7F2

Merchant reads:

Paid. Two bags, pickup at 5.

Illustration of one sealed note. The ciphertext shown is a placeholder, not real output.

Proof, straight from the logs.

Three numbers, each traced to a file in the project's evidence folder.

block.case

A shielded payment, built with the network cut and carried across Murmur:

Mined in testnet block 4,550,000 after one broadcast.

evidence/04Testnet
bytes.case

The transaction crossed the carrier between two processes:

5,222 bytes in, the same SHA-256 out.

evidence/04 · loopbackVerified
tests.case

Run from the project folder with Node 18.3 or newer:

52 tests pass. One needs a funded wallet.

node --test test/*.test.jsNo dependencies

Why Murmur

Private money shouldn't depend on a network someone can switch off.

Murmur carries a real shielded Zcash transaction and a sealed note from device to device.

Whoever reconnects first broadcasts it, and the payment confirms on chain.

Explore Murmur

Offline build, sealed notes, spend policy and payment requests: what a payment needs to move without a network.

Offline build

The payer's wallet creates, proves and signs a shielded transaction with no connection at all. Only the final raw transaction leaves the device, never the partly built file that can hold viewing keys.

See the offline log

Sealed notes

Notes and receipts are sealed to one recipient. The sender's key is mixed into the key derivation, so a forged sender is rejected. Verified in tests.

Try the simulation

Spend policy

Caps per payment and while offline, plus an optional recipient list. The policy bounds double-spend risk. It does not remove it.

See the limits

Payment request

A merchant shares a ZIP 321 request. The payer's command reads the address, amount and memo from it, then builds the payment. One was paid on the testnet in block 4,550,881; the memo did not show up on chain.

See the commands

Run it from the command line

Real commands from the project's CLI. The carrier needs only Node; payments also need the patched zcash-devtool. Testnet only.

Pick a role. The window shows the command that role runs.

request

        
simulation

See Murmur relay

Six devices in your browser, with the packet loss you choose. It follows the same flooding, hop limit, duplicate drop and retransmit rules as the real carrier, rewritten for this page. Select a device to see what it can read.

controls.sim

Pay.

The payer sends the transaction and a sealed note.

Relay.

Devices forward with a hop limit and retransmit lost packets.

Confirm.

The gateway broadcasts once and the merchant opens the receipt.

result.log

Press Send payment to run.

inspector.txt

Select a device to see what it can read.

Delivery under packet loss

Each bar is 300 simulated runs with four retransmit rounds. A run counts as delivered when the merchant received both sealed packets and the gateway broadcast exactly once.

Run it yourself
loss.chart
0%100%
10%100%
20%97.7%
30%93.0%
40%71.7%
50%43.3%
60%12.3%
Simulation. Packet loss applies on every link.

What the logs say

Lines copied from the project's evidence folder.

payer.jsonl
{"kind":"sent","txid":"5110a458…","bytes":5222}

Payer · evidence/04

wallet-list-tx
Mined: 4550000 (2026-10-28 6:21:42)

Wallet sync · evidence/04

gateway-listener.jsonl
{"kind":"broadcast","ok":true}

Gateway · evidence/04

steps.status
probe offline ok · create offline ok · prove offline ok · sign offline ok · combine offline ok · extract offline ok

Network namespace · evidence/03

early-failure.txt
Failed to sign Sapling spend 0: MissingProofGenerationKey

An early failure, fixed · signing now uses the proven file

receipt.sealed
{"kind":"receipt","amountZat":1000,"policyHash":"b94caa29…"}

Merchant, receipt opened · evidence/04

offline-probe.txt
1: dns error · 2: failed to lookup address information: Temporary failure in name resolution

Inside the no-network namespace · evidence/05

payer.jsonl
{"kind":"ack","of":"receipt","from":"fdc4b11c…","sender":"fdc4b11c…"}

Acknowledgement with the sender's key · evidence/05