Skip to content

Commit

Permalink
validator: add voting power (MystenLabs#7392)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmazzz authored Jan 14, 2023
1 parent 3acef24 commit 9ea6273
Show file tree
Hide file tree
Showing 11 changed files with 286 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ epoch: 0
validators:
validator_stake: 1
delegation_stake: 0
quorum_stake_threshold: 1
total_voting_power: 1
quorum_threshold: 1
active_validators:
- metadata:
sui_address: "0x21b60aa9a8cb189ccbe20461dbfad2202fdef55b"
Expand Down Expand Up @@ -237,6 +238,7 @@ validators:
next_epoch_delegation: 0
next_epoch_gas_price: 1
next_epoch_commission_rate: 0
voting_power: 1
stake_amount: 1
pending_stake: 0
pending_withdraw: 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ expression: common_costs_estimate
---
{
"MergeCoin": {
"computation_cost": 7112,
"storage_cost": 10209,
"computation_cost": 7159,
"storage_cost": 10279,
"storage_rebate": 0
},
"Publish": {
"computation_cost": 7971,
"storage_cost": 11412,
"computation_cost": 8018,
"storage_cost": 11482,
"storage_rebate": 0
},
"SharedCounterAssertValue": {
Expand All @@ -29,8 +29,8 @@ expression: common_costs_estimate
"storage_rebate": 0
},
"SplitCoin": {
"computation_cost": 7090,
"storage_cost": 10177,
"computation_cost": 7137,
"storage_cost": 10246,
"storage_rebate": 0
},
"TransferPortionSuiCoin": {
Expand Down
64 changes: 64 additions & 0 deletions crates/sui-framework/docs/validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
- [Function `stake_amount`](#0x2_validator_stake_amount)
- [Function `delegate_amount`](#0x2_validator_delegate_amount)
- [Function `total_stake`](#0x2_validator_total_stake)
- [Function `voting_power`](#0x2_validator_voting_power)
- [Function `set_voting_power`](#0x2_validator_set_voting_power)
- [Function `pending_stake_amount`](#0x2_validator_pending_stake_amount)
- [Function `pending_withdraw`](#0x2_validator_pending_withdraw)
- [Function `gas_price`](#0x2_validator_gas_price)
Expand Down Expand Up @@ -195,6 +197,13 @@
Summary of the validator.
</dd>
<dt>
<code>voting_power: u64</code>
</dt>
<dd>
The voting power of this validator, which might be different from its
stake amount.
</dd>
<dt>
<code>stake_amount: u64</code>
</dt>
<dd>
Expand Down Expand Up @@ -355,6 +364,10 @@
next_epoch_gas_price: gas_price,
next_epoch_commission_rate: commission_rate,
},
// Initialize the voting power <b>to</b> be the same <b>as</b> the <a href="stake.md#0x2_stake">stake</a> amount.
// At the epoch change <b>where</b> this <a href="validator.md#0x2_validator">validator</a> is actually added <b>to</b> the
// active <a href="validator.md#0x2_validator">validator</a> set, the voting power will be updated accordingly.
voting_power: stake_amount,
stake_amount,
pending_stake: 0,
pending_withdraw: 0,
Expand Down Expand Up @@ -387,6 +400,7 @@
<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="validator.md#0x2_validator_destroy">destroy</a>(self: <a href="validator.md#0x2_validator_Validator">Validator</a>, ctx: &<b>mut</b> TxContext) {
<b>let</b> <a href="validator.md#0x2_validator_Validator">Validator</a> {
metadata: _,
voting_power: _,
stake_amount: _,
pending_stake: _,
pending_withdraw: _,
Expand Down Expand Up @@ -843,6 +857,56 @@ Return the total amount staked with this validator, including both validator sta



</details>

<a name="0x2_validator_voting_power"></a>

## Function `voting_power`

Return the voting power of this validator.


<pre><code><b>public</b> <b>fun</b> <a href="validator.md#0x2_validator_voting_power">voting_power</a>(self: &<a href="validator.md#0x2_validator_Validator">validator::Validator</a>): u64
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="validator.md#0x2_validator_voting_power">voting_power</a>(self: &<a href="validator.md#0x2_validator_Validator">Validator</a>): u64 {
self.voting_power
}
</code></pre>



</details>

<a name="0x2_validator_set_voting_power"></a>

## Function `set_voting_power`

Set the voting power of this validator, called only from validator_set.


<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="validator.md#0x2_validator_set_voting_power">set_voting_power</a>(self: &<b>mut</b> <a href="validator.md#0x2_validator_Validator">validator::Validator</a>, new_voting_power: u64)
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="validator.md#0x2_validator_set_voting_power">set_voting_power</a>(self: &<b>mut</b> <a href="validator.md#0x2_validator_Validator">Validator</a>, new_voting_power: u64) {
self.voting_power = new_voting_power;
}
</code></pre>



</details>

<a name="0x2_validator_pending_stake_amount"></a>
Expand Down
135 changes: 107 additions & 28 deletions crates/sui-framework/docs/validator_set.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
- [Function `request_set_gas_price`](#0x2_validator_set_request_set_gas_price)
- [Function `request_set_commission_rate`](#0x2_validator_set_request_set_commission_rate)
- [Function `advance_epoch`](#0x2_validator_set_advance_epoch)
- [Function `update_validator_voting_power`](#0x2_validator_set_update_validator_voting_power)
- [Function `derive_reference_gas_price`](#0x2_validator_set_derive_reference_gas_price)
- [Function `total_voting_power`](#0x2_validator_set_total_voting_power)
- [Function `total_validator_stake`](#0x2_validator_set_total_validator_stake)
- [Function `total_delegation_stake`](#0x2_validator_set_total_delegation_stake)
- [Function `validator_stake_amount`](#0x2_validator_set_validator_stake_amount)
Expand All @@ -37,8 +39,8 @@
- [Function `sort_removal_list`](#0x2_validator_set_sort_removal_list)
- [Function `process_pending_delegation_switches`](#0x2_validator_set_process_pending_delegation_switches)
- [Function `process_pending_delegations_and_withdraws`](#0x2_validator_set_process_pending_delegations_and_withdraws)
- [Function `calculate_total_stake_and_quorum_threshold`](#0x2_validator_set_calculate_total_stake_and_quorum_threshold)
- [Function `calculate_quorum_threshold`](#0x2_validator_set_calculate_quorum_threshold)
- [Function `calculate_total_stakes`](#0x2_validator_set_calculate_total_stakes)
- [Function `calculate_total_voting_power_and_quorum_threshold`](#0x2_validator_set_calculate_total_voting_power_and_quorum_threshold)
- [Function `adjust_stake_and_gas_price`](#0x2_validator_set_adjust_stake_and_gas_price)
- [Function `compute_reward_distribution`](#0x2_validator_set_compute_reward_distribution)
- [Function `distribute_reward`](#0x2_validator_set_distribute_reward)
Expand Down Expand Up @@ -92,14 +94,20 @@
<code>total_delegation_stake: u64</code>
</dt>
<dd>
Total amount of stake from delegation, at the beginning of the epoch.
Total amount of stake from delegation, at the beginning of the epoch.
</dd>
<dt>
<code>quorum_stake_threshold: u64</code>
<code>total_voting_power: u64</code>
</dt>
<dd>
The amount of accumulated stake to reach a quorum among all active validators.
This is always 2/3 of total stake. Keep it here to reduce potential inconsistencies
Sum of voting power of validators.
</dd>
<dt>
<code>quorum_threshold: u64</code>
</dt>
<dd>
The amount of accumulated voting power to reach a quorum among all active validators.
This is always 2/3 of total voting power. Keep it here to reduce potential inconsistencies
among validators.
</dd>
<dt>
Expand Down Expand Up @@ -334,18 +342,23 @@ each validator, emitted during epoch advancement.


<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="validator_set.md#0x2_validator_set_new">new</a>(init_active_validators: <a href="">vector</a>&lt;Validator&gt;): <a href="validator_set.md#0x2_validator_set_ValidatorSet">ValidatorSet</a> {
<b>let</b> (total_validator_stake, total_delegation_stake, quorum_stake_threshold) = <a href="validator_set.md#0x2_validator_set_calculate_total_stake_and_quorum_threshold">calculate_total_stake_and_quorum_threshold</a>(&init_active_validators);
<b>let</b> (total_validator_stake, total_delegation_stake) =
<a href="validator_set.md#0x2_validator_set_calculate_total_stakes">calculate_total_stakes</a>(&init_active_validators);
<b>let</b> (total_voting_power, quorum_threshold) =
<a href="validator_set.md#0x2_validator_set_calculate_total_voting_power_and_quorum_threshold">calculate_total_voting_power_and_quorum_threshold</a>(&init_active_validators);
<b>let</b> validators = <a href="validator_set.md#0x2_validator_set_ValidatorSet">ValidatorSet</a> {
total_validator_stake,
total_delegation_stake,
quorum_stake_threshold,
total_voting_power,
quorum_threshold,
active_validators: init_active_validators,
pending_validators: <a href="_empty">vector::empty</a>(),
pending_removals: <a href="_empty">vector::empty</a>(),
next_epoch_validators: <a href="_empty">vector::empty</a>(),
pending_delegation_switches: <a href="vec_map.md#0x2_vec_map_empty">vec_map::empty</a>(),
};
validators.next_epoch_validators = <a href="validator_set.md#0x2_validator_set_derive_next_epoch_validators">derive_next_epoch_validators</a>(&validators);
<a href="validator_set.md#0x2_validator_set_update_validator_voting_power">update_validator_voting_power</a>(&<b>mut</b> validators);
validators
}
</code></pre>
Expand Down Expand Up @@ -784,12 +797,51 @@ It does the following things:

<a href="validator_set.md#0x2_validator_set_process_pending_removals">process_pending_removals</a>(self, ctx);

// Update the voting power of each <a href="validator.md#0x2_validator">validator</a>, now that the pending <a href="validator.md#0x2_validator">validator</a> additions
// and the removals have been processed.
<a href="validator_set.md#0x2_validator_set_update_validator_voting_power">update_validator_voting_power</a>(self);

self.next_epoch_validators = <a href="validator_set.md#0x2_validator_set_derive_next_epoch_validators">derive_next_epoch_validators</a>(self);

<b>let</b> (validator_stake, delegation_stake, quorum_stake_threshold) = <a href="validator_set.md#0x2_validator_set_calculate_total_stake_and_quorum_threshold">calculate_total_stake_and_quorum_threshold</a>(&self.active_validators);
<b>let</b> (validator_stake, delegation_stake) = <a href="validator_set.md#0x2_validator_set_calculate_total_stakes">calculate_total_stakes</a>(&self.active_validators);
self.total_validator_stake = validator_stake;
self.total_delegation_stake = delegation_stake;
self.quorum_stake_threshold = quorum_stake_threshold;

<b>let</b> (total_voting_power, quorum_threshold) =
<a href="validator_set.md#0x2_validator_set_calculate_total_voting_power_and_quorum_threshold">calculate_total_voting_power_and_quorum_threshold</a>(&self.active_validators);
self.total_voting_power = total_voting_power;
self.quorum_threshold = quorum_threshold;
}
</code></pre>



</details>

<a name="0x2_validator_set_update_validator_voting_power"></a>

## Function `update_validator_voting_power`



<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_update_validator_voting_power">update_validator_voting_power</a>(self: &<b>mut</b> <a href="validator_set.md#0x2_validator_set_ValidatorSet">validator_set::ValidatorSet</a>)
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_update_validator_voting_power">update_validator_voting_power</a>(self: &<b>mut</b> <a href="validator_set.md#0x2_validator_set_ValidatorSet">ValidatorSet</a>) {
<b>let</b> num_validators = <a href="_length">vector::length</a>(&self.active_validators);
<b>let</b> i = 0;
<b>while</b> (i &lt; num_validators) {
<b>let</b> validator_mut = <a href="_borrow_mut">vector::borrow_mut</a>(&<b>mut</b> self.active_validators, i);
<b>let</b> updated_voting_power = <a href="validator.md#0x2_validator_total_stake">validator::total_stake</a>(validator_mut);
<a href="validator.md#0x2_validator_set_voting_power">validator::set_voting_power</a>(validator_mut, updated_voting_power);
i = i + 1;
};
}
</code></pre>

Expand Down Expand Up @@ -833,7 +885,7 @@ gas price, weighted by stake.
// Build a priority queue that will pop entries <b>with</b> gas price from the highest <b>to</b> the lowest.
<b>let</b> pq = pq::new(entries);
<b>let</b> sum = 0;
<b>let</b> threshold = (<a href="validator_set.md#0x2_validator_set_total_validator_stake">total_validator_stake</a>(self) + <a href="validator_set.md#0x2_validator_set_total_delegation_stake">total_delegation_stake</a>(self)) / 3;
<b>let</b> threshold = self.total_voting_power - self.quorum_threshold;
<b>let</b> result = 0;
<b>while</b> (sum &lt; threshold) {
<b>let</b> (gas_price, <a href="stake.md#0x2_stake">stake</a>) = pq::pop_max(&<b>mut</b> pq);
Expand All @@ -846,6 +898,30 @@ gas price, weighted by stake.



</details>

<a name="0x2_validator_set_total_voting_power"></a>

## Function `total_voting_power`



<pre><code><b>public</b> <b>fun</b> <a href="validator_set.md#0x2_validator_set_total_voting_power">total_voting_power</a>(self: &<a href="validator_set.md#0x2_validator_set_ValidatorSet">validator_set::ValidatorSet</a>): u64
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="validator_set.md#0x2_validator_set_total_voting_power">total_voting_power</a>(self: &<a href="validator_set.md#0x2_validator_set_ValidatorSet">ValidatorSet</a>): u64 {
self.total_voting_power
}
</code></pre>



</details>

<a name="0x2_validator_set_total_validator_stake"></a>
Expand Down Expand Up @@ -1317,14 +1393,14 @@ Process all active validators' pending delegation deposits and withdraws.

</details>

<a name="0x2_validator_set_calculate_total_stake_and_quorum_threshold"></a>
<a name="0x2_validator_set_calculate_total_stakes"></a>

## Function `calculate_total_stake_and_quorum_threshold`
## Function `calculate_total_stakes`

Calculate the total active stake, and the amount of stake to reach quorum.
Calculate the total active validator and delegated stake.


<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_calculate_total_stake_and_quorum_threshold">calculate_total_stake_and_quorum_threshold</a>(validators: &<a href="">vector</a>&lt;<a href="validator.md#0x2_validator_Validator">validator::Validator</a>&gt;): (u64, u64, u64)
<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_calculate_total_stakes">calculate_total_stakes</a>(validators: &<a href="">vector</a>&lt;<a href="validator.md#0x2_validator_Validator">validator::Validator</a>&gt;): (u64, u64)
</code></pre>


Expand All @@ -1333,7 +1409,7 @@ Calculate the total active stake, and the amount of stake to reach quorum.
<summary>Implementation</summary>


<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_calculate_total_stake_and_quorum_threshold">calculate_total_stake_and_quorum_threshold</a>(validators: &<a href="">vector</a>&lt;Validator&gt;): (u64, u64, u64) {
<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_calculate_total_stakes">calculate_total_stakes</a>(validators: &<a href="">vector</a>&lt;Validator&gt;): (u64, u64) {
<b>let</b> validator_state = 0;
<b>let</b> delegate_stake = 0;
<b>let</b> length = <a href="_length">vector::length</a>(validators);
Expand All @@ -1344,25 +1420,22 @@ Calculate the total active stake, and the amount of stake to reach quorum.
delegate_stake = delegate_stake + <a href="validator.md#0x2_validator_delegate_amount">validator::delegate_amount</a>(v);
i = i + 1;
};
<b>let</b> total_stake = validator_state + delegate_stake;
(validator_state, delegate_stake, (total_stake + 1) * 2 / 3)
(validator_state, delegate_stake)
}
</code></pre>



</details>

<a name="0x2_validator_set_calculate_quorum_threshold"></a>
<a name="0x2_validator_set_calculate_total_voting_power_and_quorum_threshold"></a>

## Function `calculate_quorum_threshold`
## Function `calculate_total_voting_power_and_quorum_threshold`

Calculate the required percentage threshold to reach quorum.
With 3f + 1 validators, we can tolerate up to f byzantine ones.
Hence (2f + 1) / total is our threshold.
Calculate the total voting power, and the amount of voting power to reach quorum.


<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_calculate_quorum_threshold">calculate_quorum_threshold</a>(validators: &<a href="">vector</a>&lt;<a href="validator.md#0x2_validator_Validator">validator::Validator</a>&gt;): u8
<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_calculate_total_voting_power_and_quorum_threshold">calculate_total_voting_power_and_quorum_threshold</a>(validators: &<a href="">vector</a>&lt;<a href="validator.md#0x2_validator_Validator">validator::Validator</a>&gt;): (u64, u64)
</code></pre>


Expand All @@ -1371,10 +1444,16 @@ Hence (2f + 1) / total is our threshold.
<summary>Implementation</summary>


<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_calculate_quorum_threshold">calculate_quorum_threshold</a>(validators: &<a href="">vector</a>&lt;Validator&gt;): u8 {
<b>let</b> count = <a href="_length">vector::length</a>(validators);
<b>let</b> threshold = (2 * count / 3 + 1) * 100 / count;
(threshold <b>as</b> u8)
<pre><code><b>fun</b> <a href="validator_set.md#0x2_validator_set_calculate_total_voting_power_and_quorum_threshold">calculate_total_voting_power_and_quorum_threshold</a>(validators: &<a href="">vector</a>&lt;Validator&gt;): (u64, u64) {
<b>let</b> total_voting_power = 0;
<b>let</b> length = <a href="_length">vector::length</a>(validators);
<b>let</b> i = 0;
<b>while</b> (i &lt; length) {
<b>let</b> v = <a href="_borrow">vector::borrow</a>(validators, i);
total_voting_power = total_voting_power + <a href="validator.md#0x2_validator_voting_power">validator::voting_power</a>(v);
i = i + 1;
};
(total_voting_power, (total_voting_power + 1) * 2 / 3)
}
</code></pre>

Expand Down
Loading

0 comments on commit 9ea6273

Please sign in to comment.