Skip to content

Commit 76feb6f

Browse files
apenzklarryl3u
authored andcommitted
[stake] settle expired pending_inactive on rejoin and reconfig (#13)
* test(stake): add failing tests for expired pending_inactive on rejoin - assert that an inactive pool rejoining the validator set with expired pending_inactive has that bucket settled to inactive by end of the rejoining epoch - assert that the framework's published voting power matches DKG's recomputed view at the reconfig boundary, captured via cur_validator_consensus_infos and next_validator_consensus_infos - both fail on m1 today; will pass once the sweep is applied at validator rejoin / next-epoch transition * test(stake): add failing tests for rejoin gate and reconfig start-time helper - assert join_validator_set rejects rejoin when post-settlement active stake (99) falls below minimum_stake despite expired pending_inactive padding the pre-sweep total - assert get_reconfig_start_time_secs returns now_seconds() outside an active reconfiguration, instead of aborting via the inactive State variant * fix(stake): settle expired pending_inactive on validator-set entry - rename get_next_epoch_voting_power → get_voting_power; it is now a pure bucket sum (pending_active + active + pending_inactive) and callers must settle expired pending_inactive first - add settle_expired_pending_inactive helper and invoke it on each pending_active pool during on_new_epoch (using the reconfig start time as the comparison clock) and on the joining pool in join_validator_set_internal, so framework voting power agrees with DKG's post-sweep view - fix get_reconfig_start_time_secs to gate on is_in_progress() instead of is_initialized() (permanently true after genesis), which would otherwise return a stale start time outside an active reconfig and abort start_time_secs() - update stake.spec.move to use the renamed helper * test(stake): update test_inactivate_no_excess_stake for post-fix rejoin timing - prior commit settles expired pending_inactive into inactive at join_validator_set time, so the rejoining stake pool now has inactive=30000000003 and pending_inactive=0 - subsequent synchronize_delegation_pool advances the OLC, making the delegator's prior-cycle withdrawal inactive/withdrawable and eliminating the trailing pending_inactive in later assertions
1 parent 13c5211 commit 76feb6f

3 files changed

Lines changed: 264 additions & 22 deletions

File tree

aptos-move/framework/aptos-framework/sources/delegation_pool.move

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3367,29 +3367,39 @@ module aptos_framework::delegation_pool {
33673367
end_aptos_epoch();
33683368

33693369
assert!(stake::get_validator_state(pool_address) == VALIDATOR_STATUS_ACTIVE, 0);
3370-
// no rewards have been produced yet and no stake inactivated as lockup has been refreshed
3371-
stake::assert_stake_pool(pool_address, 103030100001, 20000000001, 0, 10000000002);
3370+
// No rewards have been produced yet. The expired pending_inactive (10000000002) is
3371+
// settled into inactive at join time, so the rejoining stake pool now has
3372+
// inactive = 20000000001 + 10000000002 = 30000000003 and pending_inactive = 0.
3373+
stake::assert_stake_pool(pool_address, 103030100001, 30000000003, 0, 0);
33723374

33733375
synchronize_delegation_pool(pool_address);
3376+
// The settled-on-rejoin stake (10000000002 from pending_inactive → inactive) shows up
3377+
// here as new inactive stake on the stake pool, so synchronize_delegation_pool advances
3378+
// the OLC and the delegator's prior-cycle withdrawal is now inactive (withdrawable).
33743379
assert_pending_withdrawal(validator_address, pool_address, true, 0, true, 20000000001);
3375-
assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, 10000000002);
3376-
assert!(observed_lockup_cycle(pool_address) == observed_lockup_cycle, 0);
3380+
assert_pending_withdrawal(delegator_address, pool_address, true, 1, true, 10000000002);
3381+
assert!(observed_lockup_cycle(pool_address) == observed_lockup_cycle + 1, 0);
33773382

3378-
// cannot withdraw pending_inactive stake anymore
3383+
// delegator's pending withdrawal is already inactive — it's now withdrawable.
33793384
withdraw(delegator, pool_address, 10000000002);
3380-
assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, 10000000002);
3385+
assert_pending_withdrawal(delegator_address, pool_address, false, 0, false, 0);
33813386

33823387
// earning rewards is resumed from this epoch on
33833388
end_aptos_epoch();
3384-
stake::assert_stake_pool(pool_address, 104060401001, 20000000001, 0, 10100000002);
3389+
stake::assert_stake_pool(pool_address, 104060401001, 20000000001, 0, 0);
33853390

3386-
// new pending_inactive stake earns rewards but so does the old one
3391+
// Validator unlocks its full active stake. The delegator no longer has any
3392+
// pending_inactive stake (their prior cycle was withdrawn above), so the new
3393+
// pending_inactive lives in the freshly-started OLC and is owned entirely by the
3394+
// validator. Validator's own prior-cycle inactive (OLC 0, 20000000001) gets executed
3395+
// and withdrawn as part of `buy_in_pending_inactive_shares`.
33873396
unlock(validator, pool_address, 104060401001);
3388-
assert_pending_withdrawal(validator_address, pool_address, true, 1, false, 104060401000);
3389-
assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, 10100000002);
3397+
assert_pending_withdrawal(validator_address, pool_address, true, observed_lockup_cycle + 1, false, 104060401001);
3398+
assert_pending_withdrawal(delegator_address, pool_address, false, 0, false, 0);
33903399
end_aptos_epoch();
3391-
assert_pending_withdrawal(validator_address, pool_address, true, 1, false, 105101005010);
3392-
assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, 10201000002);
3400+
// Only the validator's pending_inactive earns rewards here (delegator has none).
3401+
assert_pending_withdrawal(validator_address, pool_address, true, observed_lockup_cycle + 1, false, 105101005011);
3402+
assert_pending_withdrawal(delegator_address, pool_address, false, 0, false, 0);
33933403
}
33943404

33953405
#[test(aptos_framework = @aptos_framework, validator = @0x123)]

0 commit comments

Comments
 (0)