Priority: P1 — stuck-proof hygiene: reclaim machinery exists but is never invoked by the daemon.
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
Research direction
Start in src/merchant/merchant.go and read the wallet references in gonuts wallet/wallet.go for ReclaimUnspentProofs() and GetPendingMeltQuotes(); first verify the wallet locking and existing health-loop behavior. Add boot-time and periodic reconciliation with the specified reseller-ownership and error-handling safeguards. Done means interrupted-melt proofs recover after restart, spent-but-pending proofs are surfaced once, and the unit, integration, and failure-injection tests pass.
Written by the indexing model from the issue text.
Description
Priority: P1 — stuck-proof hygiene: reclaim machinery exists but is never invoked by the daemon.
Problem
gonuts has ReclaimUnspentProofs() (NUT-07 checkstate on pending proofs, reclaim unspent ones via swap) and GetPendingMeltQuotes(), but nothing in the TollGate daemon ever calls them — they're reachable only from the nutw CLI. Any proof that enters pending via a failed send, an ambiguous melt, or a reseller interrupted hand-off stays reserved indefinitely: invisible in balance, consuming wallet state, until a human runs a CLI.
Why it matters
Reserved-forever proofs are indistinguishable from lost funds to an operator and skew payout math. Every ambiguous-outcome path (G01 melt, reseller tokens-to-recover, clientd rejections #423) funnels into this state. Proactive reconciliation is the difference between self-healing and a support ticket.
Current behavior (source refs)
- gonuts
wallet/wallet.go:2196-2262—ReclaimUnspentProofs(checks state, swaps unspent back),:2258-2276GetPendingMeltQuotes. - TollGate: no call sites (
grep ReclaimUnspent src/→ only CLI in gonuts cmd). - Related behaviors that interact:
Melt's "leave proofs pending on error" (wallet.go:1114-1117),Send'sAddPendingProofs(:440-472) with reclaim only via CLI.
Desired invariant
No proof remains in a pending/reserved state longer than a bounded interval without a reconciliation attempt; pending proofs whose mint-side state is Unspent return to spendable automatically; spent-but-still-pending ones are surfaced (balance discrepancy) not silently held.
Proposed scope
- Boot-time reconciliation: after wallet load, run
ReclaimUnspentProofs+ resolveGetPendingMeltQuotes(Paid → finalize + counter fix per G01; Unpaid → release proofs; Pending → schedule re-check). - Periodic sweep (piggyback the mint-health proactive loop; interval ≈ minutes, only when pending set is non-empty — flash-cheap: the pending bucket read is in-memory).
- Observability: log + status surface for reclaimed amount and irreconcilable (spent-but-pending) proofs.
- Reseller interplay: ensure the reseller "tokens-to-recover" path is not fighting the sweeper (coordinate ownership: sweeper must skip proofs owned by an in-flight reseller transaction — add an owner marker or time threshold).
Areas / files
src/merchant/merchant.go (startup + hook into health loop), gonuts API already sufficient (verify ReclaimUnspentProofs is goroutine-safe under the wallet mutex — it calls createSwapRequest itself; audit locking).
Acceptance criteria
- Fault test: force proofs into pending (interrupted melt), restart daemon → proofs reclaimed automatically, balance restored, log line present.
- Spent-but-pending (mint says spent) → surfaced once, not looped.
Required tests
- Unit: sweep trigger conditions; reseller-ownership skip.
- Integration: interrupted-melt lane (with G01 proxy) → auto-recovery.
Failure-injection tests
- Mint unreachable during sweep → retry next interval, no crash-loop.
- Sweep racing a live payment → mutex audit proof (−race).
Compatibility
None.
Dependencies
G01 (melt quote resolution semantics) recommended first.
Out of scope
- Changing when proofs enter pending (that's each flow's own fix).
- Dominant language
- Go
- Stars
- 12
- Forks
- 14
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 217
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from OpenTollGate/tollgate-module-basic-go
-
go-battery needs an ndsctl on PATH: TestPurchaseSessionGuardHoldsThroughTheOutcomeUnknownWindow fails on bare hosts (passes with stub)Possibly taken @Amperstrand claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
OpenTollGate/tollgate-module-basic-go#726 · 2 comments ·
Maintainers usually reply within 1 day
-
rebrand-literal-gutter: uhttpd section-vocabulary check trips on a COMMENT (uhttpd.luci in 92-tollgate-admin-setup:178)Possibly taken @Amperstrand claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
OpenTollGate/tollgate-module-basic-go#723 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 20/100
OpenTollGate/tollgate-module-basic-go#768 ·
Maintainers usually reply within 1 day
-
Four drift fences for tests/contract/ (+ test.yml clean-container lane + pre-commit wiring)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 5/5 Over a week Newbie friendliness 25/100
OpenTollGate/tollgate-module-basic-go#767 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 20/100
OpenTollGate/tollgate-module-basic-go#763 ·
Maintainers usually reply within 1 day
All issues in OpenTollGate/tollgate-module-basic-go
Similar issues
-
Idle compaction monitors LIST the replica every tick when the newest destination file spans more than one TXIDPossibly taken @pishuv claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
benbjohnson/litestream#1563 ·
Maintainers usually reply within 2 days
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
agent-research agent-review-finding chore
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
jordansmall/spindrift#4922 ·
Maintainers usually reply within 1 day
-
gcsartifact: deleting a missing version returns an errorPossibly taken @ktsoator claimed this today. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 2 days
-
govulncheck
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 1 day