use fvm_ipld_encoding::repr::*;
use fvm_ipld_encoding::tuple::*;
use fvm_shared3::bigint::bigint_ser;
use fvm_shared3::clock::{ChainEpoch, EPOCH_UNDEFINED};
use fvm_shared3::econ::TokenAmount;
use fvm_shared3::sector::{Spacetime, StoragePower};
use fvm_shared3::smooth::FilterEstimate;
use lazy_static::lazy_static;
use num_derive::FromPrimitive;
use super::logic::*;
lazy_static! {
pub static ref INITIAL_REWARD_POSITION_ESTIMATE: TokenAmount = TokenAmount::from_atto(36266260308195979333u128);
pub static ref INITIAL_REWARD_VELOCITY_ESTIMATE: TokenAmount = TokenAmount::from_atto(-109897758509i64);
}
#[derive(Serialize_tuple, Deserialize_tuple, Default, Debug, Clone)]
pub struct State {
#[serde(with = "bigint_ser")]
pub cumsum_baseline: Spacetime,
#[serde(with = "bigint_ser")]
pub cumsum_realized: Spacetime,
pub effective_network_time: ChainEpoch,
#[serde(with = "bigint_ser")]
pub effective_baseline_power: StoragePower,
pub this_epoch_reward: TokenAmount,
pub this_epoch_reward_smoothed: FilterEstimate,
#[serde(with = "bigint_ser")]
pub this_epoch_baseline_power: StoragePower,
pub epoch: ChainEpoch,
pub total_storage_power_reward: TokenAmount,
pub simple_total: TokenAmount,
pub baseline_total: TokenAmount,
}
impl State {
pub fn new(curr_realized_power: StoragePower) -> Self {
let mut st = Self {
effective_baseline_power: BASELINE_INITIAL_VALUE.clone(),
this_epoch_baseline_power: INIT_BASELINE_POWER.clone(),
epoch: EPOCH_UNDEFINED,
this_epoch_reward_smoothed: FilterEstimate::new(
INITIAL_REWARD_POSITION_ESTIMATE.atto().clone(),
INITIAL_REWARD_VELOCITY_ESTIMATE.atto().clone(),
),
simple_total: SIMPLE_TOTAL.clone(),
baseline_total: BASELINE_TOTAL.clone(),
..Default::default()
};
st.update_to_next_epoch_with_reward(&curr_realized_power);
st
}
pub(super) fn update_to_next_epoch(&mut self, curr_realized_power: &StoragePower) {
self.epoch += 1;
self.this_epoch_baseline_power = baseline_power_from_prev(&self.this_epoch_baseline_power);
let capped_realized_power =
std::cmp::min(&self.this_epoch_baseline_power, curr_realized_power);
self.cumsum_realized += capped_realized_power;
while self.cumsum_realized > self.cumsum_baseline {
self.effective_network_time += 1;
self.effective_baseline_power =
baseline_power_from_prev(&self.effective_baseline_power);
self.cumsum_baseline += &self.effective_baseline_power;
}
}
pub(super) fn update_to_next_epoch_with_reward(&mut self, curr_realized_power: &StoragePower) {
let prev_reward_theta = compute_r_theta(
self.effective_network_time,
&self.effective_baseline_power,
&self.cumsum_realized,
&self.cumsum_baseline,
);
self.update_to_next_epoch(curr_realized_power);
let curr_reward_theta = compute_r_theta(
self.effective_network_time,
&self.effective_baseline_power,
&self.cumsum_realized,
&self.cumsum_baseline,
);
self.this_epoch_reward = compute_reward(
self.epoch,
prev_reward_theta,
curr_reward_theta,
&self.simple_total,
&self.baseline_total,
);
}
pub fn into_total_storage_power_reward(self) -> TokenAmount {
self.total_storage_power_reward
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, FromPrimitive, Serialize_repr, Deserialize_repr)]
#[repr(u8)]
pub enum VestingFunction {
None = 0,
Linear = 1,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
pub struct Reward {
pub vesting_function: VestingFunction,
pub start_epoch: ChainEpoch,
pub end_epoch: ChainEpoch,
pub value: TokenAmount,
pub amount_withdrawn: TokenAmount,
}
impl Reward {
pub fn amount_vested(&self, curr_epoch: ChainEpoch) -> TokenAmount {
match self.vesting_function {
VestingFunction::None => self.value.clone(),
VestingFunction::Linear => {
let elapsed = curr_epoch - self.start_epoch;
let vest_duration = self.end_epoch - self.start_epoch;
if elapsed >= vest_duration {
self.value.clone()
} else {
(self.value.clone() * elapsed as u64).div_floor(vest_duration)
}
}
}
}
}