A term is paid for up front, by four separate keys
The funder opens a term naming the school’s probe key, the provider, the attester, the arbiter, the contracted network, the pass bar and the daily rate. The contract takes the whole term’s money at once (rate × days), so the provider can see it exists before doing any work. It refuses a term where one key holds two roles, so nobody can be both the judge and a party.
The provider accepts by posting a bond before the first day starts. Until it does, the funder can take the money back.
A reading needs two signatures
The probe in the school signs the reading with EIP-712: when it was taken, download, upload, round-trip time, a hash of the M-Lab test ids (download and upload) and a salted hash of the client address. Change one digit and the signature breaks.
The term’s attester submits it, adding one fact the probe cannot vouch for: the network number (ASN) of the address M-Lab saw, looked up in RIPEstat. It refuses a reading sent from a different network than the one the test ran over. The contract checks the probe’s signature and that the full test ids match the signed hash. A test can be used once, ever.
A day is split into parts, and each part has to pass
A reading passes when all four hold: it ran over the contracted network, download and upload are at least the bar, and the round trip is at most the bar. The result goes on chain with the full M-Lab test ids in the ReadingRecorded event.
The school’s opening hours each day are divided into as many equal parts as the term requires passes, and only the first pass in each part counts. A line that works for half an hour cannot earn a whole day by retrying, and a probe never has to test at night: a pass outside school hours counts for nothing.
A day holds at most 24 failing readings, so a probe cannot flood a day, but a pass the day still needs is always accepted.
A probe that cannot get online says so
When the line is dead the probe cannot reach M-Lab, so it signs an offline report instead, with zero speeds and a test id that starts with offline:. Because the line it would use is down, the report is meant to travel another way, such as the headteacher’s phone on mobile data, and the contract accepts it until the day settles (a test with speeds must arrive within the late window). That makes the difference between a dead line and a dead device visible on chain, even in a cut that lasts weeks.
A day closes, waits, then settles
A reading counts for the school day it was taken in, and may arrive until the late window after that day ends. Then the challenge window runs. After both, anyone can settle the day; the demo’s attester does it so visitors never need gas. Days settle strictly in order, so runs of failures are counted correctly.
The mark decides the money
- Present: a pass in every part of the day. Paid in full.
- Partial: passes in some parts. The provider gets that share; the rest goes back. Fewer than half the parts is also a strike.
- Absent: the probe reported (failed tests or offline reports) and nothing passed. Refunded, and a strike against the provider.
- Silent: nothing reported at all, which is what a power cut or a switched-off device looks like. Refunded, no strike.
- Closed: the school declared it before any test that day. Refunded, no strike.
- Voided: a challenge was upheld. Refunded, a strike, and part of the bond goes to the funder.
Only the school can close a day, and only before it tests
Weekends, holidays, exams and floods are not the provider’s fault. The probe key signs a closure for a day or a run of up to 31 days with a reason. It is accepted only while those days have not ended and have no reading at all, so a closure can neither erase a failure the probe saw nor take back a pass the provider earned, and the same closure cannot be sent twice.
The funder can challenge; the arbiter decides, or the challenge lapses
Once a day has ended and before it settles, the funder can challenge it, for example when its test ids are missing from M-Lab’s public archive, by staking the term’s challenge deposit. Upheld: the day is voided, the deposit comes back and the bond is cut. Rejected: the deposit goes to the provider. If the arbiter stays silent for one more challenge window, the challenge lapses, the day settles as measured and the deposit goes to the provider, so nobody can freeze a term.
Repeated failure ends the term
Absent days, voided days and days passing fewer than half their parts are strikes; a day passing at least half resets the count; silent and closed days leave it alone. One weak pass a day cannot keep a failing line in a term forever. After the agreed number of strikes in a row, the funder can end the term: unserved days come back with a cut of the bond, the rest of the bond goes back to the provider. A finished day with any passing test must settle first, so a day the provider earned is always paid.
Money is never created or lost
Every unit the contract holds is owed for a future day, held as bond, or held as a challenge deposit. A fuzz test runs 500 random terms (random speeds, networks, parts of the day, closures, challenges and lapses) and checks after each that nothing was created or lost, that paid plus refunded covers every day, and that no day paid more than its rate.
What the demo simplifies
- The four roles are four separate keys, but all four are held by this demo’s server. In a real term they are four organisations.
- One attester per term. A quorum of attesters, each checking the network independently, is the next step.
- The visitor’s probe key lives in browser storage. A school device would keep it in hardware.
- The test dollar has no value and anyone can see its owner mints it for the demo.
- Speeds are what M-Lab’s server counted, relayed by the probe (falling back to the browser’s own count if the server sends none). Only an archive check proves they were not edited before signing, which is why challenges exist.