The ledger on the relays: technical specification DRAFT 0.3.0
Plain-words text · Technical specification · All documents
English text rendered from the project's source documents. The Slovene original is on lananostr.site. Where this text and the definitions differ, the definitions win.
Precedence: where this document and definitions 0.3.0 differ, the definitions (docs/bsa-records-0.3.0.json) win; the difference is a bug to fix in this document. The definitions pin a frozen copy of this text (docs/0.3.0/) by its sha256 (meta.normative_spec); this living text may change afterwards, and a change reaches the definitions only when they are generated again, which then needs a new yes.
0. Status, markers, scope#
- Status. Draft for definitions 0.3.0. Nothing is built, nothing is published, no EVENT has been sent.
RELAY_PUBLISH_OFF=1stays until the definitions are published (KIND 42893 by the Lana authority) and the project owner says yes (P7, proposal: one yes per definitions version and one per kind switched on). 0.2.0 was never published and is superseded. - Governing text.
docs/nacela-razvoja.md(six principles, the project owner, 16 Oct 2026). A design that breaks one of them is wrong. - Markers. [Decided, date] = the project owner's decision · [Decided 16 Oct 2026, An] = the project owner's answer to question n of 16 Oct 2026 (source:
_reports/2026-10-16-knjiga-na-relejih/odlocitve-2026-10-16.md) · [Decided 16 Oct 2026, 4a / 6a / 8a / 8b / 8c / 8e / 8f / 8i / 8j / start source] = the project owner's answer, the same afternoon, to a point the answers 1–9 had left open (same source file, section "Odgovori na odprte točke"); 6b fell with 6a · [Decided 16 Oct 2026, 6c] = the project owner's later answer the same day to the new open point 6c (»6c, da«; same source file, section "Odgovor na 6c") · [Decided 17 Oct 2026, C1 … C7] = the project owner's answers of 17 Oct 2026 to phase C (»1. DA - parametre shrani v posebni KIND … · 2. DA · 3. DA · 4. DA · … · 6. DA«; same source file, section "Odgovori na fazo C") and, after the explanation of points 5 and 1, »7 Da, Lahko narediš vse skupaj v fazi D …« (section "Odgovor na pojasnilo točk 5 in 1"): C1 the world rules (43920 BSA Rules; replaced on 23 Oct 2026 by E-1), C2 payments never pause for the morning (visit before touch), C3 refusals of non-members not booked, ACT_TTL_S and REJ_PER_AUTHOR_PER_DAY (circle parameters since E-1:act_ttl_s,rej_per_author_per_day), C4 no Heart member rejects a project alone, C5 the circle id and the replaceable circle key, C6 the first-seen rule in the letter to the relay owner (extra safety), C7tz, morning hour andtzdatafixed at founding · [Decided 17 Oct 2026 (evening), 1A / 2A / 3A] = the project owner's answers of the evening of 17 Oct 2026 to three questions after phase D (»vsi da« to the proposal »1A, 2A, 3A«; same source file, section "Odgovori na tri vprašanja po fazi D"): 1A for now only the rules authority's one key signs 43920, several signatures (for example 3 of 5) before the first circle the project owner does not run joins, who the signers are: open (dropped on 23 Oct 2026 with E-1); 2A thetzdataversion pinned at founding (part of C7), and witnesses compute the boundaries with it, never with a newer one of their own; 3A the transition (transition_days) runs per account from its own first receipt · [Decided 23 Oct 2026, E-1 … E-9] = the project owner's answers of 23 Oct 2026 before phase E (same source file, section "Odgovori pred fazo E" with its subsections "Dopolnitev" (E-5's duration confirmed, E-7 witnesses by lot, the accounting of closing an account confirmed) and "Referenca" (E-9, which replaces the "odpustnica" of the Dopolnitev)): E-1 the time values and limits are circle parameters, 43920 and the rules authority are retired (replaces C1, drops 1A, and makes C5's fixed 72 h a default), E-2 the Circle Heart (SL Srce kroga; one person: Heart member, SL član Srca; formerly "stewards"; members never vote on it), E-3 exclusion, readmission and closing old accounts, E-4 the Heart leads OWN processes, E-5 consensus votes instead of approvals and objections (replaces 8c), E-6 joining (open, by invitation, a maximum with a waiting list), E-7 witnesses by lot (the direction for phase I) and the Heart's vote only for exceptions, E-8 founding only by a member, one circle per founder key, one circle at a time, E-9 the reference (43921); D8 the acts for Heart and witness changes accepted; [Decided 23 Oct 2026, E-n Dopolnitev] = the same day's supplement · [Decided 23 Oct 2026, E-9 (a) / (b)] = the project owner's two answers on the reference (same source file, section "Odgovora na vprašanji o referenci") · [Consequence] = follows from the 16 Oct principles or answers, no new decision needed · (Open 3a, 8g, 8h) = a point still open, written as a proposal; 8d (no receiving project: the inflow stays in the reserve) is not open, it follows from decision 8 [A8] · (Qn) = proposal tied to open question n, waiting for the project owner's yes · anything unmarked is part of the recommended design and is also a proposal. - Number labels. [M] measured on 16 Oct 2026 · [C] relay configuration read on 16 Oct 2026 · [R] earlier report or memory · [E] estimate; the constants are in §10.1 so the arithmetic can be re-run.
- Scope. This document is the ledger: the ledger rule, roles as they touch the ledger, the event model, the write path, reads, the daily checkpoint, gravity and duties, projects and the reserve, restore, the ledger relays, sizes and capacity. Governance rules for acts (the Circle Heart, witnesses, projects and votes, parameters, exclusion, readmission, closing accounts, recovery):
docs/upravljanje-kroga.md. Cross-circle details:docs/releji-svetovna-mreza.md. Rates:docs/valute-in-tecaji.md. BSA ID and KIND 0:docs/bsa-id.md. - Glossary. witness = signer; node = the witness that proposes and orders blocks (the proposer); majority of witnesses = quorum q of n (3 of 4); Circle Heart (SL Srce kroga; formerly "stewards") = the circle's m Heart members (SL član Srca), k of whom act together (live circle: m = 4, the founder and three other Heart members [Decided 16 Oct 2026, 4a; the name: Decided 23 Oct 2026, E-2; the English names: Proposal]; a project needs at least
project_approvalsHeart "for" votes, 3 by default and never fewer, and no "against" [E-1, E-5]; k for other Heart acts: proposal, 3 of 4; for the circle key 3 of 4 [Decided 17 Oct 2026, C5]); the technical names stay: the act typessteward_*, the tagsstewardandstewards_required, the act signer role valuesteward[Proposal, E-2]; there is no custodian (no deposits [Decided 16 Oct 2026, 6a]); circle id (rojstna številka) = the event id of the circle'sfoundact (43916,t=found), the circle's name for ever [Decided 17 Oct 2026, C5]; genesis digest = the digest of block 1 (§3.1 rule 9); circle key = the key that stamps the 30910 mirror [Proposal], replaceable bycircle_key_change[C5]; circle parameters (SL nastavitve kroga) = the time values and limits each circle sets within the bounds of the definitions (§3.1 rule 11) [Decided 23 Oct 2026, E-1]; there is no world rules record and no rules authority any more (43920 retired, its number reserved) [E-1]; act = 43916; statement = 43924; block = 43911 v3; daily seal = 43917 v3; snapshot chunk = 43918; circle head = 30915 v3; circle record (mirror) = 30910 v3,d= the circle id, signed by the circle key that the ledger's mirror at itsmirror_ofnames (§3.7); member home = 30916 v3; rate quote (ponudba tečaja) = 43919 v3, signed by the node of the seller's (receiving) circle; project (projekt) = a public plan with an amount, opened by aproject_proposeact; project wallet (denarnica projekta) = the keyless system account writtenproject:<id>(its point is derived in §3.8); reserve (rezerva) = the keyless system accountreserve; vote (glas) = avoteact, "for" or "against" (an "against" with its short public reason) [E-5]; motion (predlog Srca) = a Heart member's proposal without money, put to a vote [E-5]; reference (referenca) = 43921, issued by itself after a member's "I want to leave" when its conditions hold [E-9]; exclusion (izključitev) =member_exclude[E-3]; parent circle (matični krog) = the circle a new circle grows from [E-8]; there are no objections (ugovor) any more [E-5].
1. The ledger rule [Decided 16 Oct 2026; Consequence]#
The circle's log on its relays is the ledger. A booking exists when its block carries the witness quorum and at least three of the circle's relays have stored that exact signed event [Decided 16 Oct 2026, A1]. Anything a computer holds that is not a private key, a few bytes of witness safety state, or a block in flight for seconds is a cache that can be thrown away and rebuilt from the relays, and that rebuild is tested every day.
1.1 On the relays (all public, all permanent) [Consequence]. Every payment note; every act (membership, invitation, vouch, rules acceptance, payment request, projects, motions and every vote signed by the voter's key (Q21) [E-5], exclusions and readmissions [E-3], account closes [E-3], the opening and closing of OWN processes, with no content [E-4; Proposal], parameter and cap changes, Heart, witness, rate-source and circle-key changes); every booking with every touched account's balance, wave, cap, carry, debt and counters after it; every move into and out of a project wallet or the reserve; every morning gravity line; every refusal with its reason; every daily seal and full snapshot; every rate quote the circle issued or relied on; every circle record version; every reference (43921) the circle issued [Decided 23 Oct 2026, E-9]; every member home (newest version); every witness's daily statement. Nothing is salted; no count is withheld; no threshold hides small circles.
1.2 Never published, never sent; not in BSA at all.
| What | Why | Note |
|---|---|---|
| Members' private keys (BSA WIF) [Decided 16 Oct 2026] | the key is the account | browser memory only, as today |
| Witness, node, Heart member and circle-key private keys | whoever holds a key signs | on their holders' machines, file mode 600; never on a relay. The circle key only stamps the 30910 mirror [Proposal]; a stolen or lost one is replaced by circle_key_change (k Heart members, change_notice_s of notice, 72 h by default) [Decided 17 Oct 2026, C5; the notice a circle parameter: Decided 23 Oct 2026, E-1]. There is no rate-publisher key any more [Decided 16 Oct 2026, A7] |
| Session tokens, sign-in challenges, KIND 27235 login proofs | a token is a login | already local |
| Bank account numbers, IBANs, bank statements: not in BSA at all [Decided 16 Oct 2026, A6] | BSA has no payouts ("the funds are never paid out"); bank matters belong to Lana | no longer an exception to principle 1: the data does not exist in the system. There are no deposits either [Decided 16 Oct 2026, 6a], so no reference code and no confirmation of money paid in exists; no event and no setting carries bank data |
| The server address in the relay-owner letter | operational security, not ledger | stays only in the letter that is sent |
Names [Decided 16 Oct 2026, A5]. The ledger refers to people only by HEX key (BSA ID). A name exists only in KIND 0 and in the member home 30916; both are replaceable by the person, and a relay keeps only the newest version. No ledger event (43910, 43911, 43916, 43917, 43918, 43919, 43921, 43924) ever copies a name; the join entry carries only the key. Said openly, not as a question: a name can remain in old copies of a profile that someone saved, and in free text that someone writes; the ledger itself does not carry it. Every free-text field (payment purpose, the reason of an "against" vote, an exclusion's reason, a motion's title and text, project title and description) shows "public for ever; do not write names, personal or bank data".
1.3 Irreducible local state (allowed).
| What | Where | Size, lifetime | If lost |
|---|---|---|---|
| Sign-guard: per witness key, the highest height signed and its digest | each witness host, fsync'd before any signature is released | tens of bytes | the key never signs again; a new key epoch is opened (§4.6) |
| Write-ahead log of signed blocks not yet on 3 relays | node host (and every witness in quorum mode) | seconds | only non-final blocks; members' apps resend the same note (same id, same answer) |
| Private keys | §1.2 | — | key loss rules: docs/upravljanje-kroga.md; a lost circle key: circle_key_change (§3.4) [C5] |
1.4 Disposable caches (rebuilt from the relays, never the copy of record). The app's whole SQLite database (every ledger, support, request, project, seal, profile, relay-list and settings table; only the session columns of the user table are local by nature); day files, which become a local copy of the published snapshot chunks; database backups (only for a faster restart); phone caches (IndexedDB); read-gateway and CDN caches; witness memory.
1.5 Removed from the current design. [Consequence]: the seal salt secret and salted s1 lines; the 20-account threshold for counts and gravity totals; the standby's encrypted daily export of balances; phones' encrypted proof backups; member-only proofs; payment requests as local rows deleted after 30 days; "a new relay gets only the newest circle record"; outbox held meaning "never sent, so switching on does not send the backlog" (now: held until the project owner's yes, then the whole backlog from genesis, §9.4). [Decided 16 Oct 2026]: the money cap while single-witness (A3); the legal-review gate before the first entry and 43925 free text beside the chain (A5); payout acts (payout_request, payout_cancel, payout_sent, payout_reject), the pout entry, the held_out field, the reserve bank statement and the payout circuit breaker (A6; the payout code was removed from the app by plan step D0 on 17 October 2026, after a copy of the live database showed no deposit and no payout); the hourly rate of one key for every circle and the rate panel with a median (A7); the single common-good account, the fund key and paying orders from it (A8); the founder gate of P3 (A9). [Decided 16 Oct 2026, afternoon]: deposits (6a: "a different system altogether"): the acts deposit_declare, deposit_cancel, deposit_attest, deposit_reject, deposit_correct, the dep and corr entries, the custodian role and custodian_name, the paid_in field (it counted only deposits less payouts, so with neither it has nothing to count), the main account (system:main booked only deposits, deposit corrections and payouts), question 12, the deposit alarm and 6b; the wave grows only with what a member receives. The deposit code was removed from the app by plan step D0 on 17 October 2026, after a copy of the live database showed no deposit. 8j: the xrefund entry and the refund to a payer by public decision; the project limits carried over from orders (8b). [Decided 23 Oct 2026]: the world rules record 43920 BSA Rules (retired before it was ever published; its number stays reserved and is never reused, reserved_unused [Consequence]), the rules authority (meta.rules_authority), meta.rule_values, the constant RULES_NOTICE_S, the rules tag of the found act, of seals and of heads, the line g3|rules, the rule entry rules_adopt and the restorer's 43920 records (E-1; decision 1A goes with them); project_approve, project_object, project_object_withdraw, project_answer, the status stopped, the line o3|objection and the refusal reasons objection_window, notice, objection_stands, unanswered and no_consent (E-5, which replaces 8c); steward_nominate and steward_vote (E-2: members never vote on the Heart); param_approve, param_object, step_approve and the lines o3|param and o3|step (E-1, E-5); "at most three circles per founder" (E-8).
2. Roles as they touch the ledger#
| Role | How many | Holds | Signs | Trusted for |
|---|---|---|---|---|
| Member | any | own key (BSA WIF) | 43910 notes, 43916 acts (its votes among them [E-5]), own 30916 | own acts only |
| Witness [Decided 16 Oct 2026, A3] | n = 3f+1 per circle: default 4 (f = 1, q = 3) [A3]; 7 (q = 5) above about 10,000 members [Proposal, Open 3a]; bootstrap n = 1, labelled, no money cap [A3]; until there are enough circles to draw from, one witness, the circle's own computer, publicly labelled; later drawn by lot among the circles' computers (the direction for phase I) [Decided 23 Oct 2026, E-7] | witness key, sign-guard, write-ahead log, a relay with the circle's full history | block digests, daily statements | collectively: at most f of n faulty; individually nothing |
| Node (proposer) | one witness per height (phase 1: fixed, the circle's box; phase 2: rotating, same format [Proposal]) | same | the block event itself; the circle's 43919 rate quotes as seller [Decided 16 Oct 2026, A7] | nothing: every other witness re-checks every number; a quote binds only the node's own circle and the payer accepts or refuses it |
Heart member (the Circle Heart, SL Srce kroga; formerly "steward"; the technical role value stays steward [Proposal]) [Decided 16 Oct 2026, A4 and 4a; the name: Decided 23 Oct 2026, E-2] | live circle: m = 4, the founder and three other Heart members [4a]; k for other acts: proposal, 3 of 4; the founder seats the first Heart in the found act; the Heart adds and removes Heart members (k, with change_notice_s); members never vote on the Heart [E-2] | own key | acts needing human judgement: Heart and witness changes (a witness change also fails on one Heart "against" and is only for exceptions [E-7]), parameter changes within the bounds (param_propose, k [E-1]), motions [E-5], exclusions and readmissions and account closes (the larger of k and 3 [E-3, E-10]), the opening (any member [E-10]) and closing (one Heart member) of OWN processes [E-4; the acts: Proposal], project closings (8e), rate-source changes (proposal), circle-key changes (circle_key_change, k of m with change_notice_s of notice, 72 h by default [Decided 17 Oct 2026, C5; Decided 23 Oct 2026, E-1]), recovery (k, and no Heart "against" [E-7]); every member votes on projects and motions, and a project needs at least project_approvals Heart "for" votes and no "against" [E-5] | collectively, inside public rules with notice periods |
| Verifier, auditor | anyone | nothing secret | 43924 statements | nothing: a statement carries its evidence |
| Circle relays [Decided 16 Oct 2026, A2]; bootstrap operators (Q14) | ≥ 4 per circle, ≥ 3 operators (bootstrap ≥ 2, Q14) | the circle's events | nothing | storage only; never trusted for completeness |
| Archive relays | any | whole histories, no 10-year lower limit, no expiry | nothing | extra copies |
| Root relays [Decided 14 Sep 2026; A2] | the relays in KIND 38888 (four today) | the directory (§9.1) | nothing | discovery only |
| Rate source [Decided 16 Oct 2026, A7] | one per circle, chosen by the circle itself [A7]: an outside service, some day a record on the relays; changed by a Heart act rate_source_set [Proposal]; start [Decided 16 Oct 2026, start source]: the ECB daily reference rate, its date shown in the app, quotes valid 10 minutes (quote_ttl_s, a parameter of the quoting circle: 600 s by default [E-1]) | nothing | nothing in BSA: the node reads it and signs its own quote | nothing beyond the seller circle's own quote, which the payer accepts or refuses |
| Gateways, indexers | anyone | caches | nothing | speed and name search; can hide, never forge |
| Circle key [Decided 17 Oct 2026, C5: replaceable; what it signs: Proposal, follows from A3 and A8, not confirmed by the project owner; would replace the part of P2 about what it signs] | one in office per circle (held by the app and the creator [Decided 16 Oct 2026]; P2, still a proposal: the founder's browser plus a paper copy); the first one is named in the found act; replaced by circle_key_change (k Heart members, change_notice_s of public notice (72 h by default [E-1]), a roles entry booked by the witnesses) [C5], with the new key's proof of possession and in office from the next block [Proposal]; never the founder's, a witness's or a Heart member's key [Proposal] | key | the 30910 mirror only, and once the binding of the found act in block 1 (circle_sig) [Proposal] | alone, nothing: a mirror counts only if it is signed by the circle key that the ledger's mirror at its mirror_of names (at the height of a key change already the new key; for blocks it is in office from the next height), its tags without g equal that mirror and its g names the pinned genesis digest; after a replacement a record by the old key with a mirror_of at or above the change never counts |
Where witnesses come from [Decided 16 Oct 2026, A3; the direction: Decided 23 Oct 2026, E-7]. Witnesses are computers. The direction for phase I (docs only, no code in 0.3.0) [E-7]: witnesses are drawn by lot among the circles' computers, from a public random number (for example a block of the Lana chain); the draw is known in advance and changes regularly; a new witness loads the circle from its latest seal; open for phase I: fake circles, matching the load, absent witnesses. Until there are enough circles to draw from, a circle has one witness, its own computer, publicly labelled (decision 3, unchanged for 0.3.0); the acts that add, replace or remove a witness stay in 0.3.0 and are for exceptions (for example removing a misbehaving witness until the next draw): signer_propose, signer_replace, signer_remove and recovery need the larger of k and 3 Heart members "for" (the endorsement form; a Heart of fewer than three cannot make them) and no Heart "against" (§3.4) [E-7; the threshold: Decided 23 Oct 2026, E-10]. Rule in the ledger: at most one witness per operator [Decided A3]; whether a seven-witness circle may allow two per operator is Open 3a (proposal, see docs/upravljanje-kroga.md); "fewer than q" is not enough for safety; witnesses are named publicly with their operator; any witness can be replaced by the circle's own governance. "Independent" (principle 5) means "can replace any particular partner", not "needs nobody".
3. Event model (definitions 0.3.0)#
3.1 Rules for every kind#
Ledger facts are regular events in 40000+ (strfry stores them as regular events on all four root relays [C]). "Newest" pointers are addressable (30000–39999) and every version of 30910 is also an entry in the ledger, and every 30915 mirrors a 43917 seal, which is kept for ever. 30916 is the exception: it carries name words, so its versions are never copied into the ledger; the ledger holds only the
joinentry with the key [Decided 16 Oct 2026, A5]. Never 10000–19999 (replaceable: 166 definitions once collapsed into one [R]) or 20000–29999 (ephemeral, 300 s [C]).No
expirationtag, no NIP-70-tag on any BSA kind; readers treat such events as invalid. Ledger keys never sign KIND 5 or KIND 62.Byte budget: every event ≤ 100,000 bytes serialized (relay limit 131,072 [C]) and ≤ 1,000 tags (limit 5,000 [C]), tested at maximum field lengths (180-character purpose, 15-digit amounts). Multi-account events are cut by bytes, never by a count.
Integers only: amounts in minor units as base-10 strings, at most 15 digits, BigInt end to end (today's checks allow 16 digits and compare as floating point; this changes); carry in micro-units; times in unix seconds; rates in whole ppm.
Indexed single-letter tags only where a reader queries (all single-letter tags are indexed on all four relays [M]):
ccircle id (every BSA event names its circle by["c", <circle id>]; thefoundact by["c", ""], because its own id is the circle id; a payment note by["c", <circle id>, "", "from" | "to"]; the 30910 and 30915 carry the circle id asd; no BSA kind uses theatag) [Decided 17 Oct 2026, C5: the circle id; the tag shapes: Proposal],hheight,mday,ichunk,pparty,ereference,ttype,dpointer,nname words in 30916 (x, a content hash for 43925, is no longer used [A5]). The payer counternin 43910 is single-letter too, so relays index it although no reader queries it. Signatures and chain fields use multi-letter tags (qs,prev,seq,at,root,genesis), which strfry does not index.Tag values are scoped to the circle:
scope16= the first 16 hex characters of the circle id (test_vectors.circle_id);h=<scope16>:<height>,m=<scope16>:<YYYY-MM-DD>,i=<scope16>:<YYYY-MM-DD>:<index>(unscoped values would match every circle on a shared relay).HEX only, never npub. Canonical JSON (RFC 8785) for every content; every number in a content is a base-10 string. Text [Proposal]: every free text is one line, without control characters, bidirectional controls or broken Unicode, within its length (purpose 180, act text (a motion's text and the reason of a vote or an exclusion among them) and statement text 500, project and motion title 100, circle name 80, rate-source description 300); values that enter state lines never contain
|;idemis 32 lowercase hex made by the app, never typed by a person.Trust anchor (Q10) [Decided 17 Oct 2026, C5 and C6; the details: Proposal]: the circle id together with the genesis digest. The circle id is the NIP-01 event id of the circle's
foundact (43916,t=found, first tag["c", ""]), signed by the founder: the circle's name for ever. It is a fingerprint, not a key: nobody can steal it, and anotherfoundact is another circle, so a thief cannot found a false circle under the same name (hisfoundact has another id). The genesis digest is the digest of block 1 (rule 9), whose genesis entry embeds thatfoundact. The circle link and QR carry the circle id, at least two relay hints and the genesis digest as an extra pin. A reader accepts a chain only if its block 1 embeds thefoundact whose id is the circle id and its digest is the pinned genesis (from the link, or the firstgit saw for the circle id); it never follows another. The circle key can be replaced [C5]: it only stamps the 30910 mirror (and, once, the binding of thefoundact in block 1,circle_sig) [Proposal]; k Heart members signcircle_key_change[C5] with the new key's proof of possession [Proposal], and afterchange_notice_sof public notice (72 h by default; no longer fixed [Decided 23 Oct 2026, E-1]) arolesentry, booked by the witnesses [C5], puts the new key in office from the next block [Proposal] (§3.4, §3.5); from then on a 30910 by the old key with amirror_ofat or above the change never counts, and every seal and 30915 head names the circle key of the newest mirror at or below the seal's last block (at the height of a key change already the new key) [Proposal]. A stolen and a lost key are replaced the same way; the circle id never changes. Said openly: anyone can publish a 30910 that names a circle id; only the one signed by the circle key that the ledger's mirror at itsmirror_ofnames (at the height of a key change already the new key; for blocks it is in office from the next height), whose tags withoutgequal that mirror and whosegnames the pinned genesis digest, counts. The first-seen rule of the root relays (keep the firstgand founder per circle id;relay/ledger-write-policy.py, moderoot, pins them only when the relay holds the circle'sfoundact and the record'sfounderis its author (or, for a circle configured on the relay, when its configured circle key signed the record), after every plugin of the relay accepted the record, so nobody can claim a circle id first: Proposal, §9.2) is a request in the letter to the Lana relay owner (plan phase G) and is now only extra safety [Decided 17 Oct 2026, C6].Identity by digest [Proposal]. A block or seal is named by its digest = the NIP-01 hash of
[0, pubkey, created_at, kind, tags without the qs tags, content], never by its event id (the id changes with the set and order of witness signatures). Two digests at one height, each with a valid quorum of the witnesses in office there, or two valid seals for one day, are a fork; a block without such a quorum is not the circle's and is ignored [Proposal]. Witnesses signsha256("lb-block/3|" ‖ digest)for a block andsha256("lb-seal/3|" ‖ digest)for a seal, never the digest itself, so a witness signature is never a valid Nostr signature of a stripped copy;qstags are sorted by witness HEX. Every reference to a digest also says where to find it: a block by its height, a seal by its day; NIP-10etags carry only event ids.Booking windows [Proposal; the act's validity: Decided 17 Oct 2026, C3; a circle parameter: Decided 23 Oct 2026, E-1]. A note or an act is booked only at
created_at− AT_TOLERANCE_S (5 s, a constant) ≤at≤ itsexpires; an event id is booked at most once (duplicate). Every act carriesexpires, at mostact_ttl_safter it was signed (a circle parameter: 604,800 s = 7 days by default [C3, E-1]), judged by the parameters in force at its booking [Proposal, E-1; this replaces the earlier reading "the version in force at its signing"]; during a parameter change's notice apps sign with the stricter of the two values [Proposal]. Booked act ids (and note ids, §3.8) stay in the state (a3lines) until they expire, so an old act can never be booked again, also not by a reader that starts from a seal.Circle parameters [Decided 23 Oct 2026, E-1: the time values and limits are set per circle, the values of the definitions are only defaults, and the Circle Heart changes them within the bounds; the bounds and how a change takes effect: Proposal]. There are no world rules any more: KIND 43920 (BSA Rules) is retired, its number stays reserved and is never reused (
reserved_unused) [Consequence], and with it go the rules authority (meta.rules_authority),meta.rule_values, the constant RULES_NOTICE_S, thefoundact'srulestag, the seal's and head'srulestag, the lineg3|rules, the rule entryrules_adopt, the restorer's 43920 records and decision 1A (no world signer) [E-1]. Fixed for every circle (definitions, not parameters) [E-1]: a project needs at least 3 Heart "for" votes and no "against" (project_approvals≥ 3, §3.9); the money and gravity computation; the constants XCHECK_MARGIN_S 60, AT_TOLERANCE_S 5, QUOTE_MARGIN_S 120 and RATE_STALE_ALERT_S 432,000 (their values: proposal; clock margins and the node's own timing; changing one needs a new definitions version). The circle parameters, in this order (thefoundact andparam_proposecarry all of them, each["param", <name>, "<integer>"]; a value outside its range,vote_min_s>vote_max_s, orvote_max_s≥open_lapse_sisbad_template; units and ranges also inmeta.circle_parametersof the definitions):Parameter Start (default) Bounds [Proposal] Meaning Decided band_ppm_day330 ppm/day 0 – 330 gravity on the plus up to the wave (§7.3); never stronger than today's 23 Oct 2026, E-11 excess_ppm_day22,840 ppm/day 0 – 22,840 gravity on the plus above the wave; never stronger than today's (half in 30 days) 23 Oct 2026, E-11 transition_days60 days 60 – 3,650 the transition after an account's first receipt (3A); never shorter than today's 23 Oct 2026, E-11 rest_after_days183 days 0 (off), or 183 – 3,650 resting after days without giving; never sooner than today's (1 to 182 is invalid) 23 Oct 2026, E-11 wave_cap100,000,000 minor 1 – 999,999,999,999,999 a member's cap, set at its member_joinas before w_max_s1 s 1 – 10 a block's longest atspan (§3.5)as before vote_min_s259,200 s (72 h) 86,400 – 2,592,000 the shortest vote 23 Oct 2026, E-5 Dopolnitev (72 h by default, a circle setting) vote_max_s1,209,600 s (14 days) 86,400 – 2,592,000; below open_lapse_sthe longest vote proposal project_approvals3 3 – 9 Heart members whose "for" a project needs (never the proposer's or the recipient's) 23 Oct 2026, E-1 (at least 3; a circle may require more) close_notice_s259,200 s (72 h) 86,400 – 2,592,000 between the k-th project_closeand theproject_return16 Oct 2026, 8e; a circle setting: E-1 receive_lapse_s7,776,000 s (90 days) 604,800 – 31,536,000 a receiving project not full this long after it opened lapses 16 Oct 2026, 8e; E-1 open_lapse_s2,592,000 s (30 days) 604,800 – 31,536,000 a project not opened this long after publication lapses proposal; E-1 change_notice_s259,200 s (72 h) 86,400 – 2,592,000 the notice of a change of the circle key, witnesses, Heart members, k, relays, recovery and parameters, and of a resignation 23 Oct 2026, E-1 (72 h is a default, not fixed) xcheck_s604,800 s (7 days) 86,400 – 2,592,000 the 8j check after an xoutwithoutxdoneorxundo16 Oct 2026, 8j; E-1 quote_ttl_s600 s 300 – 3,600 a rate quote's expires≤created_at+ this (the quoting circle's value)16 Oct 2026, start source; E-1 note_ttl_s600 s 60 – 3,600 a 43910's expires≤created_at+ this (each circle its own, §4.5)decided (10 minutes); E-1 act_ttl_s604,800 s (7 days) 86,400 – 2,592,000 a 43916's expires≤created_at+ this17 Oct 2026, C3; E-1 rej_per_author_per_day20 1 – 1,000 refusals of one author booked per morning day (from one morning boundary to the next, §3.5); above it the intake answers 429 and books nothing 17 Oct 2026, C3; E-1 exclusion_s7,776,000 s (90 days) 86,400 – 31,536,000 how long an exclusion runs 23 Oct 2026, E-3 (3 months, a default); 90 days: proposal invite_ttl_s604,800 s (7 days) 3,600 – 2,592,000 how long an invitation is valid 23 Oct 2026, E-6 (invitations); 7 days and one-time: proposal invite_only0 0 – 1 1: a joinneeds an open invitation (an excluded key's application excepted)23 Oct 2026, E-6 max_members0 (no limit) 0 – 999,999,999 the most members (status memberorfrozen); 0 = no limit; above it the waiting list23 Oct 2026, E-6; 0 = no limit: proposal How a parameter changes [Decided 23 Oct 2026, E-1: the Heart changes them within the bounds; the act's shape and the notice: Proposal]:
param_proposeis a Heart act in the endorsement form (§3.4): the first act carries the full new set, endorsements name it, k Heart members in office; at most one is open at a time (a second proposing act isrepeated). With k signers in office the notice starts: notice end = the k-th act'sat+ max(change_notice_s, the old value of every parameter in seconds whose value changes) [Proposal, E-1: a change of a time value takes effect only after the time it replaces has run out, never retroactively; so a stolen key cannot skip the warning]. Itso3|changeline (typeparam_propose) hasexpires= the notice end. At the notice end it is a duty: the first block whose firstatreaches it starts (after the morning header) with the rule entryparams_effective(in[theparam_proposeid]); from that entry on the block is under the new parameters, and theg3|param:<name>lines andg3|params_h(= that height) change. If fewer than k of its signers are in office then, it is void (the line ends, no entry). Never for a time before the notice end [completed 24 Oct 2026, plan step E4x; E-1: never retroactive]: the change waits while a missed morning whose boundary is at or before its notice end has not opened yet (catch-up after an outage, §7.4) and while a duty due before its notice end is due at the block; those mornings and duties are booked first, under the parameters in force before the change, andparams_effectiveis the first entry of the first block start at which neither holds. An 8j check, anxdoneor areference_returnis never such a duty (the node books them when it has read the other circle, and a hold's check at was fixed at itsxout), so none of them holdsparams_effectiveback [clarification, 25 Oct 2026, D4 N22]. Said openly: when the node was down at the notice end, a change takes effect a block or a morning later than its notice end, never earlier, and a duty due after the notice end that the same waiting block books is booked under the old parameters too [review of E4x, 24 Oct 2026].param_approve,param_objectand theeffectivetag are gone. Running deadlines keep their length (never retroactive [Consequence of E-1; as before]): each is recorded as a due time when it starts, with the parameters in force then: a vote's end, a project's open lapse and receive lapse, a close's due, a hold's check, an exclusion's end, an invitation's end, a change's notice end (the lines of §3.8). Example: a project opened under a 90-day receive lapse keeps 90 days even if the parameter later says 30. A member's cap stays whenwave_capchanges. TTL checks (act_ttl_s,note_ttl_s,quote_ttl_s, the refusal limit) use the parameters in force at the booking; during a parameter change's notice apps sign with the stricter of the two values [Proposal]. Across circles each circle applies its own values to what it books (note_ttl_s,quote_ttl_sandxcheck_s: §4.5); a mismatch can only end in a refusal and a return to the payer, so nothing is lost and both sums stay 0 [Proposal, E-1].Encodings [clarification, 17 Oct 2026 (D4 review)]. A domain-separated message is sha256 of an ASCII prefix followed by the 32 raw bytes of the digest or id for
"lb-block/3|","lb-seal/3|"and"lb-found/3|"(thefoundact's id), and by text for"lb-genesis/3|","lb-circle-key/3|","lb-home/3|"and"lb-system/3|"(ids, digests and keys as 64 lowercase hex characters, numbers in decimal, fields joined by|); the examples confirm both. An event's size (rule 3) is the number of UTF-8 bytes ofJSON.stringify({id, pubkey, created_at, kind, tags, content, sig})in that key order, without spaces. Every character limit (rule 7) counts Unicode code points. BSA text holds no control characters (rule 7), so the NIP-01 serialization of a valid BSA event equalsJSON.stringifyof the array[0, pubkey, created_at, kind, tags, content].
3.2 The kinds#
| Kind | Name | Class | Signer | Lives on | Size [E] |
|---|---|---|---|---|---|
| 0 | Lana profile (exists; minimal: key + name; lanaWalletID filled by the app) [Decided 16 Oct 2026] | replaceable | member | root (Lana) | ~0.5 KB |
| 38888 | Lana System Parameters (exists; only relay tags read) [Decided 14 Sep / 15 Oct 2026] | addressable | Lana authority | root | — |
| 42893 | Kind definitions (exists) (Q20) | regular | Lana authority | root | — |
| 30910 v3 | Circle Record: a mirror of the governance state; d = the circle id | addressable | the circle key that the ledger's mirror at its mirror_of names (the key its circle_key tag names) | root + circle relays; every version also in the ledger | 1.5–2.5 KB |
| 30915 v3 | Circle Head: the newest seal, for discovery; d = the circle id | addressable | the seal's node, with quorum | root + circle relays | ~2.5 KB |
| 30916 v3 | Member Home (mandatory) [Decided 16 Oct 2026]; replaceable by the member, never copied into the ledger [A5] | addressable | member, attested by a witness | circle relays; root while borrowed (Q16) | ~0.8 KB [M 739 B] |
| 43910 v3 | Payment Note | regular | payer | embedded in 43911; standalone only as censorship evidence | 0.8–1.0 KB standalone, ~0.37 KB embedded |
| 43911 v3 | Circle Block: the ledger | regular | node, with ≥ q witness signatures inside | circle relays (≥ 4) + archives (+ Lana relays while borrowed) | 1.9 KB (one payment, one witness) to ≤ 100 KB |
| 43916 | Circle Act | regular | the acting person | embedded in 43911; standalone copy optional | 0.5–1.2 KB |
| 43917 v3 | Day Seal (checkpoint) | regular | node, with quorum | circle relays | ~2 KB |
| 43918 | Snapshot Chunk | regular | node (valid through the seal's roots) | circle relays | ≤ 100 KB, ~450 lines |
| 43919 v3 | Rate Quote (repurposed; no longer an hourly rate reference) [Decided 16 Oct 2026, A7] | regular | the node of the seller's (receiving) circle | the seller circle's relays; the payer's circle republishes every quote its blocks rely on; archives | ~0.5 KB [E] |
| 43920 | retired: BSA Rules, the world-wide rule values, never published [Decided 23 Oct 2026, E-1]; the number stays reserved and is never reused (reserved_unused) [Consequence] | — | — | — | — |
| 43921 | Reference (new) [Decided 23 Oct 2026, E-9: a new kind; the number and the format: Proposal] | regular | the node of the circle the person leaves, right after the block that books the reference entry has its quorum | that circle's relays; the new circle republishes a reference its member_join names [Proposal] | ~0.7 KB; up to ~18 KB with 100 + 100 project ids [E] |
| 43924 | Statement (attestation or challenge) | regular | any witness, verifier, auditor | circle relays (+ partners) | ~0.7 KB + evidence ids |
| 30917 (optional, later) | Service Offer (relay, witness, archive, index operator) | addressable | operator | root | ~1 KB |
- Retired for good from 0.1.0: 30911–30914, 43912–43915. 43910 and 43911 are not retired: they return as v3. 0.2.0's "retire 43910/43911" is withdrawn.
- 43925 is not defined: the free text beside the chain was dropped with the legal-review gate [Decided 16 Oct 2026, A5]. Free text stays inside the signed note or act, public, with the field warning.
- 0 events of 43910–43919 and 23910 exist on any Lana relay today [M]; the local catalogues define none of 43916–43999 [R]; 43920 was checked free on the four Lana relays and in
kinds.jsonon 17 Oct 2026 [M] (now retired, never published, kept reserved [E-1]); 43921 was checked free on 23 Oct 2026: 0 events on the four relays of 38888, no definition, not inkinds.json2.88.0 [M]. Every number is re-checked against the livekinds.jsonand all four relays (COUNT, read only) before publication.
3.3 43910 v3 Payment Note (member-signed cause)#
kind 43910, pubkey = payer HEX, created_at = signing time
content: purpose, ≤ 180 characters, PUBLIC FOREVER; the field warns
"public for ever; do not write names, personal or bank data" [Decided 16 Oct 2026, A5]
tags, in this exact order (the canonical template; the app emits exactly this):
["p", <receiver HEX or system address>]
["c", <payer circle id>, "", "from"]
["c", <receiver circle id>, "", "to"] only across circles
["amount", "<minor>"] ["currency", "<payer currency>"]
["to_amount", "<minor>", "<receiver currency>"] only across circles: the payer signs both amounts
["e", <43919 quote id>, "", "quote"] only across currencies: exactly one, the seller
circle's quote the payer accepted [Decided 16 Oct 2026, A7]
["n", "<payer's own counter: 1, 2, …>"]
["prev", "<payer's previous note id in this circle> | genesis"]
["expires", "<unix, ≤ created_at + note_ttl_s>"] note_ttl_s: a circle parameter, 600 s by default
[E-1]; each circle judges it by its own (§4.5)
["idem", "<32 lowercase hex, made by the app>"] optional
["e", <request act id>, "", "request"] optional; the booked purpose is this note's content
["e", <project act id>, "", "project"] optional; a contribution names its project here
["v", "3"]
- Embedding: inside a block the note is stored in a compact canonical form (the variable fields plus
created_atandsig) from which the exact NIP-01 serialization, id and signature are rebuilt. The node rebuilds and verifies every note before booking it; a note that does not round-trip the frozen v3 template is refused (bad_template), never repaired. The template is frozen per definitions version for ever. - A member's KIND 5 can delete only a standalone copy, never the block that embeds the note.
- After
expiresan unbooked note can never be booked. A note is booked only atcreated_at− 5 s ≤at≤expires, and its id at most once. Itsexpiresis checked againstnote_ttl_sof the parameters in force at the booking, in each circle by its own value (the payer's circle at thexout, the receiving circle at thexin; a smaller value there refuses the note, and the payer gets the held amount back, §4.5) [Proposal, E-1]; during a parameter change's notice, and across circles, the app signs with the smaller of the two values [Proposal]. - Across currencies the note's
expiresis never later than the quote'sexpires(§3.7), andto_amountis the quote's conversion ofamount, exactly.
3.4 43916 Circle Act (person-signed cause)#
kind 43916, pubkey = the actor (member, invitee, Heart member, witness, founder)
tags: ["c", <circle id>] the found act: ["c", ""], because its own id is the circle id [C5]
["t", <act type>]
the type's tags in act_types order (["e", <ref>, "", <role>]… ["p", <subject HEX>]… typed value tags:
amount, parameter name/value …)
["after", "<height>"] (optional) ["expires", "<unix, ≤ created_at + act_ttl_s>"] (always) validity window;
act_ttl_s is a circle parameter (604,800 s = 7 days by default) [C3, E-1]
["idem", …] (optional) ["v", "3"]
content: human text where the type has one (≤ 500 characters, PUBLIC, with the field warning; the app
never puts a name into it [Decided 16 Oct 2026, A5])
| Group | Act types | Signed by |
|---|---|---|
| Founding | found (first tag ["c", ""]: its event id is the circle id, the circle's name for ever [Decided 17 Oct 2026, C5]; then, in this order: name, code, circle_key (the first circle key; never the founder's, a witness's or a Heart member's key [Proposal]), currency, tz, tzdata, morning hour (tz, morning hour and tzdata fixed at founding for 0.3.0 [Decided 17 Oct 2026, C7]), the first witness set, quorum, proposer, the first Heart (steward tags: the founder seats it [E-2]) and k, relays, archives, an optional ["bootstrap", "Q14"] label (open question 14, not decided), rate source, api, every circle parameter in the order of §3.1 rule 11 (["param", <name>, "<integer>"]) [E-1], the start, ["parent", <parent circle id>, <parent genesis digest>] (required except for the root, the live circle [Decided 23 Oct 2026, E-8; the tag: Proposal]) and right after it ["e", <the founder's 43921 id>, "", "reference"] (the founder's reference from the parent circle; required with parent [Proposal; that the founder needs it: a consequence of E-8 and E-9]), definitions version (Q20)); signed by the founder and bound to the first circle key by that key's signature in block 1 (circle_sig, §3.5); there is no rules tag any more: the world rules are retired, and the quote validity and the number of project approvals are circle parameters [E-1]; no money cap [Decided 16 Oct 2026, A3] | founder |
Membership [invite and join: Decided 23 Oct 2026, E-6 and E-9; the tags: Proposal] | invite (["p", <HEX>]; one-time; booked as o3|invite, valid invite_ttl_s [E-6]), vouch, join (the key only, never a name [A5]; optional ["e", <invite id>, "", "invite"] and ["e", <43921 id>, "", "reference"]; how it is judged and admitted: §3.11), leave (a member's "I want to leave": member_leave, then the reference when its conditions hold [E-9]; an excluded key's: only its leaving line; an applicant's: it withdraws its o3|join; §3.11), rules | members / invitee |
| Exclusion and readmission [Decided 23 Oct 2026, E-3] | member_exclude (["p", <member HEX>], optional ["e", <OWN case event id>, "", "own"] [Proposal, E-4]; text required: a short public reason [Proposal]; the larger of k and 3 Heart members [E-10], the endorsement form, no notice: effective at the act that reaches them; the excluded key never counts toward its own exclusion) · member_readmit (["e", <join act id>, "", "join"]; the larger of k and 3 Heart members [E-10], no notice; membership only, never a Heart seat [E-3]) (§3.11) | Heart members |
| Closing an old account [Decided 23 Oct 2026, E-3; the accounting confirmed 23 Oct 2026] | account_close (["p", <HEX>], text required: the public reason [Decided 23 Oct 2026, E-10 4A]; max(k, 3) Heart members [E-10], the endorsement form, no notice) (§3.11) | Heart members |
| Requests | pay_request (amount, text, expiry) | receiver |
| Projects [Decided 16 Oct 2026, A8; details 8a, 8b, 8e, 8j; the vote: Decided 23 Oct 2026, E-5; Open 8g, 8h] | project_propose (title, description, amount, recipient (a member when the act is booked, Open 8h: a recipient who left, never joined, is frozen or is excluded is refused not_member [clarification, 19 Oct 2026 (D3 review)]; for a step raise [8j] the circle's world-step [Proposal]), ["duration", "<seconds>"] right after p (vote_min_s ≤ duration ≤ vote_max_s of the parameters in force at its booking, else not_allowed; set at publication, never changed [Decided 23 Oct 2026, E-5, confirmed 23 Oct 2026]), ["img", sha256, url] (Q24)) · project_consent, project_decline (the recipient's consent, as today for an order [Proposal]; none for a step raise, whose recipient is keyless; a proposer who is the recipient consented with the project_propose itself, so no project_consent is needed and one is refused repeated [clarification, 19 Oct 2026 (D3 review)]) · project_withdraw · project_close (k Heart members; the project returns its money to the reserve after close_notice_s, 72 h of public notice by default [8e, E-1]). A project is decided by a vote (vote, next row) [E-5]: project_approve, project_object, project_object_withdraw and project_answer are gone. No Heart member rejects a project alone: there is no project_reject [Decided 17 Oct 2026, C4] | proposer / recipient / proposer / Heart members |
| Votes and motions [Decided 23 Oct 2026, E-5; the tags: Proposal] | vote (["e", <project_propose, motion or witness change id>, "", "proposal"], ["vote", "for"] or ["vote", "against"]; "against" requires its short public reason as text, "for" carries none; one vote per member per proposal: the newest counts, changeable until the vote end; the same choice again is repeated; booked only with at < the vote end, else vote_ended; on a witness change only Heart members in office vote [E-7]) · motion (a Heart member puts any other proposal to a vote: ["title", <≤ 100 characters>], ["duration", "<seconds>"]; text required: the proposal) (§3.9) | any member (a witness change: a Heart member) / a Heart member |
| Step outward | raise: a project [Decided 16 Oct 2026, 8j], a project_propose whose recipient is world-step (row above) [Proposal]; lower: step_propose (negative amount), decided by a vote like a project [E-5]; the builder does not book a lowering in 0.3.0 (no complete rule) [Proposal]; step_approve is gone | member |
| Parameters | param_propose (the full new set of circle parameters, §3.1 rule 11; a Heart act in the endorsement form, k Heart members; at most one open at a time) [Decided 23 Oct 2026, E-1: the Heart changes them within the bounds; the shape: Proposal]; param_approve and param_object are gone | Heart members |
| Roles | steward_accept (signed by the new Heart member: its consent to a steward_add, naming that act), steward_resign, signer_propose, signer_accept, signer_resign, signer_remove, signer_replace, steward_add, steward_remove, stewards_required_set (the last five: proposal (D4 review, round 3, 17 Oct 2026), accepted with the acts for Heart and witness changes [Decided 23 Oct 2026, D8]; upravljanje-kroga.md; signer_propose, signer_replace and signer_remove also fail on one Heart "against" [E-7]), proposer_swap, relay_change, rate_source_set (source id and public description; the quote validity is the circle parameter quote_ttl_s, 600 s by default [E-1]; replaces rate_panel_set; who signs and when: proposal), refusal_list_set (by circle id), circle_key_change (tags key and pop, given below the table; text optional; k Heart members by the endorsement form, change_notice_s of notice (72 h by default [E-1]) from the k-th act; then a roles entry puts the new key in office from the next block; refused if pop does not verify (bad_template), or if the new key is the key in office, the founder's, a witness's or a Heart member's key [Decided 17 Oct 2026, C5; the proof of possession, the act shape, the new key in office from the next block and the rule that the new key is not the key in office, the founder's, a witness's or a Heart member's key: Proposal]). steward_nominate and steward_vote are gone: members never vote on the Heart; the Heart adds and removes Heart members [Decided 23 Oct 2026, E-2] | the new Heart member / Heart members / witness |
| Recovery | recovery (new witness set, last height found anywhere; it also fails on one Heart "against" [E-7]) | the larger of k and 3 Heart members [E-10] |
| OWN processes [Decided 23 Oct 2026, E-4: the Heart leads them and only a decision reaches the ledger; who opens and closes: Decided 23 Oct 2026, E-10] | own_open (["p", <HEX>], optional ["e", <OWN case id>, "", "own"]; any member, alone, at once; books o3|own) · own_close (one Heart member in office; ["e", <own_open id>, "", "open"]); no content of a process ever reaches the ledger | Heart members / one Heart member |
| Member safety (Q11) | guardians_set, freeze, key_move | member / the guardians the member named |
circle_key_change tags [Decided 17 Oct 2026, C5; the shape and the proof of possession: Proposal]: ["key", <HEX of the new circle key>], ["pop", <the new key's BIP-340 signature over sha256("lb-circle-key/3|" + circle id + "|" + new key HEX + "|" + created_at)>], created_at being the act's own, in decimal (proof of possession: nobody can name a key someone else holds; and since an act is booked only within act_ttl_s of its created_at, a pop is good for its own act only, so an old one can never be used again).
There are no payout acts and no reserve statement act [Decided 16 Oct 2026, A6], no deposit acts and no custodian_name [Decided 16 Oct 2026, 6a], and no act for a refund decision [Decided 16 Oct 2026, 8j], and no project_reject: no Heart member rejects a project alone [Decided 17 Oct 2026, C4]; and no approval, objection or answer act [E-5], no steward_nominate or steward_vote [E-2], and no param_approve, param_object or step_approve [E-1, E-5]. An act has effect only once booked; it is judged by the actor's role at the booking height. The rules each act type follows (notice periods, who may approve, limits) are in docs/upravljanje-kroga.md.
Changes that need k Heart members (relay_change, rate_source_set, refusal_list_set, signer_propose, signer_remove, signer_replace, steward_add, steward_remove, stewards_required_set, proposer_swap, recovery, circle_key_change, project_close, param_propose [E-1], member_exclude, member_readmit and account_close [E-3]; for member_exclude, member_readmit, account_close and the witness exceptions signer_propose, signer_replace, signer_remove and recovery the threshold is the larger of k and 3, and a Heart of fewer than three members cannot propose them (not_allowed) [Decided 23 Oct 2026, E-10]; own_open is no Heart change since E-10 (any member books it alone); a Heart member in office who leaves the circle loses the seat: a roles entry with acts = [its leave act] right after the leave's entries (all of them: member_leave, the returns of its receiving projects with their drains and openings, and the leave's end-of-entry work, its own reference when issued at once, an account close or an admission from the waiting list among it; that leave is never cut by size) [clarification, 25 Oct 2026, D4 N21], k lowered to the number left when above it; the last Heart member cannot leave (not_allowed), and in a block that holds a roles entry already the leave is answered roles_taken [Decided 23 Oct 2026, E-11]; one open change per subject: a second proposing member_exclude or account_close of one key while one collects is refused repeated [D4 N28]; every act of an exclusion, a readmission or an account close, the proposing act and each endorsement, is judged against what it names at its booking (an endorsement after the target changed is refused) [D4 N29; clarifications of 25 Oct 2026]; the five acts of the D4 review and a person's own steward_resign or signer_resign, a change of its own committed change_notice_s later as a duty: proposal (D4 review, round 3, 17 Oct 2026), accepted [Decided 23 Oct 2026, D8]) [Proposal; k distinct Heart members: ruling of 16 Oct 2026; for circle_key_change: Decided 17 Oct 2026, C5; for an exclusion: Decided 23 Oct 2026, E-3, and its threshold, the larger of k and 3: Decided 23 Oct 2026, E-10]: one Heart member's proposing act carries the change; each further Heart member signs the same act type with only ["e", <proposing act id>, "", "proposal"], booked before the proposing act expires. An endorsement never names another endorsement. The change is committed (a roles entry; for project_close the project_return after its notice; for param_propose the params_effective at its notice end; for member_exclude, member_readmit, account_close and own_open their own entries at the k-th act, §3.11) only with the proposing act and endorsements from at least k distinct current Heart members, and for signer_propose, signer_remove, signer_replace, steward_add, steward_remove, stewards_required_set, relay_change, recovery and circle_key_change only after change_notice_s of notice from the k-th act (a circle parameter, 72 h by default, no longer fixed [Decided 23 Oct 2026, E-1; formerly C5]); for param_propose the notice of §3.1 rule 11; member_exclude, member_readmit, account_close and own_open have no notice: they take effect at the k-th act [E-3; for own_open: Proposal]; signer_propose, signer_replace, signer_remove and recovery are committed only while no Heart member in office has "against" as the newest vote naming the change (otherwise their roles entry is refused, answered not_allowed) [Decided 23 Oct 2026, E-7]; each act is used once; the o3|change line (§3.8) tracks the collection, the notice (from the act with which k Heart members in office were reached) and the time left to commit. Who is in office at a height [Ruling of 16 Oct 2026]: the circle key, the witnesses (with their since_h and until_h), the quorum, the node, the Heart and k are read from the ledger itself: the genesis mirror for block 1, then the mirror of each roles entry from the next block on (a block books at most one roles entry, and block 1 books none: its genesis mirror is the mirror of height 1 [Proposal]; so a height names one mirror, height 1 too). A roles entry changes the circle key only when its proposing act is circle_key_change, and then to exactly the key that act names [Decided 17 Oct 2026, C5]. A block is signed by a quorum of the witnesses in office at its height, a day seal by a quorum of the office after its last block (§3.6) [Proposal]; a Heart act counts only if its author was a Heart member in office when it was booked, and a roles entry needs k such Heart members still in office at the roles entry (k as in office there), except the roles entry of a resignation, which needs none (proposal (D4 review, round 3, 17 Oct 2026)). A due resignation that can no longer take effect (the person was removed meanwhile, or it would leave no Heart member or witness) is void: its line goes without an entry, so a resignation never halts a circle (proposal (D4 review, round 3, 17 Oct 2026)); void resignations are dropped first at a block start, and the earliest of the others takes the block [clarification, 19 Oct 2026 (D3 review)]. A due resignation's roles entry goes in a block of its own, before that morning's morning block (§7.4), and a second resignation of the same role by the same key while its first is open is refused repeated [proposal (D3 review, 19 Oct 2026)]. A reader that checks a run of blocks that does not start at block 1 takes the office from the mirror of the newest genesis or roles entry below its first height and the circle parameters in force from the newest genesis or params_effective below it (the found act, or the param_propose it names, carries the full set) [Consequence of E-1], both read from the ledger, never from a circle record (a record can be older or newer than the part it checks); without them what depends on them is unverifiable, never assumed, and a witness never signs what it cannot verify. What began before the run is unverifiable too, never refused and never passed: an endorsement whose proposing act, a roles entry whose acts, an xdone or xundo whose hold, a project_open whose project, or a refusal whose key's membership lies before the run; a witness checks those against its own state below the run [Proposal]. The run is judged block by block, each block under the parameters in force for it: each params_effective in it must name a param_propose whose notice end its block's first at reaches, with k of its signers in office; each note's and act's TTL is judged by the parameters in force at its booking [Proposal, E-1], and each running deadline by the due time recorded when it started [Consequence of E-1: never retroactive].
3.5 43911 v3 Circle Block (the ledger)#
kind 43911, pubkey = node of this height (a member of the witness set S(h))
created_at = at_last
tags:
["c", <circle id>]
["h", "<scope16>:<height>"] gap-free from 1 (genesis)
["prev", "<digest of block h-1>"] "" for h = 1; the hash chain
["genesis", "<genesis digest>"] with the circle id the trust anchor (§3.1 rule 8), on every block; "" in block 1 itself (multi-letter: not indexed)
["seq", "<first>", "<last>"] circle-wide entry numbers, gap-free
["at", "<first>", "<last>"] booking times, unix seconds, never decreasing (first: the first entry's at, last: the last entry's; clarification, 19 Oct 2026, D3 review)
["root", "<entries root>", "<lines root>", "<state root>"]
entries root: RFC 6962 over the canonical entries of this block
lines root: RFC 6962 over the leaves (s3 lines with full HEX, last_h from before the block, §3.8)
of the accounts touched here
state root: sparse Merkle root over the whole decision state after this block (§3.8), which holds
the circle key in office (g3|circle_key) and the circle parameters in force
(g3|param:<name>, g3|params_h), so every block names them
["p", <party HEX>]… every party touched, incl. keyless system parties
["m", "<scope16>:<date>"] ["morning", <date>, <boundary_unix>, <cutoff_seq>, <params_h>, <tzdata>] every block that books a grav entry
["more", <trigger_seq>, <work_seq>, <leaver HEX or "">, <"leave"|"exclude"|"">, <act id or "">] only a block the size rule closed with work left (the block split, below)
["qs", <witness HEX>, <BIP-340 signature over sha256("lb-block/3|" ‖ digest)>] × ≥ q, sorted by witness HEX (the node's own included)
["v", "3"]
content (canonical JSON): {"e": [entries…], "l": [lines…]}
- Digest = sha256 of the NIP-01 serialization
[0, pubkey, created_at, 43911, tags without the qs tags, content]. It covers the party list, every entry and every line, so a gateway cannot reassign a line to another party. The event id and the node's event signature then cover theqstags too. The digest names the block (prev,genesis,src, the seal'shead); the event id does not, because it changes with the set and order ofqssignatures. - Lines in content refer to parties by their index in the
plist; the leaves that the lines root and the state root are computed over carry the full HEX, so a light client's Merkle path binds its own key. Theplist is in the order in which the entries first name the parties (inside an entry:partyfirst, then each move's from and to). - Closing rule: a block closes at the first of: the intake queue is empty (an idle circle books one entry per block at once);
W_maxseconds after its first entry (the circle parameterw_max_s: 1 s at founding; proposal: a circle above about 10,000 members raises it to 2 s byparam_propose); 100,000 bytes serialized (about 90 ordinary payments, 38 at maximum field lengths, measured on the 0.3.0 examples); a block whose work would pass 100,000 bytes closes after its last whole step and the next block continues it (the block split, below). A block never spans a morning boundary: the open block closes at the boundary. So a block'satspan is at mostW_max(the parameterw_max_s; a check without the parameter lines uses 10 s, the top of its range), and no block can hold a whole notice or vote (the parameters' lower bounds are one day) [a consequence of this rule; the check: Proposal]. - The block split [completed 24 Oct 2026, plan step E4x: the size rule of every block (this section, §3.9 "Size"); the form: Proposal]. A block is at most 100,000 bytes, and its work never stops the circle: no duty, drain or admission is ever refused or left out because it does not fit, and there is no intake limit on projects [8b]. The work of a block is a fixed sequence of steps: each duty of its start (one entry), and in the end-of-entry work of every entry (§3.9) one
reserve_movewith theproject_full, the recipient's visit and theproject_payit brings (a project an entry filled exactly, by agiveor by a visit's deduct, is paid without a step of its own when the drain reaches it in the opening order; a cut before an older project'sreserve_moveleaves it receiving and full, which is allowed only while work is carried, and the continuation pays it [review of E4x, 24 Oct 2026]), oneproject_open, oneaccount_close, onereference, onemember_joinwith itsreference_grant, and oneproject_returnof a person who leaves, is excluded or whose account closes (with its own drain and openings). When the next step would take the block over 100,000 bytes, the node closes the block after its last whole step: the block carries["more", <trigger>, <work>, <leaver>, <via>, <act>](the trigger the carried end-of-entry work names, the seq of the newest entry booked outside end-of-entry work, and the person whose receiving projects are still to be returned, with how the person went and the act;""when none; a cut right after a people step, anaccount_close, areferenceor amember_joinfrom the waiting list, carries the trigger of the work in progress, never that step's own seq [D4 N23]; a cut between whole entries (between the duties of a block's start, or between a person's returns) has no work in progress: trigger = work [D4 N27]; the returns of an account close of a member line are a leave's: vialeaveand the proposingaccount_closeact [D4 N24]; clarifications of 25 Oct 2026) and books nothing else (a later cause waits for a later block, answeredblock_full). The next block starts at the cut block's lastat, so nothing new falls due in between; it opens no morning and books noparams_effective(the next block without carried work does); it begins with the carried work, exactly where it stopped and in the same order: the person's remaining project returns, each with its drain and openings; the rest of the end-of-entry work, naming the same trigger; then, unless two or more mornings are pending, the duties still due. A new cut carries again. The carried work keeps its order and every move, booked at the cut block's lastat; the duties the continuation then books are those due by thatat, right after the carried work and before any later cause (a due resignation waits for the first block without carried work) [review of E4x, 24 Oct 2026: this is the rule itself, not a claim that everyatequals that of an uncut block]. A step books at least one entry (a duty that ends without an entry, such as a close whose closers in office fell below k, is no step), and every block books at least one step, so the work always ends. Where within that the node cuts is its own choice, as every block boundary is: a replay of a block withmorestops after that block's lastseq; a block withoutmoreis replayed with all of its work. A reader checks: every block at most 100,000 bytes; a block withmoreis followed by a block that starts at its lastatand begins with a rule entry; a block withmoremay leave out duties due at its start, its successor books them; a restorer whose seal'sh_tocarriesmorecontinues that work first (§8.1). A Heart member's leave is never cut: itsrolesentry follows its entries in the same block [E-11]; when they would pass 100,000 bytes the leave is refusedtoo_bigand books nothing, and the member first declines the projects it receives (each decline's work is cut like any other). Said openly: about 100 small projects waiting behind a big one, or about 450 tiny projects whose votes end in the same second, take a few blocks of the same second; payments wait those few blocks. - Morning header: its
tzdatais the version the circle pinned at founding [Decided 17 Oct 2026, C7 and (evening) 2A; the check: Proposal], and a witness computes the boundary with that version, never with a newer one of its own [Decided 17 Oct 2026 (evening), 2A]; a witness without that version signs no morning block and no seal (how it keeps the version is its own implementation) [Proposal]; how a verifier identifies, obtains and checks a release: §7.2. - Sum rule: the circle's sum of balances is 0 after every block (principle 4); every witness checks it.
Entry types ([seq, type, at, …]):
| Type | Books | Embedded | Consequences carried |
|---|---|---|---|
genesis | the founding state; opening lines if an existing circle migrates (proposal: a migrating circle's Common Good balance opens as the reserve; there is no main line to carry [6a], since the live circle had no confirmed deposit at the check of 10 October, re-checked on a copy of the live database before migration) | found act, rebuilt with ["c", ""] (its id is the circle id [Decided 17 Oct 2026, C5]); the mirror the found act gives (§3.7); circle_sig, the signature of the circle key the found act names over sha256("lb-found/3|" ‖ found id) (below the table) | the circle key in office (from block 1), the circle parameters of the found act and its parent circle (when it names one [E-8]), as governance lines (below the table); the Heart, witness set, relays, rate source; then, in block 1, the rule entry start right after it (§3.9) [6c]: block 1 without it is invalid |
pay | member → member | 43910 | grow = min(amount, cap − wave), then settled = min(debt, max(0, balance)) read after the receipt and the grow move (today's createTransfer order), each moved receiver → reserve as one move, then drain() (§3.9) [Decided 16 Oct 2026, A8]; the amounts follow today's wave-growth and waiting-flow rules unchanged, only the destination changes (one step row per receipt, as today with Common Good renamed); a pay to a left or excluded line with a minus is a settlement: amount ≤ −balance (never above 0), no grow and no settled move (§3.11) [Decided 23 Oct 2026, E-9: anyone may settle a debt; the shape: Proposal] |
give | member → the named receiving project up to amount − received, the rest → reserve; a give naming no project → reserve; then drain() (replaces cg) | 43910 | cover: the plus only, amount ≤ max(0, balance) (today's rule; Open 8g); a project wallet has no wave, so a give makes no wave growth; a named project that has ended is refused not_found [clarification, 19 Oct 2026 (D3 review)], an open one that is not receiving not_receiving [Proposal] |
xout, xin, xdone, xundo | cross-circle legs through the world account | 43910 in xout and xin (across currencies with its 43919 quote id); the partner circle's genesis digest (g) on every leg; the partner's block as [height, digest] (src), or for the 7-day check the partner's consecutive seals as [day, digest] and the height range they cover (§4.5) | hold, final, undo (a timeout alone never undoes; after 7 days the payer's circle reads the receiver circle's sealed ledger and books xdone or xundo by rule, naming that evidence [Decided 16 Oct 2026, 8j], §4.5); xin moves grow/settled to the reserve like pay, except a settlement to a left or excluded line with a minus (≤ −balance, no grow, no settled) [E-9]; xundo moves world → payer; an excluded or left key may book an xout of its plus, amount ≤ max(0, balance), never the wave [E-3; for a left key: Proposal] |
act | any act without a money effect (project proposal, motion, vote, request, invitation, parameter proposal, exclusion, readmission, account close, OWN opening and closing) | 43916 | recorded in order, so deadlines are deterministic |
rule | a transition a public rule makes due: start in block 1 only (origin → reserve, §3.9) [6c]; member admitted (member_join) or gone (member_leave); a booked rules act (member_rules, below the table) [proposal (D4 review, 17 Oct 2026)]; member_exclude, reference, reference_grant, reference_return and account_close (§3.11) [E-3, E-9]; project_open, reserve_move, project_full, project_pay [8a], project_lapse [8e], project_return [8e] (§3.9); the end of a vote (vote_pass or vote_fall, §3.9) [E-5]; request expired (request_expire); parameters effective (params_effective, at a param_propose's notice end, §3.1 rule 11) [E-1]; a step lowering (step_lower) [Proposal]. There is no rules_adopt any more [E-1] | none: the rule and its input ids are named | the bookings the rule makes |
roles | witness, Heart, node, relay, rate-source and circle-key changes, resignations, and the loss of a Heart seat by an exclusion (§3.11) [E-3]; carries the new 30910 mirror (tags without g; mirror_of = this height; the circle id, the code and the founder never change, nor do the currency, tz, tzdata and the morning hour, which are written at founding [one currency per circle: Decided 16 Oct 2026; tz, tzdata and the morning hour: Decided 17 Oct 2026, C7; the check: Proposal]; the circle key changes only when the proposing act is circle_key_change, and then to exactly the key it names, in office from the next block (state line below the table) [Decided 17 Oct 2026, C5; in office from the next block: Proposal]); at most one roles entry per block [Proposal], so mirror_of names exactly one mirror per height and a second roles entry can never undo what the first put in office (for example a circle key change); block 1 books no roles entry: its genesis mirror is the mirror of height 1 [Proposal] | none: acts is exactly [the id of the proposing act] (or of the resign act) [proposal (D4 review, round 3, 17 Oct 2026)]; for a change of k Heart members those who signed it, at least k distinct Heart members in office at the roles entry (the proposer counts), are in its o3|change line (§3.8), and it is booked after the change's notice (§3.4); a resignation's entry is booked at its notice end (a duty, §7.4) | windows by height |
grav | one account's morning gravity (§7), computed from the cut-off state | none | avg, rule_micro, deduct, carry, debt; deduct moves to the reserve; booked right before the first entry after the boundary (in catch-up: after its morning opened) that touches the account (a visit), or else in a morning block, in HEX order and followed by drain() (§3.9, §7.4) [A8]; morning blocks hold only grav and rule entries; a payment block holds grav entries only as visits |
rej | a refused note or act, with its reason (stale_prev, no_cover, not_member, not_allowed, expired, vote_ended, bad_template, stale_quote, bad_quote, not_receiving …; every reason and their order: below the table) | the refused event's id, kind and author HEX only, never its tags or text [ruling of 16 Oct 2026, decisions 5 and 6]; src = the partner's xout block ([height, digest]) when a partner circle's note is refused | none; public; only refusals of members and applicants are booked [Decided 17 Oct 2026, C3] (and of a partner's note with src, which a verifier checks against the partner's ledger [Proposal: a ruling of the definitions, not part of C3]); refusals of any other key are answered, never booked [C3]; at most rej_per_author_per_day (a circle parameter: 20 by default [C3, E-1]) per author and morning day (below the table), above it the intake answers 429 and books nothing; an event with an invalid signature is never booked. Said openly: a refusal is the node's statement; a payer who disagrees publishes the note standalone and any verifier a 43924 |
There is no pout entry and no cg entry [Decided 16 Oct 2026, A6 and A8], no dep and no corr entry [6a], and no xrefund entry [8j].
Genesis, rule entry bodies and circle-key details [Decided 17 Oct 2026, C5; the parent: Decided 23 Oct 2026, E-8; the shapes: Proposal]:
genesisbody:{"found": <compact found act>, "mirror": <the 30910 tags without g that the found act gives>, "circle_sig": <the signature of the circle key the found act names over sha256("lb-found/3|" ‖ found id)>}(there is norulesfield any more [E-1]). Block 1 starts the state withg3|circle_key|<hex>|1, ag3|param:<name>|<integer>line for every parameter thefoundact names,g3|params_h|1, andg3|parent|<parent circle id>|<parent genesis digest>when thefoundact names a parent [E-8].- Rule entry bodies of round 5 [Proposal; the rules: E-1, E-3, E-5, E-6, E-9]:
member_join{rule, in: [join id], party, ref?, src?, g?}(ref= the 43921 id of the reference the join names,src=[height, digest]of the old circle's block that books thereferenceentry,g= that circle's genesis digest; only for a key that comes from another circle, §3.11);member_leave{rule, in: [leave act id, or the proposing account_close id], party};member_exclude{rule, in: [the proposing member_exclude id], party};reference{rule, in: [leave act id], party, wave}(wave= the party's wave);reference_grant{rule, in: [43921 id], party, to, amount, to_amount, quote?, mv}andreference_return{rule, in: [43921 id], party, src, g, wave, mv}(§3.11) [E-9 (b)];account_close{rule, in: [the proposing account_close id], party, mv?}(the movesclose_coverandclose_wave, each only when above 0);vote_passandvote_fall{rule, in: [proposal id], project?}(project= the project's id when the proposal is a project);params_effective{rule, in: [param_propose id]}. There is norules_adoptany more [E-1]. - A
rolesentry whose proposing act iscircle_key_changesetsg3|circle_key|<new key>|<since_h>,since_h= the height of the roles entry + 1; no otherrolesentry changes the circle key. The mirror of the change's own height already names the new key: the 30910 with thatmirror_ofis signed by the new key, and a day seal whoseh_tois that height names it (§3.6) [Proposal]; since a block books at most onerolesentry, no later entry of the same block can undo the change [Proposal].
Duties, end-of-entry work, rule inputs and refusals [clarification, 17 Oct 2026 (D4 review), except where marked as a proposal]:
- When a duty is booked. A duty whose due time is at or before a block's first
atis booked at the start of that block (after itsparams_effective, when one is due; while two or more mornings are pending it waits, §7.4), with the block's firstat; a due time inside a block's span (firstat< due ≤ lastat) belongs to the next block. Every due time is recorded when its deadline starts, with the parameters in force then, never retroactive [Consequence of E-1]: a vote's end (theatof its proposal's entry + its duration), the open lapse (open lapse at= published at +open_lapse_s), the receive lapse (receive lapse at= opened at +receive_lapse_s), the close return (close due= the k-th close +close_notice_s), the 8j check (check at= thexout'sat+xcheck_s), aparam_propose's notice end, and therolesentry of a resignation (at itso3|changenotice end, §3.8 [proposal (D4 review, round 3, 17 Oct 2026)]); they fall due when the block's firstatreaches them. A vote counts only atat< its proposal's vote end (elsevote_ended) [E-5].a3andi3lines, a request, an excluded key's application (o3|join…heart), ano3|inviteline, ano3|excludeline and ano3|changeline (while collecting, or a roles change of k Heart members never committed, §3.8) expire at the first block whose firstatis later than theirexpiresoruntil(request_expire's due time isexpires+ 1). The order of the entries inside a block: §7.4. - End-of-entry work =
drain()(§3.9; thereserve_move,project_full,project_payandproject_returnentries it books start no nested drain and no re-check), then the passed projects (statuspassed) re-checked in publication order: the first whose consent is given and, for a step raise, whose amount fits underbuiltopens (project_open),drain()again, repeated until none opens; then the waiting account closes, in booking order; then the leaving lines (the references), in booking order; then the waiting list, while a place is free (§3.11) [E-3, E-6, E-9; the order: Proposal]. Areserve_move'sin= [project id, seq of the entry whose end-of-entry work started this drain] (also after a restart within it). - The
inof every rule entry [proposal (D4 review, 17 Oct 2026); the entries of round 5: Proposal (E-1, E-3, E-5, E-9)]:start[found act id];member_join[join act id];member_leave[leave act id, or the proposingaccount_closeid];member_rules[rules act id];member_exclude[the proposingmember_excludeid];reference[leave act id];reference_grantandreference_return[the 43921 id];account_close[the proposingaccount_closeid];project_open[project id, theseqof the entry whose end-of-entry work opens it] [proposal (D4 review, round 3, 17 Oct 2026)];reserve_move[project id, the triggering entry's seq] (above);project_fullandproject_pay[project id];project_lapse[project id];project_return[project id] after a receive lapse or insidedrain(), [project id, the proposingproject_closeid] after a close (its Heart members are in theo3|changeline) [proposal (D4 review, round 3, 17 Oct 2026)], [project id, theproject_declineid], [project id, the leave act id], [project id, the proposingmember_excludeid] at an exclusion [Proposal] or [project id, theproject_withdrawid];vote_passandvote_fall[proposal id];request_expire[pay_requestid];params_effective[param_proposeid];step_lower[step_proposeid]. - Applicants, admission and leaving [clarification, 17 Oct 2026 (D4 review, round 3); the waiting list, invitations and references: Decided 23 Oct 2026, E-6 and E-9; the mechanics: Proposal]. An applicant is a key with an
o3|joinline (§3.8): on the waiting list (waiting, no expiry) or an excluded key's application to the Heart (heart, until itsjoinact expires); ajoinwith a free place is admitted at once and leaves no line. How ajoinis judged and admitted: §3.11.member_joinnames a bookedjoinact of that key that nomember_joinused; a key that is a member is not admitted again. A key that left and joins again keeps its line: statusmember,cap= thewave_capin force,rules_v"", its balance, wave and history unchanged [clarification, 17 Oct 2026 (D4 review, round 3)]; a closed key that joins again starts at 0 (statusmember,cap=wave_cap) [E-3]. A member's bookedleaveact is followed at once by itsmember_leave(the next entry, asmember_rulesafter arulesact), so no unused leave act stays in the state [clarification, 17 Oct 2026 (D4 review, round 3)], and it books ano3|leavingline (§3.11); an excluded key'sleavebooks only theo3|leavingline (its status staysexcluded); an applicant's ownleavewithdraws itso3|join(nomember_leave) [E-6, E-9; Proposal]. The daily refusal limit counts per author and morning day, from one morning boundary to the next, not per local calendar date, so a restorer from a seal holds every refusal of the current day in the blocks it reads (§8.1 step 5) [clarification, 17 Oct 2026 (D4 review, round 3)]. - Refusal reasons [proposal (D4 review, 17 Oct 2026); the names and their order follow the money machine of plan step D1; the cases each reason covers and the wait for an
afterheight: clarification, 17 Oct 2026 (D4 review, round 3); the list of round 5: Proposal (E-1, E-3, E-5, E-6, E-7, E-9)]. When several apply, the reason booked is the first in this order:bad_template,bad_quote(the shape of the event and its quote;bad_templatealso: a note in another currency than the circle's, a note whoseexpiresis beyondnote_ttl_sof this circle's parameters (in a receiving circle: its own value, §4.5), agivewhosepis not the named project's wallet (or the reserve), acircle_key_changenaming the key in office, the founder's, a witness's or a Heart member's key, afoundact orparam_proposewith a parameter outside its range,vote_min_s>vote_max_sorvote_max_s≥open_lapse_s;bad_quotealso: a note whoseexpiresis later than its quote's);not_found(what the event names is not open in the state: never booked, or ended; also an endorsement after its proposing act expired, or of another type, a request closed or for another receiver, a named invitation that is not open, a new circle's reference grant for a key whose reference no longer waits, §3.11);not_member,not_allowed,self_pay,refused_circle(the parties and their roles;not_memberalso: aproject_proposewhose recipient is not a member when it is booked (left, never joined, frozen or excluded) [clarification, 19 Oct 2026 (D3 review)], amember_excludenaming a key whose line is notmemberorfrozen, a payment to a left or excluded line that is not a settlement (§3.11), and an excluded key's own payment or act other than itsleaveor anxoutof its plus [Consequence: its line is notmember];not_allowedalso: a note paying a request that names another payer, an accept by another key than the change names, the last Heart member's or witness's resignation, adurationoutsidevote_min_s…vote_max_s, ajoinby a key whose exclusion runs, ajoinwithout an invitation whileinvite_only= 1 (an excluded key's application excepted), ajoinnaming another key's invitation, ajoinby a key whose newest member home names another circle without a valid reference from that circle [E-9], ajointhat brings a step while this key's reference from this circle still waits for its return [E-11], the leave of the last Heart member [E-11], amember_readmitwhen no place is free, anaccount_closeof a Heart member in office or of a line that is notmember,frozen,leftorexcluded, and therolesentry of a witness change while a Heart member in office has "against" as the newest vote [E-7]);wrong_status,not_receiving(the status of what it names:wrong_status= the project'so3|projectline exists but its status does not allow the act; an ended project isnot_found;not_receiving= agivenaming an open project that is not receiving, while agivenaming a project that has ended isnot_found[clarification, 19 Oct 2026 (D3 review)]);expired,vote_ended,stale_quote(time windows;vote_ended= a vote booked at or after its proposal's vote end [E-5]);duplicate,repeated,stale_prev(the same event id again, and ajoinnaming a reference this circle used already or one a waiting join carries [E-13]; the same author's act whose effect already holds, also ajoinact by a member or frozen key, ajoinof a key with an openo3|join, the same vote choice again, a further endorsement by a listed Heart member and a secondparam_proposewhile one is open; a second note on the sameprev);no_cover,step_full(cover;no_coveralso a reference grant whoseto_amountis below the wave, §3.11). What an event names is judged by the open lines of the state (§3.8). An act booked below itsafterheight is not refused: the node waits for that height (if the act expires first, it is refusedexpired). Removed with the objections and approvals [E-5]:objection_window,notice,no_consent,objection_standsandunanswered; new in round 5:vote_ended. The k-th exclusion act of a Heart member that finds the block's onerolesentry taken waits for the next block (the intake answersroles_taken; nothing is booked). The machine's other names (bad_amount,bad_key,bad_day,bad_k,not_started,not_first,step_floor,too_early,grav_pending,out_of_order,above_room,reserve_short,replay_only) never appear in arej: they are checks of the node's own entries or of today's app.
Line after the block (one per touched party): [index, balance, wave, cap, carry_micro, debt, aseq, last_h, note_n, note_head, last_gift_day, first_receipt_day, status, rules_v], where aseq is the account's own gap-free entry counter, last_h the previous block that touched it, and the two *_day fields are the quiet-day inputs gravity needs (all three exactly: §3.8); rules_v is the version of the circle's own rules text the member accepted (the rules act); it has nothing to do with the circle parameters. rules_v is "" until the member's first rules act (member_join sets ""); a booked rules act is followed at once by the rule entry member_rules {rule, in: [the rules act id], party} that sets rules_v to the act's version, copied as written (1 to 6 decimal digits) [clarification, 17 Oct 2026 (D4 review, round 3)] (an act entry has no party, so without it the line could not show the change) [proposal (D4 review, 17 Oct 2026)]. The found act no longer carries a rules tag [E-1], so ["rules", version, sha256] appears only in the rules act (the circle's own rules text) [clarification, 17 Oct 2026 (D4 review); E-1]. status is member, frozen, left, excluded or closed (the last two since 23 Oct 2026, E-3). Parties are HEX keys or keyless system addresses, never names [A5]. held_out is gone with payouts [A6]. paid_in is gone with deposits [6a]: it counted only money paid in less money paid out, so with neither it has nothing to count.
3.6 43917 v3 Day Seal, 43918 Snapshot Chunk, 30915 v3 Circle Head#
- 43917 (once a day, right after the morning, also on days without payments or without any block) [Decided 16 Oct 2026: one seal a day after the 04:00 morning], tags in this order:
["c", <circle id>];m=<scope16>:<date>;["day", date, n];["boundary", unix](the circle's morning hour of that day in its time zone, with the pinned tzdata);["prev", previous seal digest, its day, its boundary, its covers](["prev", ""]for the first seal, whose range always starts at height 1 and seq 1: a circle's seal chain starts at its block 1);["covers", the last at of block h_to](on a day without blocks: the previous seal's covers);["range", h_from, h_to, seq_from, seq_to](a day without blocks: h_from = h_to + 1, seq_from = seq_to + 1);["head", digest of block h_to, h_to];["pay", RFC 6962 root over the canonical JSON bytes of the day's entries in seq order, count];["state", sparse Merkle root at h_to, line count];["snap", chunks root, chunk count, bytes];["gravity", date, moved, accounts](always) [Consequence] (moved = the sum of the deducts of the morning'sgraventries in the seal's range, accounts = the number of thosegraventries [clarification, 17 Oct 2026 (D4 review)]);["sum", "0"];["world", cur, used, step, built](built, up to 20 digits: Σ (balance + wave) over every account line that is not a system account or a project wallet, of any status, members who left and excluded members included, since their money is still in the circle [clarification, 17 Oct 2026 (D1 review); the excluded: Consequence of E-3], a closed line holding 0; the formula: Proposal);["quotes", RFC 6962 root over the distinct 43919 ids that the range's entries name, count](each id once, as 32 raw bytes, sorted ascending; count = the number of distinct ids [clarification, 17 Oct 2026 (D4 review)]);["reserve", balance](the keyless reserve afterh_to) [A8];["origin", balance](the keylessorigin: −start − granted + returned since block 1; it may go above 0, and the tag is signed) [6c, E-3, E-9 (b); the tag: Proposal];["signers", hash of the witness set of the office after h_to, q, n](the hash covers the current witnesses of that office,until_h"", each as[hex, operator, since_h, ""], sorted by hex [clarification, 17 Oct 2026 (D4 review)]);["circle_key", <the circle key of the newest mirror at or below h_to>](read from theg3|circle_keyline at h_to; at the height of a key change already the new key, which also signs the 30910 of that height; the 30915 head carries it to the root directory, so a reader picks the 30910 by it) [Proposal];["params", params_h](the height of the newest genesis orparams_effectiveat or below h_to, whose parameters are in force at h_to); there is norulestag any more [Decided 23 Oct 2026, E-1];qs× ≥ q of that office's witnesses oversha256("lb-seal/3|" ‖ digest);["v","3"]. Size ~2 KB. The office of a seal [Proposal]: a seal is judged with the office after its last blockh_to, the newest mirror at or belowh_to(the genesis mirror or the newestrolesentry's, read from the ledger): at least q of its witnesses sign the seal, andsignersandcircle_keyname its witness set and circle key, as the state'sg3lines ath_todo. The seal chain [clarification, 17 Oct 2026 (D4 review)]: the first seal (n = 1,prev"") is the seal of the first day whose boundary is later than block 1'sat; each later seal is for the next day: day = the previous seal's day + 1 and n = its n + 1, one seal per day without a gap (after an outage the missed days are sealed in order); validators check it. The day-chain checks apply to seals whose range lies on the chain a verifier replays; the synthetic seal at maximum lengths of the definitions is a standalone fixture and gets only the checks that need no chain [clarification, 17 Oct 2026 (D4 review, round 3)]. What a seal covers [Decided 17 Oct 2026, C2: payments never pause for the morning]: every block booked before the boundary and, when blocks carry the day's morning header (the morning blocks, and payment blocks with visits, §7.4), every block up to and including the last of them (payment blocks booked during the morning among them); no block spans the boundary. So every block afterh_tobooks at or after the boundary, and every block beforeh_frombooks at or before the previous seal'scovers; the 8j evidence (§4.5) rests on exactly this. The seal's state is the state ath_to, even when payments follow at once. Completeness [clarification, 17 Oct 2026 (D4 review)]: that no block before the seal's boundary was left out needs blockh_to+ 1 or the next seal with an empty range fromh_to+ 1; without either it is unverifiable. - 43918:
c,m,i=<scope16>:<date>:<index>,["chunk", i, n],["range", first key, last key]; content = canonical state lines sorted by key (§3.8), ≤ 100,000 bytes (~450 account lines). Valid only against the seal'ssnapandstateroots; a reader verifies a chunk before showing anything from it. - 30915: the newest 43917 mirrored for root: the same pubkey,
created_at, content and tags (theqstags included), then["d", <circle id>]and["seal", seal digest, seal day]; the seal tag recomputes as the digest of[0, pubkey, created_at, 43917, the seal tags without qs, content].dis the circle id, so replacing the circle key never moves the head (its address is30915:<node pubkey>:<circle id>: one head per node key). Like the seal it names the circle key of the newest mirror at or below the seal'sh_toand the parameter height, under the witnesses' quorum, so a reader of the root directory picks the circle's 30910 by that key in one more query [Proposal]. Published at a per-circle offset spread over 24 hours: the first 4 bytes, big-endian, of sha256(the circle id as its 64 hex characters), mod 86,400, seconds after the seal (test_vectors.circle_id), not the hour after 04:00, so the heads of one time zone do not bunch into one hour (~560 writes/s at 10 M circles [E]).
3.7 30910 v3, 30916 v3, 43919 v3, 43924, 43921 Reference (43920 retired)#
- 30910 v3 Circle Record (mirror) (Q10; mirror-only [Proposal, follows from A3 and A8, not confirmed]; addressed by the circle id [the circle id: Decided 17 Oct 2026, C5] and signed by the circle key its mirror names), tags in this order:
["d", <circle id>](the id of thefoundact; never changes),code,name,currency(exactly one) [Decided 16 Oct 2026],tz,["tzdata", "2026a"],morning(tz,tzdataandmorningfixed at founding for 0.3.0 [Decided 17 Oct 2026, C7]),["g", genesis digest, the founder's signature over sha256("lb-genesis/3|" + circle id + "|" + genesis digest)],["mirror_of", <height of the genesis or roles entry it mirrors>],["founder", <founder HEX>](the author of thefoundact; the root directory checks decisions A9 and E-8 from it),["parent", <parent circle id>, <parent genesis digest>](only when thefoundact names a parent [Decided 23 Oct 2026, E-8; the tag: Proposal]),["circle_key", <HEX of the circle key in office from the block after mirror_of (from block 1 for the genesis mirror)>](the record's author must be this key; never the founder's, a witness's or a Heart member's key [Proposal]; changed only bycircle_key_change[C5]),["signer", hex, operator, since_h, until_h]× n (at most 100 tags; operators are names the circle declares itself, not a proof of independence),["quorum", q, n],["proposer", hex, since_h],["steward", hex]× m (the Circle Heart; the tag keeps its technical name [Proposal, E-2]) +["stewards_required", k](live circle m = 4 [4a]; k for other acts: proposal, 3; k is never above m and never below 2 while m ≥ 2 [proposal (D4 review, round 3, 17 Oct 2026)]; afoundact that breaks it is refusedbad_template[proposal (D3 review, 19 Oct 2026)]),["relay", wss, operator]× ≥ 4 of ≥ 3 operators [A2],["archive", wss]…, optional["bootstrap", "Q14"](open question 14, not decided: while declared, two relay operators give a warning instead of a refusal),["rate_source", <source id>, <public description>](any source the circle chooses [A7]; start: the ECB daily reference rate [Decided 16 Oct 2026, start source]; how it is changed: proposal),["api", https](write intake),["definitions", "0.3.0"],["v","3"]. The record carries no circle parameter: the formerquote_ttlandproject_approvalstags are gone; the parameters live in the ledger (thefoundact, eachparam_proposethat aparams_effectivenames, and the state'sg3|param:<name>lines, §3.1 rule 11) [Decided 23 Oct 2026, E-1]. No fund key [A8], no founder gate [A9], no rate panel [A7], no custodian tag [6a]. Canonical address30910:<circle key in office>:<circle id>: it changes when the circle key is replaced, so readers query#d= the circle id and take the record the ledger confirms; every version is also carried in the ledger (genesis orrolesentry). Authority rule: a 30910 counts only if it is signed by the circle key that the ledger's mirror at itsmirror_ofnames (at the height of a key change already the new key; for blocks it is in office from the next height), its tags withoutgequal that mirror (the one the committed genesis orrolesentry atmirror_ofcarries; a block books at most onerolesentry, so a height names one mirror), and itsgnames the pinned genesis digest; readers take the valid record with the highestmirror_of; a record by an old circle key with amirror_ofat or above its replacement can never match; when they differ, readers follow the ledger. The genesis mirror is a function of the signedfoundact. Said openly: the circle key is no longer part of the record's address, so anyone can publish a 30910 that names a circle id; it counts only when the ledger's mirror at itsmirror_ofnames its author. No key can re-pointg: it carries the founder's signature over the circle id and the genesis digest; a reader keeps the genesis it pinned (from the circle link or QR, or the firstgit saw for the circle id) and never follows another, and root relays keep the first-seengand founder per circle id (relay/ledger-write-policy.py, moderoot, which also checks the founder's signature ing, and pins them only when it holds the circle'sfoundact and the record'sfounderis its author (or, for a circle configured on the relay, when its configured circle key signed the record) [Proposal], §9.2): a request in the letter to the Lana relay owner, now only extra safety [Decided 17 Oct 2026, C6]. The circle key can be replaced (§3.1 rule 8, §3.4). - 30916 v3 Member Home [Decided 16 Oct 2026: mandatory]:
d=letsbalance,["c", <circle id>],["g", genesis digest],["join", <height of the member_join rule entry>],["attest", witness hex, since_day, sig](by a witness current at the join height; the signature over sha256("lb-home/3|" + member + "|" + circle id + "|" + genesis digest + "|" + join + "|" + since_day)),nname words from KIND 0 (always [Consequence], formerly P9),wLANA address,["v","3"]. Truth = the join entry; 30916 is a pointer. Before paying, the app checks the join (and absence of a leave) in the circle's ledger. Where a key is a member [Decided 23 Oct 2026, E-8 and E-9; the reading: Proposal]: the newest 30916 of a key (the newest counts) names the circle the key last joined; a new circle reads it on the root relays to see whether a joining key comes from another circle, and then needs that circle's reference (§3.11). A key with no member home anywhere was never a member and needs no reference [Proposal]. Root relays keep member homes (no deletion by KIND 5) [Proposal; at scale this meets Q16]. Said openly: a deleted home or a second key is not caught; that needs Lana's person check. Names [Decided 16 Oct 2026, A5]: the member can replace 30916 at any time; when KIND 0 changes, the app republishes 30916 with the newnwords and the witness re-attests; relays keep only the newest version; no version is ever copied into the ledger. - 43919 v3 Rate Quote [Decided 16 Oct 2026, A7: the seller's circle quotes, the payer accepts by signing both amounts; the format below is the proposal for 0.3.0, the same word for word in every document]:
pubkey= the node (proposer) of the seller's (receiving) circle atcreated_at, checked against that circle'sroleswindows (the office at a time: §4.5); a quote signed in the very second of a node change is the new node's, although that block was still ordered by the old one [clarification, 17 Oct 2026 (D4 review, round 3)].- Tags:
["c", <seller circle id>],["source", <source id = the circle's rate_source at created_at>, "<the source's own time for this rate, unix>"],["base", "EUR"],["rate", "<currency>", "<whole ppm: units of that currency per 1 EUR × 10^6>"]once for each currency the source gives (r_EUR= 1,000,000, implicit),["expires", "<unix, ≤ created_at + quote_ttl_s>"](quote_ttl_s: a parameter of the quoting circle, 600 s by default [E-1]; both circles judge a quote by the quoting circle's value: the quoting circle by its parameters in force at the booking, the payer's circle by the value it reads in the quoting circle's ledger, §4.5 [Proposal]; never NIP-40expiration),["prev", "<this circle's previous 43919 id, or \"\" on its first>"],["v", "3"]; content"". - Conversion:
to_amount = floor(amount × r_to / r_from)in BigInt, one rounding, no intermediate rounding. A price set in the receiver's currency:amount = ceil(price × r_from / r_to), which givesto_amount ≥ price; a payment request counts as paid whento_amount ≥the requested amount.to_amount = 0is refused. - Valid for a booking when: signed by that node;
cis the seller circle; the source id equals itsrate_sourceatcreated_at;source time ≤ created_at < expires ≤ created_at + quote_ttl_s(the quoting circle's value); the payer circle'sxoutat≤expires;to_amountequals the conversion exactly. Refusal reasons:stale_quote(expired),bad_quote(anything else). - Audit checks, not booking conditions (a quote enters a ledger only when a payment references it): the circle's
prevchain has no gap, and for one source id the source time never goes back. A break is published as a 43924fail. - Issuing: the node keeps at most one live quote and makes a new one only when asked and the live one has expired, has less than QUOTE_MARGIN_S left (a constant; proposal 120 s) or the source has given a newer rate; it publishes each quote to its circle's relays before handing it to any app. At most ≈ 180 a day per circle, none on a day without payments from other currencies. The payer's circle republishes to its own relays every quote its blocks reference, so each circle restores without the partner. the project owner's rate key is no longer needed; it may be one source a circle chooses.
- Start source [Decided 16 Oct 2026, start source]: the ECB daily reference rate (EUR base, USD and GBP), read once a day by the node; the app shows the rate's date (the source time in
source); a quote is valid 600 s (quote_ttl_sby default [E-1]). Proposal: RATE_STALE_ALERT_S = 432,000 s (120 h), a constant. Details and test vectors:docs/valute-in-tecaji.md.
- 43924 Statement:
c,["about", "seal"|"range"|"block"|"signer"|"restore"], exactly one target (["target", digest, "h:<height>" | "d:<day>"]for a block or seal,["e", id, "", "target"]for any other event),["range", from, to](the heights whose blocks the author checked for it: from the first block it replayed (1 when it replayed from genesis;h_fromof the target seal when it started from the state of a seal it had verified before) toh_tofor anok, or to the last height it could check formissingorfail),["result", "ok"|"fail"|"equivocation"|"missing"|"ignored"](missingalso means "could not be checked", with the missing event as evidence; neverok),["state", root the author computed],["votes", root, count](Q23; the root: RFC 6962 over the 32 raw bytes of each block digest the author signed among the blocks of the statement's range (for a seal: the sealed day's blocks, the seal's range, also when the statement's range starts at block 1 [clarification, 17 Oct 2026 (D4 review, round 3)]; not the calendar day of signing), in height order), evidence the same way (["evidence", digest, "h:<height>" | "d:<day>"]or["e", id, "", "evidence"]), short content [the range,missingand the votes root: clarification, 17 Oct 2026 (D4 review)]. Uses: each witness's dailyokwith the root it computed and a root over every vote it signed for the sealed day (Q23); the daily restore drill result (§8.3); any verifier's challenge. A verifier checks arej's reason only with the events that the reasons before it in the refusal order (§3.5) need (abad_quoteorstale_quoteneeds the quote and, across circles, the partner'sxouttime); without them the reason is unverifiable, never assumed [clarification, 17 Oct 2026 (D4 review, round 3)]. - 43920 (retired) [Decided 23 Oct 2026, E-1]: the BSA Rules record of world-wide rule values was never published and is retired; its number stays reserved and is never reused (
reserved_unused) [Consequence]. The time values and limits it held are circle parameters (§3.1 rule 11), set in thefoundact and changed byparam_propose; there is no rules authority and no world signer, so decision 1A's signer question is gone. - 43921 Reference (new) [Decided 23 Oct 2026, E-9: a new kind, issued by itself after a member's "I want to leave" when the conditions hold, carrying the projects published and taken part in, the step built and the open OWN processes; the number, the tags and the verification: Proposal]:
- Regular (40000+): every reference is its own event, kept for ever.
pubkey= the node of the circle the person leaves, at the block that books thereferenceentry; the node signs it right after that block has its quorum and publishes it on the circle's relays (§3.11). - Tags in this order:
["c", <circle id>],["p", <the person's HEX>],["block", "<height>", <block digest>](the block with thereferenceentry),["g", <genesis digest>],["currency", <code>],["wave", "<minor>"](the step the person built: thewaveof thereferenceentry),["own", "0"](a reference is issued only while no OWN process about the person is open [E-9 (a)]),["joined", "<unix>"]and["left", "<unix>"](theatof the newestmember_join, and theatof the entry that booked the leave act, also for an excluded key) [Proposal],["published", "<count>"]then up to 100["e", <project_propose id>, "", "published"](newest first),["took_part", "<count>"]then up to 100["e", <project id>, "", "took_part"](the projects that paid the person, newest first [Proposal: the reading of »projekti, pri katerih je sodeloval«, "the projects they took part in"]),["v", "3"]; content"". - The ledger entry is the authority (under the witnesses' quorum); the 43921 is the findable copy with the node's summary, which anyone checks against the circle's public blocks.
- How the new circle checks it, and where it is kept: §3.11. Size ~0.7 KB; up to ~18 KB with 100 + 100 project ids [E].
- Regular (40000+): every reference is its own event, kept for ever.
3.8 System accounts and the decision state#
- System accounts have no key [Decided 16 Oct 2026, A8 for project wallets and the reserve; 8i for
worldandworld-step; 6c fororigin, the name: Proposal]: every project wallet,reserve,world,world-stepandoriginare x-only pointslift_x(sha256("lb-system/3|" + role + "|" + circle id + "|" + i))for the first decimali= 0, 1, 2 … that gives a valid point, where role isreserve,world,world-step,origin, or for a project walletproject|+ the 64-hex id of itsproject_proposeact (so the string is"lb-system/3|project|" + <project_propose id> + "|" + circle id + "|" + i). A project wallet is writtenproject:<id>for display only; the point always comes from the string above. The test vectors (circle id, act id → x-only HEX) aretest_vectors.system_addressesof the definitions. Nobody can sign for them; only entries that follow public rules move them. The singlecommon-goodaccount and the fund key on the server are gone. There is nomainaccount: today it books only deposits, deposit corrections and payouts, and BSA has neither [A6, 6a] (the project owner also confirmedmainas keyless under 8i before it went with 6a). - System accounts have no wave, no cap, no gravity and no debt (project wallets,
reserve,world,world-step,origin): a receipt into one makes no wave growth and no counter-booking. The reserve and every project wallet never go below 0; a project wallet never exceeds its amount;worldmay be negative, as today;originholds −start from block 1 and moves only bygrant(origin → reserve, a newcomer's step) andclose_wave(reserve → origin, a closed or moved account's wave), §3.11: origin = −start − granted + returned, and it may go above 0 [6c; E-3, E-9 (b); the shape: Proposal]. - The decision state (everything the next booking depends on, committed by the state root; exact fields, value sets and lifetimes:
state_linesof 43911 in the definitions): account liness3|<hex>|balance|wave|cap|carry_micro|debt|aseq|last_h|note_n|note_head|last_gift_day|first_receipt_day|status|rules_v(statusmember,frozen,left,excludedorclosed, the last two new [E-3]; noheld_out[A6], nopaid_in[6a]; keys only, never names [A5]); governance linesg3|<key>|<value>(code, name, currency, tz, tzdata, morning, founder, the circle key in office with itssince_h(g3|circle_key|<hex>|<since_h>, changed only by arolesentry whose proposing act iscircle_key_change[C5]), quorum, proposer, every signer with operator and window, the Heart (stewardlines) and k, relays and archives, the bootstrap label while declared, rate source, api, every circle parameter (g3|param:<name>|<integer>, §3.1 rule 11) and their height (g3|params_h|<h>, the height of the genesis or of the newestparams_effective) [E-1], the start, the parent circle (g3|parent|<parent circle id>|<parent genesis digest>, only when thefoundact names one) [E-8], the refusal list (by circle id), definitions version andg3|mirror_h|<h>, the height of the newest genesis orrolesentry, whose mirror, in tag order, is the mirror in office [proposal (D4 review, round 3, 17 Oct 2026)]; there is nog3|rulesline any more [E-1], and the fixed constants are not lines); open-item lineso3|<type>|<id>|…(the set of round 5 [Proposal; the rules: E-1, E-3, E-4, E-5, E-6, E-9]): projectso3|project|<id>|<status>|<amount>|<received>|<proposer>|<recipient>|<consent>|<published at>|<published seq>|<vote end>|<open lapse at>|<opened at>|<open seq>|<receive lapse at>|<close due>, 17 parts: statusproposed(voting) /passed/receiving/fullwhile open; published at = theatof the entry that booked theproject_proposeact [clarification, 17 Oct 2026 (D4 review)] and published seq = that entry'sseq(the publication order of duties and re-checks); vote end = published at + its duration; open lapse at = published at + theopen_lapse_sin force then; opened at = theatofproject_openand open seq = itsseq(the drain order), both""before; receive lapse at = opened at + thereceive_lapse_sin force then (""before); close due; these due times replace the former rules-version fields, so a running deadline keeps its length [Consequence of E-1]; the line is removed in the entry that gives the project a final status:paid,declined,withdrawn,lapsed,closedorfell; there is no statusrejected[Decided 17 Oct 2026, C4] and no statusstopped[E-5]; motionso3|motion|<id>|voting|<proposer>|<published at>|<published seq>|<vote end>(8 parts) [E-5]; voteso3|vote|<proposal id>|<voter HEX>|<for or against>|<vote act id>(6 parts; the key is the first 4, so one member has one vote per proposal and a newer vote replaces it) [E-5]; cross-circle holdso3|hold|<note id>|held|<amount>|<payer>|<to circle id>|<to genesis digest>|<note expires>|<xout at>|<check at>|<party>(12 parts; a reference grant is held the same way, with the 43921 id as the note id, the reserve as payer, note expires""and party = the newcomer whose wave it opened,""for a leg [Decided 23 Oct 2026, E-11: the newcomer's step is revoked if the old circle refuses]; check at = xout at + thexcheck_sin force then, which replaces the rules version at thexout[Consequence of E-1]; anxdonenames the note id, which commits toto_amount, its currency and the quote, so the hold's line suffices to judge it; that thexinmoved exactlyto_amountis the receiving circle's own booking rule [clarification, 17 Oct 2026 (D4 review, round 3)]); open requests; applicantso3|join|<join act id>|<key>|<waiting or heart>|<expires, "" while waiting>|<booked seq>(7 parts: the waiting list, admitted by rule in booked order, or an excluded key's application to the Heart, until itsjoinact expires or the key'saccount_close[clarification, 25 Oct 2026, D4: a closed key joins as anyone does]; while it exists its key is an applicant) [E-6]; invitationso3|invite|<invite id>|<key>|<inviter>|<until>(6 parts; until = at +invite_ttl_s; one-time) [E-6]; exclusionso3|exclude|<hex>|<until>|<act id>(5 parts; until = the k-th act'sat+exclusion_s) [E-3]; waiting account closeso3|close|<hex>|<act id>|<booked seq>(5 parts) [E-3]; leaving lineso3|leaving|<hex>|<leave act id>|<booked seq>(5 parts; booked seq = the seq of themember_leavethe leave act books, or of the leave act's own entry for an excluded key [D4 N25]; until the reference, the key'smember_join, or the act that reaches the threshold of itsaccount_close[D4 N26], §3.11) [E-9]; references waiting for their returno3|reference|<hex>|<leave act id>|<wave>(5 parts; from thereferenceentry untilreference_return, the key'smember_joinhere or itsaccount_close) [E-9 (b)]; a waiting join's granto3|grant|<join act id>|<43921 id>|<old circle id>|<old genesis digest>|<src height>|<src digest>|<G>|<W>|<quote id or "">(11 parts, beside itso3|joinline, until themember_joinandreference_grantthat use it) [E-9 (b)]; open OWN processeso3|own|<own_open id>|<hex>(4 parts) [E-4, Proposal]; and changes of k Heart members being collected or under notice and resignations under notice (o3|change, below); there are noo3|objection,o3|paramoro3|steplines any more [E-1, E-5]; booked acts and notesa3|<event id>|<expires>(every act and every note booked in this circle, so a duplicate is judged from the state [clarification, 17 Oct 2026 (D4 review, round 3), for the rule; proposal (D4 review, round 3, 17 Oct 2026), for the notes' lines]) and the idem windowi3|<payer>|<idem>|<expires>, each removed at the start of the first block whose firstatis later than itsexpires; and the used referencesu3|<old genesis>|<src height>|<newcomer hex>|<src digest>|<43921 id>|<member_join seq>(7 parts; the key is the first 4: a reference is the old circle's reference entry, named by its circle's genesis, the height of its block with the entry and the person, so two valid 43921 copies of one entry are one reference [review of E-13, 25 Oct 2026]; every reference amember_joinof this circle carried, at the join or from the waiting list, whatever its step, also 0 [clarification]; never removed, so a restore from a seal keeps them and the circle never accepts that reference again, through any copy) [Decided 25 Oct 2026, E-13 (A)]. No value that enters a line contains|. No salt in any line [Consequence]. - The
o3|changeline [clarification, 17 Oct 2026 (D4 review), for the fields and the k-th act; proposal (D4 review, 17 Oct 2026), for the lapse and theprojectfield; proposal (D4 review, round 3, 17 Oct 2026), forconsent,booked h, the new governance acts and the resignations]:o3|change|<proposing act id>|<collecting|notice>|<act type>|<stewards>|<expires>|<notice end or "">|<project or "">|<consent>|<booked h>, eleven fields (the fieldstewardskeeps its technical name and lists the Heart members who signed; the types of round 5 addparam_propose,member_exclude,member_readmitandaccount_close[E-1, E-3];own_openhas noo3|changeline since E-10: any member books it alone, at once);projectis theproject_proposeid aproject_closecloses and""for a roles change (the next booking needs it, to refuse a second close of one project and to end the line when the project ends).stewards= the HEX keys of the proposing act's author and of every booked endorsement's author, sorted, joined by,(never a count).consent=waitinguntil the named key's accept act (signer_acceptforsigner_proposeandsigner_replace,steward_acceptforsteward_add) is booked, thenyes;""for every other type.booked h= the height of the block that booked the proposing (or resign) act: a restorer reads that block for what the change names (§8.1 step 5). One line for every change of k Heart members of an endorsable type,project_closeincluded, and one for every resignation (steward_resign,signer_resign, signed by the person alone: the resign act id,stewards= the resigning key, in notice from its booking, notice end = itsat+ thechange_notice_sin force then, 259,200 s by default [E-1]); the acts:docs/upravljanje-kroga.md. It is created by the entry that books the proposing act; an endorsement adds its author. It turns tonoticeat the act after which the listed keys that are Heart members in office reach k (in office for that block): notice end = that act'sat+ the type's notice (thechange_notice_sthen in force, 259,200 s by default, forsigner_propose,signer_remove,signer_replace,steward_add,steward_remove,stewards_required_set,relay_change,circle_key_changeandrecovery[E-1]; max(change_notice_s, the old value of every changed parameter in seconds) forparam_propose[Proposal, E-1]; 0 forproposer_swap,rate_source_setandrefusal_list_set; theclose_notice_sthen in force forproject_close);member_exclude,member_readmit,account_closeandown_opentake effect at that act, with no notice [E-3;own_open: Proposal].expires: while collecting, the proposing act's ownexpires; in notice, notice end + theact_ttl_sin force at that act for a roles change (the commit window: proposal, so a change that is never committed does not stay for ever), and notice end forproject_close,param_proposeand a resignation (its return, itsparams_effectiveor the resignation'srolesentry is a duty at notice end). The line ends with the entry that commits the change (therolesentry; forproject_closetheproject_return; forparam_proposetheparams_effective; formember_exclude,member_readmit,account_closeandown_openthe entry at the k-th act), or at the first block whose firstatis later thanexpires(collecting, or a roles change of k Heart members never committed); aproject_closeline also ends with the entry that gives its project a final status (project_pay,project_return,project_lapse), or at its close due when fewer than k of its Heart members are in office then (the close is void, and the project'sclose duegoes back to""[clarification, 17 Oct 2026 (D4 review, round 3)]). Arolesentry for a change of k Heart members is booked at anatwith notice end ≤at≤expires, with k of the line's Heart members in office at therolesentry and, where the type needs one, the consentyes; later endorsements may still be booked while the proposing act is valid (they never move the notice). A further endorsement by a listed Heart member is refusedrepeated. A second proposingproject_closefor a project whose close line exists is refusedrepeated(the Heart members endorse the open one). Aparam_proposein notice is void at its notice end when fewer than k of its signers are in office then (the line ends, no entry) [Proposal, E-1]. - Lines, exactly [clarification, 17 Oct 2026 (D4 review), except where marked as a proposal]: state lines are sorted by their key (the key fields joined by
|, not the whole line), compared as UTF-8 bytes. A member'scapis thewave_capin force at itsmember_join; a laterwave_capchange does not change existing caps [proposal (D4 review, 17 Oct 2026)].last_gift_day= the circle's local calendar date (tz, pinnedtzdata) of theatof the newestpay,giveorxoutthe account booked as payer;first_receipt_day= the local date of its first receipt (payorxinas receiver,project_payto it), never changed afterwards;xundo,grav,growandsettledset neither. "Touch" has two meanings: for theplist, the lines andaseqan entry touches every account it names (itspartyand every move's from and to); for visit before touch only money moves count (§7.4).last_hin the state is the height of the newest block that touched the account (""before any); a block's own line (the lines root leaf) shows the value from before that block, so it points back to the block that touched the account before (a chain a light client follows), and the next block's line comes from the state alone [clarification, 17 Oct 2026 (D4 review, round 3)]. A project wallet's account line appears with the first entry that names it and always carries the project's status.i3lines are kept only by the payer's circle, for the notes it books aspay,giveorxout; anxinkeeps none. - Restore from a seal (§8.1 step 5) must equal full replay, checked by comparing this canonical state hash, never the SQLite file (which has UUIDs and rowids).
3.9 Projects and the reserve [Decided 16 Oct 2026, A8; details decided the same afternoon: 8a, 8b, 8e, 8f, 8j; the start decided later the same day: 6c; 8d follows from A8; no rejection by one Heart member (C4) decided 17 Oct 2026; the vote instead of approvals and objections (E-5, which replaces 8c) and the time values as circle parameters (E-1) decided 23 Oct 2026; Open 8g, 8h]#
the project owner: "money always goes to projects, which have no key … So it is always projects that are funded." The rules below are public, deterministic and recomputed by every witness; every move is between two lines of the same circle, so the sum stays 0 [A8, 8f]. This section is the one canonical text; docs/upravljanje-kroga.md, docs/prepoznavanje-goljufov.md, docs/nov-krog.md and docs/implementation-notes.md point here. The time values and the number of Heart "for" votes below are circle parameters [Decided 23 Oct 2026, E-1] (the defaults are shown; §3.1 rule 11): the number of votes is that of the parameters in force at the vote end [Proposal], and a running deadline is recorded as a due time when it starts and keeps its length, never retroactive [Consequence of E-1]. Said openly: a circle with fewer Heart members whose "for" counts than project_approvals opens no project; its start stays in the reserve.
| Step | Rule | Status |
|---|---|---|
| Publish | a member's project_propose (title, description, amount, recipient, duration) is booked; status proposed (voting): its vote end = the entry's at + its duration (vote_min_s ≤ duration ≤ vote_max_s, else not_allowed); its keyless wallet exists with balance 0. A step raise is a project_propose whose recipient is the circle's world-step account | [A8]; the duration set by the proposer at publication, never changed [Decided 23 Oct 2026, E-5, confirmed 23 Oct]; a step raise is a project [8j], world-step as its recipient [Proposal]; the recipient's consent as today [Proposal], implied when the proposer is the recipient [clarification, 19 Oct 2026 (D3 review)]; recipient a member when the act is booked (else not_member): Open 8h [clarification, 19 Oct 2026 (D3 review)] |
| Vote | until the vote end every member may book a vote naming the project: "for", or "against" with its short public reason; one vote per member per project, the newest counts (o3|vote), changeable until the end; the same choice again is repeated; a vote at or after the vote end is refused vote_ended. There is no objection, no stop and no approval any more | [Decided 23 Oct 2026, E-5]; replaces 8c and the approvals; the refusal's name: proposal |
| Decline, withdraw | the recipient's project_decline before it receives → declined (the recipient's leaving or exclusion does the same, below the table); the proposer's project_withdraw before it receives → withdrawn; a decline or withdrawal during the vote ends the project and its votes; the wallet is empty, nothing moves. No Heart member rejects a project alone: there is no project_reject and no status rejected | decline: as today [Proposal]; during the vote: unchanged by E-5; no rejection by one Heart member [Decided 17 Oct 2026, C4]; at an exclusion: Proposal |
| End of the vote | at the vote end (a duty: the first block whose first at reaches it) the newest votes are counted with the roles at that moment [Proposal]: the project passes only if no member (status member) has "against" as the newest vote and at least project_approvals Heart members in office have "for" (on a project the proposer's and the recipient's "for" do not count toward that number; on a motion the proposer's own "for" counts [Decided 23 Oct 2026, E-11]); rule vote_pass (status passed) or vote_fall (status fell, final; it may be proposed again, changed); its o3|vote lines go | [Decided 23 Oct 2026, E-5: no "against" from anyone and at least 3 Heart "for" (E-1: project_approvals ≥ 3)]; the proposer never decides on their own proposal [Decided 10/15 Oct]; the roles at the vote end: proposal |
| Open | a passed project opens at the end of the first entry after which its consent is booked (a step raise needs none: its recipient is keyless) and, for a step raise, its amount fits under built: a rule entry project_open sets status receiving, records the opening time and seq (o3|project, §3.8) and is followed at once by drain(); passed projects are re-checked in publication order at the end of every entry [clarification, 17 Oct 2026 (D1 review)]; a project that has not opened by its open lapse lapses (below) | [E-5]; consent stays [Proposal] |
| Inflow | every inflow moves to reserve inside the entry that produces it, then drain() (below) moves it on to receiving projects | [A8]; one move per receipt, as today with Common Good renamed |
| with several receiving projects, the oldest opening first; the part that would pass a project's amount goes on to the next; no project limits for now | [8b] | |
| with no receiving project the inflow stays in the reserve | follows from decision 8 [A8] (8d, no longer open) | |
| Full and pay | when received = amount, rule project_full (status full), then in the same block rule project_pay: the project's whole balance → the recipient (status paid); the recipient's grow and settled go to the reserve and on by drain(). For a step raise the recipient is world-step [Proposal], which has no wave, so nothing flows back: this project really uses up community money, and the circle's step rises by the amount | [A8, 8a, 8j] |
| Lapse before opening | a project that has not opened by its open lapse at (published at + open_lapse_s, 30 days by default, recorded at publication) lapses (rule project_lapse, status lapsed); its wallet is empty, so nothing moves; since vote_max_s < open_lapse_s, its vote has always ended by then | proposal carried over from orders; the due time: Consequence of E-1 |
| Closing a receiving project | k Heart members book project_close; after close_notice_s (72 h by default; its close due recorded at the k-th project_close) of public notice a rule project_return moves the project's whole balance → reserve in one move (none when the wallet held 0 [proposal (D3 review, 19 Oct 2026)]) (status closed), then drain() moves it on to the next project; the close commits only if at least k distinct Heart members in office at the commit signed project_close, otherwise the collection is void [clarification, 17 Oct 2026 (D1 review)] | [8e]; k = 3 of 4: proposal |
| Lapse of a receiving project | a receiving project that is not full by its receive lapse at (opened at + receive_lapse_s, 90 days by default, recorded at its opening, so a project opened under 90 days keeps 90 even if the parameter later says 30 [clarification, 17 Oct 2026 (D1 review); Consequence of E-1]): rule project_lapse, then project_return → reserve (status lapsed), then drain() | [8e]; counting from opening is a proposal (the project owner: "in 90 days") |
| Other returns | project_return (status closed) also when the recipient books project_decline or leave while it receives, the recipient is excluded while it receives, the proposer books project_withdraw while it receives, or project_pay falls due but the recipient is no longer a member | proposal, not covered by 8e (the exclusion: Proposal, E-3) |
Project statuses [E-5]: proposed (voting), passed, receiving, full, paid, declined, withdrawn, lapsed, closed, fell; final: paid, declined, withdrawn, lapsed, closed and fell.
Motions [Decided 23 Oct 2026, E-5: a Heart member may put any proposal to a vote, and a proposal without money is a public decision in the ledger; the shape: Proposal]: a Heart member's motion (title, duration, the proposal as text) is booked as o3|motion and voted on like a project, with the same rule (no "against" from any member and at least project_approvals Heart members "for") [Proposal], except that the proposer's own "for" counts toward them [Decided 23 Oct 2026, E-11]; at its vote end vote_pass or vote_fall is booked and its line goes: the entry is the public decision. A motion moves no money.
Inflows (each one move into reserve inside the entry that produces it): the grow and settled of every receipt (pay, xin, a project_pay to a member); every grav deduct; the part of a named give above the project's room, and a whole unnamed give (Open 8g); a step lowering (world-step → reserve, proposal); a project_return; once, in block 1, the start from origin [6c]. The reserve pays out only by reserve_move (to a project), by an account close or a reference return (close_cover to the closed line, close_wave to origin) and by a reference grant (reference_out to world), §3.11 [E-3, E-9 (b)]; a newcomer's grant comes in from origin and a returned step's reference_in from world.
drain(), run at the end of every entry [clarification, 17 Oct 2026 (D1 review)] as the first part of its end-of-entry work (§3.5), not only after an entry that moved money into the reserve or booked a project_open, since a give that exactly fills a named project moves nothing into the reserve and the full project must still be paid (a grav entry in a morning block included; the deducts of grav entries booked as visits are drained at the end of the entry they precede, §7.4), also in payment blocks during the morning; a member who leaves while the recipient of several receiving projects gives one project_return per project, each followed by its own drain(), as every inflow is [clarification, 17 Oct 2026 (D1 review)]: a member_leave (and likewise a member_exclude [Proposal, E-3]) first ends declined every project not yet receiving whose recipient is the leaver (the leaver's projects are those whose recipient is the leaver [clarification, 17 Oct 2026 (D4 review, round 3)]; no entry of its own; the member_leave entry carries the change), then returns each receiving project whose recipient is the leaver in drain order (project_open height, seq), each project_return followed by its end-of-entry work [proposal (D4 review, 17 Oct 2026)]; identically by every witness:
repeat
for P in receiving projects, ordered by (height, seq) of their project_open entry [8b]
t = min(balance(reserve), amount(P) − received(P))
if t > 0: rule reserve_move: reserve → P, t
if received(P) = amount(P):
rule project_full(P); rule project_pay(P): P → recipient(P), the whole amount [8a]
(if recipient(P) is no longer a member: rule project_return(P): P → reserve instead, below)
if recipient(P) is a member: the recipient's grow, then settled (read after the
receipt and the grow move), recipient → reserve; if the recipient's grav entry
of an open morning is still pending, it is booked first, right before
project_pay (visit before touch, §7.4)
if recipient(P) is world-step: no wave, nothing flows back; the step
(= balance(world-step)) has risen by amount(P) [8j]
restart the for-loop from the first project
until balance(reserve) = 0 or no receiving project has room
- It ends: every pass either empties the reserve or pays a project, and a project pays at most once (
paidnever receives again). - A recipient who has left [clarification, 17 Oct 2026 (D4 review)]: inside
drain(), a full project whose recipient's account is no longer a member (it left, or it is excluded or closed [Consequence of E-3]) booksproject_full, thenproject_return(statusclosed, the money to the reserve), anddrain()goes on; a frozen recipient is still a member and is paid. - Invariant every witness checks: after the end-of-entry work of every entry except a
graventry booked as a visit (§3.5),balance(reserve) > 0only if no receiving project has room. - Several
project_opendue in one block: a passed project opens at the end of the first entry after which its consent is given and, for a step raise, it fits underbuilt, whether an act completed its last condition or not (a step raise that did not fit underbuiltwhen its vote passed; a change of the parameters in force); passed projects are re-checked in publication order at the end of every entry, and projects that become openable at the end of the same entry open in publication order (project_proposeseq) [clarification, 17 Oct 2026 (D1 review)]; those whose votes pass at the start of a block, byproject_proposeseq; each is followed at once bydrain(). - Size: a cascade that would pass 100,000 bytes closes the block after its last whole step; the next block, at the same
at, starts with the remaining steps, exactly as they would have come (the block split, §3.5) [completed 24 Oct 2026, plan step E4x]. Invariant every witness checks: after the end-of-entry work of every entry except agraventry booked as a visit,balance(reserve) > 0only if no receiving project has room, or the block was cut (more) and the next block continues the drain. - The money fact [Decided 16 Oct 2026, 8f]: below the recipient's wave cap a project payment grows the recipient's wave by the whole amount, and the same amount goes on as inflow, so paying a project does not shrink project wallets plus reserve. The pool shrinks only by a step raise (its money goes into
world-step, which has no wave) or a recipient at the cap, and grows back by a step lowering. The brake on projects is the vote (no "against" and at leastproject_approvalsHeart "for"), not money [8f, E-5]; that the proposer's and the recipient's "for" do not count stays the guard. - No project limits for now [Decided 16 Oct 2026, 8b]: no maximum amount per project, no daily proposal limit, no limit on open proposals per member; today's order limits (
SUPPORT_MAX_AMOUNT100,000, one proposal a day, three open) are not carried over. Said openly: one large project holds back every project behind it until it is full or lapses after 90 days [8e]. - The step outward [Decided 16 Oct 2026, 8j]: a raise is a project like any other; its recipient is
world-step[Proposal]; when full, itsproject_paymoves the wallet intoworld-stepand the step rises by that amount. Said openly:world-stephas no wave, so a step-raise project really uses up community money. A lowering by s [Proposal]:step_proposewith a negative amount, decided by a vote like a project [E-5], thenruleworld-step→reserveanddrain(), only ifstep − s ≥ max(0, world_used); the builder does not book a lowering in 0.3.0 (no complete rule), andstep_approveis gone. The step never exceeds what the members have built [Decided 15 Oct 2026];built= Σ (balance + wave) over every account line that is not a system account or a project wallet, of any status, members who left included, since their money is still in the circle [clarification, 17 Oct 2026 (D1 review)]; the formula ofbuiltand the checkstep + s ≤ builtatproject_openandproject_pay(docs/prepoznavanje-goljufov.md§5) are a proposal. - Every
ruleentry names the rule and its input ids (the acts and entries it follows from), so any reader can replay it. - Contributions (
give) name a project in statusreceivingor no project; a contribution naming an open project in any other status is refusednot_receiving[Proposal], and one naming a project that has ended (paid,declined,withdrawn,lapsed,closedorfell: itso3|projectline is gone)not_found[clarification, 19 Oct 2026 (D3 review)]. - The seal's snapshot carries every project's
o3line and the reserve'ss3line, and the seal carries["reserve", balance], so the state of every project is public every day. - The start [Decided 16 Oct 2026, 6c: »6c, da«]: a circle's first money is one start of 1,000 in the circle's currency for the reserve at founding, and nothing else (no starting wave per member, no bridge from Lana). Block 1 books, right after its
genesisentry, oneruleentrystart:origin→reserve,"100000"minor units (1,000.00; EUR, USD and GBP all have two decimals), thendrain()(no project receives at genesis, so the start stays in the reserve).origin(SL »izvor«) is a keyless system account, derived like the others (§3.8, roleorigin); its line is −100000 from block 1 and moves only bygrantandclose_wave(§3.11) [E-3, E-9 (b)]; it is in every snapshot and every seal (["origin", balance], §3.6), and the sum stays 0. By 8f the start keeps coming back: a project payment to a member below the cap grows that member's wave by the whole amount, and the same amount flows on as inflow to the next receiving project or the reserve. The namesstartandoriginand the exact shape of the entry are a proposal for definitions 0.3.0 (plan C1); thatorigintakes back a closed account's wave is decided [E-3, confirmed 23 Oct 2026]. The live circle gets the same start in its block 1 (plan E6; proposal: 1,000 EUR ="100000").
3.10 Size budget [E, from the measured 0.2.0 sizes]#
| Item | Bytes |
|---|---|
Payment entry inside a block (compact note ~370, header ~40, two lines ~250, two p tags ~144) | ~800 |
Cross-circle payment, all legs in both circles (xout 800 + xdone 200 in A, xin 800 in B) | ~1,800 |
| Block envelope without signatures (id, pubkey, sig, header tags, roots, the project or reserve line) | ~850 |
One qs tag | ~205 |
| One-payment block: single witness / quorum 3 / FROST later | ~1.9 KB / ~2.3 KB / ~1.8 KB |
| Full block | ≤ 100 KB (~120 payments) |
Morning gravity, per account (grav entry + line + p tag; while a project receives, also its reserve_move) | ~420; ~700 while a project receives (a morning block holds about 240 accounts, about 140 while a project receives; measured on the synthetic morning block of the definitions) |
| Snapshot line, full decision record | ~200 (≤ ~450 per chunk) |
| Seal + head | ~4.5 KB a day |
| A reference (43921) | ~0.7 KB; up to ~18 KB with 100 + 100 project ids [E] |
3.11 Membership, exclusion, the reference and closing accounts [Decided 23 Oct 2026, E-3, E-4, E-6, E-8, E-9; the mechanics: Proposal]#
This section gathers the rules of round 5 that move people into and out of a circle. The parameters it names are circle parameters (§3.1 rule 11). Every rule here is deterministic and recomputed by every witness; the sum stays 0.
Joining [Decided 23 Oct 2026, E-6 and E-9; the order of the checks: Proposal]. A join act (optional ["e", <invite id>, "", "invite"], optional ["e", <43921 id>, "", "reference"]) is judged by these checks (when several apply, the reason booked is the first in refusal_order: so not_allowed before duplicate, and duplicate before repeated [clarification, 25 Oct 2026; D4 round 5 N4]): a key whose line is member or frozen: repeated; a key whose exclusion runs (an open o3|exclude): not_allowed; a key with an open o3|join: repeated; a named invitation that is not open: not_found, one of another key: not_allowed; invite_only = 1 and no invitation (except an excluded key's application): not_allowed; a key whose newest member home (30916; the node reads it on the root relays) names another circle, without a valid reference from that circle (below): not_allowed [E-9: a rule for every circle, not a setting]; a join that brings a step (a reference with a wave above 0) while this key's own reference from this circle still waits for the return of its wave (o3|reference): not_allowed [Decided 23 Oct 2026, E-11: no step while an earlier move out is not settled, A → B → A]; a join naming a reference this circle granted a step on already (its u3 line, whatever the step and whether the grant's hold has ended, through any 43921 copy of the same entry), or one that a waiting join already carries (its o3|grant line): duplicate, also for a member or an applicant whose join waits (not repeated) [Decided 25 Oct 2026, E-13 (A): a circle accepts a reference once]. Then:
- an excluded key whose exclusion is over →
o3|join|<id>|<key>|heart|<the join act's expires>|<seq>: it is never admitted by rule and never from the waiting list;member_readmit(the larger of k and 3 Heart members [E-10], no notice; tag["e", <join act id>, "", "join"]) admits it at the k-th act (member_join,in[join act id]); refusednot_allowedwhen no place is free; readmission gives membership only, never a Heart seat [E-3]; - a free place (
max_members= 0, or the members (statusmemberorfrozen) fewer thanmax_members) →member_joinat once (in[join act id]; with a reference alsoref,srcandg); - otherwise the waiting list:
o3|join|<id>|<key>|waiting||<seq>(no expiry; its latermember_joinnames the join's reference when it has one).
An invite (["p", <HEX>], by a member) books o3|invite|<invite id>|<key>|<inviter>|<until>, until = at + invite_ttl_s; it is one-time: the line ends when a join uses it, or at the first block whose first at is later than until [E-6; one-time and 7 days: Proposal]. When a place frees (a leave, an exclusion, a close, a move, a parameter change), at the end of every entry (after drain(), the openings and the closes, §3.5) the first on the waiting list (the lowest seq) is admitted by rule, member_join (in [its join act]), while a place is free [Decided 23 Oct 2026, E-6]. An excluded key is never admitted from the list; only the Heart readmits it. An applicant's own leave act withdraws its o3|join (no member_leave).
Exclusion [Decided 23 Oct 2026, E-3; the shape: Proposal]. member_exclude is a Heart act in the endorsement form: the larger of k and 3 Heart members in office [Decided 23 Oct 2026, E-10], no notice, effective at the act that reaches them (the k-th act); ["p", <member HEX>], optional ["e", <OWN case event id>, "", "own"] [Proposal, E-4]; text required: a short public reason [Proposal]. The excluded key never counts toward its own exclusion. The named key must have a line with status member or frozen (else not_member). At the k-th act:
- if the key is a Heart member: first a
rolesentry (acts = [the proposing act]; the mirror without itsstewardtag;stewards_requiredlowered to the number left when it is above it; at least one Heart member stays) [Decided E-3: "who first loses the Heart seat"]; if the block already holds arolesentry, the k-th act waits for the next block (the intake answersroles_taken); - then the rule entry
member_exclude(in[the proposing act], party): statusexcluded;o3|exclude|<hex>|<until>|<act id>with until = at +exclusion_s; the key's projects end as at a leave (not yet receiving:declined; receiving: returned, in drain order) [Proposal, as for a leave].
The o3|exclude line ends at the first block whose first at is later than until; then the person may apply (a join, above).
An excluded line [Decided 23 Oct 2026, E-3]: frozen inside the circle (no payment, no give, no vote, no proposal; it receives nothing except a settlement, below); every morning still visits its plus (§7.2); it may send its plus to another circle (xout, amount ≤ max(0, balance), never the wave); the minus stays.
Leaving and the reference [Decided 23 Oct 2026, E-9: the reference is issued by itself after "I want to leave" when its conditions hold, otherwise not, and nobody moves to another circle without it; the mechanics: Proposal]. A leave act of a member (member_leave, status left) or of an excluded key (its status stays excluded) books o3|leaving|<hex>|<leave act id>|<seq>. At the end of every entry (after drain(), the openings and the closes, before the waiting list) each leaving line, in booking order, whose conditions hold gets the rule entry reference (in [leave act id], party, wave = its wave), and its leaving line goes. So the reference comes at the leave, or later, when a settlement brings the balance to 0 or the last OWN process closes. A leaving line also ends when its key joins again here or its account is closed (an account_close never gives a reference). The conditions [Decided 23 Oct 2026, E-9 and E-9 (a)]: no minus (balance ≥ 0) and no open OWN process about the key (o3|own), also without a debt: the process must close first (said openly: the Heart, which leads the processes, can hold a person back this way). The reference entry opens o3|reference|<hex>|<leave act id>|<wave> until the new circle's payment arrives (reference_return), the key joins here again or its account is closed [E-9 (b); Proposal].
Settlement [Decided 23 Oct 2026, E-9: a debt must be settled in any case, and anyone may settle it, by payments into the account, never above 0; during an exclusion too: Proposal (the supplement's proposal; the project owner: »če je bil izključen se rabi vrnit nazaj, poplačati predno se lahko seli«); the shape: Proposal]. A left or excluded line with a minus may receive payments that settle it: a pay from a member of the circle, or an xin from another circle, to that line, amount ≤ −balance (never above 0), with no grow and no settled move. Any other payment to it is refused not_member. A key that left (also to move) may send its plus to another circle like an excluded key (xout, ≤ max(0, balance)) [Proposal: so a person who moves takes the plus along].
43921 and the new circle's check [Proposal]. The node signs the 43921 (§3.7) right after the block that books the reference entry has its quorum, and publishes it on the circle's relays. A join that comes from another circle names it, ["e", <43921 id>, "", "reference"]; the new circle's node checks that its c is the circle the key's newest member home (30916) names (the last circle), that its p is the key, and that the named block of that circle carries the reference entry of the key with the same wave and a quorum of that circle's witnesses in office at that height (as for the 8j evidence, §4.5). The member_join entry then names it: {rule: "member_join", in: [join id], party, ref: <43921 id>, src: [height, digest], g: <that circle's genesis digest>}. The new circle republishes that 43921 and the named block to its own relays, so it restores without the old circle [Proposal]. A key with no member home anywhere was never a member and needs no reference [Proposal]. Said openly: a deleted home or a second key is not caught (that needs Lana's person check); root relays keep member homes (no deletion by KIND 5) [Proposal].
The step (wave) in the new circle [Decided 23 Oct 2026, E-9 (b), the project owner's own model: »… in se zadeva izniči«, "… and it cancels out"; the bookings, the rounding and the step brake: Proposal]. In the old circle the balance is 0; the new circle opens the same step (wave) the reference states and, as with every growth of a step, the same amount goes to its community, counter-booked from its own origin; the new circle sends that amount to the old circle's community; the old circle closes the account (its wave to 0) and returns exactly that amount to its origin. Both communities hold what they held before.
- In the new circle: the
member_jointhat names a reference with a wave W above 0 is followed in the same entry by the rule entryreference_grant(in[the 43921 id], party = the newcomer,to= the old circle id,amount= G in this circle's currency,to_amount= W in the old circle's,quote= the old circle's 43919 id, only across currencies,mv): the movesgrantorigin → reserve G andreference_outreserve → world G, in one entry (nothing drains between); the newcomer's wave grows by G (cap =wave_cap; a wave above it grows no more). G = W in one currency; across currencies G = ceil(W × r_new / r_old) under the old circle's 43919 valid at the join, soto_amount= floor(G × r_old / r_new) ≥ W. G is held like anxout(o3|hold, with the 43921 id as the note id and the reserve as payer) untilxdoneon the old circle'sreference_return, orxundoon its refusal (reasonrefused), which gives G back to the reserve. A circle accepts a reference once [Decided 25 Oct 2026, E-13 (A); before it, plan step E4x refused it only while the grant's hold lasted]: themember_jointhat names a reference opens itsu3line, never removed (a restore from a seal keeps it), keyed by the reference's entry (the old circle's genesis, the block with the entry, the person), so any 43921 copy of that entry is the same reference [review of E-13, 25 Oct 2026]; a laterjoinnaming that reference, at the door or from the waiting list, after a readmission or after the person left and came back, is refusedduplicate, and so is ajoinnaming a reference that a waiting join carries already; the waiting list never admits a join with a used reference. A reference is valid once [Decided 23 Oct 2026, E-11]: right after thatxundothe rule entrygrant_revoke(in[the 43921 id], party = the newcomer, which theo3|holdline names;mv:close_wavereserve → origin r, none when r = 0) takes the unused part of the granted wave back to origin, r = min(G, wave − max(0, −balance)); the membership stays; a wave already used as cover stays (the circle bears it); nothing is taken from a closed line or from one whose step moved on with a reference of this circle that still waits for its return; the newcomer'sgraventry of the open morning comes first, also when nothing is taken (r = 0: the touch is thexundo's) [clarification, 25 Oct 2026, D4 N19]. A grant has noexpires, so the 8j evidence ofnot_booked(the partner's seals up to the note'sexpires) can never be complete and the old circle may book itsreference_returnlater: a grant's hold is never undone asnot_booked(not_allowed), and a silent old circle keeps it waiting, as any silent partner does [Decided 23 Oct 2026, E-11 (1A); D4 round 5 N6]. - In the old circle: when it reads the new circle's block with the
reference_grant, the rule entryreference_return(in[the 43921 id], party = the key,src= [height, digest] of that block,g= the new circle's genesis digest,wave= W,mv):reference_inworld → reserve what arrives (to_amount), thenclose_wavereserve → origin exactly W, covered at once by what arrived (a rounding rest stays in the reserve); the line's wave, cap and debt become 0, and it isclosedwhen its balance is 0 and none of its payments to other circles is still held (a plus left over, or a held payment, keeps the lineleftwithout a wave: gravity takes the plus, a refused payment comes back to it; then only anaccount_closecloses it) [review of E4x, 24 Oct 2026]. Itsgraventry of the open morning is booked first (visit before touch). It is refused, withsrcnaming that block so that the new circle returns its hold byxundo, when no reference of the key waits for its wave (not_found: the key joined here again, its account was closed, or this reference was already returned or refused for another grant: every grant is answered on its own, E-11) or when what arrives is below W (no_cover). [review of E4x, 24 Oct 2026] The old circle returns only a grant that is right, else it refuses it the same way: the reference's wave is above 0 and the grant's party is the reference's person (not_allowed), and what the grant says arrives is exactly the wave in this circle's currency: W in one currency, across currencies floor(G × r_old / r_new) with G = ceil(W × r_new / r_old), in whole numbers (each division rounded once, as written; r_new and r_old are the rates of the new and the old circle's currencies in whole ppm per 1 EUR, r_EUR = 1,000,000, as the 43919ratetags give them) under this circle's own 43919 that the grant names, signed by its node in office, naming this circle and valid at the grant'sat(bad_quote). A node ends a hold only on an answer to its own block: thexin,reference_returnorrejit reads names, as itssrc, this circle's block with the hold'sxoutorreference_grant(height and digest); an answer to another block ends nothing here; the booking decides: arejof the note (or of the return) after itsxin(orreference_return) naming the same block is a duplicate's refusal, no answer. A key whose reference of this circle another circle has granted comes back here only with that circle's reference. - Both sums stay 0 at every entry; in each circle
origin= −start − granted + returned, which may go above 0. - [Decided 23 Oct 2026, E-10 (2A), safety] G counts against the new circle's step outward (world used + G ≤ step): a join whose grant does not fit waits on the waiting list until it fits, with its grant in
o3|grant(§3.8) beside itso3|joinline. Open question for the project owner: so a circle that cannot raise its step outward takes in no waves from other circles.
Closing an old account [Decided 23 Oct 2026, E-3; the accounting confirmed 23 Oct 2026 (»ostalo si pravilno razumel«); the circle covers a minus only when the member has died (E-3 Dopolnitev); the shape: Proposal]. account_close is a Heart act in the endorsement form: max(k, 3) Heart members [Decided 23 Oct 2026, E-10], no notice; ["p", <HEX>], text required: the public reason [Decided 23 Oct 2026, E-10 4A; D4 round 5 N9]. The line must be member, frozen, left or excluded and not a Heart member in office (else not_allowed). At the k-th act: a member or frozen line (a death) first gets member_leave (in [the proposing act]; never a reference); then o3|close|<hex>|<act id>|<seq> waits (seq: the member_leave it books first, else the k-th act's own entry; D4 round 5 N1). At the end of every entry (after drain() and the openings, before the references and the waiting list) each waiting close, in booking order, completes when its grav entry of the open morning is not pending, no leg of the account to another circle is held [D4 round 5 N2; with E-10], balance ≤ 0, and reserve ≥ −balance + wave. Then the rule entry account_close (in [the proposing act], party): close_cover reserve → line (−balance, when below 0), close_wave reserve → origin (the wave, when above 0); wave, cap, debt and carry become 0; status closed; its o3|close line goes. The new move reasons are close_cover (reserve → line), close_wave (reserve → origin), grant (origin → reserve), reference_out (reserve → world) and reference_in (world → reserve); origin moves only by start, grant and close_wave. A plus waits for gravity (or is sent away first). Never urgent; nothing breaks if an account stays. Invariants: origin = −start − granted + returned; Σ waves = grown + granted − returned. A closed key that joins again starts at 0 (status member, cap = wave_cap). Said openly: by E-3 Dopolnitev the circle covers a minus only when the member has died; the ledger cannot see a death, so this rests on the Heart's public act (k Heart members), and a line that left with a minus is otherwise not closed: its debt stays written, and anyone may settle it.
Gravity [Consequence of E-3]: every morning visits every line with status member, frozen, excluded or left (not closed) (§7.2); before, left lines were not visited, so leaving and coming back escaped gravity.
OWN processes [Decided 23 Oct 2026, E-4: the Heart leads and oversees them; they run in the existing OWN apps (encrypted), and only a decision reaches the ledger; the acts: Proposal, a consequence of E-9]. So that the rule can judge the reference's OWN condition, the ledger books that a process is open and that it is closed, with no content: own_open (any member, alone, at once [Decided 23 Oct 2026, E-10]; ["p", <HEX>], optional ["e", <OWN case id>, "", "own"]) books o3|own|<own_open id>|<hex> (about a key with an account line here, a closed one too; a key with no line is not_found [clarification, 25 Oct 2026, D4 N20]); own_close (one Heart member in office; ["e", <own_open id>, "", "open"]) ends it. Said openly: since an open process blocks the reference (E-9 (a)), any member can hold another's reference back until a Heart member closes the process. A member who does this on purpose to harm another can be excluded for it by the Heart (the usual exclusion, at least three Heart members) [Decided 23 Oct 2026, E-10]. An exclusion after an OWN process may name the OWN case event id, ["e", id, "", "own"] [Proposal].
Founding [Decided 23 Oct 2026, E-8: only a member of an existing circle founds a circle, every circle grows from the first one, one circle per founder key, ever, and a person is a member of one circle at a time; the shapes and mechanisms: Proposal]. The found act names its parent: ["parent", <parent circle id>, <parent genesis digest>] after start, required except for the root (the live circle); right after it the founder's reference from the parent, ["e", <43921 id>, "", "reference"] (required with parent [Proposal]; that the founder needs it: a consequence of E-8 and E-9). meta.root_circle names the root's circle id (empty while a draft; the examples use circle A as the TEST root, and circle B names A). The 30910 mirror carries ["parent", …] after founder when the found act names one. That the founder was a member of the parent when founding (its member home and the parent's member_join) is checked by the root directory and by readers [Proposal: details in phase G]. One circle per founder key, ever: the root relays keep the first found act per founder key (first-seen, like the genesis pin) and refuse a second circle record of the same founder [Proposal: the mechanism]; this replaces "at most three circles per founder". A person is a member of one circle at a time: joining (or founding) another means leaving the old one, and nobody moves without a reference, which is issued only after a leave; so a key cannot be a member of two circles (a second join finds the first new circle in the newest home). The founder's own join in the new circle may name the same reference. Said openly: one person with two keys is not prevented; that needs Lana's person check.
4. Payment write path#
4.1 Steps#
- Prepare (app). From the relays (or its cache) the app knows the circle's witness set and relays (from the ledger, cached ≤ 24 h), its own newest line (balance, wave,
note_n,note_head) and that the receiver is a member. Across currencies it first asks the receiver circle's node for a 43919 quote, shows the converted price and the quote's validity, and continues only if the payer accepts [Decided 16 Oct 2026, A7]. It signs the canonical 43910 (n = note_n + 1,prev = note_head,expires= now +note_ttl_s(600 s by default; across circles, and during a parameter change's notice, the smaller of the two values [Proposal, E-1]), across currenciesto_amountand the quote id) in the browser. 5–20 ms. - Submit. HTTPS POST of the signed note to the node's
api(write intake only; nothing is read from it that is not on the relays). 30–100 ms. - Check and order (node). Signature and template round-trip;
n/prevequal the payer's head (elsestale_prev, a refusal, never "fraud"); not expired; payer and receiver are members (a payment to a left or excluded line with a minus is a settlement, §3.11); coveramount ≤ balance + waveat this exactseq(noheld_out[A6]); receiver can receive; idem unused for (payer, prev). Assignseq,at(own clock, seconds, never below the previousat); computegrowandsettled, their move to the reserve and thedrain()that follows (§3.9), the lines and the state root. 2–10 ms. - Close the block by the closing rule (§3.5).
- Witness round (quorum mode only) [Decided 16 Oct 2026, A3]. The node sends the unsigned block body to every witness over direct authenticated links. Each witness checks that the node is the node of this height in S(h), that
h= its last + 1 andprevmatches; re-runs every check and recomputes every line and root from its own state (built only from relay blocks); checks the sum is 0 andatis within ±5 s of its clock; writes its sign-guard (fsync); returns its signature oversha256("lb-block/3|" ‖ digest). q signatures (the node's included) = commit. 50–150 ms regional. - Seal the event. The node adds the
qstags, signs the 43911, writes it to its write-ahead log (fsync) and sends the final event to the witnesses (they fsync it too). - Publish (single publisher). The node sends the event on persistent sockets to every listed relay, pipelined in height order. Witnesses republish only what is still missing from a relay after 5 s (covers a node crash after step 6 without 4× message amplification).
- Final per §4.2. The node answers the POST with the block's height and digest and the relays that confirmed.
- The payer's app verifies by itself: one REQ
{"kinds":[43911],"authors":S,"#h":["<scope16>:<h>"]}to 2 relays; exactly one block at that height on each, same digest (two events with one digest are the same block and may differ only in their witness signatures), signatures, embedded note, own line arithmetic (previous line ± moves = new line). Then "paid · block h · public on N of M relays · confirmed by q of n". This height-uniqueness read also closes single-witness equivocation across overlapping relay sets. - The receiver's app keeps a live subscription
{"kinds":[43911],"authors":S,"#p":[me],"limit":0}on 2 circle relays while open and shows "received" after the same checks. - Repair. The circle's replication audit (§9.3) makes every block reach every listed relay.
4.2 When a payment counts [Decided 16 Oct 2026, A1]; operators (Q14); sending on (Q17)#
- Final when the block carries ≥ q valid signatures of S(h) and ≥ 3 listed relays [A1]; of ≥ 3 operators (bootstrap ≥ 2) [Proposal Q14]; answered
OK truefor this exact id and every lower height is final. The app shows "paid · public on N of M relays" [A1]. - Sending to every other listed relay continues; the app always shows the real "N of M" (Q17). This replaces the rule of 14 Sep 2026 that publishing waits for every relay's answer; the project owner decides.
- The Lana relays count toward the three only after their owner applies the ledger write policy of §9.2 (Q18); the box relay ships with it.
- [Open] (Q14, Q18): until the Lana relay owner applies the write policy, only the box relay counts, so under A1 no block could become final and the circle would depend on one outside owner. the project owner chooses: (a) the circle books nothing until then; (b) until then the Lana relays count as copies, publicly labelled "copies without protection against deletion"; (c) until then the circle finds two more relays with the same policy at other operators.
- Durability before commit is each witness's local write-ahead log, not its relay; durability at commit is the final event on ≥ 3 relays.
4.3 Latency budget (payer sees "paid") [E]#
| Step | Single witness, borrowed Lana relays | Own regional relays, quorum 3 of 4 | p99 target |
|---|---|---|---|
| Sign in browser | 5–20 ms | 5–20 ms | 50 ms |
| POST to node | 30–100 ms | 30–100 ms | 300 ms |
| Checks, ordering, roots | 2–10 ms | 2–10 ms | 30 ms |
| Block closing (idle / busy) | 0–50 ms / ≤ W_max | 0–50 ms / ≤ W_max | 2 s |
| Witness round | — | 50–150 ms | 400 ms |
| fsync guard + WAL | 1–10 ms | 1–10 ms | 30 ms |
Third relay OK (EVENT→OK never measured; REQ→EOSE as proxy: third-fastest Lana relay ~390 ms [R]) | 300–1,000 ms | 80–300 ms | 1.5 s |
| Answer to app | 30–100 ms | 30–100 ms | 300 ms |
| App's own read-back on 2 relays (warm) | 60–220 ms [M] | 60–220 ms [M] | 700 ms |
| Payer sees "paid" | ~0.5–1.5 s | ~0.3–0.9 s | < 3 s |
Today's same-machine v2 payment takes ~12 ms [R]. The first build step measures EVENT→OK; until then these are estimates.
4.4 Bootstrap: one witness [Decided 16 Oct 2026, A3]#
- n = 1, q = 1: the circle's box is node and only witness, with full crash discipline (§4.6). Until there are enough circles to draw witnesses by lot (phase I), a circle has this one witness, its own computer, publicly labelled [Decided 23 Oct 2026, E-7].
- The app shows "not yet decentralised" on every screen that shows money.
- No money cap (the project owner: "no money cap"). There is no cap parameter in the
foundact. - An independent verifier replays the ledger daily and publishes 43924; the daily restore drill (§8.3) is public; any
failstatement shows in every member's app. There are no payouts, so there is no payout circuit breaker [A6], and no deposits, so there is no deposit alarm [6a]. - Known weakness, said openly: in single-witness mode a wrong entry can be booked before it is caught; a stolen node key can book alone (it cannot forge a member's note, but it can mis-book rule entries, for example moves between project wallets and the reserve). With no cap, what bounds the damage is how fast the public label, the daily verifier and the drill catch it, and then the move to four witnesses.
4.5 Spending twice is prevented#
The member's chain: one successor per (
n,prev); a second note on the sameprevcan never be booked; it is refusedstale_prev(a stale read, not a crime).One block per height: each witness signs at most one digest per (circle, height) and persists that first; two blocks at one height would need two quorums, which overlap in ≥ f+1 witnesses, so at least one honest witness would have signed both, which it never does. A witness that signs two digests at one height leaves public proof (43924
equivocation) and is removed.Cover at a fixed point: the spendable check runs against the state after
seq − 1, identical for every witness.Across circles: the payer's circle (A) books
xout(a hold onworld) before the receiver's circle (B) books anything. The step bounds the net outflow [clarification, 17 Oct 2026 (D4 review)]: world used = the balance ofworld= what the circle's members paid out to other circles less what came in (xout−xin−xundo); it may be negative. Anxoutcounts only if used + amount ≤ step (the balance ofworld-step; elsestep_full): what members received from other circles they may spend in other circles even with step 0; the step bounds the net outflow. A timeout alone never undoes.xundo(world→ payer) on B's signed refusal or "expired". A payment that hangs [Decided 16 Oct 2026, 8j]: nobody pays a refund. If A has booked neitherxdonenorxundoby the hold'scheck at(thexout'sat+ A'sxcheck_sthen in force, 7 days by default [8j, E-1], recorded in itso3|holdline, so a later change never moves it [Consequence of E-1]), a duty falls due in A: every witness of A reads B's ledger from B's relays (B's witness set from B's log; quorum checked) and looks for the note in every B block whoseatlies from A'sxoutat− 60 s to the note'sexpires(the margin is a proposal), found by height inside B's sealed ranges (heights are gap-free andatnever goes back). B's office [Proposal]: A reads it from B's ledger, the office below the lowest block read and then eachrolesentry in the blocks read, in office from the next height, and judges each B seal with the office after itsh_to(§3.6); a B block counts only with a valid quorum of B's witnesses in office at its height: a block without one (for example signed only by an old, retired or stolen key) is not B's and is ignored, and two blocks with valid quorums at one height are a fork, so the evidence is not used. A block or seal copy without a valid quorum of B's witnesses in office never counts and never hides a copy that has one, and what rests on an office that a missing block leaves unknown is unverifiable. So a hold whose evidence spans a key or witness change of B can still be settled, and noise signed by keys that are no quorum of the witnesses in office at that height cannot stall it; a key that was in office at a height (for example the single witness of a one-witness circle, later stolen) can still fork that height, and a fork stops the evidence. B can never book the note after itsexpires(§3.3; at mostnote_ttl_safter signing, 10 minutes by default; B judges the note by its ownnote_ttl_s), so once B's daily seals cover the whole time up toexpires, B's answer is fixed:- B booked
xinfor this note id with exactlyto_amount→ A booksxdoneby rule, naming B's block as[height, digest]; - B booked no
xinfor it (arej, or nothing) → A booksxundoby rule,world→ payer, naming as its evidence B's consecutive seals as[day, digest]and the height range they cover [Proposal]: from the last seal whose predecessor covered only bookings before ws = A'sxoutat− 60 s (itsprevcovers < ws; the last such seal, so no named seal is superfluous [clarification, 17 Oct 2026 (D4 review)]) to the first seal whose boundary is later than the note'sexpires(strictly), so one or two seals; thexundoalso names, asbefore=[day, digest], the real seal before the first one (omitted only when that is B's first seal), and every witness of A fetches it, checks B's quorum on it and that it chains to the first seal exactly as that seal'sprevdescribes (digest, day, boundary,covers); without it the evidence cannot be verified and nothing is booked, because the first seal's own description of its predecessor is B's word alone. B's seals chain by digest and each names its predecessor's boundary andcovers(§3.6), so every B block before that range books before the window and every B block after it at or after a boundary later thanexpires, when the note can no longer be booked. An idle B still seals every day (possibly with an empty range). Every witness checks the evidence against B's blocks, not only its seals: the seal before and every named seal must match B's blocks of their ranges (heights, digests,head,covers, entries, state root), and B's first seal always covers from its block 1. The evidence is closed by B's block right after the last seal (it follows that seal'sheadand books at or after its boundary) or, when B has booked no block since, by B's next daily seal, named asnext(the seal of the day after, chained byprev, with B's quorum and an empty range fromh_to+ 1; a block at that height booked before its boundary refutes it); before relying on the next seal, a witness confirms on at least two of B's relays that no block exists ath_to+ 1 (a runtime rule: a verifier without blockh_to+ 1 reports this check unverifiable [clarification, 17 Oct 2026 (D4 review)]). A block or seal that is not given leaves the evidence unverifiable, so nothing is booked; a B that stops sealing keeps the hold waiting. Every leg names B's genesis digest (g), so A reads only the B chain it pinned; - B's ledger cannot be read in full (B's relays silent, a missing height in the span, no B seal yet covering
expires, a seal without B's quorum, two B seals for one day) → nothing is booked; never a guess. A witness that cannot read the span does not sign, so there is no quorum. The duty repeats [Proposal: every day after the morning] and the amount stays held.
An unreadable partner never holds up A's own bookings: unlike the other duties (§7.4), this check becomes a due entry only once the node has read the evidence, and witnesses refuse an
xdoneorxundothey cannot verify themselves, never a block that leaves the check out. A node that keeps leaving out a check its witnesses can verify is replaced, as for censorship (§4.8). The payer gets the amount back at most once, and only on evidence; the refund by public decision (xrefund, reserve → payer) is gone [8j]. Across currencies (§3.7) [A7]:- the payer's circle checks the quote first, exactly as the receiver's circle will (signed by B's node of that time, B's source, not expired at this booking's
at,to_amountexact; the office at a time t (a quote's node and rate source at itscreated_at) is that of the newest mirror booked at or before t (its genesis orrolesentry'sat≤ t) [clarification, 17 Oct 2026 (D4 review)]), and refuses at intake with a publicrejstale_quoteorbad_quote, nothing held. In plain words: if the quote runs out before the payment is booked, the payment does not count and nothing is held; the app shows a new price and the payer signs again; - the receiver's circle books
xinonly if the quote is its own,to_amount=floor(amount × r_to / r_from)exactly, and the payer's circle bookedxout(itsat) no later than the quote'sexpires; else a publicrejwithbad_quoteorstale_quote. A circle honours its own valid quote; there is no other tolerance; - back in the payer's circle,
xdoneis booked only if B'sxinembeds the same note id and books exactlyto_amount; anything else counts as a refusal (xundo).
Different parameters in A and B [Decided 23 Oct 2026, E-1: each circle sets its own values; how they meet: Proposal]. Each circle applies its own values to what it books, and a mismatch can only end in a refusal and a return to the payer, so nothing is lost and both sums stay 0:
note_ttl_s: A judges the note at thexoutby its own value, B at thexinby its own. If B's value is smaller, B refuses the note (rejwithsrc,bad_template); A booksxundo(refused) and the payer gets the held amount back. The app signs with the smaller of the two values.quote_ttl_s: the quote belongs to the receiving (selling) circle B, and both circles judge it by B's own value: B by its parameters in force, A by the value it reads in B's ledger (as it reads B's node and rate source). If A read an older value, either A refuses (nothing moves), or B refuses at thexin(rejwithsrc) and A returns the hold (xundo, refused).xcheck_s: only A uses it, for its own holds (recorded at thexoutas the hold'scheck at). A short wait can only find the evidence incomplete (B's seals do not yet pass the note'sexpires): nothing is booked and the check repeats; it never returns early.
- B booked
Relays do not refuse a second block at a height (a stateful "first block wins" rule could lock the honest chain out on a relay that saw a bad branch first); readers detect forks from the public evidence.
4.6 Crash discipline (every mode)#
- Sign-guard for every witness, the node included: fsync
{circle, key, last_h, last_digest}before releasing a signature; never sign a different digest at or belowlast_h. - Restart: read every listed relay, every archive and (in quorum mode) the other witnesses' write-ahead logs; adopt the highest valid chain seen anywhere; republish it until it is final; continue at tip + 1. Never sequence after reading only some relays (relays can lose an acknowledged event).
- Guard lost: the key does not sign again. A new key epoch: a
rolesentry (node swap, decided by k of m Heart members and committed by the quorum; in single-witness mode by the Heart's acts alone, a known bootstrap weakness) names the new key andlast_h= the highest height found anywhere. - Orphans versus forks: a block that never became final may be superseded at its height only by a block of a new key epoch whose
rolesentry names alast_hbelow it; any copy of the old block found anywhere must otherwise be adopted. Pipelined successors of an orphan are void by rule, not fraud. Fraud is only: two final blocks at one height, or one key signing two digests at one height. - Node crash after the witness round, before any relay has the block (quorum mode): witness locks are per (circle, node key, height). A committed
proposer_swapnaminglast_hreleases the old key's locks above it; if any copy of the old block exists, it is adopted instead.
4.7 Throughput and the size of one circle (Q13)#
- Every relay of a circle holds all of it, so one circle's peak must fit one relay.
- Blocks keep the event rate low: a 1M-member circle at 10 payments per member a day peaks at ~940 entries/s (5× peak, cross legs counted) but only ~7.5 blocks/s [E].
- Binding limits: the node (today's v2 books 19–80 payments/s, an estimated 100–200 after known fixes [R]; Schnorr checks ~722/s per JS core, ~11,000/s native [R]) and serial blocks (one witness round + third
OKper height → 2–9 blocks/s [E]). Pipelining: witnesses may sign h+1 once h has its quorum and is on ≥ 1 relay; publication and finality stay in height order. - Provisional cap: 100,000 members per circle at 10 payments a day (500,000 at 2 a day), raised only from measured numbers; a bigger community splits into circles.
4.8 Intake abuse and censorship#
- Per-author rate limits at the intake and on the circle relays; refusals are booked publicly only up to a per-author daily limit (
rej_per_author_per_day, a circle parameter, 20 by default [E-1]), and refusals of keys that are neither members nor applicants are answered, never booked [Decided 17 Oct 2026, C3]. - The node returns a signed receipt (its signature over the note id) for every note it accepts into the queue. A receipted note that is neither booked nor refused within 60 s is public evidence (43924
ignored). - A member whose note gets no receipt within 10 s may publish it standalone to ≥ 3 circle relays (evidence, rate-limited). Witnesses forward such notes to the node and require a receipt. Evidence never halts the circle by itself; a node that keeps refusing receipts for notes forwarded by ≥ q witnesses is replaced (phase 1:
proposer_swap; phase 2: view change).
5. Read path#
5.1 The reader contract (apps, witnesses, gateways, verifiers)#
- Discover from the circle link/QR (circle id, genesis digest, at least two relay hints) (Q10; the circle id [Decided 17 Oct 2026, C5]); read the root relays only at first install, and only those in the newest 38888 (
relaytags only; never the retired alias host, seedocs/releji-svetovna-mreza.md) [Decided 14 Sep 2026]. - Read the witness set and the circle key in office from the ledger (genesis +
rolesentries), and the circle parameters from the ledger's state (g3|param:<name>), not from the newest 30910; cache ≤ 24 h; refresh on any refusal. Pinauthorsto that set for blocks, seals and chunks (writes are open on today's relays [C]). - Ask 2 relays in parallel; "not found" needs EOSE from ≥ 2; a relay that did not answer never means "nothing", and silence is never balance 0 (a silent
[]once wiped a wallet list in 26 ms [R]). Always show the real "answered N of M". - Raw WebSocket readers with timeouts above the reader's own budget; never the nostr-tools pool for ledger reads (it drops queued reads after a 4.4 s fake EOSE [R]).
- Fetch by height (
#h, ≤ 500 values per filter, ≤ 200 filters per REQ; the 500 cap is per filter [M]); page bycreated_atonly where no number exists, withuntil= oldest seen inclusive and de-duplication by id (until-1lost 227 of 1,753 events [R]). - Verify every event signature and every block's quorum before use; verify chunks against their seal.
5.2 Queries#
| Need | Query (on 2 relays) | Checks |
|---|---|---|
| My balance now | one REQ, two filters: {"kinds":[43911],"authors":S,"#p":[me],"limit":1} and {"kinds":[43911],"authors":S,"#c":[<circle id>],"limit":1} (the tip) | quorum, my line vs leaf, aseq continuity |
| Freshness at the tip | if the tip is newer than my block: a sparse-Merkle proof of my line at the tip (from any witness API or gateway, ~1–2 KB), checked against the tip's quorum-signed state root | the only full answer to withheld tips |
| My history | walk last_h back from my newest line, fetching heights in batches by #h | aseq runs 1…N with no gap |
| Is my note booked? | #h from the POST answer, or {"kinds":[43911],"authors":S,"#p":[me],"since":…} | embedded note id |
| A range of the circle | #h values in batches of 500 | every height present, every prev links |
| Yesterday's state | 43917 by #m, then 43918 by #i | chunk count, chunks root, state root, sum = 0 |
| Any other account | as "my balance", with that account's HEX | same checks: everything is public [Consequence] |
| The circle in the root directory | 30915 by #d = [circle id] (where the root relay carries the head: open, §9.2), then 30910 by #d = [circle id] (both from root or circle relays) | the head's seal tag recomputes and its qs carry the quorum; pick the 30910 whose author is the circle_key the head names; then author = the circle key that the ledger's mirror at mirror_of names (at the height of a key change already the new key), tags without g = that mirror, g = the pinned genesis; the valid record with the highest mirror_of |
| A reference | 43921 by #p = [the key] and #c = [the last circle id], from that circle's relays (or the new circle's, which republishes it) | the node's signature; the named block carries the key's reference entry with the same wave, under a quorum of that circle's witnesses in office at its height (§3.11) |
| Where a key comes from | the newest 30916 of the key (root relays; the newest counts) | the circle it names; a key with none was never a member (§3.11) |
Cost: one REQ to each of 2 relays, ~5–10 KB in small circles; 60–214 ms warm, 0.5–0.9 s including opening the socket [M]; ~4 signature checks (~5–10 ms on a phone).
5.3 Completeness, as named numbers#
| Question | Proof | A gap looks like |
|---|---|---|
| Every block? | heights 1…H, each prev = the digest of h−1 | a missing height, a broken prev |
| Is H the newest? | tip from ≥ 2 relays; tip state root + my proof | relays disagree → third relay or live feed |
| Every entry of a day? | the seal's range, pay root and count; COUNT on the day's #m is exact for small sets [M] | fewer entries, another root |
| A member's whole history? | aseq 1…n, last_h pointers | a missing aseq |
| The whole snapshot? | n chunks, chunks root, state root | a missing index, a root mismatch |
| Is a balance right? | previous line + entries + rules = this line; quorum; sum 0 | a 43924 fail with the block as evidence |
The 500-per-filter cap, partial lists and silent relays can delay a reader but never fool it: every gap is a named number.
5.4 Phones at scale (Q16)#
At small scale phones hold one live subscription on 2 circle relays while the app is open. At billions of users (0.2–1 billion concurrent sockets [E]; carrier-grade NAT against the 100-connections-per-address limit [C]) phones read through verified read gateways with push: anyone may run one; every byte is a signed event or a proof against a quorum-signed root, so a gateway can hide but never forge, and the app compares two sources. Circle relays size per-address limits for carrier-grade NAT and limit per author instead. Phones never hold sockets to root relays after first install.
6. Daily checkpoint (seal + public snapshot) [Decided 16 Oct 2026: one seal a day; Consequence: unsalted, always counts]#
- After the morning blocks (§7) the node builds the snapshot: every line of the decision state (§3.8, including every project and the reserve), sorted by key, cut into ≤ 100 KB chunks (43918), and the 43917 seal committing to the day's range, entries, chunks root, state root, counts, gravity totals,
sum = 0, world numbers, the reserve balance, the rate quotes the day's entries referenced, the witness set and the circle key of the office afterh_to[Proposal] and the parameter height (params). Witnesses recompute everything before signing the seal. The seal's range ends at the last block that carries the day's morning header (the morning blocks and payment blocks with visits, §7.4), or, on a day without such blocks, at the last block booked before the boundary; payments booked during the morning up to that block belong to it, later ones to the next day's seal [Decided 17 Oct 2026, C2: payments never pause for the morning]. The snapshot is the state ath_to. - Chunks [E]: 1,000 members → 3 chunks (0.2 MB); 100,000 → ~220 chunks (20 MB); 1,000,000 → ~2,200 chunks (~200 MB). Fetched by
#ivalues, ≤ 500 per filter. - The seal is mirrored to root as 30915, spread over the day (§3.6).
- Restore from a seal (what it reads, and why seal + tail alone is not enough: §8.1 step 5) equals full replay, checked by the canonical state hash; this is part of the daily drill (§8.3).
- Independent attestations: every witness publishes a daily 43924
okwith the state root it computed (and the root over its votes, Q23); any verifier may add its own. A restorer that finds ≥ 2 independentokstatements (not all from the node) may start from that seal without replaying from genesis. - One seal per day, after the 04:00 morning, every day, also without payments; a day without a seal is a public fact.
7. Gravity and other time-driven work#
7.1 Choice#
Gravity is a deterministic integer rule over public data and its per-account result is published in morning blocks (grav entries plus lines), so phones never recompute it and auditors can check it. One event per wallet per day is avoided (it would be 10 billion events a day at the target).
7.2 Determinism#
| Today | Rule |
|---|---|
| The room for deduction uses the balance at run time | cut-off = the last seq booked before the morning opened (on time: the last seq with at < boundary; in catch-up: §7.4) [clarification, 17 Oct 2026 (D4 review)]; every input of an account's gravity (balance, wave, cap, carry, debt) is read at the cut-off, room = max(0, balance at the cut-off); visit before touch (§7.4) keeps the account untouched until its grav entry, so this is also its balance just before the entry; after an outage the missed mornings are booked in date order: a later missed morning reads its cut-off state with the grav results of every earlier missed morning applied, as if each had been booked on time, and an earlier morning's grav entry never counts as touching an account for a later morning [clarification, 17 Oct 2026] |
| Parameters read at run time | the parameter revision in force at the cut-off (params_h in the morning header) |
| Floating-point powers, a 30.4375-day month, double averages | parameters published as whole ppm (band_ppm_day, excess_ppm_day, transition_days, rest_after_days); BigInt averages at second resolution; the first window of a circle runs from the boundary before block 1 (an account's balance is 0 before its first entry), every later window from the previous boundary [clarification, 17 Oct 2026 (D4 review)]; one rounding rule in the spec |
| Server clock and time zone | at assigned by the node, bounded ±5 s by every witness; boundary instant published per day with the pinned tzdata (a verifier identifies a release by its IANA version string (the release's version file, the first line of its tzdata.zi, a +VERSION file, or the tz version a runtime reports, such as ICU's) and can obtain the pinned release from the IANA archive, which keeps every release (informative: data.iana.org/time-zones/releases/); it may compute with another release it holds only after checking, with the pinned release, that the circle's zone has identical UTC offsets and transitions over the dates it checks (from the boundary before the first date to the day after the last): identical transitions give identical boundaries and local dates; without the pinned release, or when the transitions differ, every result that depends on a boundary or a local date is unverifiable, never a guess [Decided 17 Oct 2026 (evening), 2A: the pinned version; clarification, 17 Oct 2026 (D4 review, round 3): how a verifier holds it]; the node makes the same check with its runtime's time-zone data before it signs a morning block or a seal, and otherwise waits [proposal (D3 review, 19 Oct 2026)]); tz, morning hour and tzdata are fixed in the found act for 0.3.0 [Decided 17 Oct 2026, C7] (no act or parameter changes them; a later definitions version may say how a circle follows new clock rules); a morning hour inside a clock change: a local hour that occurs twice counts at its first occurrence, a skipped local hour at the first instant after the gap |
| Database row order ≠ time order | one order: seq |
| Three separate engines | one written spec with test vectors; a second, independent implementation in the verifier |
| Who is visited | every account line whose status at the cut-off is member, frozen, excluded or left (not closed, not a system account or project wallet) [Consequence of E-3: before, left lines were not visited, so leaving and coming back escaped gravity]; a grav entry is booked only if its deduct is above 0 or it changes carry or debt; 0.3.0 has no rules gate: rules_v never gates gravity (today's app has its gate off) [clarification, 17 Oct 2026 (D4 review)] |
debt changes between mornings | settled is an entry consequence, in order |
| Catch-up after an outage | each missed morning is booked as its own morning blocks, in date order, with its own boundary and cut-off. With two or more missed mornings the reading is chained: a later missed morning reads its cut-off state with the grav results of every earlier missed morning applied, exactly as if each had been booked on time (the result today's engine gives) [clarification, 17 Oct 2026], their drains included, and the whole catch-up comes before any other entry (§7.4) [clarification, 17 Oct 2026 (D4 review)] |
Fairness at the boundary: the morning is cut by at, not by when the node decides to run it; the node can move a payment's at by at most the ±5 s the witnesses allow, and in single-witness mode that discretion is visible in public and flagged by the verifier.
7.3 The integer rule (today's morning computation, float inputs replaced)#
S = Σ balance_i × seconds_i BigInt over the window of W_s seconds
(86,400; in the Ljubljana time zone 90,000 for the window
that contains 25 Oct 2026 and 82,800 for 28 Mar 2027)
avg = floor((2·S + W_s) / (2·W_s)) half rounds up, as today's rounding of positive values; avg ≤ 0 → rule 0
rule_µ = min(avg, wave)·band + max(0, avg − wave)·excess (band and excess: the quiet-day switch below)
total_µ = rule_µ + carry_µ; cents = total_µ div 10^6; carry_µ' = total_µ mod 10^6
wanted = cents + debt; deduct = min(wanted, room); debt' = min(wanted − deduct, wave)
The quiet-day switch, exactly [clarification, 17 Oct 2026 (D4 review): today's switch, with the transition per account (3A)]: with D the morning's local date and every day a local calendar date, quiet = 0 if the line has neither last_gift_day nor first_receipt_day, else max(0, D − the later of the two that are set); in_transition = first_receipt_day is set and D − first_receipt_day < transition_days; resting = rest_after_days > 0 and quiet ≥ rest_after_days; excess = band_ppm_day if in_transition, else excess_ppm_day; band = excess if resting, else band_ppm_day; rule_µ (rule_micro) = 0 if avg ≤ 0, else min(avg, wave) × band + max(0, avg − wave) × excess. All of it is read at the cut-off (visit before touch leaves the line untouched until the grav entry).
Whole seconds, and where a deduct counts [clarification, 17 Oct 2026]. at, every boundary and every window are whole unix seconds, and seconds_i is the whole number of seconds balance_i lasted inside the window (milliseconds exist only in today's app). In the window that ends at the next morning's boundary, a grav entry of morning D changes the balance from D's boundary (the window's start), not from the entry's at: visit before touch (§7.4) leaves the account untouched between the cut-off and its grav entry, so from the boundary on its balance is the cut-off balance minus the deduct, whatever the entry's at. Counting from at would make the next morning's S depend on the HEX order of the remaining entries and on when a visit happened. The same holds after an outage: the grav entries of a missed morning count from that morning's boundary, and the next missed morning reads its cut-off state with them applied (§7.2).
Rounding is checked against today's engine in shadow for 14 clean mornings before the switch.
7.4 Order of the morning and other duties#
- At the boundary the open block closes: no block spans a boundary. Payments keep flowing after it in their own blocks, with
at≥ boundary, interleaved with the morning blocks [Decided 17 Oct 2026, C2: payments never pause for the morning] (after an outage, once only the current morning is pending: catch-up, below). Visit before touch [the same decision, C2]: each account's gravity for day D is computed purely from the cut-off state (its balance, wave, cap, carry and debt at the cut-off, §7.2):deduct = min(wanted, max(0, balance)),debt' = min(wanted − deduct, wave)(§7.3). After the boundary (in catch-up: after the morning opened, below), before any entry touches an account (a move from or to it; only money entries touch:pay,give,xout,xin,xundo,grav,project_payto a member, an entry that returns money; anactentry, which has no party and no move, and aruleentry that only names a party (member_join, amember_leavethat moves nothing) touch none [clarification, 17 Oct 2026 (D1 review)]) whosegraventry for D is still pending, thatgraventry is booked first, in the same block, right before the touching entry (several in HEX order). For a note, the visits of the accounts it would touch are booked before the note is judged, and it is judged on the state after them; a refused note leaves its visits booked (they are due anyway), and itsrejfollows them; a refusal that is only answered, never booked (a key that is neither a member nor an applicant [C3]; aboverej_per_author_per_day), books nothing, its visits neither [proposal (D3 review, 19 Oct 2026)]. The account is therefore untouched between the cut-off and itsgraventry, so the order in which the node books payments never changes anyone's gravity, and the order loses no debt: a debt the morning records (at most the wave, as the rule caps it) is settled by the next receipt. A block that books agraventry carries the morning header. After an outage the missed mornings are booked in date order: a later missed morning reads its cut-off state with thegravresults of every earlier missed morning applied, as if each had been booked on time, and an earlier morning'sgraventry never counts as touching an account for a later morning [clarification, 17 Oct 2026]. Catch-up after an outage [clarification, 17 Oct 2026 (D4 review)]: the node books the missed mornings completely, in date order, in morning blocks, before any other entry. Mornings open at block starts, one at a time, in date order: a morning opens when its boundary is at or before the block's firstatand every earlier morning is complete (on time: at the first block start at or after its boundary; a restorer from the seal of day D starts with morning D complete, since the seal is made right after it [clarification, 19 Oct 2026 (D3 review)]); its gravity is computed from the state at that moment, and its header's cut-offseqis the lastseqbooked before it opened (on time: the lastseqwithat< boundary; in catch-up: the last entry of the earlier morning), so a later missed morning reads thegravresults of every earlier one and their drains, as if each had been booked on time. While two or more mornings are pending (one is open and a later boundary has passed too), a block holds only the open morning'sgraventries (HEX order; visits only inside its drains) with their end-of-entry work (§3.5): no payment, act,rolesentry, refusal or duty. A block carries one morning header, so the block that completes a morning ends there. [completed 24 Oct 2026, plan step E4x] A block that continues the carried work of a cut catch-up block (the block split, §3.5) holds that work first and opens no morning (when it books nograventry it carries no header); aparams_effectivedue during the catch-up waits until every missed morning whose boundary is at or before its notice end has opened, so it never applies to a morning before its notice end (§3.1 rule 11). Visit before touch for morning D covers the entries from D's opening on, so an earlier morning's catch-up entries are no touches for D, and it applies only to the newest, current morning. Payments, acts and duties resume as soon as only one morning is pending: this is C2, payments never wait for the current morning. In the next window's average every entry, including a catch-up's drain, counts by itsat; onlygravdeducts count from their morning's boundary (§7.3). A new morning cannot open (no block carries morning D+1's header) while anygraventry of morning D is still pending; witnesses refuse such a block (grav_pending) [clarification, 17 Oct 2026 (D1 review)]. - Morning blocks book the remaining
graventries, in HEX order, of the accounts not yet visited (an account a drain's entry already needed is skipped) [clarification, 19 Oct 2026 (D3 review)]: headermorning(boundary, cut-off, parameter revision, thetzdatapinned at founding, §3.5);graventries and lines only for accounts where something changes, ≤ 100 KB each, counting the block's own entries only [clarification, 19 Oct 2026 (D3 review)] (about 240 accounts, about 140 while a project receives), withptags of exactly the accounts they touch. Morning blocks hold onlygravandruleentries (due rules and thedrain()steps), booked at or after the boundary; a payment block holdsgraventries only as visits (right before the entry that touches the account, or before therejof a refused note [proposal (D3 review, 19 Oct 2026)]); a morning with nothing to book books no morning block. - Witnesses recompute every
gravline from the cut-off state; everygravdeduct moves to the reserve, anddrain()runs at the end of every entry, as at any other time (§3.9) [clarification, 17 Oct 2026 (D1 review)]: after eachgraventry of a morning block, and at the end of the entry that a visit precedes.drain()fills projects oldest first and is defined per entry; a project that fills during the morning pays a recipient whose owngraventry, if still pending, is booked first (visit before touch), so it never sees the project payment. A mismatch means no quorum, so no morning: an alarm, never a guess (in single-witness mode the verifier and the drill catch it). - The due
ruleentries open the block, earliest due time first (project_lapse(open_lapse_s, 30 days by default, before opening: proposal;receive_lapse_s, 90 days by default, after opening [8e]);project_return[8e]; the end of a vote (vote_passorvote_fall) [E-5]; request expiry; the 7-day cross-circle checks (xcheck_s, §4.5) [8j], once their evidence is read; each followed by its end-of-entry work,drain()with itsproject_fullandproject_pay[8a]); they never wait for the morning blocks (the order inside a block: below) [clarification, 17 Oct 2026 (D4 review)]. A project that passed its vote is no duty when it opens: it opens in the end-of-entry work of the entry after which its consent is given and, for a step raise, it fits underbuilt(§3.9). After the morning come the seal and chunks; the seal's range ends at the last block that carries the day's morning header.
Every time-driven change is such a duty: a block whose first at reaches a due time must start with all due entries in canonical order (when a duty is booked: §3.5), and witnesses refuse a block that omits one. The order inside a block [clarification, 17 Oct 2026 (D4 review), except where marked]: while two or more mornings are pending (catch-up, item 1) a block holds only the open morning's grav entries, with their end-of-entry work, nothing else; after a block the size rule closed, the carried work first and only it (the block split, §3.5: no morning opens and no params_effective in that block; then the duties still due) [completed 24 Oct 2026, plan step E4x]; otherwise first params_effective when a param_propose's notice end is due by the block's first at (after the morning header) [Proposal, E-1] and it does not wait (it waits while a missed morning at or before its notice end has not opened, or a duty due before its notice end is due: §3.1 rule 11) [completed 24 Oct 2026, plan step E4x], then the rule entries of item 4, every duty due by the block's first at, each followed by its end-of-entry work (§3.5), then the block's other entries (payments and acts with their visits, roles entries, refusals) or the open morning's remaining grav entries. Duties that fall due in the same second go in this order: the return after a closing notice (close_return), the lapse of a receiving project (receive_lapse), the lapse of a project that never opened (open_lapse), the end of a vote (vote_end) [Proposal, E-5], request_expire, a resignation; within a kind by publication (projects and motions: their published seq, which their o3 line holds) or by id (requests by request id) [clarification, 17 Oct 2026 (D1 review; D4 review and its round 3)], since the order changes who is paid. A due resignation is committed in a block of its own: its leading params_effective (when one is due), then the resignation's roles entry, nothing else; it comes before the morning block of an open morning (a morning block holds no roles entry), and the other duties due by then open the next block [proposal (D3 review, 19 Oct 2026)]. At the block start the void resignations are dropped first (§3.4); the earliest of the others, by notice end and then act id, takes the block [clarification, 19 Oct 2026 (D3 review)]. A due duty whose project already ended earlier in the same block (a receive lapse and a close return both overdue after an outage) is dropped [clarification, 17 Oct 2026 (D4 review, round 3)]. Due entries go earliest due time first; the kinds that item 4 lists are not an order among them, and project duties due in the same second follow the order just given [clarification, 17 Oct 2026]. A note's, quote's and act's TTL and the daily refusal limit are judged by the parameters in force at the booking, and the number of Heart votes by those in force at the vote end [Proposal, E-1]; a running deadline (a vote, a lapse, a closing notice, the 8j wait, an exclusion, an invitation, a change's notice) keeps the due time recorded in its open item when it started, never retroactive [Consequence of E-1] (§3.1 rule 11). The morning's grav entries are the exception: they follow item 1 (visit before touch) and item 2 (the rest in morning blocks), so payments never wait for the current morning (after an outage they wait only while the missed mornings are booked, item 1). Today's separate timers for support, gravity, seals and clean-up stop being independent.
Observation for volume: below the cap every receipt grows the wave and is counter-booked to the reserve and on to the receiving project [A8], so balances do not rise and gravity books almost nothing today.
8. Restore#
8.1 A circle whose server is gone, step by step#
Inputs: the circle link/QR (circle id, genesis digest, relay hints) or any member's 30916; plus, only to resume booking, the Heart's acts for a new node (live circle: the founder and three other Heart members [Decided 16 Oct 2026, A4 and 4a]; three of four must sign: proposal).
- Find the circle. From the link, or from root (newest 38888 → the circle's 30915 head by
#d= the circle id (where the root relay carries the head: open, §9.2), then its 30910 by#d, signed by the circle key the head names). Switch to the circle's relays named there; trust nothing whose block 1 does not embed thefoundact whose id is the circle id, and nothing that does not chain to the genesis digest. - Governance chain. Read genesis and every
rolesentry (by height; they are few); build the witness windows and the circle key in office by height. [proposal (D3 review, 19 Oct 2026)] For a restore from a seal the chain is mandatory: block 1 (its digest is the pinned genesis, its mirror the one its signedfoundact gives) and every block with arolesentry up to the heightg3|mirror_hnames, in height order, each signed by a quorum of the office the mirror before it puts in power; no block carries a pointer back to the previousrolesblock (none is added for it), so the restorer reads them from the circle's relays. The circle parameters and every change of them are in the circle's blocks (thefoundact and eachparam_proposethat aparams_effectivenames) and in the snapshot'sg3|param:<name>lines, so a restore needs only the circle's relays [Consequence of E-1]. - Newest checkpoint. Newest 43917 from ≥ 2 relays with a valid quorum for its window; follow
preva few days; prefer a seal with ≥ 2 independent 43924okstatements. Two valid seals for one day = fork alarm: stop and report. - Snapshot. All chunks by
#i; verify chunks root and state root; load every line. - The day's blocks after the boundary, the named blocks and the tail [what a restore from the seal of day D reads, and why: clarification, 17 Oct 2026 (D4 review); the complete list: clarification, 17 Oct 2026 (D4 review, round 3); the lines it rests on (§3.8): proposal (D4 review, round 3, 17 Oct 2026)]. The decision state holds everything the next booking depends on, so a restorer from the seal of day D judges the tail exactly as a replay from block 1. For that it reads, besides the seal and its snapshot chunks (steps 3 and 4) and the governance chain of step 2 (mandatory: it shows that the seal's quorum is the office in power, from the pinned genesis on [proposal (D3 review, 19 Oct 2026)]), exactly: every block whose first
atis at or after boundary(D), up toh_to(the window of the next morning's averages, and the refusals of the current morning day; none when the range ends before the boundary; after an outage also the catch-up blocks of earlier mornings in earlier seals' ranges, and eachgravdeduct counts from its own morning's boundary [clarification, 19 Oct 2026 (D3 review)]); the block right before the first of them, or the seal's head block when there is none, whose lastatmust be before boundary(D), so no block after the boundary is left out [proposal (D3 review, 19 Oct 2026)]; the block at the height the state'sg3|mirror_hnames (its genesis orrolesentry carries the mirror in office, in tag order); the blocks at the booked heights of the openo3|changelines (what each change names: its relays, keys, witness, k, parameters (aparam_propose), or the key it excludes, readmits or closes); every block afterh_to(the tail, fromh_to + 1to the tip). The 43920 records are no longer read [E-1]. Nothing else. Blocks by#h, from every listed relay in parallel (union, de-duplicated); verify chain, quorum and every embedded signature; replay every tail entry with the pure state machine and compare every line and root. Why: the next morning's averages need each account's balance over [boundary(D), boundary(D+1)); its balance at boundary(D) is the snapshot balance less the moves of those blocks of the range other thangravdeducts (which count from the boundary), and then every move in order. Seal + tail alone cannot give the next gravity. The restore proof of the definitions: §12. - Gaps. A missing height: other circle relays, archives, partners' relays, witnesses' logs. If no copy exists anywhere: stop, report the height, never guess. A cut head [completed 24 Oct 2026, plan step E4x]: when the seal's
h_toblock carriesmore(the block split, §3.5), the state ath_tocarries that work: the restorer reads it from that block'smoretag, and the tail's first block continues it at the sameat. - Caches. Rebuild the SQLite projection from the replayed state.
- Resume. A new node key via
proposer_swap(k Heart members + current quorum, orrecoveryif fewer than q witnesses survive (the larger of k and 3 Heart members and no Heart "against" [E-7, E-10]); recovery is void if any quorum-valid block above its named height appears during its notice); the new node starts at tip + 1. A lost or stolen circle key does not stop a restore: the Heart replaces it bycircle_key_change(§3.4) [Decided 17 Oct 2026, C5]. - Compare. The canonical state hash of the restored state equals the seal's state root replayed forward; if an old database exists anywhere, its sums must match.
8.2 Costs (checkpoint + one day of tail, the worst moment) [E]#
Basis: reading 3 relays in parallel at the measured single-connection speeds (356–2,416 events/s, 0.55–3.7 MB/s per relay [M]), the slower of the event and byte rates; signature checks 11,000/s per native core, 722/s per JS core [R], 8 cores.
| Circle | Snapshot | Tail of one day | Read time | All signatures (notes + quorum), native / JS | Quorum only, JS |
|---|---|---|---|---|---|
| 1,000 members, 2/day | 0.2 MB | ~3,100 blocks, 7 MB | 1–4 s | 15,000: 0.2 s / 3 s | 2 s |
| 1,000 members, 10/day | 0.2 MB | ~12,700 blocks, 30 MB | 3–18 s | 64,000: 0.7 s / 11 s | 9 s |
| 100,000 members, 10/day | 20 MB | ~56,000 blocks, 1.2 GB | 2–12 min | 1.5 M: 17 s / 4.4 min | 39 s |
| 1,000,000 members, 10/day | 200 MB | ~133,000 blocks, 11.4 GB | 17 min – 1.9 h | 13.6 M: 2.6 min / 39 min | 1.5 min |
- Restore cost is bounded by the seal interval, not by the circle's age; hence the provisional cap of 100,000 members (§4.7, Q13).
- Full replay from genesis (auditors, once, then they follow live): one circle-year of 1,000 members at 2 payments a day is ~1.1 M events, 2.6 GB; at 10 a day ~4.6 M events, 11 GB; linear in years and parallel by day (snapshot(d−1) + blocks(d) = snapshot(d)).
- Several connections per relay at once and MB/s for large restores are unmeasured.
8.3 Restorable as a tested fact: the daily restore drill [Consequence]#
Every day, after the seal, the node (and any independent verifier) restores the circle from the relays alone into a scratch database, compares the canonical state hash with the seal and publishes the result as a 43924 statement (about = restore). A failed drill is an alarm on the admin page and in every member's app ("restore check failed on <day>"), not only for an administrator (a shared sync tool once ran "0 synced, 2000 errors" for days unnoticed [R]).
8.4 A new phone#
Scan the circle QR (or open the member's 30916), read the witness set from the circle relays, then §5.2: a balance in about a second. Nothing to back up on the phone except the BSA WIF.
9. Relays for the ledger#
9.1 Tiers#
| Tier | Run by | Carries | Rules |
|---|---|---|---|
| Root (the relays in KIND 38888; four today) [Decided 14 Sep 2026; A2] | the Lana relay owner(s) | 38888, 42893 definitions, every circle's found act (its id is the circle id) [Proposal] and the first found act of every founder key (one circle per founder key, ever [E-8]; the mechanism: Proposal), newest 30910 of every circle (by circle id), 30915 heads (spread over 24 h), KIND 0; while borrowed [Decided 16 Oct 2026; A2, A9: limited space]: small circles' ledgers under a quota (size: proposal, 1 GB or one year per circle, whichever comes first, Q18); optional 30917 offers. No rate records: quotes live on circle relays [A7] | no payments at scale; no member homes beyond the borrowed phase (Q16), except that a new circle reads where a key comes from in its newest 30916 (E-8, E-9), so the root relays (or, at scale, the index relays) keep the newest 30916 of every key [Proposal]; phones only at first install |
| Circle relays [Decided 16 Oct 2026, A2] | the circle's box relay + witnesses' relays + partners, cooperatives, hosting providers (+ Lana relays while borrowed) | the circle's whole ledger: blocks, seals, chunks, acts, homes, the rate quotes it issued or relied on, and partner blocks; the references (43921) it issued, and those its member_join entries named [Proposal] | ≥ 4 relays, ≥ 3 operators [A2] (bootstrap ≥ 2, Q14); write policy §9.2 |
| Archive relays | anyone | full histories, compressed | no 10-year lower limit, no expiry, KIND 5 refused |
| Index relays (Q16) | anyone | 30916 member homes sharded by key prefix; name search | at scale only |
| Gateways | anyone | verified HTTP caches with push | can hide, never forge |
"Root relays only from KIND 38888" stays for root relays and Lana apps; circle relays are named by each circle in its own ledger [Decided 16 Oct 2026, A2: the project owner's yes to this new reading of the 14 Sep rule]. 38888 is the directory, but no circle's validity depends on it (Q10).
9.2 Write policy on every relay that stores ledger kinds#
The box relay ships with it; the Lana relays need their owner's change (Q18).
- each served circle is configured by its
id(the circle id) andcircle_key(the key in office; after acircle_key_changethe old key moves toretired); ledger kinds are recognised by theirctag; thefoundact is accepted when its id is a served circle id [the circle id: Decided 17 Oct 2026, C5; the configuration: Proposal]; aretiredentry carries its role,{"key": <HEX>, "until": <unix>, "role": "signer" | "node" | "circle_key"}, and a retired key counts only in its own role, for events up to itsuntil(a retired circle key can sign only an old 30910, never a block, seal, chunk, head or quote) [Proposal]; - 43911, 43917, 43918 accepted only from keys in the circle's current witness set, read from its ledger;
- 43916 and standalone 43910 only from members and applicants of that circle, rate-limited per author;
- 43919 only from the circle's node of the time, as named by its ledger;
- 43924 from the circle's witnesses, and from any other author rate-limited per author (a verifier's or auditor's challenge must always be publishable);
- 43921 only from the circle's node of the time, as named by its ledger, and a partner's 43921 that this circle's
member_joinnamed (as for a partner's 43919) [Proposal]; 43920 is retired and no longer a ledger kind [E-1]; - mode
root(the Lana relays; a request in the letter to their owner, plan phase G): keep the first-seengand founder per circle id, check the founder's signature over the circle id and the genesis digest, and accept a v3 30910 only from thecircle_keyit names; with the circle id this is only extra safety [the first-seen rule in the letter: Decided 17 Oct 2026, C6; the checks: Proposal]. How it keeps them [Proposal]: a root relay keeps every circle'sfoundact (a 43916 whose first tag is["c", ""]and that has no otherctag, from any author: its id is the circle id, so nobody can make a false one), and pins a circle id's genesis digest and founder only when it holds thatfoundact and the record'sfounderis its author (or, for a circle configured on the relay, when its configured circle key signed the record); otherwise the relay stores the record unpinned (readers check it anyway), so nobody can claim a circle id first on a root relay; the plugin remembers at mostseen_ids_maxfoundacts, and beyond that a newer circle's records are kept unpinned, never falsely pinned; a pin is written only after every plugin of the relay (the chain) accepted the record; pins are not in LMDB and are not rebuilt from lookback, so a relay seeded from another relay's LMDB copy also copies the write policy'spins_file; - [Open] the policy must also admit 43916 from keys the log names as witness or guardian who are not members (
docs/upravljanje-kroga.md); - [Open] whether a root relay accepts the 30915 head of a circle it is not configured for (checked against the witnesses of its pinned record); the prepared write policy accepts heads only of configured circles;
- refuse KIND 5 and KIND 62 that target ledger kinds or are authored by any ledger key; refuse
expirationand-on BSA kinds; - keep BSA kinds out of every purge and hard-delete filter;
- no 10-year lower limit on circle and archive relays (
rejectEventsOlderThanSeconds = 4000000000(larger than the current unix time; measured 16 Oct 2026 on strfry 1.1.0: the value0refuses every event, even one made now)); - per-address limits sized for carrier-grade NAT, per-author limits instead;
- tested before the first publish, including whether strfry refuses to re-insert an id after a KIND 5 (unverified).
9.3 Sync and the replication audit#
- The node publishes to every listed relay itself (§4.1 step 7). A replication audit runs daily and after outages (NIP-77 negentropy scoped by
#cand day, cheap on small scoped sets [M]), republishes what is missing and publishes "copies N of M", which the app shows. - Never lana-relay-sync for any BSA kind until its four loss bugs are fixed (per-kind
sinceloss above 500 events per 10 min,until-1, "complete" after a failed connection, a full-history diff every cycle); never the strfry router (a live stream with a fixed 45-kind list that has no BSA kind [C]). - Replica drift is real: up to 18 % within one kind today [M]. A reader always takes the union of signed events.
9.4 Switch-on and new relays [Consequence]#
- Outbox
held= "waiting for the project owner's yes on the definitions" (P7: one yes per kind). At switch-on the whole backlog goes out from genesis, oldest first, paged at a rate the relays accept. - A new or empty circle relay is back-filled with the full history (every block, seal, chunk and act), checked by height numbers and seal roots, before it is listed by a
relay_changeentry. - A new root relay gets the directory only (newest 30910, 30915 heads, every circle's
foundact, homes while borrowed, and the newest home of every key for E-8 and E-9 [Proposal]); seeded from another root relay's LMDB copy, it also gets that relay'spins_file(§9.2).
9.5 Today's four Lana relays#
- Identical strfry 1.1.0 on 2-vCPU servers; free disk 11 / 90 / 23 / 51 GB; ingest 2,245–4,513 events a day [M/C]; the smallest is about 70 % full [C].
- As the only replication they carry the whole public ledger of about 2 circle-years of one 1,000-member circle at 2 payments a day (11 GB free against ~5 GB a year per copy), half a circle-year at 10 a day [E]; the 1 October finding (the smallest relay full at ~8,500 payments a day [R]) says the same [Decided 16 Oct 2026: the four Lana relays will not carry 100 billion; the system must scale].
- BSA kinds are not in the router's 45-kind list [C], so the relays would not copy each other; the circle publishes to each itself.
- Operator independence is unclear (Q14): until shown otherwise the four count as one operator for the ≥ 3-operator rule.
- Role [Decided 16 Oct 2026, A2]: the root directory for ever, and a borrowed home for small circles with limited space, counted as copies only after the owner applies §9.2 (Q18).
10. Sizes and capacity#
10.1 Model constants [E]#
Per payment ~1.1 KB of entries (cross legs included: 1.62 entries per payment at the 10 October simulation's ~31 % cross share [R], ~45 % more bytes); block envelope ~0.85 KB + 0.205 KB per signature (3 signatures, or one FROST signature ~0.15 KB); payments per block = (entries/s while awake) × W_max + 1, at most ~120; morning lines ~0.25 KB for half the accounts; snapshot ~0.2 KB per account; disk factor 2× [M]; 16 waking hours; peak 5× per circle, 3× for the world; relay planning budget 300 events/s (1/6 of an external ~1,856/s benchmark [R], never measured on our relays).
10.2 One circle [E]#
| Circle | Payments/day | Entries/day | Events/day (blocks + morning + chunks) | Peak entries/s → blocks/s | Raw per day, one copy | Disk/year, one copy | Disk/year, 3 copies | Bytes per payment, all-in |
|---|---|---|---|---|---|---|---|---|
| 1,000 × 2 | 2,000 | 3,240 | ~3,100 | 0.2 → 0.2 | 7 MB | 5 GB | 15 GB | 3.5 KB |
| 1,000 × 10 | 10,000 | 16,200 | ~12,700 | 0.9 → 0.7 | 30 MB | 22 GB | 66 GB | 3.0 KB |
| 5,000 × 10 (W = 2 s, FROST) | 50,000 | 81,000 | ~21,000 | 4.7 → 1.2 | 78 MB | 57 GB | 172 GB | 1.6 KB |
| 100,000 × 10 | 1 M | 1.6 M | ~56,000 | 94 → 3.2 | 1.2 GB | 0.9 TB | 2.7 TB | 1.2 KB |
| 1,000,000 × 10 | 10 M | 16.2 M | ~133,000 | 940 → 7.5 | 11.6 GB | 8.5 TB | 25 TB | 1.2 KB |
Small circles pay mostly for envelopes (one payment per block); that is the price of sub-second publication, and the absolute cost is tiny (a 1,000-member circle's box needs ~20–90 GB a year for 4 copies). The 5,000-member row assumes W_max = 2 s, while w_max_s is 1 s at founding (§3.5; proposal: a circle above about 10,000 members raises it to 2 s by param_propose); re-run it with the parameter chosen.
10.3 One million circles, one billion users [E]#
| 2 payments/day | 10 payments/day | |
|---|---|---|
| Payments | 2 B/day (23,000/s) | 10 B/day (116,000/s) |
| Events/s average / 3× peak | 36,000 / 107,000 | 146,000 / 439,000 |
| Raw per day, one copy | 7 TB | 30 TB |
| Disk per year, 3 copies / 4 copies | 15 PB / 21 PB | 66 PB / 87 PB |
| Relay-equivalents for 4 copies at 3× peak: 300 ev/s / 1,856 ev/s | 1,400 / 230 | 5,900 / 950 |
| Root: 30910 + 30915 | ~9 GB on disk, 12 head writes/s | same |
10.4 The principle-6 target: 10 billion users, 100 billion payments a day, ≥ 3 copies [E]#
100 billion a day = 1.157 million payments a second on average.
| Profile | 2 M circles × 5,000, W = 2 s, one FROST signature | 10 M circles × 1,000, W = 1 s, 3 signatures |
|---|---|---|
| Payments per block (average while awake) | 3.8 | 1.3 |
| Bytes per payment, all-in | 1.6 KB | 3.0 KB |
| Events/s average / 3× world peak | 0.49 M / 1.48 M | 1.46 M / 4.39 M |
| Raw per day, one copy | 157 TB | 300 TB |
| Raw per year, one copy | 57 PB | 109 PB |
| Disk per year, 3 copies (4 copies) | 343 PB (458 PB) | 656 PB (875 PB) |
| Over 10 years if volume grows linearly to the target, 3 copies, uncompressed | ~1.7 EB | ~3.3 EB |
| Relay-equivalents for 4 copies at 3× peak, 300 ev/s / 1,856 ev/s | 19,700 / 3,200 | 58,600 / 9,500 |
| Circle-box model instead | 2 M box relays, ~57 GB a year each per copy, ~1–5 events/s at peak | 10 M box relays, ~22 GB a year each |
| Root | 30910 + 30915 ≈ 18 GB on disk; 23 head writes/s | ≈ 90 GB; 116 head writes/s (the smallest root relay's disk must grow or root gains relays) |
- Per user: ~34–66 MB a year on disk across 3 copies; at ~$15 per TB-year of disk plus servers and power (~3×) about $0.002–0.004 per user a year. Bytes are cheap; running tens of thousands of reliable relays is the cost (Q15).
- The floor is the payments' own payload (signatures, keys, amounts, balances after): ~65 TB a day per copy even with no envelope [R]; binary encoding would halve JSON-hex but would leave Nostr.
- Nostr has never run anything like this: the largest public relays ingest 2–6 events/s [R]; 1.16 M/s is the sum of millions of light cells, not one system. No component sees the world total.
- KIND 0 and member homes of 10 B members on every root relay would be ~10 TB and ~15 TB per relay; the smallest root relay fits ~11 M profiles, ~7 M homes [E] (Q16).
10.5 Storage over ten years without breaking principle 2 (Q19, Q15)#
- Shard by circle: each circle's growth sits on its own relays and partners (a 5,000-member circle at 10 a day: ~57 GB a year per copy).
- Checkpoints are read compaction, not deletion.
- Circle boxes keep everything (it is small). Shared relay groups at scale: hot relays keep 30–90 days; older blocks move to ≥ 3 archive relays of different operators, are verified there by negentropy and against the seal roots, and only then may leave the hot relay (the only place an operator removes a ledger event, Q19).
- Archives compress (strfry zstd dictionaries, unverified on our build; JSON-hex compresses 2–3× [E]).
- No 10-year lower limit on circle and archive relays, or history older than 10 years can never be copied to a new relay [C].
- Who pays (Q15): each circle pays its relay operators through a project (Common Good no longer exists [A8]); partners by reciprocity; archives by the circles that use them.
10.6 Not measured, not certain#
strfry EVENT→OK latency and sustained ingest at 2 KB and 100 KB events; whether OK means fsync'd (power-cut test); the cost of a duplicate EVENT; concurrent sockets and subscriptions per relay; MB/s served for a restore; negentropy on 1–2 M scoped events; whether strfry refuses re-insertion after KIND 5; zstd ratio; witness round times on real networks; all event sizes until the 0.3.0 examples are signed. The first build step measures them on a separate strfry with the production configuration, never on the Lana relays.
11. Failure modes (ledger)#
| Failure | Defence | What still breaks |
|---|---|---|
Relay silent, [], 429, timeout | EOSE from ≥ 2; named numbers expose gaps; raw readers; "answered N of M" | nothing, if 2 relays answer |
| Partial results (500 cap, 4.4 s pool drop) | reads by height ≤ 500 per filter; inclusive until + dedupe; no nostr-tools pool | — |
| Replica drift | union of signed events; daily scoped negentropy audit; "copies N of M" public | — |
| Operator hard-delete | ≥ 4 relays of ≥ 3 operators; a gap is visible at once; any holder republishes the identical signed event | an operator can always delete their own copy |
KIND 5 / expiration (NIP-09 and NIP-40 on all four [M]) | ledger keys never sign KIND 5; §9.2 policy; tested before the first publish | a relay without the policy can lose copies; archives are the backstop |
| A relay censors the circle | replace it by relay_change; 3 of ≥ 4 suffice | — |
| Node censors a note | receipts; standalone evidence to ≥ 3 relays; witnesses forward; proposer_swap / view change | a delay of seconds to minutes |
| Node or witness crash | sign-guard, WAL, restart reads all relays, adopt the highest chain, lock release rules (§4.6) | non-final blocks; apps resend |
| Up to f witnesses faulty | quorum q = 2f+1 of 3f+1 | — |
| More than f witnesses down | liveness lost, safety kept: reads work, payments wait | until replaced by governance |
| More than f witnesses collude | verifiers replay and publish fail with evidence; apps check their own lines; partners stop accepting; cross-circle exposure bounded by the step outward | safety lost until people choose the honest branch (the limit of any BFT system) |
| Single-witness mode lies or its key is stolen [Decided 16 Oct 2026, A3] | public label, daily verifier and drill, height-uniqueness check by apps | a wrong entry can be booked before it is caught; no money cap bounds it (A3) |
| A bug shared by every witness | second independent implementation; test vectors; planted-bug tests; upgrades effective at a named height with shadow runs | until found, a shared bug passes the quorum |
| A wrong move between project wallets and the reserve | keyless wallets [A8]; only rule entries naming their inputs; one canonical drain(); every witness recomputes them and checks the reserve invariant; verifiers replay | in single-witness mode, until caught |
| Money stuck in a receiving project (recipient gone, project found bad, never fills) | the Circle Heart closes it with public notice (close_notice_s, 72 h by default), or it lapses 90 days (by default) after opening; project_return moves its balance to the reserve, then drain() [Decided 16 Oct 2026, 8e] | the money waits in the keyless wallet until the notice or the 90 days have passed |
| The seller circle quotes a bad rate | the payer sees the converted price and does not pay [A7]; the quote is public and signed by that circle's node | a payer who does not look |
| Stale chain head on a member's device | refused stale_prev; the app re-reads and re-signs | — |
| Clock skew, tz database change | at checked ±5 s; note expires; published boundary; tzdata pinned in the found act and unchanged in 0.3.0 [Decided 17 Oct 2026, C7] | a government that changes its clock rules: how a circle follows is left to a later definitions version |
| Oversized event | ≤ 100 KB by bytes, tested at maximum lengths | — |
| Spam, open writes, disk filling | authors pinned; circle-relay policy; per-author limits; borrowed quota; disk alarm at 70 % | root relays keep open writes (owner's choice) |
| 10-year window | no lower limit on circle and archive relays | the four Lana relays refuse events older than 10 years [C] |
| Circle key lost or stolen | it only stamps the 30910 mirror (and once the binding of the found act in block 1) [Proposal]; readers follow the ledger; k Heart members replace it by circle_key_change with the new key's proof of possession and public notice (change_notice_s, 72 h by default [E-1]), the witnesses book it, and from the height of the change only the new key's records count (it signs the 30910 of that height; for blocks it is in office from the next one); every seal and head names the circle key of the office after its last block [Decided 17 Oct 2026, C5; the proof of possession, when the new key counts and the key in the seal: Proposal]; the circle id never changes | until the change is booked, a thief can only publish records that equal the ledger's mirror (anything else does not count); a lost key leaves new mirrors unsigned until the change (the ledger goes on; readers follow the ledger) |
| A false circle under the same name | the name is the circle id, the id of the founder's found act: another found act has another id, so it is another circle [Decided 17 Oct 2026, C5]; readers pin the circle id and the genesis digest from the link or QR; root relays with the first-seen rule keep the first g and founder per circle id (extra safety [C6]) | a reader who has neither the link nor the QR must compare the circle id itself |
| A Heart member's key is stolen | every Heart change needs k Heart members, so one key cannot exclude, close an account, change parameters or change witnesses alone; a parameter change waits at least the time it replaces, so a stolen key cannot skip the warning [Proposal, E-1]; a witness change also fails on one Heart "against" [E-7]; every act is public | k stolen keys act as k Heart members; every member sees it in public, and whoever disagrees can leave with a reference and join or found another circle |
| Circles with different parameters | each circle applies its own values to what it books; a mismatch in note_ttl_s or quote_ttl_s ends in a refusal and xundo, and a short xcheck_s only repeats the check (§4.5) [Proposal, E-1] | nothing is lost; a payer may have to sign again |
| A member leaves in minus | no reference while in minus [E-9]; the debt stays written in the old circle, and anyone may settle it, never above 0 [E-9]; the circle covers it only when the member has died (an account close) [E-3 Dopolnitev] | the debt can stay open for ever; no other circle admits the person from that circle without a reference |
| One person with two keys | one key, one circle, through the member home and the reference (E-8, E-9) | not prevented: that needs Lana's person check (said openly) |
| Member key lost or stolen (Q11) | optional guardians, freeze, key_move | without guardians the balance stays frozen and public |
| Cross-circle partner silent | a timeout alone never undoes; after 7 days every witness of the payer's circle reads the partner's sealed ledger up to the note's expires: not booked → xundo naming the partner's seals and the real seal before them (§4.5); booked → xdone [Decided 16 Oct 2026, 8j]; a partner block counts only with a valid quorum of the partner's witnesses in office at its height, so noise signed by keys that are no quorum of the witnesses in office at that height (for example an old or stolen key) cannot stall the check [Proposal] | while the partner's ledger cannot be read (relays gone, a missing height, no seal covering expires), the amount stays held: never a guess; a key that was in office at a height (for example the single witness of a one-witness circle, later stolen) can still fork that height, and a fork stops the check |
| A person wants their name gone [Decided 16 Oct 2026, A5] | the ledger carries keys only; the name lives only in KIND 0 and 30916, which the person replaces; relays keep only the newest version | old copies of a profile someone saved, and names someone wrote into free text despite the field warning; a payment's existence and amount stay, by principle |
12. Tests (when built)#
- Replay equals restore: a restore from a seal (what it reads: §8.1 step 5) and full replay from genesis give the same canonical state hash, for every day of a generated year.
- Block arithmetic: every line = previous line ± entries; the sum is 0 after every block; a changed line, a dropped entry or a line moved to another party fails the digest or the witness check; a block whose
atspan is abovew_max_s(10 s without the parameter lines) is refused. - Sign-guard: a witness never signs a second digest at a height, across a kill at every step of §4.1; restart adopts the highest chain found on any relay or archive.
- Double spend: two notes on one
prev→ one booked, onerej stale_prev; an expired note is never booked; two blocks at one height are detected by the app's height-uniqueness read. - Byte budget: every example and every generated block ≤ 100,000 bytes and ≤ 1,000 tags at maximum field lengths; morning blocks cut by bytes.
- Template round-trip: a note that does not round-trip the v3 template is refused, never repaired.
- Readers: a silent relay, an empty
[], a 429 or a timeout never produce "not found" or balance 0; a missing height is reported by number; paging with inclusiveuntilloses nothing on a 1,753-event fixture. - Gravity: the integer rule matches today's engine for 14 clean shadow mornings; clock-change windows use 90,000 and 82,800 s; a morning hour inside a clock change gives the first occurrence of a repeated hour and the first instant after a skipped one (Ljubljana and New York, both changes); a missed morning is booked as its own morning, and with two missed mornings the later reads its cut-off state with the earlier one's
gravresults applied; agravdeduct counts from its morning's boundary, not from the entry'sat[clarification, 17 Oct 2026]; a morning header whosetzdatais not the one pinned at founding is refused; the morning cut byatis independent of when the node runs it; a payment booked before or after an account'sgraventry gives the same lines (visit before touch); the order loses no debt: a debt the morning records (capped at the wave by the rule) is settled by the next receipt; an entry that touches an account after the boundary (in catch-up: after the morning opened) before itsgraventry is refused; anactentry, or aruleentry that only names a party, touches no account and needs no visit [clarification, 17 Oct 2026 (D1 review)]; a block that carries morning D+1's header while agraventry of morning D is pending is refused (grav_pending) [clarification, 17 Oct 2026 (D1 review)]. - Snapshot: every chunk verifies against the seal; a missing or altered chunk is reported, never shown.
- Relay policy (test relay only): KIND 5 against a block refused; an
expirationblock refused; a block by an unknown key refused; whether an id deleted by KIND 5 can be re-inserted. - Drill: a deliberately broken relay copy makes the daily drill fail and every member's app shows it.
- Projects and reserve: a project passes only with no "against" from any member and at least
project_approvalsHeart "for" votes, the proposer's and the recipient's "for" not counted; one "against" as the newest vote makes it fall; the newest vote counts, and a repeated choice isrepeated; a vote at or after the vote end is refusedvote_ended; a duration outsidevote_min_s…vote_max_sis refusednot_allowed; a passed project opens at the end of the entry after which its consent is given (a step raise: once it fits underbuilt), and lapses at its open lapse if it has not opened; a decline or withdrawal during the vote ends the project and its votes; the reserve moves to a newly opened project up to its amount in the same block; inflow stops at the amount and the surplus goes on (to the next project or the reserve); after every entry except agraventry booked as a visit the reserve is above 0 only if no receiving project has room; one receipt makes exactly onestepmove (into the reserve); a full project is paid once and its recipient'sgrow/settledcascade ends;drain()runs at the end of every entry, every morninggraventry and every entry with visits included, and agivethat exactly fills a named project gets it paid [clarification, 17 Oct 2026 (D1 review)]; a contribution from the wave (above the plus) and a contribution to a project that is not receiving are refused;project_returnmoves a receiving project's balance to the reserve after aproject_closeandclose_notice_s, and for a receiving project not full by its receive lapse [8e]; a full step-raise project moves its wallet intoworld-step, raises the step by its amount and books no wave growth [8j]; the sum is 0 after every move; nobody can sign for a project wallet, the reserve,worldorworld-step; the project wallet address matches the test vector (roleproject|<id>before the circle id); and [clarification, 17 Oct 2026 (D1 review)] a step raise that did not fit underbuiltwhen its vote passed opens at the end of the first entry after which it fits, and projects that become openable at the end of one entry open in publication order; duties due in the same second go in the order close return, receive lapse, open lapse, vote end, request expiry, resignation;builtcounts every account line that is not a system account or a project wallet, members who left included; aproject_closewithout k distinct Heart members still in office at the commit commits nothing; a recipient of several receiving projects who leaves or is excluded gives oneproject_returnper project, each followed by its owndrain(). - Cross-circle check after 7 days [8j]: a note B never booked up to its
expires, with B's seals covering that time, returns the hold to the payer byxundonaming B's consecutive seals as[day, digest]and the height range they cover: from the last seal whose predecessor covered only bookings before A'sxoutat− 60 s to the first seal whose boundary is later than the note'sexpires(strictly), one or two seals (an idle B still seals every day), each checked against B's blocks, and closed by B's block right after the last seal or, for a B that booked no block since, by B's next daily seal (a next seal that hides a block is refused; a missing one leaves the hold waiting), plus the real seal before them (before), checked against B's chain; an evidence that skips the seal holding the booking is refused, so is a first seal whoseprevmisdescribes the seal before it, and an evidence without the seal before is unverifiable; a note B booked givesxdone; with B's relays silent, a missing height in the span or no B seal coveringexpires, nothing is booked and A's other bookings continue; a B block without a valid quorum of B's witnesses in office at its height (for example signed only by an old, retired or stolen key) is ignored and does not stall the check, a key or witness change of B inside the span does not stop it, and two quorum-valid B blocks at one height make the evidence unusable; a later answer from B never moves the amount a second time. - Rate quotes: a note whose
to_amountdiffers from the quote's conversion, a quote not signed by the seller circle's node of that time, or anxoutbooked after the quote'sexpiresis refused publicly (bad_quote,stale_quote); the payer's circle refuses an expired quote at intake and holds nothing;xdoneis booked only for axinwith the same note id and exactlyto_amount; a valid quote is honoured exactly; the conversion test vectors ofdocs/valute-in-tecaji.md(EUR→USD, USD→EUR, USD→GBP, a price in the receiver's currency,to_amount = 0) give the same cents in the node, the witness and the verifier. - Circle id and circle key [C5]: the circle id equals the
foundact's id, rebuilt with["c", ""](test_vectors.circle_id: scope16 and the head offset); the system addresses matchtest_vectors.system_addresses; a 30910 by any key other than the circle key that the ledger's mirror at itsmirror_ofnames (at the height of a key change already the new key), or by the old key at or above acircle_key_change, never counts; acircle_key_changewhosepopdoes not verify is refused (bad_template), also when thepopwas made for an older act (anothercreated_at); arolesentry that changes the circle key withoutcircle_key_change, or to another key than the one it names, is refused, and so is a secondrolesentry in one block; the seal whoseh_tois the height of a key change names the new key. - Circle parameters [E-1]: a
foundact orparam_proposewith a value outside its range,vote_min_s>vote_max_sorvote_max_s≥open_lapse_sisbad_template; a secondparam_proposewhile one is open isrepeated; the notice end is the k-th act'sat+ max(change_notice_s, the old value of every changed parameter in seconds);params_effectivecomes at the notice end, first in its block, and the block is under the new parameters from it; a change with fewer than k of its signers in office at its notice end is void; a running deadline keeps the due time recorded when it started (a project opened under a 90-day receive lapse keeps 90 days when the parameter later says 30); TTL checks use the parameters in force at the booking; a restore from the circle's relays alone gives the same parameters (thefoundact, theparam_proposeacts and theg3|param:<name>lines); across circles a mismatch innote_ttl_sorquote_ttl_sends only in a refusal andxundo, and a shortxcheck_snever returns early; no 43920 is read or accepted. - Round 5: membership, the reference and the Heart [Decided 23 Oct 2026, E-2 … E-9; the tests: Proposal]: an exclusion takes effect at the act that reaches max(k, 3) Heart members [E-10], never counts the excluded key, first takes a Heart seat (a
rolesentry, or a wait for the next block when the block'srolesentry is taken) and ends the key's projects as at a leave; an excluded line pays, gives, votes and proposes nothing, receives only a settlement, is visited by every morning and mayxoutonly its plus; an excluded key'sjoinbefore the end isnot_allowed, after it goes to the Heart, never to the waiting list, andmember_readmitadmits it only with a free place; a member'sleavebooksmember_leaveand its leaving line; the reference comes when its conditions hold, at the leave or later (a settlement to 0, the last OWN process closed), and never while in minus, nor with an open OWN process and a minus; an open OWN process blocks the reference also without a debt [E-9 (a)]; the step transfer (reference_grantwithgrantandreference_out,reference_returnwithreference_inandclose_wave) keeps both sums 0, rounds G up across currencies so thatto_amount≥ W, returns G to the reserve byxundowhen the old circle refuses it, never asnot_booked, andgrant_revokethen takes the unused part of the granted wave back to origin [E-11], a join with a step waits until an earlier move out of the circle is settled [E-11], a Heart member who leaves loses the seat [E-11], and a grant that does not fit under the step waits on the waiting list; a settlement never takes a line above 0 and moves nogroworsettled; ajoinfrom another circle without a valid reference isnot_allowed, and with one itsmember_joinnamesref,srcandg; a key with no member home needs none; an account close waits for a pendinggraventry, a held leg, a plus and a short reserve, then movesclose_coverandclose_wave, sets wave, cap, debt and carry to 0, and keeps origin = −start − granted + returned and Σ waves = grown + granted − returned; a closed key that joins again starts at 0;own_openneeds one member andown_closeone Heart member [E-10]; the morning visits every line that is not closed, also through the block builder [review of round 5]; invitations are one-time and expire afterinvite_ttl_s;invite_onlyrefuses ajoinwithout an invitation; the waiting list admits in booking order while a place is free; a motion passes and falls like a project and moves no money; a witness change is refused while a Heart member in office has "against"; the examples rebuild byte for byte; at least 15 planted bugs in the new rules (scripts/plant-def5-bugs.ts) are each caught; the random workloads (test:long) include votes, motions, exclusions, readmissions, closes, settlements, references, OWN processes, invitations, the waiting list and parameter changes. - Checks from the D4 review [clarification, 17 Oct 2026 (D4 review); the commit window, the
projectfield and the mirror: proposal (D4 review, 17 Oct 2026)]: catch-up after an outage (the missed mornings booked complete, in date order, before any other entry, one morning open at a time, each morning's cut-offseqthe lastseqbooked before it opened, a later missed morning reading the earlier ones'gravresults and drains, no payment, act,rolesentry, refusal or duty while two or more mornings are pending, and payments again as soon as only one is; §7.4); theo3|changeline (its eleven fields, the turn tonoticeat the act with which k Heart members in office are reached, the commit window and the lapse,repeatedfor a further endorsement by a listed Heart member and for a second close of one project, a close line ended by its project's final status; §3.8); the seal day chain (the first seal is that of the first day whose boundary is later than block 1'sat, then day + 1 and n + 1 without a gap; §3.6); a block'satspan checked exactly againstw_max_swhen the validator has the parameter lines (Block arithmetic, above); and the mirror a change of k Heart members gives (the mirror in office with exactly that change and nothing else;docs/upravljanje-kroga.md). - Checks from the D4 review, round 3 [clarification, 17 Oct 2026 (D4 review, round 3); the new lines, fields and acts and the resignation duty: proposal (D4 review, round 3, 17 Oct 2026)]: the restore proof (circle B and circle A each restored from a seal of the examples; since round 5, A's seal of 16 Oct covers its blocks 1–4, each reading exactly what §8.1 step 5 lists, rebuild the tail byte for byte and reach the same judgement as a replay from block 1); the new governance acts (
steward_add,steward_remove,stewards_required_set,signer_removeandsigner_replace, with the accept acts that set a change'sconsent;docs/upravljanje-kroga.md); the resignation duty (therolesentry of asteward_resignorsigner_resignfalls duechange_notice_s(72 h by default) after its booking, due resignations go one per block, the earliest notice end first, and a block that leaves a due one out is refused). - The D3 review [clarification, 19 Oct 2026 (D3 review); the new rules: proposal (D3 review, 19 Oct 2026)]: the block library and the independent verifier agreed on about 1.3 million generated entries except two points these rules settle: a
giveor any act naming a project that has ended isnot_found, and aproject_proposewhose recipient is not a member when it is booked isnot_member. Further: a proposer who is the recipient has consented; aproject_returnfrom an empty wallet books no move; a note's visits are booked before it is judged and stay booked when it is refused; the restorer's list (§8.1 steps 2 and 5: the mandatory governance chain, the block before the first block after the boundary, the catch-up blocks after an outage, and the 43920 records of everything still running, which are no longer read since E-1); a block's firstatis its first entry's; a morning block skips accounts already visited; a due resignation in a block of its own, void ones dropped first; afoundact that breaks the bound on k isbad_template; a second resignation of one role by the same key isrepeated;signer_replacekeeps the quorum; asteward_acceptnaming a nomination had no effect (nominations are gone since 23 Oct 2026, E-2); a node checks its time-zone data before it signs. - No payouts, no deposits: no act, entry, line or setting for payouts or deposits exists;
held_outandpaid_inare absent from every line and from the state hash; there is nomainaccount and no custodian. - No secret leaves: no event, log line or statement contains a private key, a WIF, a session token or an account number; no ledger event contains a name (only HEX keys); HEX only, never npub.
13. Decided and open points that touch this specification#
Decided 16 Oct 2026 (the project owner's answers): A1 finality (quorum and three relays) · A2 circle relays and the new reading of "only from 38888" · A3 witnesses, at most one per operator, single-witness bootstrap without a money cap · A4 stewards (names; now the Circle Heart, E-2) · A5 keys only in the ledger, names only in KIND 0 and 30916, no legal-review gate, no 43925 · A6 no bank data, no payouts (no payout acts, pout, held_out, reserve statement or payout breaker) · A7 rate quotes by the seller circle (43919), the payer signs both amounts · A8 keyless project wallets and keyless reserve instead of Common Good · A9 founding without personal approval (P3 dropped). Kept from 10/15 Oct: 72 h notice (now the default shortest vote, E-1 and E-5), every objection answered before approval (gone with the objections, E-5), the proposer never decides.
Decided 16 Oct 2026, afternoon (the project owner's answers to the open points; same source file, section "Odgovori na odprte točke"): 4a four stewards (now Heart members, E-2) in the live circle, the founder and three other Heart members; a project needs three of four · 6a no money deposits in BSA ("a different system altogether"): no deposit acts, no dep or corr, no custodian, no paid_in, no main account, no question 12, no deposit alarm, no 6b; the wave grows only with what a member receives · 8a a project pays its recipient once the whole amount is collected · 8b inflow to projects in order, oldest first; no project limits for now · 8c an objection within 72 h of publication; the project stays stopped until the objector withdraws; no effect once receiving (replaced on 23 Oct 2026 by E-5) · 8e the Heart closes a receiving project with 72 h notice (a default since E-1), the money goes to the reserve; a project that does not fill in 90 days lapses · 8f a project payment does not use up community money; the brake is the Heart's approval (since E-5, the vote); sum 0 · 8i world and world-step keyless (main also confirmed, then gone with 6a) · start source: the ECB daily rate, its date shown, quotes valid 10 minutes · 8j a hanging cross-circle payment: no refund payer; after 7 days the payer's circle reads the receiver circle's sealed ledger: not booked → xundo naming the receiver's seals, booked → xdone, unreadable → wait; the 7-day refund by public decision and xrefund are dropped; a step raise is a project, and the step rises by its amount when it is full · 8d follows from A8: with no receiving project the inflow stays in the reserve.
Decided 16 Oct 2026, later the same day (the project owner's answer to the new open point 6c, »6c, da«; same source file, section "Odgovor na 6c"): 6c the first money in a new circle is one start of 1,000 in the circle's currency for the reserve at founding, booked in block 1 as the rule entry start from the keyless origin (−100000 from then on; that it never moves again is a proposal), sum 0; by 8f it keeps coming back; no starting wave per member, no bridge from Lana; the names start and origin and the entry shape are a proposal for 0.3.0 (plan step C1); the live circle gets the same start at its genesis (E6; proposal: 1,000 EUR) (§3.9).
Decided 17 Oct 2026 (the project owner's answers to phase C, »1. DA - parametre shrani v posebni KIND … · 2. DA · 3. DA · 4. DA · … · 6. DA«, and after the explanation of points 5 and 1, »7 Da, Lahko narediš vse skupaj v fazi D …«; same source file, sections "Odgovori na fazo C" and "Odgovor na pojasnilo točk 5 in 1"): C1 the time values and the number of project approvals are world rule values in one world-wide record, 43920 BSA Rules, signed by the key that publishes the definitions on lananostr.site; a change counts from its effective, at least 7 days after publication, never retroactively; every block and seal names the version it used; several signatures later (for example 3 of 5) (replaced on 23 Oct 2026 by E-1: §3.1 rule 11) · C2 payments never pause for the morning; visit before touch (§7.4) · C3 refusals of keys that are neither members nor applicants are answered, never booked; an act is valid 7 days (ACT_TTL_S); at most 20 refusals of one key a day are booked (REJ_PER_AUTHOR_PER_DAY) (§3.5; both are circle parameters since E-1: act_ttl_s, rej_per_author_per_day) · C4 no Heart member rejects a project alone: no project_reject and no status rejected; an objection stopped a project (gone since E-5) (§3.9) · C5 the circle's name is its circle id, the id of the found act the founder signs; the circle key can be replaced by k Heart members (three of four in the live circle) with 72 h of public notice (a default since E-1), booked by the witnesses (§3.1 rule 8, §3.4) · C6 the first-seen rule ("the first ledger stands") goes into the letter to the Lana relay owner (phase G); with C5 it is only extra safety (§9.2) · C7 tz, morning hour and tzdata are written at founding and do not change in 0.3.0 (§7.2).
Decided 17 Oct 2026, evening (the project owner's answers to three questions after phase D, »vsi da« to the proposal »1A, 2A, 3A«; same source file, section "Odgovori na tri vprašanja po fazi D"): 1A for now only the rules authority's one key (the key that publishes the definitions) signs 43920; several signatures (for example 3 of 5) come before the first circle the project owner does not run joins (for example the first circle from another ecosystem); who the signers are stays open; the tension with principle 3 is thereby limited in time and said openly (dropped on 23 Oct 2026 with E-1) · 2A the tzdata part of C7: the version is pinned at founding with tz and the morning hour, and every witness computes the boundaries with it, never with a newer one of its own; in 0.3.0 it never changes, not even by the Circle Heart; how the Heart could later move a circle to a newer version is for a later definitions version (§3.5, §7.2) · 3A the transition (transition_days, 60 days) runs per account from its own first receipt (first_receipt_day), as the definitions say; today's app counts from the circle's start (the live circle has no payments), and the switch to the 0.3.0 gravity applies the per-account rule (§7.3).
Decided 23 Oct 2026 (the project owner's answers before phase E; same source file, section "Odgovori pred fazo E" with its subsections "Dopolnitev" and "Referenca"): E-1 the time values and limits are circle parameters, which the Circle Heart changes within the bounds of the definitions; 43920 and the rules authority are retired (the number reserved), which replaces C1 and drops 1A; fixed for every circle: a project needs at least 3 Heart "for" votes and no "against", and the money and gravity computation; 72 h is fixed nowhere (C5's fixed notice becomes change_notice_s) (§3.1 rule 11) · E-2 the stewards are the Circle Heart (one person: a Heart member); members never vote on the Heart (steward_nominate and steward_vote are gone); the Heart adds and removes Heart members (§2, §3.4) · E-3 the Heart excludes any member by three votes (E-10: the larger of k and 3), at once, with a public reason; an exclusion lasts 3 months; the Heart readmits, membership only; an excluded line is frozen, gravity visits its plus, and it may take its plus to another circle; the Heart closes old accounts: a minus is covered by the reserve only when the member has died, a plus waits for gravity, and at 0 the wave goes to 0 and the reserve returns the same amount to origin (confirmed in the supplement) (§3.11) · E-4 the Heart leads and oversees OWN processes; only a decision reaches the ledger (§3.11) · E-5 consensus votes ("all for, or it falls"): no "against" from any member and at least 3 Heart "for"; the proposer sets the duration at publication, at least 72 h by default (confirmed); an "against" carries a short public reason, the newest vote counts; a proposal without money is a public decision; replaces 8c and the approvals (§3.9) · E-6 joining: open, by invitation only, or a maximum with a waiting list; the first on the list is admitted by rule; the Heart decides about an excluded person (§3.11) · E-7 witnesses are computers drawn by lot among the circles' computers (the direction for phase I); until then one witness, the circle's own computer, labelled; the Heart's vote (three "for", none "against") only for exceptions (§2, §3.4) · E-8 only a member of an existing circle founds a circle; every circle grows from the first; one circle per founder; one circle at a time, per key through the member home; replaces "at most three circles per founder" (§3.11) · E-9 the reference (43921): issued by itself after "I want to leave" when not in minus; a debt must be settled, and anyone may settle it, up to 0; an open OWN process with a minus: no reference; no move without a reference: a new circle admits a person from another circle only with one (a rule for every circle) (§3.7, §3.11) · D8 the acts for Heart and witness changes are accepted, with E-7 for witnesses and E-1 for the notice · E-9 (a) an open OWN process blocks the reference also without a debt · E-9 (b) the step moves with the person: the new circle opens the same wave from its origin and pays the same amount to the old circle's community, which closes the account and returns the wave to its origin; "it cancels out" (§3.11) · E-11 (»1a,2a in 3c«) a grant's hold ends only by the old circle's word, a silent old circle means waiting; on a motion the proposer's own "for" counts, on a project the recipient never counts for itself; gravity never stronger than today's and tightened only with at least 30 days of notice; a Heart member who leaves loses the seat; no join with a step while an earlier move out is unsettled; a reference is valid once (grant_revoke) (§3.4, §3.9, §3.11, §7) · E-10 (answers 1B, 2A, 3A, 4A) an exclusion, a readmission, an account close and the Heart's witness exceptions always need at least three Heart members (the larger of k and 3; a Heart of fewer than three cannot do them), the Heart's other changes and the parameters k; any member opens an OWN process, one Heart member closes it; the wave a reference brings counts against the new circle's step outward; the longest vote 14 days by default; the Heart may close anyone's account with a public reason and cover its minus (§3.4, §3.9, §3.11).
Still open (proposals in §3.1, §3.4, §3.5, §3.7, §3.9, §3.11, §4.5 and §2): Open 3a (seven witnesses above about 10,000 members; may one owner then hold two) · Open 8g (contributions only from the plus; unnamed to the reserve) · Open 8h (the recipient is a member). Proposals that come with the afternoon answers and were not confirmed: k = 3 of 4 for other Heart acts and for closing a project · world-step as the recipient of a step-raise project · the recipient's consent as today · more ways to return a receiving project's money (recipient declines or leaves, proposer withdraws, recipient no longer a member at payment) · the 90 days counted from opening · the 30-day lapse before opening · the step lowering, and the formula and check of the built limit · the daily retry and the 60 s margin of the 7-day check · rate_source_set and rate_stale_alert 120 h · the circle key signs only the 30910 mirror and, once, the binding of the found act in block 1. Proposals that come with C5 (17 Oct 2026): the circle key of the newest mirror at or below the seal's last block in every seal and 30915 head · at most one roles entry per block · the proof of possession of a new circle key, bound to the act's created_at, and that the circle key is never the founder's, a witness's or a Heart member's key, nor the key already in office · the new circle key in office from the next block · the tag shapes (c tags, circle_key_change). Proposals that come with C6, C7 and 8j (17 Oct 2026): root relays keep every circle's found act and pin a circle id only with it (or, for a circle configured on the relay, when its configured circle key signed the record), after every plugin accepted the record, and a retired key counts only in its own role (§9.2) · the 8j evidence counts a partner block only with a valid quorum of the partner's witnesses in office at its height (§4.5) · a block's at span is at most w_max_s, and the morning header's tzdata is the one pinned at founding (§3.5). Proposal that comes with 2A: a witness without the pinned tzdata signs no morning block and no seal; how it keeps that version is its own implementation (§3.5). The notice of Heart changes (witnesses, relays, Heart members, recovery, the circle key) was a fixed 72 h [Decided 17 Oct 2026, C5]; since 23 Oct 2026 it is the circle parameter change_notice_s, 72 h by default [Decided 23 Oct 2026, E-1]. Open question: whether a root relay accepts the 30915 head of a circle it is not configured for (checked against the witnesses of its pinned record); the prepared write policy accepts heads only of configured circles (§9.2). Dropped with E-1 (23 Oct 2026): the proposals that came with C1 (the bounds of the rule values and the shape of 43920, rules_adopt, a witness's first-seen time of a 43920) and the open question of who signs the world rules. Proposals of round 5 (23 Oct 2026): the bounds of the circle parameters, and vote_max_s (14 days) (§3.1 rule 11) · the notice of a parameter change, max(change_notice_s, the old value of every changed time), one change open at a time, void without k signers in office at its end · TTL checks with the parameters in force at the booking; the stricter value during a notice and the smaller one across circles · each circle applies its own values across circles (§4.5) · the vote: the roles at the vote end, the same rule for a motion, consent kept, vote_ended, the place of vote_end among the duties (§3.9, §7.4) · the exclusion: a required public reason, exclusion_s 90 days, the projects ended as at a leave, an optional OWN case id · the reference: its mechanics (o3|leaving, a later issue), the 43921 tags (joined, left, "took part" = the projects that paid the person), the new circle's check and republication, no reference for a key that was never a member, root relays keeping member homes (§3.7, §3.11) · the settlement's shape (no grow, no settled), settling during an exclusion, a left key's xout of its plus · own_open (any member, E-10) and own_close (one Heart member) · the parent and founder-reference tags, the root relays' first found act per founder, the founder's membership check (phase G) · invitations valid 7 days and once, the applicant's withdrawal, max_members 0 = no limit · the technical names steward_* and the English names "Circle Heart" and "Heart member". Proposals of E-9 (b): the bookings of the step transfer (reference_grant, reference_return, the moves grant, reference_out, reference_in), the rounding across currencies, an account close waiting while a leg is held. Round 5's open questions were answered by E-10 (23 Oct 2026: at least three Heart members; the step brake kept; the longest vote 14 days; any account may be closed).
Still open questions: Q10 (the trust anchor, the circle id with the genesis digest: decided, C5 and C6; what the link and QR carry: proposal), 38888 as directory only · Q11 guardians · Q13 circle size cap · Q14 operators per circle, the four Lana relays as one operator, the bootstrap tension (no finality until the Lana relays apply §9.2); decision 2 says ≥ 3 operators, so the bootstrap ≥ 2 is a temporary departure the project owner must approve (proposal: three operators at the latest when the circle has four witnesses) · Q15 who pays relays (now through a project) · Q16 KIND 0 and homes at scale · Q17 sending on after three relays (changes the 14 Sep "wait for all" rule) · Q18 the new letter to the Lana relay owner (replaces P6; carries the borrowed-space size and the first-seen rule [C6]) · Q19 removal from hot relays · Q20 definitions version pinned per circle · Q21 votes (formerly objections) signed by key and public, purpose public for ever · Q23 witness votes · Q24 project images off the relays · P2 where the circle key lives · P7 one yes per definitions version and per kind. Q12 (a deposit limit per signature) is moot: there are no deposits [6a].
Clarifications of 17 Oct 2026 (D1 review) [no decision needed: each follows from existing text or decisions]: they need no decision from the project owner; two of them make "never retroactive" (C1, now E-1) concrete: a project opens without an act once its last condition holds (§3.9), and a running deadline keeps the length in force when it started (§3.1 rule 11, §3.8). The others: drain() at the end of every entry, and after each project_return (§3.9); the order of project duties due in the same second (§7.4); built over every account line that is not a system account or a project wallet, members who left included (§3.6, §3.9); an approval was refused unless booked after the notice, with no standing objection, every objection answered and the recipient's consent given (approvals and objections are gone since E-5) (§3.9); no block carries morning D+1's header while a grav entry of morning D is pending (§7.4); only money entries touch an account for visit before touch (§7.4); a project_close commits only with k Heart members in office at the commit (§3.9).