Skip to content

Act on previous_cycle_invalid_count instead of only logging it #956

Description

@xdustinface

feed_qr_info reports previous-cycle rotation commitments that fail validation through QRInfoFeedResult::previous_cycle_invalid_count, but nothing acts on the number.

Where it stands

MasternodeListEngine::validate_and_store_previous_cycle_quorums is best-effort enrichment: a previous-cycle rotated quorum that fails its aggregate signature check is left out of the stored cycle and counted, and the feed continues. The count exists so a caller can judge the peer that served the data. In dash-spv the only consumer is a tracing::info! line in MasternodesManager::handle_message.

The result is that a peer serving corrupt previous-cycle commitments costs it nothing and costs us the cycle:

  • The QRInfo is recorded as processed (last_processed_qrinfo_tip), so should_process_qrinfo drops anything else arriving for that tip.
  • next_pipeline_mode fires at most one QRInfo per new tip inside the DKG mining window, so there is no retry against a different peer within the same tip.
  • The dropped indices stay unverifiable until a later QRInfo happens to carry them again, which means InstantSend locks selecting those quorums fail in the meantime.

Why PR #934 did not fix it

PR #934 makes the count trustworthy (it no longer blames the peer for a quarter signature our own elimination pass had to guess), but every minimal way to act on it is either a no-op or a hazard:

  • Not recording last_processed_qrinfo_tip when the count is non-zero achieves nothing on its own: should_process_qrinfo also requires a matching in-flight request, and no new request is issued for the same tip.
  • Re-requesting on the same tip has no peer-selection input at that layer, so it can loop against the peer that just served the bad data.

Making this actionable needs peer attribution and a retry path that can pick a different peer, which is a larger change than PR #934 should carry.

Suggested direction

  1. Attribute the QRInfo response to the peer it came from and penalise it when previous_cycle_invalid_count > 0, reusing the existing peer reputation/scoring rather than adding a parallel mechanism.
  2. Allow one re-request of the same tip when the response was penalised, routed to a different peer, bounded so a cycle cannot spend more than a couple of attempts on it.
  3. Keep the storage behaviour as is. Storing the verified subset is correct and the retry only needs to fill in what was dropped.

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