Open
Description
ManagedWalletInfo::restore_utxos (#1295) places each restored UTXO in the account whose pools derive its script, and grows the pools to their gap limit as it goes. A wallet loaded from storage often has more to restore than its UTXOs. It also has the addresses that were used and whose coins have since been spent. Today a caller has to rebuild that state around restore_utxos itself, and doing that correctly is subtle.
What callers currently have to do (dashpay/platform#5780 does all of it in platform-wallet-storage):
- Mark the persisted used addresses in whichever account derives them. Then refill, and repeat until nothing new is marked and no refill derives anything new. A spent address only becomes reachable after an earlier coin's refill, and it can in turn lead to a deeper coin, so the coins and the used addresses must reach one fixed point.
- Call
restore_utxoswith no UTXOs just to trigger a refill, and comparehighest_generatedper pool to see whether a pass derived anything. - Check each refill's size before running it, which means mirroring
AddressPool::maintain_gap_limit's target arithmetic outside the crate. That arithmetic is unchecked, and a pool whose refill would be too large or unrepresentable gives no structured refusal. - When one pool can't be refilled, still place the coins whose scripts are already derived, with the same account precedence and copy removal as
restore_utxos. There is no public way to place coins without a refill. fix(platform-wallet-storage): restore UTXOs into the account that derives them platform#5780 works around it by callingrestore_utxoswith aWalletthat carries no accounts, soextend_poolsfinds no key source and skips every pool. That relies on howrestore_utxosuses the wallet internally, and a public no-refill placement would replace it.
Proposed API shape:
- A restore entry point that takes the persisted used addresses (or scripts) alongside the UTXOs, and owns the combined fixed point: mark, refill and match until stable, then place each UTXO by script with the existing precedence and copy removal.
- A checked refill plan: per pool, the refill a gap-limit maintenance would perform (target index, count), computed with checked arithmetic. The caller can then apply its own bound before anything is derived.
- Structured per-pool refusals (account type, pool type, reason) instead of an opaque error, and a mode that places by already-derived scripts when a pool is refused, returning the coins it couldn't place.
Out of scope: storage, SQL attribution, allocation budgets and load policy. Those stay with the caller.
Related:
- feat(key-wallet): restore UTXOs into the account that owns their address #1295 (UTXO placement by owning account);
- fix(platform-wallet-storage): restore UTXOs into the account that derives them platform#5780 (the storage adapter that coordinates this today);
- SQLite persister never writes gap-extended addresses, so CoinJoin address rows stop at the registration window platform#5723 (persisting gap-extended pool addresses).
Metadata
Metadata
Assignees
Labels
No labels
Activity