Feature/blk 1005 delegator restaking#388
Open
sfffaaa wants to merge 7 commits into
Open
Conversation
added 3 commits
July 3, 2026 18:13
Delegator staking rewards are restaked automatically at payout time instead of landing in free balance; each reward is added to the delegator's bonded stake and their collator. Collator rewards stay liquid. Two-phase (preflight -> transfer -> infallible commit) payout in on_finalize; increase_lock_from_reward leaves pending Unstaking untouched; all delegators of a collator share one candidate (batch-flushed once). on_initialize conditionally reserves the payout weight; do_try_state asserts totals + the STAKING_ID lock invariant (incl. fully-exited accounts). New DelegatorRewardRestaked / DelegatorRewardPaidNotRestaked events; reward for round R restakes in R+1, compounds from R+2. Design: inline restake at payout over a deferred queue -- no new storage/migration/keeper; per-block delegator count already bounded by MaxDelegatorsPerCollator.
…e benchmarks Add payout_collator (1 collator x n delegators = the per-block payout worst case) and prepare_delayed_rewards (n collators x m delegators = the session-boundary snapshot block, the heaviest single block in the flow) benchmarks, so both heavy blocks are measurable for weight/PoV. weights.rs keeps a conservative placeholder for payout_collator until the CLI numbers are generated. Fix two pre-existing benchmarks broken by round rotation moving to pallet_session: remove on_initialize_round_update, repair execute_leave_candidates (bump Round.current directly).
added 3 commits
July 8, 2026 10:48
…nd snapshot Replace the hand-estimated payout_collator weight and the manual reads_writes plumbing in prepare_delayed_rewards with the numbers generated by the frame-benchmarking CLI (delegator component measured to 100). - weightinfo.rs: declare prepare_delayed_rewards(n, m) in the trait - weights.rs: benchmarked payout_collator, add prepare_delayed_rewards - lib.rs: prepare_delayed_rewards now returns WeightInfo::prepare_delayed_rewards(n, m); the manual read/write tally (and the helper weight returns it summed) are dropped in favor of the measured weight.
|
The preview deployment for peaqnetwork/peaq-network-node:ci/012453_add-auto-upgrade-on-preview-environment-iswg08ckww0c4k48oggoo400 is ready. 🟢 Open Preview | Open Build Logs Last updated at: 2026-07-08 09:40:51 CET |
… observable The reward payout runs in on_finalize (Mandatory): it must neither panic nor silently lose funds. Harden the path: - Log every failed pot -> account transfer (restake, plain-payout fallback, and collator reward) instead of skipping the reward with no signal. The failure is still handled (skip, never propagate); it is now visible. - Replace the expect() in get_delgators_reward_per_session with truncate_from: the vec can never exceed MaxDelegatorsPerCollator (1:1 map over a bounded snapshot), but truncate_from cannot panic in the Mandatory hook and logs the provably-impossible overflow. - Use saturating add/sub in the reward math so arithmetic can never panic on overflow (values are bounded by issuance; belt-and-braces). No happy-path behavior change; 78 pallet tests still pass.
|
The preview deployment for peaqnetwork/peaq-network-node:ci/012453_add-auto-upgrade-on-preview-environment-iswg08ckww0c4k48oggoo400 is ready. 🟢 Open Preview | Open Build Logs Last updated at: 2026-07-09 10:21:44 CET |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Delegator staking rewards are restaked in place — added to the delegator's balance
lock, its delegation to that collator, and the collator's total — instead of paid out
as liquid balance. Every delegator auto-compounds with no keeper transaction and no
user action; a delegator wanting cash calls
delegator_stake_less(14-day unbondingon peaq, 7 on krest).
What changed
payout_collatoris reworked into a two-phase (preflight → commit) payout per delegator reward:lock exists, no overflow); Phase 2 does only guaranteed-success writes. Required because
on_finalizeis Mandatory class and cannot revert — "pay then fail midway" is split-brain.update_top_candidates+CandidatePool/TotalCollatorStakewrite), keeping the loop O(m·log m).Also:
increase_lock_from_reward— adds the reward to the lock without touching pendingUnstaking(reusingincrease_lockwould silently consume queued withdrawals; soledivergence from
delegator_stake_more).DelegatorRewardRestaked(compounded) /DelegatorRewardPaidNotRestaked(fallback).try_stateinvariants (the pallet had none):lock == total + Σ Unstaking,candidate.total == Σ stakes + self,TotalCollatorStake == Σ selected.on_initialize— reserve the heavy payout weight only when apayout is pending (
DelayedPayoutInfo::exists()), so idle blocks keep their capacity.payout_collatorandprepare_delayed_rewards(delegator component to100); fixed two pre-existing stale benchmarks that broke when round rotation moved to Session.
AUTO_RESTAKE.md— indexer/wallet migration note + user withdrawal note.Design decisions
blocks, but per-block PoV/weight has large headroom, so deferral is unnecessary; inline
reuses existing code with zero new storage.
delegator_stake_lessis the opt-out.Test plan
paths, zero-reward skip, batch at 100, compounding, session-boundary ordering,
try_state, idempotency, 0/1-delegator boundary, EVM-precompile contract).
payout_collatorat m=100 → proof_size 377 kB (< 500 kB), ref_time18.9 ms (< 100 ms).
on a local parachain, on both the peaq-dev and peaq mainnet runtimes: 6400 delegators
restaked, 0 failures, verified block-by-block; the heavy snapshot block never stalls
(real PoV ~410 kB = 8% of the 5 MiB budget).
Note
These weights are machine-generated by the frame-benchmarking CLI (peaq-node benchmark pallet --chain dev-local --pallet parachain_staking --extrinsic payout_collator --steps 20 --repeat 5, same for prepare_delayed_rewards), not hand-tuned. It runs each call ~100 times across a sweep of the delegator/collator counts and linear-regresses to the intercept + slope·n coefficients, so from_parts(ref_time, proof_size) is measured compute-picoseconds plus worst-case PoV bytes, with the base taken as the regression intercept — a safe upper bound above the fastest run. At the 64×100 mainnet ceiling that's ≈18.9 ms / ≈377 KiB PoV for payout_collator, and the snapshot's PoV scales with collator count only, so it stays well within the block PoV budget.