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:
- Capture the
FeeResult at each drive call (use _with_costs variants where available, or pass Some(epoch) to query helpers and read outcome.cost()).
- Add the cost to the threaded
execution_context via add_operation(ValidationOperation::PrecalculatedOperation(fee_result)).
- 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.
- 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:
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:common/— bounds checking, key-uniqueness lookups, key-id existence checks. Used by identity create / update flows.The detailed inventory (specific files, line numbers, severity, expected fee deltas) is documented in
docs/paid-error-fee-audit.mdon 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:
FeeResultat each drive call (use_with_costsvariants where available, or passSome(epoch)to query helpers and readoutcome.cost()).execution_contextviaadd_operation(ValidationOperation::PrecalculatedOperation(fee_result))._v1alongside the unchanged_v0) with dispatch outside, and a new value on the relevantDriveAbci*ValidationVersionsfield — fee changes are consensus-affecting.processing_feeon 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: