Summary
Three gating decisions in the reward automation have no test at any level, and none is reachable from the localnet IT, which only exercises the happy one-delegation / node-is-an-assigner path:
| Path |
Location |
Behaviour |
| zero active delegations |
reward_automation.rs active_delegation |
silent no-op |
| more than one active delegation |
active_delegation |
returns Err, every tick |
| this node's member is not an assigner |
run_once_for_party |
log and skip |
The middle one is the consequential case: it is the tick-level half of the total-loss mode this PR guards at the propose boundary (two live delegations). If it ever stopped returning Err and started guessing which split was authoritative, that would be rewards paid to a superseded split — and nothing would catch the regression.
Why they are untested
active_delegation performs the ACS read and the ambiguity decision in one function, so there is no seam to test the decision without a ledger. The same is true of the assigner check inside run_once_for_party.
Requirements
- Separate the decision from the I/O: a pure function taking the decoded records (or a count) and returning no-op / act / refuse, and a pure check for "is this node's member an assigner".
parse_delegation_record is already factored out this way and unit-tested, so the pattern exists in the file.
- Unit-test all three outcomes, with the two-delegations case asserting that it refuses rather than picks — the assertion should read as a statement about safety, not about a return type.
- Leave the ledger reads where they are; this is about testability of the rules, not restructuring the reads.
References
crates/decman/src/server/reward_automation.rs — active_delegation (ambiguity refusal, zero-delegation no-op), run_once_for_party (assigner skip).
crates/decman/tests/common/phases/coupon_reassignment.rs — the IT, happy path only.
Summary
Three gating decisions in the reward automation have no test at any level, and none is reachable from the localnet IT, which only exercises the happy one-delegation / node-is-an-assigner path:
reward_automation.rsactive_delegationactive_delegationErr, every tickrun_once_for_partyThe middle one is the consequential case: it is the tick-level half of the total-loss mode this PR guards at the propose boundary (two live delegations). If it ever stopped returning
Errand started guessing which split was authoritative, that would be rewards paid to a superseded split — and nothing would catch the regression.Why they are untested
active_delegationperforms the ACS read and the ambiguity decision in one function, so there is no seam to test the decision without a ledger. The same is true of the assigner check insiderun_once_for_party.Requirements
parse_delegation_recordis already factored out this way and unit-tested, so the pattern exists in the file.References
crates/decman/src/server/reward_automation.rs—active_delegation(ambiguity refusal, zero-delegation no-op),run_once_for_party(assigner skip).crates/decman/tests/common/phases/coupon_reassignment.rs— the IT, happy path only.