Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sui-framework] cap staking rewards using voting power #10011

Merged
merged 1 commit into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -240,56 +240,56 @@ validators:
next_epoch_worker_address: ~
extra_fields:
id:
id: "0x4698a1200a083f745edbeb4b6e14ecb87b93b10622693e17dee6155a9cfd16d0"
id: "0x2c57ac797096d821f01f7f417c3d29bc895cec4090669c68cbe5245056c44b61"
size: 0
voting_power: 10000
operation_cap_id: "0xafda133167a4d1f2277c993b997df94a8d6d7f9d3c4435e759cdc26b733d915d"
operation_cap_id: "0xf01e395f91fee123e9c6b4b13cfaee2aaebc9f81fca3e328e7d0b58b4aeb9ffe"
gas_price: 1000
staking_pool:
id: "0xe213928b716ca14d2f05da96b084f82a55debb66cfc3933ca12d44adb419f653"
id: "0x6a88c152225d331ccd2e87322722785be7269b8a732daf4965eb226cd237c1c3"
activation_epoch: 0
deactivation_epoch: ~
sui_balance: 20000000000000000
rewards_pool:
value: 0
pool_token_balance: 20000000000000000
exchange_rates:
id: "0x44d2d2e6c3ede295ec416a9de2b01d86bf0ab9aa47c06c2094037b336988c282"
id: "0xcf11258f4a7319021d11e25afb72baa71d8543181b92ee7c62e228975db4a678"
size: 1
pending_stake: 0
pending_total_sui_withdraw: 0
pending_pool_token_withdraw: 0
extra_fields:
id:
id: "0xa5fa3db0c1b873fdf5c473d48c308199767cddce39bc18931f7ada5f286a05d7"
id: "0x798e438d12c7dafe7be9281e72b6e86c233566f9aebc669a8c35787c64e49220"
size: 0
commission_rate: 200
next_epoch_stake: 20000000000000000
next_epoch_gas_price: 1000
next_epoch_commission_rate: 200
extra_fields:
id:
id: "0x3e227a71ae680ce3d4c0de8412e4dec8acbf85a3a8da8a9ceba716626a201852"
id: "0x924d417ff92e8e31ea5773677659aedab23388169a66578a3fa0f970c8f330d1"
size: 0
pending_active_validators:
contents:
id: "0xf8da2b06e312c975a0bab7050174c3c25e5ef5be61529369915311c738d73646"
id: "0x9afb79741e72a743155bcbe8c3a9bcbaf894f641a8a8760f8596537af14d9b62"
size: 0
pending_removals: []
staking_pool_mappings:
id: "0x091312e62799d01fbddb9f66995076d6fab22477c35bf1f716ecb180763deb1a"
id: "0x0b767ac173ddec6621e78fa147c44c181840155ffbb64f770c2a0f4f0154a505"
size: 1
inactive_validators:
id: "0x0adb50e8df4da0eae33d2f885e6b3d2a875ef565bf2a38ca2c36043fa3287963"
id: "0x03e06386abda2843e5d82cc78927a231325db5bd1764c09ad9c3028e70c2b2fa"
size: 0
validator_candidates:
id: "0x8842a624a3cf90e6b6e194d9b4ae84db71e19d32ef00cca0e9774a208fde9f11"
id: "0xbde7a9d543e37e50a68ad7fc28a07cdb43ca5ff541344f2b4b3bdf5a12806f1d"
size: 0
at_risk_validators:
contents: []
extra_fields:
id:
id: "0xd7f77c52ee9fe2df95a30f84cee701d400de984347937450c4759691c06947a7"
id: "0xc5cb7edb8f81a9c90edd9cfa3358ab462824c6e528b710ce675c2667e17a73cb"
size: 0
storage_fund:
total_object_storage_rebates:
Expand All @@ -306,7 +306,7 @@ parameters:
validator_low_stake_grace_period: 7
extra_fields:
id:
id: "0x20568512514b67fcf2fcc90404346ab79941a6459d2410e7bc2dfcaf2275b05d"
id: "0x5363d2185302242c32532eb3ffbac714eed754f906a01527764f769116cbb088"
size: 0
reference_gas_price: 1000
validator_report_records:
Expand All @@ -320,7 +320,7 @@ stake_subsidy:
stake_subsidy_decrease_rate: 10000
extra_fields:
id:
id: "0xbe6150357ceb092bc8e6389d641a21be177ec82909345126e20f85201f98e3a6"
id: "0x44d17fd2664b4be905d0692cdd423104cc9cab24284cda707e99c6fc233baf3d"
size: 0
safe_mode: false
safe_mode_storage_rewards:
Expand All @@ -332,6 +332,6 @@ safe_mode_non_refundable_storage_fee: 0
epoch_start_timestamp_ms: 10
extra_fields:
id:
id: "0x39dc6f66d0d0c99bb6a015ae15b9505c00aab9420592bb4cf0e5cf9cdb3cb707"
id: "0x11524b3694567f917f11b7f14ff0497bc09d98bcba7a45ca646b3435a6545323"
size: 0

