Skip to content

Commit b78f663

Browse files
authored
Merge pull request #14 from buffrr/perf-prover-stats-updates
Perf prover stats updates
2 parents c8a8ec3 + dbedcdc commit b78f663

20 files changed

Lines changed: 1684 additions & 241 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ subs-core = { path = "core" }
1212
libveritas = { version = "=0.3.3", features = ["elf"] }
1313
libveritas_zk = "=0.1.1"
1414
libveritas_testutil = "=0.3.3"
15-
spacedb = "0.1.3"
15+
# hash-idx builds a sidecar index that speeds up .prove(); it is not a default
16+
# feature and pulls in rusqlite, which we already depend on.
17+
spacedb = { version = "0.1.3", features = ["hash-idx"] }
1618
relay = { git = "https://github.com/spacesprotocol/certrelay.git" }
1719
fabric = { package = "fabric-resolver", version = "=0.2.7" }
1820

REGISTRY.md

Lines changed: 98 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -11,65 +11,50 @@ work.
1111
(yours) (private)
1212
```
1313

14-
**subs always initiates.** The registry never calls subs, never needs to reach
15-
it, and never needs a public address for it. Your registry is an HTTP server
16-
that subs polls.
14+
**subs always initiates.** The registry never calls subs and never needs a
15+
public address for it. Your registry is an HTTP server that subs polls.
1716

1817
## Scope
1918

20-
This document covers **only** the four endpoints subs calls. Everything else
21-
about your registry is yours to decide and subs neither sees nor cares about:
19+
This document covers **only** the four endpoints subs calls. Everything else is
20+
yours to decide and subs neither sees nor cares about: how requests get in, how
21+
you authenticate or bill the people making them, how you store or display them.
2222

23-
- how handle requests get in — a public form, a paid checkout, an admin panel
24-
- how you authenticate, bill, or rate-limit the people making requests
25-
- how you store registrations, notify users, or expose status to them
26-
27-
Implement the four endpoints below and subs will work with it.
2823
[`examples/registry-server`](examples/registry-server) is a working
29-
implementation you can run and read; the intake it happens to ship is
30-
illustrative, not part of this contract.
24+
implementation you can run and read.
3125

3226
---
3327

3428
## The cycle
3529

36-
Each pass, subs:
30+
Each pass, per space, subs:
3731

3832
1. `GET /pending` — collect handles awaiting registration
39-
2. stages them locally (validating and de-duplicating)
40-
3. `POST /ack` — report which ones it took
33+
2. stages them locally, validating and de-duplicating
34+
3. `POST /ack` — report what it took
4135
4. publishes certificates to the relay network
4236

43-
Steps 1–3 are what your registry participates in. Step 4 is internal to subs.
44-
45-
Later, when a batch is committed on-chain, subs can call
46-
[`POST /committed`](#post-committed) — that one is **not** automatic.
37+
Steps 1–3 involve your registry; step 4 is internal to subs. `POST /committed`
38+
fires separately and is **not** automatic.
4739

4840
---
4941

5042
## Authentication
5143

52-
All four endpoints are authenticated with a single shared bearer token:
44+
All four endpoints take a single shared bearer token:
5345

5446
```
5547
Authorization: Bearer <token>
5648
```
5749

5850
Configure it in subs under **Settings → Registry Server → Auth Token**. Reject
59-
anything without a valid token with **`401`**. subs surfaces `401` and `403`
60-
distinctly from other failures, so an operator sees "registry rejected the auth
61-
token" rather than a generic upstream error.
62-
63-
This token grants access to your work queue — reading pending handles and
64-
marking them staged or committed. If other systems of yours write to the
65-
registry, give them their own credentials; there's no reason for them to share
66-
the one subs holds.
51+
anything without a valid token with **`401`**; subs surfaces `401`/`403`
52+
distinctly, so an operator sees "registry rejected the auth token" rather than a
53+
generic upstream error.
6754

68-
**`/health` is authenticated too**, deliberately. subs' **Test** button probes
69-
it, so a successful test proves both reachability *and* that the token is
70-
accepted — rather than showing green for a registry that will reject every
71-
request after it. If you need an open liveness probe for a load balancer,
72-
expose it on a path subs doesn't use.
55+
**`/health` is authenticated too.** subs' **Test** button probes it, so a
56+
successful test proves both reachability and that the token works. If you need
57+
an open liveness probe, expose it on a path subs doesn't use.
7358

7459
---
7560

@@ -81,7 +66,24 @@ Return `200` with any body.
8166

8267
### `GET /pending`
8368

84-
Return handles waiting to be staged.
69+
Return handles waiting to be staged. subs asks about **one space per request**:
70+
71+
```
72+
GET /pending?space=@example
73+
GET /pending?space=%233438-1-0
74+
```
75+
76+
**Return only handles in that space.** A handle for a space this operator cannot
77+
act on can never be staged, so it is never acked — serve it and it comes back
78+
every cycle, forever.
79+
80+
The value is a canonical space label, percent-encoded; numeric spaces look like
81+
`#3438-1-0`, so `#` arrives as `%23`.
82+
83+
Scope includes spaces **delegated to the operator's wallet but not yet
84+
started** — staging the first handle adopts such a space automatically. Scope is
85+
recomputed every cycle, so a new delegation takes effect without restarting
86+
subs.
8587

