Summary
Auto-delegate / auto-settle is meant to let a client delegate once and have the cosigner refresh (settle) the VTXO later — before expiry — without the client online. In practice it can perform only one settle, and only within ~120s of the client signing the delegate. Past that, the stored intent's proof-of-ownership expires and arkd rejects it (INVALID_INTENT_TIMERANGE: proof of ownership expired).
Root causes
- Fixed 120s intent window — the delegate intent's proof time range is hardcoded:
rust-sdk/ark-client/src/batch.rs:1253 — let expire_at = now + (2 * 60); (delegate path)
crates/ark/src/client/batch.rs:191 — let expire_at = now + 120; (boarding settle)
The delegate is signed once and stored; when tick_auto_settle registers it >120s later, arkd rejects it.
- Single-use intent —
tick_auto_settle consumes the stored delegate (state.delegate_session.take()), and a successful settle produces a NEW VTXO with no delegate. So one delegation ⇒ at most one auto-settle.
- Server can't re-sign — creating a fresh intent needs the client's FROST share, so the cosigner can't autonomously re-arm the new VTXO; it depends on the client reconnecting and re-delegating.
Observed (regtest)
auto-settle drive failed: ... INVALID_INTENT_TIMERANGE (20): proof of ownership expired
valid_at=1780137236 expire_at=1780137356 now=1780137534 (120s window, 178s late)
... clearing stored intent so client can re-delegate
- With margin > VTXO lifetime: settles every 60s tick (intent always fresh, but wasteful loop).
- With an intended delay > 120s: every attempt fails with proof-expired, then the client re-delegates on next refresh. Max reliable delay before settle ≈ 120s.
Impact
- "Delegate once, stay protected offline until near expiry" does NOT hold — the cosigner can settle only within ~120s of an online delegation, once per delegation.
- Short regtest expiries mostly self-heal via client re-delegation on refresh, but it churns error logs and burns batches.
- Production (long VTXO expiry): a fully-closed app is unprotected beyond ~2 min after its last delegation.
Proposed directions
- Extend the delegate intent's
expire_at to cover the settle horizon (e.g. the VTXO expires_at minus a buffer) instead of fixed 120s — subject to any max window arkd enforces (verify).
- Pre-sign a window / multi-use delegation so the cosigner can settle near expiry without the client.
- If arkd caps the proof window, reconsider the model (periodic client re-delegation; document the bounded horizon).
Files
rust-sdk/ark-client/src/batch.rs:1253, crates/ark/src/client/batch.rs:191 (intent expire_at)
cosigner-runtime/src/cosigner/handlers/auto_settle.rs (tick_auto_settle, consumes delegate)
cosigner-runtime/src/cosigner/handlers/ark_send.rs (settle_delegate / delegate generation)
Related: #37 (ASP-info cache after restart).
Summary
Auto-delegate / auto-settle is meant to let a client delegate once and have the cosigner refresh (settle) the VTXO later — before expiry — without the client online. In practice it can perform only one settle, and only within ~120s of the client signing the delegate. Past that, the stored intent's proof-of-ownership expires and arkd rejects it (
INVALID_INTENT_TIMERANGE: proof of ownership expired).Root causes
rust-sdk/ark-client/src/batch.rs:1253—let expire_at = now + (2 * 60);(delegate path)crates/ark/src/client/batch.rs:191—let expire_at = now + 120;(boarding settle)The delegate is signed once and stored; when
tick_auto_settleregisters it >120s later, arkd rejects it.tick_auto_settleconsumes the stored delegate (state.delegate_session.take()), and a successful settle produces a NEW VTXO with no delegate. So one delegation ⇒ at most one auto-settle.Observed (regtest)
Impact
Proposed directions
expire_atto cover the settle horizon (e.g. the VTXOexpires_atminus a buffer) instead of fixed 120s — subject to any max window arkd enforces (verify).Files
rust-sdk/ark-client/src/batch.rs:1253,crates/ark/src/client/batch.rs:191(intentexpire_at)cosigner-runtime/src/cosigner/handlers/auto_settle.rs(tick_auto_settle, consumes delegate)cosigner-runtime/src/cosigner/handlers/ark_send.rs(settle_delegate/ delegate generation)Related: #37 (ASP-info cache after restart).