Survive oversized Electrum replies and ignore dust deposits (B-75, ELC-20, DEP-01, DAT-10)

A reply line over asyncio's default 64 KiB StreamReader limit raised out of
_read_loop and closed the only connection; the pool address's get_history passes
that after ~800 transactions, and dust sent to any public address does it on
purpose.

- ElectrumClient opens the stream with a 16 MiB limit and frames lines itself:
  an oversized line is discarded up to its newline, a non-JSON line is dropped,
  and the request whose id is readable in the first/last 256 bytes fails at once;
  the connection stays up either way.
- Coins below DUST_LIMIT_SATS are never offered as credit candidates, never
  credited, and select_utxos never selects them.
- Spec (ELC-20, DEP-01, DAT-10, ARC), storico, BUGS.md and test counts updated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-14 12:14:12 +02:00
1 parent b424f670c5
commit daec4749c2
15 files changed
+245 -49

No files matched your search

-13
View File
@@ -137,19 +137,6 @@ the intermediate headers (`blockchain.block.headers`) and validate the chain; on
linkage mismatch walk back up to 10 headers to find the fork point and follow the
reorg instead of ending the session (reorg handling: B-85).
### B-75 — Replies over 64 KiB kill the connection; the pool's history grows past that
`asyncio.open_connection` uses the default 64 KiB `StreamReader` limit; a longer
reply line raises `ValueError` in `_read_loop` and closes the connection. The
confirmation poller and the reconciler fetch the pool address's full history every
cycle, which passes 64 KiB after ~800 transactions: from then on every 10s poll
drops the only connection and payouts never confirm. A few hundred dust outputs sent
to any public address trigger the same thing on purpose.
Fix: 16 MiB reader limit; an oversized or malformed reply is a request error, not a
dead connection; UTXOs below `DUST_LIMIT_SATS` are ignored for crediting and
selection; per-round pool addresses (B-80) keep every address's history bounded.
### B-76 — An ambiguous broadcast is rolled back as if refused
`place_bet`/`request_withdrawal` release everything on *any* broadcast exception,