Skip to content

ChainTransport::with_peer_reads is never called, so the NC-12 corroborated chain source fails closed and every chain read goes to a third-party oracle #578

Description

@MichaelTaylor3d

ChainTransport::with_peer_reads(db) is never called — the NC-12 corroborated chain path fails closed in production

Found by the dig-node#574 lane while investigating whether bond confirmation could move off the third-party oracle. Reported rather than fixed, correctly — it is pre-existing and wider than that ticket.

What is true today

ChainTransport::corroborated_chain_source exists, and CorroboratedChainSource implements the NC-12 shape properly: agreement across independently-queried peers, refusing rather than falling back. But with_peer_reads(db) is never called anywhere in dig-node-service, so the peer-read half is never populated and the corroborated source fails closed in production.

The consequence is visible on a live host. Every chain read logs:

dig_wallet::sage::rpc: wallet balance read routed to the third-party chain oracle {"tier":"fallback"}
dig_wallet::sage::rpc: coin-spend read routed to the third-party chain oracle {"tier":"fallback"}

And the balance surface says so itself: NOT CURRENT — this node cannot say what height this answer reflects; it is not evidence that there is nothing there.

This is not new and not caused by #574 — it affects the pre-existing observe_chain and coin_confirmation calls identically. #574 simply made it visible by asking whether its new re-verification could use the corroborated path.

Why it matters more than "a slower read"

The mirror-coin path writes to chain and locks $DIG collateral. Today the node decides what its own bonds are by asking a single third party, with no corroboration and no height it can vouch for. NC-12's whole posture — believe a fact because independent sources agree, never because one source asserted it — is implemented and then not switched on.

Measured tonight, the practical cost: an independent api.coinset.org query showed two funding coins already spent at block 9251995 while dign's own read still reported them unspent. The node self-corrected a pass later, so nothing was lost — but it was, for a window, wrong about its own money on the word of one source.

Why it is a small change with a large effect — and what to establish first

coin_record(coin_id) is already corroborated under quorum via #503. What is missing is only that nothing populates the peer-read side.

So establish, before writing anything:

  1. Why is with_peer_reads never called? It may be deliberate — an unfinished rollout, a performance concern, or a dependency that is not available at that construction site. A deliberate omission with a reason is a different ticket from an oversight, and the reason may be good.
  2. What db does it need, and is that handle available where ChainTransport is built? If it is not, the fix is a plumbing change and larger than it looks.
  3. What happens when too few peers answer? CorroboratedChainSource refuses rather than falling back — which is correct, but it means enabling this could turn "a slow, uncertain answer" into "no answer" on a node with poor peer connectivity. That trade must be deliberate, and there needs to be an honest surface for it rather than a silent stall.

The failure direction to preserve

Refusing is the right behaviour and must not be softened into a fallback. A corroborated source that quietly reverts to the oracle when peers are short would be strictly worse than today: it would carry the appearance of corroboration with none of the property. If the answer is "some nodes cannot corroborate", say so on the surface — do not paper it over.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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