Skip to content

Commit

Permalink
[sui-system] skip stake subsidy distribution if epoch is short (Myste…
Browse files Browse the repository at this point in the history
…nLabs#10500)

## Description 

If the length of an epoch is shorter than our set duration then skip
stake subsidy distribution.

## Test Plan 

added a test
---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [x] breaking change for FNs (FN binary must upgrade)
- [x] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
  • Loading branch information
emmazzz authored Apr 6, 2023
1 parent 94a753c commit a1850b4
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 12 deletions.
15 changes: 10 additions & 5 deletions crates/sui-framework/docs/sui_system_state_inner.md
Original file line number Diff line number Diff line change
Expand Up @@ -2090,6 +2090,7 @@ gas coins.
epoch_start_timestamp_ms: u64, // Timestamp of the epoch start
ctx: &<b>mut</b> TxContext,
) : Balance&lt;SUI&gt; {
<b>let</b> prev_epoch_start_timestamp = self.epoch_start_timestamp_ms;
self.epoch_start_timestamp_ms = epoch_start_timestamp_ms;

<b>let</b> bps_denominator_u64 = (<a href="sui_system_state_inner.md#0x3_sui_system_state_inner_BASIS_POINT_DENOMINATOR">BASIS_POINT_DENOMINATOR</a> <b>as</b> u64);
Expand Down Expand Up @@ -2119,11 +2120,15 @@ gas coins.

// Include stake subsidy in the rewards given out <b>to</b> validators and stakers.
// Delay distributing any stake subsidies until after `stake_subsidy_start_epoch`.
<b>let</b> <a href="stake_subsidy.md#0x3_stake_subsidy">stake_subsidy</a> = <b>if</b> (<a href="_epoch">tx_context::epoch</a>(ctx) &gt;= self.parameters.stake_subsidy_start_epoch) {
<a href="stake_subsidy.md#0x3_stake_subsidy_advance_epoch">stake_subsidy::advance_epoch</a>(&<b>mut</b> self.<a href="stake_subsidy.md#0x3_stake_subsidy">stake_subsidy</a>)
} <b>else</b> {
<a href="_zero">balance::zero</a>()
};
// And <b>if</b> this epoch is shorter than the regular epoch duration, don't distribute any stake subsidy.
<b>let</b> <a href="stake_subsidy.md#0x3_stake_subsidy">stake_subsidy</a> =
<b>if</b> (<a href="_epoch">tx_context::epoch</a>(ctx) &gt;= self.parameters.stake_subsidy_start_epoch &&
epoch_start_timestamp_ms &gt;= prev_epoch_start_timestamp + self.parameters.epoch_duration_ms)
{
<a href="stake_subsidy.md#0x3_stake_subsidy_advance_epoch">stake_subsidy::advance_epoch</a>(&<b>mut</b> self.<a href="stake_subsidy.md#0x3_stake_subsidy">stake_subsidy</a>)
} <b>else</b> {
<a href="_zero">balance::zero</a>()
};

<b>let</b> stake_subsidy_amount = <a href="_value">balance::value</a>(&<a href="stake_subsidy.md#0x3_stake_subsidy">stake_subsidy</a>);
<a href="_join">balance::join</a>(&<b>mut</b> computation_reward, <a href="stake_subsidy.md#0x3_stake_subsidy">stake_subsidy</a>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,10 @@ module sui_system::stake_subsidy {
public fun current_epoch_subsidy_amount(self: &StakeSubsidy): u64 {
math::min(self.current_distribution_amount, balance::value(&self.balance))
}

#[test_only]
/// Returns the number of distributions that have occurred.
public(friend) fun get_distribution_counter(self: &StakeSubsidy): u64 {
self.distribution_counter
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ module sui_system::sui_system {

#[test_only]
friend sui_system::governance_test_utils;
#[test_only]
friend sui_system::sui_system_tests;

struct SuiSystemState has key {
id: UID,
Expand Down Expand Up @@ -653,6 +655,12 @@ module sui_system::sui_system {
sui_system_state_inner::get_storage_fund_object_rebates(self)
}

#[test_only]
public fun get_stake_subsidy_distribution_counter(wrapper: &mut SuiSystemState): u64 {
let self = load_system_state(wrapper);
sui_system_state_inner::get_stake_subsidy_distribution_counter(self)
}

// CAUTION: THIS CODE IS ONLY FOR TESTING AND THIS MACRO MUST NEVER EVER BE REMOVED. Creates a
// candidate validator - bypassing the proof of possession check and other metadata validation
// in the process.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,7 @@ module sui_system::sui_system_state_inner {
epoch_start_timestamp_ms: u64, // Timestamp of the epoch start
ctx: &mut TxContext,
) : Balance<SUI> {
let prev_epoch_start_timestamp = self.epoch_start_timestamp_ms;
self.epoch_start_timestamp_ms = epoch_start_timestamp_ms;

let bps_denominator_u64 = (BASIS_POINT_DENOMINATOR as u64);
Expand Down Expand Up @@ -871,11 +872,15 @@ module sui_system::sui_system_state_inner {

// Include stake subsidy in the rewards given out to validators and stakers.
// Delay distributing any stake subsidies until after `stake_subsidy_start_epoch`.
let stake_subsidy = if (tx_context::epoch(ctx) >= self.parameters.stake_subsidy_start_epoch) {
stake_subsidy::advance_epoch(&mut self.stake_subsidy)
} else {
balance::zero()
};
// And if this epoch is shorter than the regular epoch duration, don't distribute any stake subsidy.
let stake_subsidy =
if (tx_context::epoch(ctx) >= self.parameters.stake_subsidy_start_epoch &&
epoch_start_timestamp_ms >= prev_epoch_start_timestamp + self.parameters.epoch_duration_ms)
{
stake_subsidy::advance_epoch(&mut self.stake_subsidy)
} else {
balance::zero()
};

let stake_subsidy_amount = balance::value(&stake_subsidy);
balance::join(&mut computation_reward, stake_subsidy);
Expand Down Expand Up @@ -1074,6 +1079,11 @@ module sui_system::sui_system_state_inner {
validator_set::get_candidate_validator_ref(validators(self), validator_address)
}

#[test_only]
public(friend) fun get_stake_subsidy_distribution_counter(self: &SuiSystemStateInnerV2): u64 {
stake_subsidy::get_distribution_counter(&self.stake_subsidy)
}

#[test_only]
public(friend) fun set_epoch_for_testing(self: &mut SuiSystemStateInnerV2, epoch_num: u64) {
self.epoch = epoch_num
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ module sui_system::sui_system_tests {
use sui::table;
use std::vector;
use sui::balance;
use sui::test_utils::assert_eq;
use sui::test_utils::{assert_eq, destroy};
use std::option::Self;
use sui::url;
use std::string;
use std::ascii;
use sui::tx_context;

#[test]
fun test_report_validator() {
Expand Down Expand Up @@ -957,4 +958,34 @@ module sui_system::sui_system_tests {
test_scenario::return_shared(system_state);
test_scenario::end(scenario_val);
}

#[test]
fun test_skip_stake_subsidy() {
let scenario_val = test_scenario::begin(@0x0);
let scenario = &mut scenario_val;
// Epoch duration is set to be 42 here.
set_up_sui_system_state(vector[@0x1, @0x2]);

// If the epoch length is less than 42 then the stake subsidy distribution counter should not be incremented. Otherwise it should.
advance_epoch_and_check_distribution_counter(scenario, 42, true);
advance_epoch_and_check_distribution_counter(scenario, 32, false);
advance_epoch_and_check_distribution_counter(scenario, 52, true);
test_scenario::end(scenario_val);
}

fun advance_epoch_and_check_distribution_counter(scenario: &mut Scenario, epoch_length: u64, should_increment_counter: bool) {
test_scenario::next_tx(scenario, @0x0);
let new_epoch = tx_context::epoch(test_scenario::ctx(scenario)) + 1;
let system_state = test_scenario::take_shared<SuiSystemState>(scenario);
let prev_epoch_time = sui_system::epoch_start_timestamp_ms(&mut system_state);
let prev_counter = sui_system::get_stake_subsidy_distribution_counter(&mut system_state);

let rebate = sui_system::advance_epoch_for_testing(
&mut system_state, new_epoch, 1, 0, 0, 0, 0, 0, 0, prev_epoch_time + epoch_length, test_scenario::ctx(scenario)
);
destroy(rebate);
assert_eq(sui_system::get_stake_subsidy_distribution_counter(&mut system_state), prev_counter + (if (should_increment_counter) 1 else 0));
test_scenario::return_shared(system_state);
test_scenario::next_epoch(scenario, @0x0);
}
}
3 changes: 2 additions & 1 deletion crates/sui-protocol-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ const MAX_PROTOCOL_VERSION: u64 = 4;
// Version 3: gas model v2, including all sui conservation fixes. Fix for loaded child object
// changes, enable package upgrades, add limits on `max_size_written_objects`,
// `max_size_written_objects_system_tx`
// Version 4: New reward slashing rate.
// Version 4: New reward slashing rate. Framework changes to skip stake susbidy when the epoch
// length is short.

#[derive(
Copy, Clone, Debug, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, JsonSchema,
Expand Down

0 comments on commit a1850b4

Please sign in to comment.