56 changes: 26 additions & 30 deletions crates/sui-framework/docs/validator_set.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
- [Function `calculate_total_stakes`](#0x3_validator_set_calculate_total_stakes)
- [Function `adjust_stake_and_gas_price`](#0x3_validator_set_adjust_stake_and_gas_price)
- [Function `compute_reward_adjustments`](#0x3_validator_set_compute_reward_adjustments)
- [Function `compute_slashed_validators_and_total_stake`](#0x3_validator_set_compute_slashed_validators_and_total_stake)
- [Function `compute_slashed_validators`](#0x3_validator_set_compute_slashed_validators)
- [Function `compute_unadjusted_reward_distribution`](#0x3_validator_set_compute_unadjusted_reward_distribution)
- [Function `compute_adjusted_reward_distribution`](#0x3_validator_set_compute_adjusted_reward_distribution)
- [Function `distribute_reward`](#0x3_validator_set_distribute_reward)
Expand Down Expand Up @@ -926,23 +926,21 @@ It does the following things:
ctx: &<b>mut</b> TxContext,
) {
<b>let</b> new_epoch = <a href="_epoch">tx_context::epoch</a>(ctx) + 1;
<b>let</b> total_stake = self.total_stake;
<b>let</b> total_voting_power = <a href="voting_power.md#0x3_voting_power_total_voting_power">voting_power::total_voting_power</a>();

// Compute the reward distribution without taking into account the tallying rule slashing.
<b>let</b> (unadjusted_staking_reward_amounts, unadjusted_storage_fund_reward_amounts) = <a href="validator_set.md#0x3_validator_set_compute_unadjusted_reward_distribution">compute_unadjusted_reward_distribution</a>(
&self.active_validators,
total_stake,
total_voting_power,
<a href="_value">balance::value</a>(computation_reward),
<a href="_value">balance::value</a>(storage_fund_reward),
);

// Use the tallying rule report records for the epoch <b>to</b> compute validators that will be
// punished and the sum of their stakes.
<b>let</b> (slashed_validators, total_slashed_validator_stake) =
<a href="validator_set.md#0x3_validator_set_compute_slashed_validators_and_total_stake">compute_slashed_validators_and_total_stake</a>(
self,
*validator_report_records,
);
// punished.
<b>let</b> slashed_validators = <a href="validator_set.md#0x3_validator_set_compute_slashed_validators">compute_slashed_validators</a>(self, *validator_report_records);

<b>let</b> total_slashed_validator_voting_power = <a href="validator_set.md#0x3_validator_set_sum_voting_power_by_addresses">sum_voting_power_by_addresses</a>(&self.active_validators, &slashed_validators);

// Compute the reward adjustments of slashed validators, <b>to</b> be taken into
// account in adjusted reward computation.
Expand All @@ -962,8 +960,8 @@ It does the following things:
// make sure we are using the current epoch's stake information <b>to</b> compute reward distribution.
<b>let</b> (adjusted_staking_reward_amounts, adjusted_storage_fund_reward_amounts) = <a href="validator_set.md#0x3_validator_set_compute_adjusted_reward_distribution">compute_adjusted_reward_distribution</a>(
&self.active_validators,
total_stake,
total_slashed_validator_stake,
total_voting_power,
total_slashed_validator_voting_power,
unadjusted_staking_reward_amounts,
unadjusted_storage_fund_reward_amounts,
total_staking_reward_adjustment,
Expand Down Expand Up @@ -2331,15 +2329,15 @@ as well as storage fund rewards.

</details>

<a name="0x3_validator_set_compute_slashed_validators_and_total_stake"></a>
<a name="0x3_validator_set_compute_slashed_validators"></a>

## Function `compute_slashed_validators_and_total_stake`
## Function `compute_slashed_validators`

Process the validator report records of the epoch and return the addresses of the
non-performant validators according to the input threshold.


<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_slashed_validators_and_total_stake">compute_slashed_validators_and_total_stake</a>(self: &<a href="validator_set.md#0x3_validator_set_ValidatorSet">validator_set::ValidatorSet</a>, validator_report_records: <a href="_VecMap">vec_map::VecMap</a>&lt;<b>address</b>, <a href="_VecSet">vec_set::VecSet</a>&lt;<b>address</b>&gt;&gt;): (<a href="">vector</a>&lt;<b>address</b>&gt;, u64)
<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_slashed_validators">compute_slashed_validators</a>(self: &<a href="validator_set.md#0x3_validator_set_ValidatorSet">validator_set::ValidatorSet</a>, validator_report_records: <a href="_VecMap">vec_map::VecMap</a>&lt;<b>address</b>, <a href="_VecSet">vec_set::VecSet</a>&lt;<b>address</b>&gt;&gt;): <a href="">vector</a>&lt;<b>address</b>&gt;
</code></pre>


Expand All @@ -2348,12 +2346,11 @@ non-performant validators according to the input threshold.
<summary>Implementation</summary>


<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_slashed_validators_and_total_stake">compute_slashed_validators_and_total_stake</a>(
<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_slashed_validators">compute_slashed_validators</a>(
self: &<a href="validator_set.md#0x3_validator_set_ValidatorSet">ValidatorSet</a>,
validator_report_records: VecMap&lt;<b>address</b>, VecSet&lt;<b>address</b>&gt;&gt;,
): (<a href="">vector</a>&lt;<b>address</b>&gt;, u64) {
): <a href="">vector</a>&lt;<b>address</b>&gt; {
<b>let</b> slashed_validators = <a href="">vector</a>[];
<b>let</b> sum_of_stake = 0;
<b>while</b> (!<a href="_is_empty">vec_map::is_empty</a>(&validator_report_records)) {
<b>let</b> (validator_address, reporters) = <a href="_pop">vec_map::pop</a>(&<b>mut</b> validator_report_records);
<b>assert</b>!(
Expand All @@ -2364,11 +2361,10 @@ non-performant validators according to the input threshold.
// passed the slashing threshold.
<b>let</b> reporter_votes = <a href="validator_set.md#0x3_validator_set_sum_voting_power_by_addresses">sum_voting_power_by_addresses</a>(&self.active_validators, &<a href="_into_keys">vec_set::into_keys</a>(reporters));
<b>if</b> (reporter_votes &gt;= <a href="voting_power.md#0x3_voting_power_quorum_threshold">voting_power::quorum_threshold</a>()) {
sum_of_stake = sum_of_stake + <a href="validator_set.md#0x3_validator_set_validator_total_stake_amount">validator_total_stake_amount</a>(self, validator_address);
<a href="_push_back">vector::push_back</a>(&<b>mut</b> slashed_validators, validator_address);
}
};
(slashed_validators, sum_of_stake)
slashed_validators
}
</code></pre>

Expand All @@ -2386,7 +2382,7 @@ account the tallyig rule results.
Returns the unadjusted amounts of staking reward and storage fund reward for each validator.


<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_unadjusted_reward_distribution">compute_unadjusted_reward_distribution</a>(validators: &<a href="">vector</a>&lt;<a href="validator.md#0x3_validator_Validator">validator::Validator</a>&gt;, total_stake: u64, total_staking_reward: u64, total_storage_fund_reward: u64): (<a href="">vector</a>&lt;u64&gt;, <a href="">vector</a>&lt;u64&gt;)
<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_unadjusted_reward_distribution">compute_unadjusted_reward_distribution</a>(validators: &<a href="">vector</a>&lt;<a href="validator.md#0x3_validator_Validator">validator::Validator</a>&gt;, total_voting_power: u64, total_staking_reward: u64, total_storage_fund_reward: u64): (<a href="">vector</a>&lt;u64&gt;, <a href="">vector</a>&lt;u64&gt;)
</code></pre>


Expand All @@ -2397,7 +2393,7 @@ Returns the unadjusted amounts of staking reward and storage fund reward for eac

<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_unadjusted_reward_distribution">compute_unadjusted_reward_distribution</a>(
validators: &<a href="">vector</a>&lt;Validator&gt;,
total_stake: u64,
total_voting_power: u64,
total_staking_reward: u64,
total_storage_fund_reward: u64,
): (<a href="">vector</a>&lt;u64&gt;, <a href="">vector</a>&lt;u64&gt;) {
Expand All @@ -2411,8 +2407,8 @@ Returns the unadjusted amounts of staking reward and storage fund reward for eac
// Integer divisions will truncate the results. Because of this, we expect that at the end
// there will be some reward remaining in `total_staking_reward`.
// Use u128 <b>to</b> avoid multiplication overflow.
<b>let</b> stake_amount: u128 = (<a href="validator.md#0x3_validator_total_stake_amount">validator::total_stake_amount</a>(<a href="validator.md#0x3_validator">validator</a>) <b>as</b> u128);
<b>let</b> reward_amount = stake_amount * (total_staking_reward <b>as</b> u128) / (total_stake <b>as</b> u128);
<b>let</b> <a href="voting_power.md#0x3_voting_power">voting_power</a>: u128 = (<a href="validator.md#0x3_validator_voting_power">validator::voting_power</a>(<a href="validator.md#0x3_validator">validator</a>) <b>as</b> u128);
<b>let</b> reward_amount = <a href="voting_power.md#0x3_voting_power">voting_power</a> * (total_staking_reward <b>as</b> u128) / (total_voting_power <b>as</b> u128);
<a href="_push_back">vector::push_back</a>(&<b>mut</b> staking_reward_amounts, (reward_amount <b>as</b> u64));
// Storage fund's share of the rewards are equally distributed among validators.
<a href="_push_back">vector::push_back</a>(&<b>mut</b> storage_fund_reward_amounts, storage_fund_reward_per_validator);
Expand All @@ -2435,7 +2431,7 @@ Returns the staking rewards each validator gets and the storage fund rewards eac
The staking rewards are shared with the stakers while the storage fund ones are not.


<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_adjusted_reward_distribution">compute_adjusted_reward_distribution</a>(validators: &<a href="">vector</a>&lt;<a href="validator.md#0x3_validator_Validator">validator::Validator</a>&gt;, total_stake: u64, total_slashed_validator_stake: u64, unadjusted_staking_reward_amounts: <a href="">vector</a>&lt;u64&gt;, unadjusted_storage_fund_reward_amounts: <a href="">vector</a>&lt;u64&gt;, total_staking_reward_adjustment: u64, individual_staking_reward_adjustments: <a href="_VecMap">vec_map::VecMap</a>&lt;u64, u64&gt;, total_storage_fund_reward_adjustment: u64, individual_storage_fund_reward_adjustments: <a href="_VecMap">vec_map::VecMap</a>&lt;u64, u64&gt;): (<a href="">vector</a>&lt;u64&gt;, <a href="">vector</a>&lt;u64&gt;)
<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_adjusted_reward_distribution">compute_adjusted_reward_distribution</a>(validators: &<a href="">vector</a>&lt;<a href="validator.md#0x3_validator_Validator">validator::Validator</a>&gt;, total_voting_power: u64, total_slashed_validator_voting_power: u64, unadjusted_staking_reward_amounts: <a href="">vector</a>&lt;u64&gt;, unadjusted_storage_fund_reward_amounts: <a href="">vector</a>&lt;u64&gt;, total_staking_reward_adjustment: u64, individual_staking_reward_adjustments: <a href="_VecMap">vec_map::VecMap</a>&lt;u64, u64&gt;, total_storage_fund_reward_adjustment: u64, individual_storage_fund_reward_adjustments: <a href="_VecMap">vec_map::VecMap</a>&lt;u64, u64&gt;): (<a href="">vector</a>&lt;u64&gt;, <a href="">vector</a>&lt;u64&gt;)
</code></pre>


Expand All @@ -2446,16 +2442,16 @@ The staking rewards are shared with the stakers while the storage fund ones are

<pre><code><b>fun</b> <a href="validator_set.md#0x3_validator_set_compute_adjusted_reward_distribution">compute_adjusted_reward_distribution</a>(
validators: &<a href="">vector</a>&lt;Validator&gt;,
total_stake: u64,
total_slashed_validator_stake: u64,
total_voting_power: u64,
total_slashed_validator_voting_power: u64,
unadjusted_staking_reward_amounts: <a href="">vector</a>&lt;u64&gt;,
unadjusted_storage_fund_reward_amounts: <a href="">vector</a>&lt;u64&gt;,
total_staking_reward_adjustment: u64,
individual_staking_reward_adjustments: VecMap&lt;u64, u64&gt;,
total_storage_fund_reward_adjustment: u64,
individual_storage_fund_reward_adjustments: VecMap&lt;u64, u64&gt;,
): (<a href="">vector</a>&lt;u64&gt;, <a href="">vector</a>&lt;u64&gt;) {
<b>let</b> total_unslashed_validator_stake = total_stake - total_slashed_validator_stake;
<b>let</b> total_unslashed_validator_voting_power = total_voting_power - total_slashed_validator_voting_power;
<b>let</b> adjusted_staking_reward_amounts = <a href="_empty">vector::empty</a>();
<b>let</b> adjusted_storage_fund_reward_amounts = <a href="_empty">vector::empty</a>();

Expand All @@ -2468,7 +2464,7 @@ The staking rewards are shared with the stakers while the storage fund ones are
// Integer divisions will truncate the results. Because of this, we expect that at the end
// there will be some reward remaining in `total_reward`.
// Use u128 <b>to</b> avoid multiplication overflow.
<b>let</b> stake_amount: u128 = (<a href="validator.md#0x3_validator_total_stake_amount">validator::total_stake_amount</a>(<a href="validator.md#0x3_validator">validator</a>) <b>as</b> u128);
<b>let</b> <a href="voting_power.md#0x3_voting_power">voting_power</a>: u128 = (<a href="validator.md#0x3_validator_voting_power">validator::voting_power</a>(<a href="validator.md#0x3_validator">validator</a>) <b>as</b> u128);

// Compute adjusted staking reward.
<b>let</b> unadjusted_staking_reward_amount = *<a href="_borrow">vector::borrow</a>(&unadjusted_staking_reward_amounts, i);
Expand All @@ -2480,8 +2476,8 @@ The staking rewards are shared with the stakers while the storage fund ones are
} <b>else</b> {
// Otherwise the slashed rewards should be distributed among the unslashed
// validators so add the corresponding adjustment.
<b>let</b> adjustment = (total_staking_reward_adjustment <b>as</b> u128) * stake_amount
/ (total_unslashed_validator_stake <b>as</b> u128);
<b>let</b> adjustment = (total_staking_reward_adjustment <b>as</b> u128) * <a href="voting_power.md#0x3_voting_power">voting_power</a>
/ (total_unslashed_validator_voting_power <b>as</b> u128);
unadjusted_staking_reward_amount + (adjustment <b>as</b> u64)
};
<a href="_push_back">vector::push_back</a>(&<b>mut</b> adjusted_staking_reward_amounts, adjusted_staking_reward_amount);
Expand Down
Loading