Task
Make the mirror pass observable from a chain PUSH, so a mirror coin spent out from under this node is reflected in the §25.8 surface in seconds rather than up to one round (10 min) late.
The user's instruction on dig-node#465 was that "the observe_disk and observe_chain need to be event based, only using a timer as backup". The disk half shipped in #470. The chain half is DECLINED for a physical reason, recorded here so the residue is a checkable ticket rather than a spec paragraph explaining a decline.
The blocker, measured
ChainSource has no subscription surface at all. dig-chainsource-interface 0.3.2 src/source.rs:31 — the whole trait is coin_record, coin_records_by_puzzle_hash, coin_records_by_parent, coin_spend. Request/response only: no stream, no callback, nothing a select! can wait on. MirrorEffects::observe_chain (crates/dig-node-service/src/mirror/lifecycle.rs:337) reads through it.
- The node's §14.2 chain-watch is itself a poll loop (
crates/dig-node-core/src/chainwatch.rs), so it is not a push source either.
- The one real push path cannot say WHICH coin changed. The wallet's direct-peer sync holds a genuine
request_puzzle_state(subscribe = true) subscription and publishes to the §18.14 EventBus, but SyncEvent::CoinState (crates/dig-wallet/src/sage/events.rs) is a fieldless variant — no coin id, no puzzle hash, no height — and it describes the WALLET DB, not the mirror's chain view. Waking on it would drive a money-spending, chain-reading pass on any wallet coin activity at all, down to the SETTLING_WINDOW_MS floor, with zero evidence of relevance.
What would have to exist
Either:
SyncEvent::CoinState carries the coin state it applied (at minimum the puzzle hash, ideally the coin id + height), and the mirror subscribes to the bus and filters on owner_puzzle_hash; or
ChainSource (or a sibling trait) gains a subscription surface, and the node's provider implements it.
The first is much the smaller change and stays inside this repo; it also needs confirming that the operator wallet's own puzzle hash is in the subscribed set, which is not established here.
Scope
This is a FRESHNESS improvement on a read-only surface (§25.8 reporting a stale locked-collateral figure), not a money-safety gap: a create is decided from disk presence, which is already event-driven, and the epoch rollover a reclaim waits on is wall-clock rather than a chain event. Priority accordingly.
Do not implement by waking on the fieldless event — that is the amplification this ticket exists to avoid.
Context
Task
Make the mirror pass observable from a chain PUSH, so a mirror coin spent out from under this node is reflected in the §25.8 surface in seconds rather than up to one round (10 min) late.
The user's instruction on dig-node#465 was that "the observe_disk and observe_chain need to be event based, only using a timer as backup". The disk half shipped in #470. The chain half is DECLINED for a physical reason, recorded here so the residue is a checkable ticket rather than a spec paragraph explaining a decline.
The blocker, measured
ChainSourcehas no subscription surface at all.dig-chainsource-interface0.3.2src/source.rs:31— the whole trait iscoin_record,coin_records_by_puzzle_hash,coin_records_by_parent,coin_spend. Request/response only: no stream, no callback, nothing aselect!can wait on.MirrorEffects::observe_chain(crates/dig-node-service/src/mirror/lifecycle.rs:337) reads through it.crates/dig-node-core/src/chainwatch.rs), so it is not a push source either.request_puzzle_state(subscribe = true)subscription and publishes to the §18.14EventBus, butSyncEvent::CoinState(crates/dig-wallet/src/sage/events.rs) is a fieldless variant — no coin id, no puzzle hash, no height — and it describes the WALLET DB, not the mirror's chain view. Waking on it would drive a money-spending, chain-reading pass on any wallet coin activity at all, down to theSETTLING_WINDOW_MSfloor, with zero evidence of relevance.What would have to exist
Either:
SyncEvent::CoinStatecarries the coin state it applied (at minimum the puzzle hash, ideally the coin id + height), and the mirror subscribes to the bus and filters onowner_puzzle_hash; orChainSource(or a sibling trait) gains a subscription surface, and the node's provider implements it.The first is much the smaller change and stays inside this repo; it also needs confirming that the operator wallet's own puzzle hash is in the subscribed set, which is not established here.
Scope
This is a FRESHNESS improvement on a read-only surface (§25.8 reporting a stale locked-collateral figure), not a money-safety gap: a create is decided from disk presence, which is already event-driven, and the epoch rollover a reclaim waits on is wall-clock rather than a chain event. Priority accordingly.
Do not implement by waking on the fieldless event — that is the amplification this ticket exists to avoid.
Context