FoodBlock 1.7
Deals that fit how food really trades, and nothing filled in for anyone.
A large revision of 1.6. It came from testing the protocol against how people really organise food work, from fuzzing two independent engines against each other, and from two full reviews: one against its founding ideas, one against attackers.
The thinking behind 1.7
Silence is not agreement. Most of 1.7 applies one rule more strictly than 1.6 did: a signed word binds only its signer, and nothing fills in what anyone left out. So the protocol now holds no defaults, records facts rather than verdicts, puts no duty on anyone who didn't sign it, and gives no company, state or law a special place.
Never their body. A signed word binds only its signer, never their body. What one can hand on is what one acquired or was handed; a body was never acquired, so no word hands it on.
The three remedies
A broken deal has three remedies, and 1.7 now carries all three as facts: what is still the other side's comes back, what both signed for this case moves, and anyone may refuse to deal again. Force or fraud is not a broken deal but an attack; it goes to the victim's judge.
What's new
Richer deals, still one shape
- Promises not to do something: "no pesticide until March", "sell only to me".
- Conditions the protocol can check: "after that is paid", "after this deed", a sensor reading, a signal from named people.
- A new condition,
accepted: "I buy in Leeds only if York says yes." A trader can sign both halves at once and never get stuck holding goods nobody wants. - Open offers anyone can answer. Haggling with them works over any number of counter-offers. Whoever accepts the last counter makes a deal, and it counts against the offer's stock, so nobody oversells by accident.
- Limits in any unit (kilos, covers, hours, not just money), and a cap on any single act.
- Vouches with a written-out cap and shares back: a voucher can write "all I hold" (shown as "no limit"), and co-vouchers can sign how they share what one of them pays. Nothing is equal or unlimited by default.
- Savings circles that anyone can check: a draw for turns from commitments and reveals (a late reveal goes last by the member's own word), rule changes only within bounds a member signed, a lock on a pot, and a share of the members as a count.
- A circle can be the judge of a claim of harm, ruling through the members who hold the power to sign for it.
- Real calendars and time zones, and repeats. Each week's payment names its own week.
- Catch weight: "10 kg of cod, give or take 5%".
- Pay-by dates.
- Referees the deal names in advance. When more than one is named, the deal says how many must agree, or nothing rules.
- Group pledges, as a published schema: "I pay my share if pledges reach KSh 12,000." The schema counts money pledged, not keys.
- Conditions that something didn't happen by a time: "if he hasn't arrived by 9am, the £200 is yours." The time comes from a clock both sides chose, so nobody can backdate.
- A transfer can carry a condition: title moves when the condition holds, with no second act. Kept until paid, an escrow, a pawn. The one it would benefit can let it go by her own word.
- A cap can be a count of things, not only money: "up to 2 heifers", for a vouch or a pool. And a vouch reaches whoever holds anything made from the lot it stands behind.
- A price in any kind: "6 sacks of flour" or "40 eggs" as well as money. Goods paid toward it count in their own unit, and nothing is converted. Money counts toward a goods price, or goods toward a money price, only where the payee signed that they cover it.
- A price fixed later: the figure comes from named readers on a named clock, or as a fraction of a reader's figure, within a minimum and maximum the deal states. A reader who signs two figures counts for none.
- Letting go, and sealed bids: a signed release says "we are settled, nothing more is owed between us, except these debts." Sealed bids count only when they state the same deadline, clock and currency; there is no default clock.
- A visible limit binds: a public grant that shows a limit makes an act past it not under the grant. The side that charges cannot start a charge alone, and a new pay-by date counts only when both sides signed it.
- A share of the members is a count: "two thirds of us" or "all of us", read at the block's own moment. A message can carry a receipt, and a demand counts only once it reached him.
- More shared forms, no new rule: the issuers she relies on, a market-price reading, a holder's record of a loss, who pays any confirmer, and a place's bound as a walk of named marks.
- Leases as shares: 'bench 3, Tuesdays, until June' is a thing the tenant owns, and selling the kitchen doesn't take it away. A share never reaches a kind, a copy, a replanted seed or a person.
- First use of a place or a use (a water draw since 2014): a dated record of acts with its bound, shown with its seasons, its overlaps with a neighbour's, and a clock that is not the author's own. Evidence a referee reads, never title; a resting field stays its user's.
- A will is a transfer conditioned on the successor's close, one worked example, no new primitive.
- On demand, on notice, or on a date: a note can say how long after you ask it pays.
- Pay on a code: "if anyone shows the code, my £5 becomes the rider's." Any computer checks it alike, with no judge or clock.
- A fair clock for "in time": an offer can name a clock both sides trust, so an accept it received in time binds even if the offerer stays unreachable.
- Paid for, never delivered, owed back: money paid for a deal that never came is still the payer's, unless the deal said it's kept. A promise nobody paid for is just a broken word, shown.
- Sell what you're owed: the person owed can sell or give the claim, and the debtor then pays the new holder, unless the deal said it can't be passed on.
- A standard promise of no side payments: anyone acting for you (a buyer, an agent, an AI's operator) can sign "I take nothing from anyone else about what I do for you", with money behind it.
- Vouching: "I stand behind Jide up to £100 until June", with the record showing how much is left, and Jide's own "if you pay for me, I owe you back". An operator can stand behind his own machine for any stranger it harms, and a broker behind the goats he sells.
- Trade rulebooks: a deal can name a shared rulebook and glossary by fingerprint, with a cover price from three quotes, a judge who reads only papers on a deadline, and a window to fix a bad lot before anyone has broken their word.
- Two-key links: "this phone key and that laptop key are both mine" counts as one hand only when both keys sign it. One signature is only that key's word.
Groups
- Refusing together: "none of us deals with X until he settles", binding once enough members have signed, and lifting the moment he pays.
- Mutual pools: members pay in, and a member is paid when the confirmer they all named says it happened, never past what the pool holds.
- Each group states its own removal rule when it's founded. Every removal-like act needs that many holders of the power to remove.
- What someone outside the group built on stands, whatever happens inside it later.
- Closing an open invitation stops new joins. It doesn't throw anyone out.
- A block signed "as the group" is the signer's own word, unless the group asks for more signatures.
Identity and keys
- A recovery key is named in your first block or never.
- Rotating your own key only closes the future. You can't un-sign yesterday's sale.
- A fork (one key signing two different things at the same point) never frees the signer from what they owe. It only voids what they claim.
- One rule for who may add your keys, whatever you call yourself: you, your recovery key, or someone you signed a grant to. A stopped operator can never add a key again: a key grant the decline did not see counts for nothing.
- Your first block may be private.
- Harm with no deal behind it: the person harmed can name a judge, whose ruling is shown as a fact. The accused can answer with his own judge. Nobody gets a veto by refusing to choose one.
- A judge's remark is not a ruling: only her confirms or defeats moves what counts; "no term on this" rules nothing.
Nothing fills your silence
- Force can be named: a signer can add "I signed that under force" (or "that wasn't me", or "I couldn't understand it") beside any block she signed. It's shown forever, nothing is erased, and a judge the deal named can rule it doesn't count.
- The protocol holds no defaults. A block must say who can see it, when it was written and what kind of thing its author is. A grant gives only what it writes down. A repeat names its time zone.
- What a node does is its own published promise, never the protocol's rule. That covers whom it admits, how much it serves and what it forgets.
- Facts, never verdicts. The protocol reports who did what and when. "Kept" or "broken" is each reader's call. There are no scores about people, and no probabilities.
No one governs it
- Public domain (CC0), replacing MIT. Anyone's fork is equal.
- The repository is FoodX's copy. There will never be a steward.
- The words lock once two nodes and one implementation by other people pass the tests. Anyone can check that for themselves.
- No special place for any company, state, law or standards body. A regulator's recall is an ordinary grant. A currency code is one issuer's label.
Security
- One signature, one form: strict Ed25519, low-S P-256, deterministic nonces (RFC 6979).
- A long chain of permissions is checked once per block, so a few crafted blocks can't stall a node (one case went from 36 s to 0.02 s).
- Hard limits on size, depth and digits. Expensive cases were measured and cut, for example a 400-member group from 35 s to 0.5 s, and a forked push from 20 s to 0.3 s.
- A block with no author can't take another block's identity. A block that fails the byte checks is refused at once, out loud, never dropped silently.
- The reference node trusts nothing it's sent, keeps waiting blocks only from their own author, and refuses to start until its owner states every choice.
- Private keys are never printed, and are wiped from memory after use.
- A pinned toolchain, a reproducible WebAssembly core, locked builds and no install scripts.
Smaller and cleaner
- Each rule is stated once, under a named primitive. A text pass cut the spec from about 41,500 words to about 30,200; the later additions brought it to about 50,400 (the profiles, which are optional, to about 14,800). Most of the growth is worked examples.
- One Rust core decides every rule. All five SDKs (JavaScript, Python, Go, Swift, Kotlin) wrap it with code generated from one list of operations.
Breaking changes from 1.6
- Removed:
state.confidence,state.orderer,state.reason;- the recovery pair on a key grant;
versionon messages;- any
suitenamed beside a block (the suite comes from the signing key).
- Now required where it would otherwise widen something:
audience,atand an actor'skindwhen writing;- a repeat's
zone; - a grant's
partiesandacts(unstated means none); - a node's admission, cap and pair choices.
- Renamed: the bearer slip is a "note", never a "voucher" (a voucher is the person who vouches). A grant's
scope.perisscope.every. A refrain past its date iselapsed, notdone. The deposits profile and its admission fielddepositare nowearnest("deposit" keeps one meaning: custody). A right to be paid is owed (stage fieldclaimsis nowowed); "claim" keeps one meaning, a signed assertion not yet settled. - No longer refused: an ask with no expiry, and a membership or key grant with an end date.
- Produce, kinds and letting go: the owner of a hen is the first owner of its eggs; a recipe or any kind has no owner (an idea is not property); an owner who lets a thing go with no receiver ends her title, and whoever next takes it is its first owner.
- Each pay-in is kept or held, in a pool's own terms; a lead may speak for refusal signals by a grant; "all current holders" can be a count; one payment can pay several occurrences; a place use can name a layer, and a dispute of a first use shows its standing; a claim of harm shows whether a signed order is among the evidence and whether the accused was told.
- Re-issued: base schema ids were published again (
kept_promisesandkept_and_brokenare gone), and the CBOR key table was reordered. - Converting old data: 1.6 blocks that carry none of the removed fields are 1.7 blocks. Older data enters once, through
fb convert, which fills in nothing.
How it was checked
- Vectors: 2,927 shared test vectors, passed exactly by the Rust core and by an independent oracle written from the spec text alone.
- Fuzzing: on the final build, 296,087 random cases at the door over 400 random worlds and 90,007 fold queries over 402 worlds, ownership included, with 0 disagreements and 0 answers that depend on order.
- The necessity table: every listed thing is used and tested, none dead.
- Two release reviews (20 readers on the premise, 20 on security). Their 62 findings are fixed or decided.
- Every SDK's own tests, plus the reference node, MCP door and CLI suites. Kotlin and the TLA+ model pass on the final build.
Install
Every package is version 1.7.0. Until the 1.7 packages are published, install from a clone: see DISTRIBUTION.md.
Known limits
spec/THREAT-MODEL.md says plainly who FoodBlock defends against and what it doesn't promise. That includes what a thief with a stolen key can do before the recovery key acts, and the fact that a flood from free keys is bounded only by what each node chooses to charge or admit, including a total for all strangers that a node can publish.
The MCP door's suite has 4 failing tests that come from FoodX's own code, which still writes a 1.6-shaped first block; FoodBlock itself passes.
The full history of every decision is in CHANGELOG.md, and the spec, code and tests are at github.com/FoodXDevelopment/FoodBlock.