Resume a round in drawing from the database after an exception or a restart (B-81, RND-01, RND-15, RND-36, ARC-27, OPS-09, OPS-13, LIM-01)

`_tick` skipped `drawing`: the wait for the draw block lived only inside the
`_close_and_draw` call that entered it, so any exception (a locked database writing an
audit row, a malformed header) or a restart left the round in `drawing` for ever with the
pool inside and no new round able to open.

Since B-73 everything the draw needs is committed on entering `drawing` (encrypted secret,
ordered list with `draw_position`, `participants_hash`, `draw_height`, `draw_confirmations`),
so `_tick` now calls `_complete_draw` for a round in `drawing`. `_complete_draw` rereads that
state, is idempotent (a round no longer `drawing`, or with a winner, is left alone; the
winner write is re-checked under BEGIN IMMEDIATE) and runs inside the single scheduler loop,
so the inline call from `_close_and_draw` and the tick can never run concurrently.

Tests (test_draw_proof.py): an exception in the quorum query, then a tick, completes with the
same height, list, fingerprint and the winner the public proof recomputes; a brand-new
scheduler (restart) resumes and a second tick draws and triggers nothing again; a failure in
the very transaction that stores the winner leaves no winner and no revealed secret, and the
next tick completes. Mutation-checked: without the `_tick` branch all three fail.

Docs: the B-81 `*Stato:*`/`*Oggi:*` lines are gone (RND-01, RND-15, RND-36, ARC-27, OPS-09,
ADR-12, ADR-25), OPS-13 no longer prescribes the manual `closing` workaround, LIM-01 is
struck, storico-bug.md and BUGS.md updated. No existing test changed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-16 13:34:43 +02:00
1 parent db24287ea5
commit 473d541ab5
12 files changed
+230 -126

No files matched your search

@@ -1,6 +1,6 @@
# ADR-12 — Il server gira solo in Docker, in sviluppo come in produzione
- **Stato:** Accettata — implementazione da completare (B-81)
- **Stato:** Accettata
- **Area:** Configurazione e ambiente
- **Fonte di verità per:** la scelta di progetto descritta qui sotto; i requisiti (`PREFISSO-NN`) che la attuano stanno nei documenti di dominio, indicati nelle *Conseguenze*.
@@ -19,5 +19,3 @@ script della chiave.
*Codice:* `Dockerfile` · `docker-compose.yml` · `Caddyfile` ·
*Test:* `tests/unit/test_docs_no_bare_uvicorn.py`
*Stato:* da implementare (B-81) · *Oggi:* dopo un crash `closing` e
`paying_out` riprendono da soli, `drawing` no ([LIM-01]).
@@ -1,6 +1,6 @@
# ADR-25 — Il blocco di estrazione è fissato per altezza, è successivo alla chiusura, e si usa solo quando è confermato e corroborato
- **Stato:** Accettata — implementazione da completare (B-81)
- **Stato:** Accettata
- **Area:** Round ed estrazione
- **Fonte di verità per:** la scelta di progetto descritta qui sotto; i requisiti (`PREFISSO-NN`) che la attuano stanno nei documenti di dominio, indicati nelle *Conseguenze*.
@@ -32,6 +32,3 @@ chiusura significa «sconosciuta»: la prima altezza appresa fa da base.
*Codice:* `app/rounds/scheduler.py:RoundScheduler._wait_for_draw_block` · `app/rounds/scheduler.py:RoundScheduler._close_and_draw` · `app/rounds/scheduler.py:RoundScheduler._tick` ·
*Test:* `tests/unit/test_scheduler.py::test_a_block_relayer_cannot_choose_the_block_that_seeds_the_draw`, `tests/unit/test_scheduler.py::test_a_disagreement_asks_the_same_height_again_and_is_audited_once_per_hash`
*Stato:* da implementare (B-81) · *Oggi:* `draw_height`, `participants_hash` e le
posizioni sono salvati, ma `_tick` salta i round in `drawing`: dopo un errore
o un riavvio il round non riparte.