crates/sui-framework/docs/sui_system/voting_power.md
VotingPowerInfoVotingPowerInfoV2set_voting_powerinit_voting_power_infoderive_raw_voting_powerinsertadjust_voting_powerupdate_voting_powercheck_invariantstotal_voting_powerquorum_threshold<a name="sui_system_voting_power_VotingPowerInfo"></a>
VotingPowerInfoDeprecated. Use VotingPowerInfoV2 instead.
<pre><code><b>public</b> <b>struct</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfo">VotingPowerInfo</a> <b>has</b> drop </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>validator_index: u64</code> </dt> <dd> </dd> <dt> <code><a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>: u64</code> </dt> <dd> </dd> </dl> </details><a name="sui_system_voting_power_VotingPowerInfoV2"></a>
VotingPowerInfoV2<a name="@Constants_0"></a>
<a name="sui_system_voting_power_TOTAL_VOTING_POWER"></a>
Set total_voting_power as 10_000 by convention. Individual voting powers can be interpreted as easily understandable basis points (e.g., voting_power: 100 = 1%, voting_power: 1 = 0.01%) rather than opaque quantities whose meaning changes from epoch to epoch as the total amount staked shifts. Fixing the total voting power allows clients to hardcode the quorum threshold and total_voting power rather than recomputing these.
<pre><code><b>const</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_TOTAL_VOTING_POWER">TOTAL_VOTING_POWER</a>: u64 = 10000; </code></pre><a name="sui_system_voting_power_QUORUM_THRESHOLD"></a>
Quorum threshold for our fixed voting power--any message signed by this much voting power can be trusted up to BFT assumptions
<pre><code><b>const</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_QUORUM_THRESHOLD">QUORUM_THRESHOLD</a>: u64 = 6667; </code></pre><a name="sui_system_voting_power_MAX_VOTING_POWER"></a>
<pre><code><b>const</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_MAX_VOTING_POWER">MAX_VOTING_POWER</a>: u64 = 1000; </code></pre><a name="sui_system_voting_power_ETotalPowerMismatch"></a>
<pre><code><b>const</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_ETotalPowerMismatch">ETotalPowerMismatch</a>: u64 = 1; </code></pre><a name="sui_system_voting_power_ERelativePowerMismatch"></a>
<pre><code><b>const</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_ERelativePowerMismatch">ERelativePowerMismatch</a>: u64 = 2; </code></pre><a name="sui_system_voting_power_EVotingPowerOverThreshold"></a>
<pre><code><b>const</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_EVotingPowerOverThreshold">EVotingPowerOverThreshold</a>: u64 = 3; </code></pre><a name="sui_system_voting_power_EInvalidVotingPower"></a>
<pre><code><b>const</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_EInvalidVotingPower">EInvalidVotingPower</a>: u64 = 4; </code></pre><a name="sui_system_voting_power_set_voting_power"></a>
set_voting_powerSet the voting power of all validators. Each validator's voting power is initialized using their stake. We then attempt to cap their voting power at <code><a href="../sui_system/voting_power.md#sui_system_voting_power_MAX_VOTING_POWER">MAX_VOTING_POWER</a></code>. If <code><a href="../sui_system/voting_power.md#sui_system_voting_power_MAX_VOTING_POWER">MAX_VOTING_POWER</a></code> is not a feasible cap, we pick the lowest possible cap.
<pre><code><b>public</b>(package) <b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_set_voting_power">set_voting_power</a>(validators: &<b>mut</b> vector<<a href="../sui_system/validator.md#sui_system_validator_Validator">sui_system::validator::Validator</a>>, total_stake: u64) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b>(package) <b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_set_voting_power">set_voting_power</a>(validators: &<b>mut</b> vector<Validator>, total_stake: u64) { // If threshold_pct is too small, it's possible that even when all validators reach the threshold we still don't // have 100%. So we bound the threshold_pct to be always enough to find a solution. <b>let</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_total_voting_power">total_voting_power</a> = <a href="../sui_system/voting_power.md#sui_system_voting_power_TOTAL_VOTING_POWER">TOTAL_VOTING_POWER</a>; <b>let</b> average_voting_power = <a href="../sui_system/voting_power.md#sui_system_voting_power_total_voting_power">total_voting_power</a>.divide_and_round_up(validators.length()); <b>let</b> threshold = <a href="../sui_system/voting_power.md#sui_system_voting_power_total_voting_power">total_voting_power</a>.min(<a href="../sui_system/voting_power.md#sui_system_voting_power_MAX_VOTING_POWER">MAX_VOTING_POWER</a>.max(average_voting_power)); <b>let</b> (<b>mut</b> info_list, remaining_power) = <a href="../sui_system/voting_power.md#sui_system_voting_power_init_voting_power_info">init_voting_power_info</a>( validators, threshold, total_stake, ); <a href="../sui_system/voting_power.md#sui_system_voting_power_adjust_voting_power">adjust_voting_power</a>(&<b>mut</b> info_list, threshold, remaining_power); <a href="../sui_system/voting_power.md#sui_system_voting_power_update_voting_power">update_voting_power</a>(validators, info_list); <a href="../sui_system/voting_power.md#sui_system_voting_power_check_invariants">check_invariants</a>(validators); } </code></pre> </details><a name="sui_system_voting_power_init_voting_power_info"></a>
init_voting_power_infoCreate the initial voting power of each validator, set using their stake, but capped using threshold. We also perform insertion sort while creating the voting power list, by maintaining the list in descending order using voting power. Anything beyond the threshold is added to the remaining_power, which is also returned.
<pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_init_voting_power_info">init_voting_power_info</a>(validators: &vector<<a href="../sui_system/validator.md#sui_system_validator_Validator">sui_system::validator::Validator</a>>, threshold: u64, total_stake: u64): (vector<<a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">sui_system::voting_power::VotingPowerInfoV2</a>>, u64) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_init_voting_power_info">init_voting_power_info</a>( validators: &vector<Validator>, threshold: u64, total_stake: u64, ): (vector<<a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">VotingPowerInfoV2</a>>, u64) { <b>let</b> <b>mut</b> total_power = 0; <b>let</b> <b>mut</b> result = vector[]; validators.length().do!(|i| { <b>let</b> stake = validators[i].total_stake(); <b>let</b> <a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a> = <a href="../sui_system/voting_power.md#sui_system_voting_power_derive_raw_voting_power">derive_raw_voting_power</a>(stake, total_stake).min(threshold); <a href="../sui_system/voting_power.md#sui_system_voting_power_insert">insert</a>(&<b>mut</b> result, <a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">VotingPowerInfoV2</a> { validator_index: i, <a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>, stake }); total_power = total_power + <a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>; }); (result, <a href="../sui_system/voting_power.md#sui_system_voting_power_TOTAL_VOTING_POWER">TOTAL_VOTING_POWER</a> - total_power) } </code></pre> </details><a name="sui_system_voting_power_derive_raw_voting_power"></a>
derive_raw_voting_power<a name="sui_system_voting_power_insert"></a>
insertInsert <code>new_info</code> to <code>info_list</code> as part of insertion sort, such that <code>info_list</code> is always sorted using stake, in descending order.
<pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_insert">insert</a>(info_list: &<b>mut</b> vector<<a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">sui_system::voting_power::VotingPowerInfoV2</a>>, new_info: <a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">sui_system::voting_power::VotingPowerInfoV2</a>) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_insert">insert</a>(info_list: &<b>mut</b> vector<<a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">VotingPowerInfoV2</a>>, new_info: <a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">VotingPowerInfoV2</a>) { <b>let</b> len = info_list.length(); <b>let</b> idx = info_list.find_index!(|info| new_info.stake >= info.stake); info_list.<a href="../sui_system/voting_power.md#sui_system_voting_power_insert">insert</a>(new_info, idx.destroy_or!(len)); } </code></pre> </details><a name="sui_system_voting_power_adjust_voting_power"></a>
adjust_voting_powerDistribute remaining_power to validators that are not capped at threshold.
<pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_adjust_voting_power">adjust_voting_power</a>(info_list: &<b>mut</b> vector<<a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">sui_system::voting_power::VotingPowerInfoV2</a>>, threshold: u64, remaining_power: u64) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_adjust_voting_power">adjust_voting_power</a>( info_list: &<b>mut</b> vector<<a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">VotingPowerInfoV2</a>>, threshold: u64, <b>mut</b> remaining_power: u64, ) { <b>let</b> <b>mut</b> i = 0; <b>let</b> len = info_list.length(); <b>while</b> (i < len && remaining_power > 0) { <b>let</b> v = &<b>mut</b> info_list[i]; // planned is the amount of extra power we want to distribute to this <a href="../sui_system/validator.md#sui_system_validator">validator</a>. <b>let</b> planned = remaining_power.divide_and_round_up(len - i); // target is the targeting power this <a href="../sui_system/validator.md#sui_system_validator">validator</a> will reach, capped by threshold. <b>let</b> target = threshold.min(v.<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a> + planned); // actual is the actual amount of power we will be distributing to this <a href="../sui_system/validator.md#sui_system_validator">validator</a>. <b>let</b> actual = remaining_power.min(target - v.<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>); v.<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a> = v.<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a> + actual; <b>assert</b>!(v.<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a> <= threshold, <a href="../sui_system/voting_power.md#sui_system_voting_power_EVotingPowerOverThreshold">EVotingPowerOverThreshold</a>); remaining_power = remaining_power - actual; i = i + 1; }; <b>assert</b>!(remaining_power == 0, <a href="../sui_system/voting_power.md#sui_system_voting_power_ETotalPowerMismatch">ETotalPowerMismatch</a>); } </code></pre> </details><a name="sui_system_voting_power_update_voting_power"></a>
update_voting_powerUpdate validators with the decided voting power.
<pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_update_voting_power">update_voting_power</a>(validators: &<b>mut</b> vector<<a href="../sui_system/validator.md#sui_system_validator_Validator">sui_system::validator::Validator</a>>, info_list: vector<<a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">sui_system::voting_power::VotingPowerInfoV2</a>>) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_update_voting_power">update_voting_power</a>(validators: &<b>mut</b> vector<Validator>, info_list: vector<<a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">VotingPowerInfoV2</a>>) { info_list.destroy!(|<a href="../sui_system/voting_power.md#sui_system_voting_power_VotingPowerInfoV2">VotingPowerInfoV2</a> { validator_index, <a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>, .. }| { validators[validator_index].<a href="../sui_system/voting_power.md#sui_system_voting_power_set_voting_power">set_voting_power</a>(<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>); }); } </code></pre> </details><a name="sui_system_voting_power_check_invariants"></a>
check_invariantsCheck a few invariants that must hold after setting the voting power.
<pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_check_invariants">check_invariants</a>(v: &vector<<a href="../sui_system/validator.md#sui_system_validator_Validator">sui_system::validator::Validator</a>>) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_check_invariants">check_invariants</a>(v: &vector<Validator>) { <b>let</b> <b>mut</b> total = 0; v.do_ref!(|v| { <b>let</b> <a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a> = v.<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>(); <b>assert</b>!(<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a> > 0, <a href="../sui_system/voting_power.md#sui_system_voting_power_EInvalidVotingPower">EInvalidVotingPower</a>); total = total + <a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>; }); <b>assert</b>!(total == <a href="../sui_system/voting_power.md#sui_system_voting_power_TOTAL_VOTING_POWER">TOTAL_VOTING_POWER</a>, <a href="../sui_system/voting_power.md#sui_system_voting_power_ETotalPowerMismatch">ETotalPowerMismatch</a>); // Second check that <b>if</b> <a href="../sui_system/validator.md#sui_system_validator">validator</a> A's stake is larger than B's stake, A's // voting power must be no less than B's voting power; similarly, <b>if</b> A's // stake is less than B's stake, A's voting power must be no larger than // B's voting power. <b>let</b> length = v.length(); length.do!(|a| { (a + 1).range_do!(length, |b| { <b>let</b> validator_a = &v[a]; <b>let</b> validator_b = &v[b]; <b>let</b> stake_a = validator_a.total_stake(); <b>let</b> stake_b = validator_b.total_stake(); <b>let</b> power_a = validator_a.<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>(); <b>let</b> power_b = validator_b.<a href="../sui_system/voting_power.md#sui_system_voting_power">voting_power</a>(); <b>if</b> (stake_a > stake_b) { <b>assert</b>!(power_a >= power_b, <a href="../sui_system/voting_power.md#sui_system_voting_power_ERelativePowerMismatch">ERelativePowerMismatch</a>); }; <b>if</b> (stake_a < stake_b) { <b>assert</b>!(power_a <= power_b, <a href="../sui_system/voting_power.md#sui_system_voting_power_ERelativePowerMismatch">ERelativePowerMismatch</a>); }; }) }); } </code></pre> </details><a name="sui_system_voting_power_total_voting_power"></a>
total_voting_powerReturn the (constant) total voting power
<pre><code><b>public</b> <b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_total_voting_power">total_voting_power</a>(): u64 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_total_voting_power">total_voting_power</a>(): u64 { <a href="../sui_system/voting_power.md#sui_system_voting_power_TOTAL_VOTING_POWER">TOTAL_VOTING_POWER</a> } </code></pre> </details><a name="sui_system_voting_power_quorum_threshold"></a>
quorum_thresholdReturn the (constant) quorum threshold
<pre><code><b>public</b> <b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_quorum_threshold">quorum_threshold</a>(): u64 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="../sui_system/voting_power.md#sui_system_voting_power_quorum_threshold">quorum_threshold</a>(): u64 { <a href="../sui_system/voting_power.md#sui_system_voting_power_QUORUM_THRESHOLD">QUORUM_THRESHOLD</a> } </code></pre> </details>