Skip to content

Fee under-billing in non-batch paid-error state transition paths (follow-up to #3670) #3673

@shumkov

Description

@shumkov

Expected Behavior

When a non-batch state transition returns a PaidConsensusError, the user should pay for the drive reads that ran during validation — same correctness principle as PR #3616 established for batch transitions.

Current Behavior

The fee-charging audit done during PR #3670 surfaced a tier of pre-existing under-billing in non-batch state transition paths that predate #3616. PR #3670 closes the batch path and data-trigger sites; this issue tracks the remaining non-batch follow-up work.

Scope

Non-batch state transitions where validation performs grovedb reads but the resulting cost is not added to StateTransitionExecutionContext. Categories surfaced by the audit:

  • Identity transitions — sender/recipient balance checks in credit transfer, existence checks in identity creation flows.
  • Masternode voting — existing-vote lookup on contested resources.
  • Shared key/contract validators in common/ — bounds checking, key-uniqueness lookups, key-id existence checks. Used by identity create / update flows.
  • Asset-lock proof validation — outpoint spent-check and instant-lock signature verification, shared across identity creation, top-up, and shield transitions from asset locks.

The detailed inventory (specific files, line numbers, severity, expected fee deltas) is documented in docs/paid-error-fee-audit.md on PR #3670 (Tier 3 section). All sites stay open until the corresponding fix lands.

Possible Solution

Same convention as PR #3670 used for the batch path:

  1. Capture the FeeResult at each drive call (use _with_costs variants where available, or pass Some(epoch) to query helpers and read outcome.cost()).
  2. Add the cost to the threaded execution_context via add_operation(ValidationOperation::PrecalculatedOperation(fee_result)).
  3. Gate behind a new function version (_v1 alongside the unchanged _v0) with dispatch outside, and a new value on the relevant DriveAbci*ValidationVersions field — fee changes are consensus-affecting.
  4. Pin pre-fix and post-fix processing_fee on a representative scenario test for each fix so the fee delta is observable in code review.

Context

These sites have been latent since the affected state transitions were introduced. Per-transition under-charge is small (low thousands of credits per missed read) but compounds across the chain.

Splitting this out of #3670 keeps that PR scoped to the batch path that #3616 directly touched. This issue can be addressed in one PR per transition kind, or bundled into a single non-batch follow-up PR.

Related:

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions