Skip to content

dign wallet peak reports synced: true on a replica 1,875 blocks behind — the latch, not the freshness gate #293

Description

@MichaelTaylor3d

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:1850chain_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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:businessa person can DO something new, or money moves, or a shipped surface stops lying to them

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions