Moving-Bound Auctions: Early Refunds Without Oracle Key Custody (Deep Dive)
- Moving-Bound Auctions: Early Refunds Without Oracle Key Custody
- 1. The Problem
- 2. SatsAndSports’ Coordinator Proposals
- 3. The Fundamental Tension
- 4. Why You Can’t Get Early Refunds Within Current NUT-11 Without Adding a Key
- 5. The Solution: Moving-Bound Per-Bid Locktimes
- 6. Detailed Comparison
- 7. Benefits of the Moving-Bound Approach
- 8. How It Fits Into the Settlement Policy Versioning Scheme
- 9. Remaining Open Questions
- 10. Conclusion
Moving-Bound Auctions: Early Refunds Without Oracle Key Custody
Date: May 24, 2026
Companion to: AUCTIONS.md (v1 codex), docs/auctions-v2-revised.md (moving-bound proposal)
Related proposals: SatsAndSports SIG_ALL gist, SIG_INPUTs gist
1. The Problem
The v1 path-oracle auction (AUCTIONS.md, settlement_policy: cashu_p2pk_path_oracle_v1) has a known user-experience gap:
Losing bidders must wait for the full locktime to expire before reclaiming their ecash — even if the seller settles within seconds.
The locktime is max_end_at + settlement_grace (typically 1–3 hours after bidding closes). Every losing bidder, regardless of when they placed their bid, waits the same full duration. A bidder who bid 24 hours before the auction ends waits just as long as a bidder who bid 5 minutes before.
The v1 codex acknowledges this explicitly (§8.1):
“under the path-oracle profile the issuer holds no Cashu key material and cannot proactively spend a loser’s locked proofs. Losing bidders therefore self-refund at locktime… A potential future
claim_refundtool — needing a different mechanism (e.g. issuer-signed unlock paths for losers) — is out of scope for v1.”
A related problem is capital-inefficient rebidding: a bidder who raises their own bid must lock the full new amount while the old amount remains locked. With a 2-hour locktime, a bidder who rebids three times has three separate locks outstanding.
2. SatsAndSports’ Coordinator Proposals
Two proposals from SatsAndSports (@SatsAndSports) address the early-refund gap by introducing a coordinator (Carol) who holds a Cashu signing key per auction.
Gist 1 — SIG_ALL (May 22)
- Bidder locks proofs in 2-of-2 P2PK (coordinator key + bidder key) with timelocked refund.
- Bidder pre-signs two Cashu swap transactions using
SIG_ALL(outputs are committed):- Swap A: outputs locked 1-of-1 to seller
- Swap B: outputs locked 1-of-1 to bidder
- Coordinator picks which swap to co-sign at settlement time.
- For the winner: coordinator co-signs Swap A → seller gets paid.
- For losers: coordinator co-signs Swap B → bidder gets immediate refund.
- Key property: Cashu’s double-spend prevention ensures only one swap can execute per proof set. The coordinator cannot execute both.
Gist 2 — SIG_INPUTs (May 24)
- Same 2-of-2 lock, but bidder shares only message hashes with coordinator (not the full token).
- Coordinator signs the hashes blind — does not see the actual proofs.
- For winner: coordinator gives bidder’s signature to seller → seller adds their own swap → claims.
- For losers: coordinator gives their signature to bidder → bidder swaps back to self.
- Key property: coordinator never sees the token (privacy advantage). Per-auction key isolation prevents cross-auction signature abuse.
What both proposals achieve
| Capability | Status |
|---|---|
| Instant refund for losers | ✓ Coordinator co-signs immediately |
| Capital-efficient rebidding | ✓ Superseded bids refunded immediately |
| Coordinator can’t steal | ✓ 2-of-2 requires bidder’s cooperation |
| Seller can’t claim prematurely | ✓ Coordinator gates via signature release |
What both proposals trade away (vs path-oracle v1)
| Property | Path-Oracle v1 | Coordinator Model |
|---|---|---|
| Oracle holds no key material | ✓ Holds only derivation paths | ✗ Holds a signing key per auction |
| Seller autonomy after settlement | ✓ Path reveal → seller claims alone | ✗ Seller needs coordinator’s signature |
| Mint compatibility | Basic NUT-11 (1-of-1 P2PK + locktime + refund) | NUT-11 with M-of-N multisig + SIG_ALL/SIG_INPUTs |
| Safe failure (oracle offline) | ✓ All bids refund at locktime | ✓ All bids refund at locktime |
| Gate mechanism | Information release (path revelation) | Signature release (co-signing) |
3. The Fundamental Tension
The path-oracle gates settlement through information release: the seller cannot claim without the derivation path, which the oracle holds secret. The oracle holds no Cashu keys — it cannot steal under any failure mode, only delay settlement.
The coordinator model gates settlement through signature release: the seller cannot claim without the coordinator’s co-signature. The coordinator holds a Cashu signing key.
These are substitute mechanisms for the same function (preventing premature seller claims). Adding a coordinator key to the lock for early refunds makes the path oracle’s information gate redundant for settlement control — the coordinator’s signature already gates spending.
The design question becomes: can we enable early refunds for losers without adding any entity’s key to the lock?
4. Why You Can’t Get Early Refunds Within Current NUT-11 Without Adding a Key
NUT-11 P2PK enforces two spending phases:
- Before locktime: only the lock pubkey(s) can spend.
- After locktime: the refund pubkey can also spend.
In v1, the lock pubkey is the seller’s HD-derived child key. The bidder holds only a refund key that activates at locktime. Nobody can spend the proofs before locktime except the holder of the child privkey (the seller, after the oracle reveals the path).
To enable a loser’s refund before locktime, someone must be able to spend the proofs before locktime. There are only three ways:
- Give someone a lock pubkey (oracle, bidder, or coordinator) → they can spend before locktime.
- Shorten the locktime for losers → the mint opens the refund path sooner.
- Extend the NUT-11 spec → mint accepts a trusted third party’s “early refund authorization” as a substitute for locktime expiry.
Options 1 and 3 require new trust assumptions or mint cooperation. Option 2 is achievable within current NUT-11 using per-bid locktimes.
5. The Solution: Moving-Bound Per-Bid Locktimes
Core idea
Instead of a single uniform locktime (max_end_at + settlement_grace) for all bids, each bid carries its own locktime. The oracle dictates the locktime when issuing a path grant, based on the auction’s current state.
locktime = max(current_effective_end + settlement_grace, now + minimum_bid_duration)
Where:
current_effective_endis derived from the current highest bid’s locktime (or the auction’send_atif no bids yet).settlement_graceis the seller’s settlement window (same as v1).minimum_bid_durationis a floor ensuring every bid stays live for at least a short period (e.g., 5–10 minutes).
The auction’s effective_end_at becomes:
effective_end_at = highest_bid_locktime − settlement_grace
This is the moving-bound design from docs/auctions-v2-revised.md. The auction ends at a fixed interval before the highest bidder’s locktime expires.
How this enables early refunds
Consider an auction with end_at = 12:00, settlement_grace = 10 min, minimum_bid_duration = 5 min:
| Time | Bidder | Amount | Locktime assigned | Notes |
|---|---|---|---|---|
| 10:00 | Alice | 1,000 sats | 12:10 (end_at + grace) | First bid, long locktime |
| 10:30 | Bob | 1,500 sats | 12:15 (effective_end 12:05 + grace) | Outbids Alice |
| 11:00 | Carol | 2,000 sats | 12:20 (effective_end 12:10 + grace) | Outbids Bob |
| 11:30 | Alice | 2,500 sats | 12:25 (effective_end 12:15 + grace) | Alice rebids |
When Carol outbids Bob at 11:00, Bob’s locktime is 12:15. Bob waits 1 hour 15 minutes from his bid time to refund — but this is much less than the full auction duration. Compare with v1 where Bob would wait until max_end_at + grace (potentially 12:10 or later if anti-snipe extends it).
More importantly: Alice’s first bid (10:00, locktime 12:10) is superseded at 10:30. Alice’s first locktime expires at 12:10, while the auction’s effective end is now 12:15. Alice’s first bid naturally refunds at 12:10 — only 1 hour 40 minutes after she placed it, and she already has her second bid active with a later locktime.
With shorter minimum_bid_duration and tighter locktime calculations, losers’ refunds can be very fast:
minimum_bid_duration |
Loser refund latency (after being outbid) |
|---|---|
| 30 min | Up to 30 min |
| 10 min | Up to 10 min |
| 5 min | Up to 5 min |
This is not instant (like SatsAndSports’ coordinator co-sign), but it’s dramatically faster than v1 and requires zero changes to the lock profile or trust model.
How this prevents retractions
The winning bidder’s locktime IS the auction’s effective end (minus grace). The bidder cannot retract because:
- The proofs are locked to the seller’s child key (1-of-1 P2PK). The bidder holds no spending key.
- The bidder’s refund key only activates at locktime.
- The locktime is set to extend past the auction’s current effective end.
- If the bidder is the highest bidder, their locktime is the latest — it defines when the auction can settle.
The mint enforces the locktime. No oracle key is needed in the lock. Retraction is prevented by the same mechanism that prevents it in v1: the bidder simply cannot spend the proofs.
Self-rebidding becomes capital-efficient
When Alice rebids at 11:30:
- Alice locks 2,500 sats with locktime 12:25.
- Alice’s first bid (1,000 sats, locktime 12:10) is still outstanding.
- At 12:10, Alice’s first bid refunds automatically — she recovers 1,000 sats.
- Only the 2,500-sat bid remains active.
With short minimum_bid_duration (e.g., 10 min), old bids recycle quickly. The maximum capital overhead for a rebidding chain is previous_bid_amount × number_of_outstanding_bids, but each outstanding bid recycles within minimum_bid_duration of being superseded.
This is not as capital-efficient as SatsAndSports’ instant coordinator refund (where superseded bids return immediately), but it’s a significant improvement over v1 where all bids share the same long locktime.
6. Detailed Comparison
vs v1 Path-Oracle
| Property | v1 (uniform locktime) | Moving-Bound (per-bid locktime) |
|---|---|---|
| Lock profile | 1-of-1 P2PK + timelocked refund | 1-of-1 P2PK + timelocked refund (unchanged) |
| Oracle key material | None (derivation paths only) | None (derivation paths only, unchanged) |
| Seller autonomy | After path reveal, claims alone | After path reveal, claims alone (unchanged) |
| Mint compatibility | Basic NUT-11 | Basic NUT-11 (unchanged) |
| Loser refund latency | max_end_at + grace − bid_time (hours) |
minimum_bid_duration (minutes) |
| Rebidding capital waste | Full old amount locked for hours | Old amount locked for minimum_bid_duration |
max_end_at tag |
Required, seller-chosen hard cap | Optional — replaced by moving bound |
| Anti-snipe mechanism | Fixed window + min_bid_curve |
Built into moving bound (each bid extends) |
| Retraction prevention | Mint-enforced locktime | Mint-enforced locktime (unchanged) |
vs SatsAndSports Coordinator (both gists)
| Property | Moving-Bound | Coordinator (SIG_ALL) | Coordinator (SIG_INPUTs) |
|---|---|---|---|
| Lock profile | 1-of-1 P2PK (unchanged from v1) | 2-of-2 (coordinator + bidder) | 2-of-2 (coordinator + bidder) |
| Oracle key material | None | Signing key per auction | Signing key per auction |
| Seller autonomy | ✓ Claims alone after path reveal | ✗ Needs coordinator co-signature | ✗ Needs coordinator co-signature |
| Mint compatibility | Basic NUT-11 | NUT-11 M-of-N + SIG_ALL | NUT-11 M-of-N + SIG_INPUTs |
| Loser refund latency | Minutes (wait for per-bid locktime) | Instant (coordinator co-signs) | Instant (coordinator co-signs) |
| Rebidding capital waste | Low (short locktimes recycle fast) | None (instant coordinator refund) | None (instant coordinator refund) |
| Bid retraction possible | No (bidder has no spending key) | No (needs coordinator co-signature) | No (needs coordinator co-signature) |
| Coordinator blind to tokens | N/A (no coordinator) | No (sees full swap) | Yes (signs hashes only) |
| Retraction prevention mechanism | Mint locktime | 2-of-2 signature gate | 2-of-2 signature gate |
7. Benefits of the Moving-Bound Approach
Preserved from v1
- Oracle holds no Cashu key material. Even a fully compromised oracle cannot steal funds. It can only delay settlement (DoS), same as v1.
- Seller autonomy. After the oracle reveals the winning derivation path, the seller derives the child privkey and claims independently. No ongoing coordinator involvement.
- Minimal mint compatibility. Standard NUT-11 P2PK with locktime and refund is sufficient. No M-of-N multisig, no SIG_ALL, no SIG_INPUTs.
- Safe failure mode. If the oracle goes offline, all bids refund at their respective locktimes. No funds are trapped.
- Bidder-side path verification (§5.6). The bidder still verifies
HDKey(xpub).derive(path).publicKey == childPubkeybefore locking. This prevents a malicious oracle from substituting its own key.
New benefits vs v1
- Fast loser refunds. Losers wait minutes instead of hours. The refund isn’t instant, but it’s fast enough for practical use.
- Capital-efficient rebidding. Old bids recycle within
minimum_bid_durationof being superseded. A bidder who rebids doesn’t have capital locked for the full auction duration. - No hard
max_end_atrequired. The auction’s effective end is determined by bidder behavior, not by a seller-chosen cap. This supports the “auctions without a hard end time” use case (Chief Monkey’s request). - Anti-snipe is built-in. Each new bid extends the effective end. No separate
extension_ruleormin_bid_curveneeded (though the curve can still be used for bid-floor escalation). - No new trust assumptions. The same three parties (seller, oracle, bidder) with the same trust boundaries. No coordinator, no signing keys, no multisig.
Tradeoffs vs coordinator model
- Refunds are fast, not instant. Losers wait
minimum_bid_durationinstead of getting immediate coordinator co-signature. With a 5-minute minimum, this is acceptable for most auction types. - Rebidding has brief capital overlap. The old bid is still locked for
minimum_bid_durationafter being superseded. Not instant release, but vastly better than v1’s hours-long overlap. - Moving-bound complexity. The oracle must track the current effective end and compute per-bid locktimes. This is new logic compared to v1’s uniform locktime, but it’s straightforward (the formula above).
8. How It Fits Into the Settlement Policy Versioning Scheme
The existing codebase already supports settlement policy versioning via the settlement_policy tag on auction events. The moving-bound design can be introduced as a new policy:
| Tag value | Lock profile | Locktime | Effective end | Anti-snipe |
|---|---|---|---|---|
cashu_p2pk_path_oracle_v1 |
1-of-1 P2PK, uniform | max_end_at + grace |
max_end_at (fixed) |
min_bid_curve in (end_at, max_end_at] |
cashu_p2pk_path_oracle_v2 |
1-of-1 P2PK, per-bid | max(effective_end + grace, now + min_duration) |
highest_locktime − grace (moving) |
Built into moving bound |
Both policies coexist on relays. Old auctions settle under v1 rules forever. New auctions can use either policy at the seller’s choice. The auction kind (30408), bid kind (1023), settlement kind (1024), and path registry kind (30410) remain unchanged. Only the oracle’s request_path logic and the getAuctionEffectiveEndAt() calculation differ between policies.
The vast majority of the auction infrastructure is policy-agnostic: path oracle transport, HD key derivation, P2PK lock and ecash receive, token envelopes, bid event structure, and settlement plan computation.
9. Remaining Open Questions
-
What should
minimum_bid_durationdefault to? Short values (5 min) give fast refunds but constrain the seller’s settlement window. Long values (30 min) are safer but reduce the refund-speed advantage. This may be a per-auction seller parameter. -
Is “fast but not instant” refund acceptable? The coordinator model gives truly instant refunds. Moving-bound gives 5–30 minute refunds. For high-frequency or time-sensitive auctions, the difference may matter. For typical marketplace auctions (hours-long), it likely doesn’t.
-
Can the moving-bound design be combined with a coordinator as a future upgrade? Yes. If instant refunds become necessary, the lock profile can be upgraded to 2-of-2 (coordinator + bidder) with SIG_ALL pre-signed swaps. The moving-bound per-bid locktime logic remains useful for the fallback case (coordinator offline).
-
How does this interact with the bid floor curve? The moving-bound design replaces the fixed
(end_at, max_end_at]anti-snipe window. Themin_bid_curvecan still be applied relative to the effective end: bids near the effective end pay a premium. The curve formula stays the same; only the reference point (max_end_at) moves. -
Should there be an absolute maximum duration? Even with the moving bound, an auction could theoretically run for weeks if bids keep arriving. A generous absolute cap (e.g., 7 days from
start_at) is worth considering as a safety net.
10. Conclusion
The moving-bound per-bid locktime design gives you the two things SatsAndSports’ coordinator model provides — fast loser refunds and capital-efficient rebidding — while preserving every unique advantage of the path-oracle architecture:
- Oracle holds no keys
- Seller claims independently after path reveal
- Basic NUT-11 mint compatibility
- No new trust assumptions
The tradeoff is speed: refunds take minutes instead of being instant. For a marketplace where auctions run for hours or days, this is a favorable tradeoff — you get the UX improvement without the architectural cost of adding a coordinator with signing authority.
Write a comment