You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ots: isOtsCommit tristate (closes the strip-wire OTS hole)
Implements the design from ORDPOOL-FLAGS-ARCHITECTURE.md §4. The OTS
bit is the only indexer-derived ordpool flag; the frontend cannot
recompute it from witness bytes. Strip wire surfaces (REST /api/tx/:txid,
WS track-tx) were silently dropping it. This commit fills the hole
without touching the upstream wire shapes.
Backend:
- New optional field on TransactionExtended: isOtsCommit?: boolean | null.
null = 'not computed' (bulk surfaces leave it absent; OTS bit travels
in tx.flags there). true/false = server-attached answer from
ordpoolOtsTxidSet.has(txid).
- bitcoin.routes.ts:getTransaction attaches isOtsCommit before
res.json(transaction). O(1) Set.has() lookup.
- websocket-handler.ts track-tx attaches isOtsCommit on both
$getMempoolTransactionExtended call sites (esplora + bitcoind backends).
- New lazy endpoint: GET /api/v1/ordpool/ots/is-commit/:txid ->
{ result: boolean }. Validates txid via isValidTxid, Cache-Control:
public, max-age=60 (matches OTS poller cycle and the false-monotonicity
window).
Frontend:
- New OtsKnowledgeService in services/ordinals/. Three-source decision:
server-attached tristate -> OP_RETURN fast path (no OP_RETURN ->
definitely false, no fetch) -> lazy backend probe (cached).
- Cache semantics: true cached forever (monotonic), false cached 60s
(poller can later flip to true). Probe failures degrade to false
WITHOUT caching the failure (so retries work).
- transaction.utils.ts::getTransactionFlags gains an optional
otsKnowledge parameter, applies the OTS bit via the three-source
logic before returning. When undefined (utility-only callers), still
respects the server-attached tristate.
- 3 component call sites updated to inject + pass the service:
transaction.component, transaction-raw.component, tracker.component.
Regression tests:
- 5 backend tests for the new lazy endpoint (positive, negative,
Cache-Control header, malformed-txid rejection, wrong-length
rejection). Mocks ordpoolOtsTxidSet (the IO boundary).
- 11 frontend tests for OtsKnowledgeService covering every branch of
the three-source logic + cache semantics + graceful degradation
under probe failure.
Test count delta: backend 299 -> 304, frontend 173 -> 184.
AOT prod build clean.
"note": "Floor for .github/workflows/test-count-floor-backend.yml. Count of passing tests from the single jest config (node). Only an ordpool core maintainer is authorised to lower this number; every other change that reduces test count is treated as an accident and rejected. To raise the floor after legitimately adding tests, bump this value and commit. See also workspace CLAUDE.md, HARD RULE 'Never delete a passing test without explicit permission'."
"note": "Floor for .github/workflows/test-count-floor-frontend.yml. Count of passing tests from the single jest config (jsdom). Only an ordpool core maintainer is authorised to lower this number; every other change that reduces test count is treated as an accident and rejected. To raise the floor after legitimately adding tests, bump this value and commit. See also workspace CLAUDE.md, HARD RULE 'Never delete a passing test without explicit permission'."
0 commit comments