Three steps, and no account
Think of an arcade: you buy tokens at the counter, then spend them on the games. Here the counter is the router's shop, the tokens are vouchers, and the game is internet access.
1 · Get vouchers
Pay with Lightning, hand over vouchers you already have, or take free ones if the owner gives access away.
2 · Pick a speed
Fast, Balanced or Duration. The router opens the gate at that speed, and the clock starts. The faster the speed, the sooner your balance runs out.
3 · Run out, top up
When the time is up, the gate closes and the next page you open is the sign-in page again. Top up or slow down whenever you like before that.
A voucher is not money. It is a promise from this router to carry one byte for you. The price in sats, dollars or euros is set only where vouchers are sold.
You rent a lane, not a pile of bytes
Picking a speed is like renting a lane on a road: it is kept open for you at that width, so the clock runs whether or not you use it. That is why the sign-in page shows your balance as time left, not data left: a data counter would keep falling while your phone sits idle, as if you were charged for bytes you never used.
Pick a slower speed and the same balance lasts longer.
The same rule can sell bytes instead of time: reserve no speed, and only what you actually move is taken. How one rule does both →
A small core, and an add-on for phones
Open the box one layer at a time. Then tap any part to see what it does.
Tap any part to see what it does. Parts marked + open a description below.
From the outside it is just a Wi-Fi router. Phones join it; it connects them to the internet, and only as fast and as long as they paid for.
From joining the Wi-Fi to the time running out
Choose how the phone pays, then step through. The diagram lights up the parts that are busy; the phone shows what its owner sees.
Pick how the phone pays, then press Next or Play. Tap a dot to jump to a step.
Under the hood
What the phone shows
Money goes to the shop, vouchers go to the gate
Only one place in the router ever sees money: the shop, merchantd. Everything after it deals in vouchers, which count bytes, not sats.
Drag the sliders to see how long a payment lasts at each speed.
How long does a payment last?
How the maths works
A Mbit is 125,000 bytes, so one sat buys 125000 / price_per_mbit bytes. At the packaged price that is about 17.9 MB per sat, so 1 GB costs 56 sats.
The time shown is bytes × 8 / (Mbit/s × 10⁶), and it is exactly how long it lasts: a session buys its speed for every second it runs, whether you download flat out or sit idle. Browsing lightly does not stretch it; picking a slower speed does.
The clock runs while you're connected, used or not, so a slower speed makes the same payment last longer.
No price on the wire
The gate only counts: one voucher, one byte. Whoever wants to charge more sells their vouchers dearer. Nothing is haggled once you are connected.
Paid just ahead
A few seconds at your speed are paid for before they start, used or not. Paying again early loses nothing: what's left carries over. If payments stop, the gate slows to a trickle. Nobody ever owes the router afterwards.
Used means cancelled
Once bytes are delivered, the gatekeeper cancels those vouchers at the mint. What the mint still has out is exactly what the router still owes.
A locked jar, and a note every few seconds
Vouchers are not handed over one byte at a time. The buyer locks a batch in a jar (a payment channel) that only the router can open. Then, every few seconds, it signs a note: "you may now take this much in total." What the total went up by is added to the buyer's budget. The note also names a reserved speed: every second the router takes that much from the budget, busy or idle, and more only if more was moved.
Pick a speed, then press Run it to watch the jar fill.
Press Run it. Gold is what is still locked in the jar; teal is what the signed notes have already handed to the router.
Why a jar, and what happens when it fills
The jar is a Spilman payment channel: vouchers locked so that spending them needs both sides' signatures, or the buyer's alone after it expires (one hour by default). Each note is a TopUp: a signed, ever larger running total, plus a window and a reserved speed. What the total went up by (the grant) is added to the budget; nothing already there is lost. Every second the router takes the larger of what was moved and the reserved speed, so idle seconds still cost. Whatever is left expires only at the deadline, which each note pushes out to at least now + window. A buyer renewing early simply carries the rest over. More on the one rule →
Why not just hand over vouchers? Not to prevent theft. Every spent voucher stays in the mint's records forever, and a jar puts its vouchers there once, when it is cashed in, instead of a dozen at every note: roughly 700 times fewer records.
At 80% full (or near expiry) the buyer locks a second jar. The first is drained to 100%; a note that straddles the two is signed across both at once. proxyd uses jars of up to 256 MiB per phone, and funds a new one only if the phone still has credit to cover it.
Cashing in: only the router settles, at the mint that printed the vouchers. Its own vouchers are then cancelled (burned) at mintd; another mint's are kept and handed to merchantd, or burned, as the owner chooses per mint. The buyer's unspent change goes back to it.
Devices that speak TollGate skip the portal
The portal add-on exists because phones don't run TollGate. A laptop or another router that does run it talks to the gatekeeper directly, and does for itself what proxyd does for a phone.
How the two differ
- Getting vouchers. The device's own merchantd tries the router's mint first (free, if it gives them away), then buys at the router's shop. For a phone, proxyd turns whatever the phone paid into the router's vouchers.
- Keys and wallet. The device has its own. For a phone, proxyd makes a key per device, kept in memory, and keeps all phones' vouchers in one wallet with a budget per device.
- Who pays whom. A phone or a laptop is a plain customer: it buys, the router never buys back, so there is one jar and the customer needs no mint of its own (its session says
no_charge). Two routers that peer each sell to the other, with two offers and two jars, one per sale. - Uploads. The router's offer says how much a byte the buyer sends costs next to a byte it receives (
from_payer_weight). The default is 1, so an upload costs the same as a download, for phones and devices alike. An owner on a lopsided line can raise it; 0 makes uploads free. Peering routers usually set 0, so each pays only for what flows towards it. Who pays for upload → - Talking to the gate. A device connects from its own address. proxyd connects from the phone's address, so the gatekeeper applies the phone's gate and speed to the phone's real traffic. proxyd never touches that traffic.
The part that talks to strangers holds nothing worth stealing
Each program holds only what its job needs. Tap one to see what someone could do if they broke into it, and what they still couldn't.
Tap a program to see what a break-in would expose.
Not "trustless", on purpose
The router prints its own vouchers, so the one who could refuse to honour them is the one who sold them. No clever maths fixes that. What limits the risk is size: you only ever have a few seconds at your speed paid ahead, and a router that stops honouring its vouchers soon finds nobody buying them.
Private by design
No account, no email, no card. The mint signs vouchers without being able to see which ones it signed, so it cannot link a voucher back to who bought it.
More detail
Vouchers are blind-signed bearer tokens in unit byte. A router does know which device it is talking to: that is how it gates and shapes it. What it cannot do is tie the payment itself to a person.
Where it is still rough
Everything above is built and tested on a computer, except where a row below says otherwise. Here is what isn't finished yet.
Running on a real router
Packaged for OpenWrt 24.10 and 25.12. The first real-router demo works: a phone joins, lands on the portal, takes free vouchers or pays by Lightning, picks a speed and browses. Wider testing is next.
The portal shows time left, not data left
A session buys its speed whether or not the phone uses it, so a data counter fell even while the phone was idle, which looked like being charged for bytes it never used. The sign-in page is moving to show the balance as time at the chosen speed, such as “2h 14m left at Balanced”, with the data amount as a detail.
One rule for paying
Paying now works one way for everyone: a budget with a deadline, drawn every second at the larger of what was moved and the reserved speed, with uploads weighed by the router's offer. Paying again early no longer throws the rest away, and a budget survives a reconnect or a restart of the router. The design is settled and described on this page; the code is catching up. See how it works →
A restart forgets the phones
proxyd keeps sessions in memory. If it restarts, every phone lands back on the portal and its unspent credit is lost. It needs saving to disk.
Speeds aren't capped by the real link yet
Fast, Balanced and Duration should be limited to what the uplink really carries, as measured by tollgated. Until then the owner sets it by hand, or it is uncapped.
IPv6 is gated per phone
Phones pick several IPv6 addresses and change them daily, so the router ties them to the phone's hardware (MAC) address. A phone's IPv6 now goes through the same gate and speed as its IPv4, on the same balance. Catch: a phone with only IPv6 can't buy yet, since sessions still start over IPv4.
An upload costs the same as a download
Out of the box the router weighs a byte a phone sends the same as a byte it receives, so uploading costs no more than downloading, and its time left runs down at the same rate either way. The owner can change that weight in the router's offer, but it can never go below zero: nobody gets paid for sending.
A phone mustn't run TollGate itself while on the portal
While proxyd speaks for a phone, anything the gatekeeper sends to the phone's TollGate ports is diverted to proxyd.
The shop on another machine
All three core programs are meant to run on one box today. Running merchantd elsewhere needs authentication in place of local-only access, and is left for later.
- Voucher
- A promise from one router to carry one byte for whoever holds it.
- Captive portal
- The sign-in page a phone sees when it joins, before it has paid.
- Jar (payment channel)
- Vouchers locked for one router, paid out note by note.
- Grant
- What one signed note adds to your budget. Nothing already in the budget is lost when a new one arrives.
- Budget and deadline
- What you have paid for and not yet used, and when what's left expires. Every second the router takes the larger of what you moved and your reserved speed.
- Reserved speed
- The speed kept free for you, paid for busy or idle. Reserve none, where the router allows it, and you pay only for what you move.
- Mint
- What prints and cancels vouchers. Each router has its own.
- Free mode (auto-accept)
- The owner's switch to give vouchers away, a limited number of requests per minute.