Task
control.wallet.peak reports synced: true while the replica is ~1,875 blocks behind. Compute
synced from replica_answer_is_current, not from the initial_sync_complete latch, and correct the
now-false doc claim that the two endpoints cannot disagree.
Measured on a running node, not inferred
dign 0.134.0, three reads over ~10 minutes:
$ dign wallet sync-status
{"phase":"syncing","peak_height":9180969,"chia_peer_count":5,
"subscription_peer_count":1,"chia_peer_peak_height":9182844,"watched_addresses":null}
$ dign wallet peak
{"peak_height":9180969,"synced":true}
- Replica peak frozen at 9180969 across all three reads.
- Peer peak advancing: 9182825 → 9182833 → 9182844. The peers are alive and working.
- Independent control:
api.coinset.org/get_blockchain_state returned peak 9182833 at the same
moment the node reported chia_peer_peak_height: 9182833 — an exact match. The peers are honest and
current; the replica is the thing that is stuck, ~1,875 blocks / ~9.8 hours behind.
Same process, same moment: sync-status says syncing, peak says synced: true.
Cause
crates/dig-wallet/src/sage/rpc.rs:1850 — chain_peak() computes synced as self.db.is_synced(),
the initial_sync_complete latch, and returns early on the replica-served path without ever calling
replica_answer_is_current.
That method exists precisely to prevent this. rpc.rs:958-962 says so:
"db_synced … is initial_sync_complete, which records that a catch-up once FINISHED … a replica
hundreds of blocks behind still satisfies it. Reporting synced: true on that basis told a client a
stale balance was settled, which is the money-adjacent falsehood dig_ecosystem#2869 exists to remove."
And rpc.rs:964-966 claims the endpoints are kept in agreement:
"It reuses is_following — the SAME predicate control.wallet.syncStatus reports its phase from — so
a client cannot be told synced by one endpoint and syncing by the other about the same moment."
That sentence is false on the running node. FOLLOWING_TOLERANCE is 4 blocks
(sync_supervisor.rs:218); the measured gap is 1,875.
Why it matters
control.wallet.peak exists specifically for "a caller bounding a claimed confirmation"
(dig-node-service/src/control.rs:1924-1929). A caller using it to decide whether a payment settled is
told yes on a replica nine hours stale. That is the money-adjacent-lie class, which is why it is not
deferrable as hardening.
Not a duplicate of #249
#249 is about the chain tip coming from two independent measurements. This is a boolean computed
from the wrong predicate on one of them; #249's fix (inject the provider registry) does not touch
chain_peak's synced line.
Scope
The fix is small. The test is the point: a regression test must construct a replica that satisfies
initial_sync_complete and lags past FOLLOWING_TOLERANCE, and assert synced == false. A test that
only exercises a fresh or fully-caught-up replica cannot fail on this defect and is worth nothing here.
While in the file, make the two endpoints structurally unable to disagree rather than separately correct
— the doc comment already promises that, and a promise held by care rather than construction is what
produced this.
Parent
https://github.com/DIG-Network/dig_ecosystem/issues/2760 — this is the epic's own headline acceptance
bar ("an honest sync report") failing in production.
Task
control.wallet.peakreportssynced: truewhile the replica is ~1,875 blocks behind. Computesyncedfromreplica_answer_is_current, not from theinitial_sync_completelatch, and correct thenow-false doc claim that the two endpoints cannot disagree.
Measured on a running node, not inferred
dign 0.134.0, three reads over ~10 minutes:api.coinset.org/get_blockchain_statereturned peak 9182833 at the samemoment the node reported
chia_peer_peak_height: 9182833— an exact match. The peers are honest andcurrent; the replica is the thing that is stuck, ~1,875 blocks / ~9.8 hours behind.
Same process, same moment:
sync-statussayssyncing,peaksayssynced: true.Cause
crates/dig-wallet/src/sage/rpc.rs:1850—chain_peak()computessyncedasself.db.is_synced(),the
initial_sync_completelatch, and returns early on the replica-served path without ever callingreplica_answer_is_current.That method exists precisely to prevent this.
rpc.rs:958-962says so:And
rpc.rs:964-966claims the endpoints are kept in agreement:That sentence is false on the running node.
FOLLOWING_TOLERANCEis 4 blocks(
sync_supervisor.rs:218); the measured gap is 1,875.Why it matters
control.wallet.peakexists specifically for "a caller bounding a claimed confirmation"(
dig-node-service/src/control.rs:1924-1929). A caller using it to decide whether a payment settled istold yes on a replica nine hours stale. That is the money-adjacent-lie class, which is why it is not
deferrable as hardening.
Not a duplicate of #249
#249 is about the chain tip coming from two independent measurements. This is a boolean computed
from the wrong predicate on one of them; #249's fix (inject the provider registry) does not touch
chain_peak'ssyncedline.Scope
The fix is small. The test is the point: a regression test must construct a replica that satisfies
initial_sync_completeand lags pastFOLLOWING_TOLERANCE, and assertsynced == false. A test thatonly exercises a fresh or fully-caught-up replica cannot fail on this defect and is worth nothing here.
While in the file, make the two endpoints structurally unable to disagree rather than separately correct
— the doc comment already promises that, and a promise held by care rather than construction is what
produced this.
Parent
https://github.com/DIG-Network/dig_ecosystem/issues/2760 — this is the epic's own headline acceptance
bar ("an honest sync report") failing in production.