8688
```json
8789
{
@@ -99,31 +101,59 @@ Return handles waiting to be staged.
99101

100102
Return `{"handles": []}` when there's nothing pending — not `404`.
101103

102-
**Any non-2xx aborts the entire sync**, including the ack step, so nothing is
103-
staged that pass. subs retries on the next cycle. The request times out after
104-
10 seconds.
104+
**Any non-2xx aborts that space's sync**, including its ack, so nothing is
105+
staged for it that pass. subs retries next cycle. The request times out after 10
106+
seconds.
105107

106108
Returning already-staged handles is harmless — subs de-duplicates — but
107109
filtering them keeps payloads small.
108110

111+
**Pagination** is optional: return the full set for the space, or cap it and let
112+
the next cycle collect the rest. subs stages an entire response in one pass.
113+
Capping per space starves nothing, since each request covers one space.
114+
109115
### `POST /ack`
110116

111-
Called after subs stages the handles it pulled.
117+
Called once subs has decided each handle's fate.
112118

113119
```json
114-
{ "handles": ["alice@example", "bob@example"] }
120+
{
121+
"handles": [
122+
{ "handle": "alice@example", "outcome": "staged" },
123+
{ "handle": "bob@example", "outcome": "already_committed_different_spk" }
124+
]
125+
}
115126
```
116127

117128
Move these out of your pending set. Return `2xx`; the body is ignored.
118129

119-
**This must be idempotent.** subs acks every handle it pulled, including ones
120-
already staged locally, and re-acks after a failure. Re-acking an
121-
already-acked handle must succeed, not error.
130+
**Every outcome is terminal** — a handle appears here only once settled, and
131+
will not be offered again.
132+
133+
| Outcome | Meaning | What to tell the user |
134+
|---|---|---|
135+
| `staged` | Accepted; awaiting commitment | In progress |
136+
| `already_staged_same_spk` | Already pending under the same owner | In progress — a duplicate request |
137+
| `already_committed_same_spk` | Already registered to this owner | Already theirs |
138+
| `already_staged_different_spk` | Another owner has it pending | **Cannot be fulfilled** |
139+
| `already_committed_different_spk` | Another owner already holds it | **Cannot be fulfilled** |
140+
| `invalid` | Not a parseable `name@space` handle | **Cannot be fulfilled** |
141+
142+
The last three can never succeed, however many times they are retried. If you
143+
take payment, they are your refund signal.
144+
145+
**This must be idempotent.** If the ack fails, subs logs it and continues —
146+
staging already happened on its side — so the next cycle re-pulls, re-stages (a
147+
no-op) and re-acks. The flow self-heals, but only if re-acking succeeds rather
148+
than errors.
122149

123-
If the ack fails, subs logs it and continues — staging already succeeded on its
124-
side. Your registry still has those handles pending, so the next cycle
125-
re-pulls, re-stages (a no-op), and re-acks. **The flow self-heals, but only if
126-
`/ack` is idempotent.**
150+
#### Retryable failures
151+
152+
Some handles are neither staged nor settled: subs could not reach a decision,
153+
typically because the space could not be loaded or the wallet could not operate
154+
it. These are **deliberately absent** from the ack body. They stay in
155+
`/pending`, and a later cycle picks them up once the operator's configuration is
156+
fixed. Acking them would mark them done and lose them.
127157

128158
### `POST /committed`
129159

@@ -134,47 +164,30 @@ re-pulls, re-stages (a no-op), and re-acks. **The flow self-heals, but only if
134164
Mark these committed and record the root. Return `2xx`.
135165

136166
**This is not automatic.** It fires only when someone calls
137-
`POST /registry/notify` on subs with a `space` and `root`; nothing triggers it
138-
on a timer. If you need committed state and aren't calling `/registry/notify`,
139-
track it by watching the chain or by querying the relay network for the
140-
handle's certificate.
167+
`POST /registry/notify` on subs with a `space` and `root`. If you need committed
168+
state and aren't calling that, track it by watching the chain or by querying the
169+
relay network for the handle's certificate.
141170

142171
---
143172

144173
## Delivery semantics
145174

146175
**At-least-once, never exactly-once.** A handle may be delivered more than once
147-
— an ack that fails after subs staged the handle is the ordinary case. Design
148-
so a repeat delivery is a no-op.
176+
— an ack that fails after subs staged the handle is the ordinary case. Design so
177+
a repeat delivery is a no-op.
149178

150-
**subs is the source of truth for what is registered**, not your registry.
151-
`/ack` means subs accepted a handle into staging; it does not mean the handle
152-
is committed on-chain. Only the commit notification means that.
179+
**subs is the source of truth for what is registered**, not your registry. An
180+
ack of `staged` means subs accepted the handle into staging; it does not mean
181+
the handle is committed on-chain. Only the commit notification means that.
153182

154183
---
155184

156185
## Handle validation
157186

158-
`handle` must parse as a spaces name in `name@space` form. Handles that don't
159-
parse are **skipped and never acked** — so they stay pending on your side and
160-
are re-pulled on every cycle, forever.
161-
162-
Validate at intake. A malformed handle accepted into your pending queue becomes
163-
a permanent poison entry.
164-
165-
subs may also decline to stage a well-formed handle:
166-
167-
| Reason | Meaning |
168-
|---|---|
169-
| `already staged` | Same handle and script pubkey already pending locally |
170-
| `already committed` | Already committed on-chain |
171-
| `already staged with different spk` | Conflicts with a pending entry under a different owner |
172-
| `already committed with different spk` | The handle is taken |
173-
174-
These are logged by subs and **still acked** — they're settled outcomes, not
175-
retryable failures. The last two mean the request cannot be fulfilled; your
176-
registry has no way to learn this today, so surfacing it to users requires
177-
polling on-chain state yourself.
187+
`handle` must parse as a spaces name in `name@space` form. One that doesn't is
188+
acked `invalid` and settled immediately, so it won't linger in your queue — but
189+
validate at intake anyway. A malformed handle that reaches `/pending` has
190+
already cost a round trip and, if you charged for it, a refund.
178191

179192
---
180193

@@ -191,9 +204,10 @@ In subs' **Settings → Registry Server**:
191204
With automatic sync **off**, the cycle runs only on **Sync Now** (or
192205
`POST /registry/sync`).
193206

194-
With it **on**, subs runs continuously: every 30 seconds when idle, every 5
195-
seconds while certificates remain to publish. It defaults to off because
196-
publishing broadcasts to the relay network.
207+
With it **on**, subs sleeps 2 seconds *after* each cycle finishes rather than
208+
running on a fixed schedule, so cycles never overlap and a slow one simply
209+
delays the next. It defaults to off because publishing broadcasts to the relay
210+
network.
197211

198212
---
199213

@@ -202,7 +216,11 @@ publishing broadcasts to the relay network.
202216
- [ ] `/health`, `/pending`, `/ack`, `/committed` all require the bearer token
203217
- [ ] Missing or wrong token returns `401`
204218
- [ ] `GET /pending` returns the documented shape, `{"handles": []}` when empty
205-
- [ ] `POST /ack` is idempotent and returns `2xx` for already-acked handles
219+
- [ ] `GET /pending` filters on `?space=`
220+
- [ ] `GET /pending` includes spaces delegated to the operator but not yet started
221+
- [ ] `POST /ack` reads a per-handle `outcome` and is idempotent
222+
- [ ] The `*_different_spk` and `invalid` outcomes are surfaced to the user, and refunded if paid
223+
- [ ] Handles absent from an ack stay pending — they are retryable, not settled
206224
- [ ] Handles are validated as `name@space` **at intake**
207225
- [ ] Repeat delivery of the same handle is a no-op
208-
- [ ] `POST /committed` implemented, if you need committed state
226+
- [ ] `POST /committed` implemented, if you need committed state

0 commit comments

Comments
 (0)