Skip to content

mirror funding: unbounded selected-input count on a publicly-derivable address, one chain read per input #427

Description

@MichaelTaylor3d

Task

mirror::funding::select_operator_dig_cats places no bound on how many coins it selects, and each
selected coin costs one further chain read. The scanned address —
dig_cat_puzzle_hash(owner_puzzle_hash) — is derivable by anyone who knows this node's operator
puzzle hash, so the number of candidates is not under this node's control.

Context

crates/dig-node-service/src/mirror/funding.rs:194-215 (as of dig-node#423):

  • :190 reads every unspent row at the scan hash — one chain call, unbounded row count.
  • :197-201 filters spent and committed rows.
  • :207 select_largest_first takes as many as the shortfall needs, with no cap.
  • :214-216 then calls authenticate(source, record, owner_puzzle_hash) per selected coin, and
    authenticate resolves lineage from the creating spend — a chain read each.

A party who sends the operator a large number of dust $DIG CATs makes the selection walk many of
them to reach the required amount, and each one becomes a lineage read. The cost is borne by this
node and by whatever ChainSource it is pointed at.

This is NOT the truncation case: dig_mirror_coin::list's incomplete-scan refusal
(mirror/lifecycle.rs, observe_chain) covers the inventory read, not this selection.

Scope

Assess first, then bound. Two questions the assessment must answer, because they change the shape:

  1. Is there an amount below which a candidate cannot usefully contribute, given the collateral
    amounts §25.3 produces? A dust floor removes most of the population without a cap.
  2. What is the honest failure when the bound is hit — a refusal (fail closed, consistent with every
    other refusal in this module) or a partial selection? A partial selection funds a create at the
    wrong amount, which §25.3's apply_safety_margin note says locks money and advertises nothing,
    so a refusal is the likely answer and should be stated rather than assumed.

Whatever bound lands must be pinned from BOTH sides in tests: one coin over must refuse, at-bound
must select.

Evidence

Raised by the pre-merge security gate on dig-node#423 as a non-gating follow-up. Not absorbed into
that PR, whose re-gate scope was the reservation defect.

Parent: #421

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions