Skip to content
Draft
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
7 changes: 7 additions & 0 deletions src/flamenco/stakes/Local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ $(call run-unit-test,test_stake_delegations)
endif
endif

$(call add-hdrs,fd_stake_warmup_cooldown_allowance.h)
$(call add-objs,fd_stake_warmup_cooldown_allowance,fd_flamenco)
ifdef FD_HAS_HOSTED
$(call make-unit-test,test_stake_warmup_cooldown_allowance,test_stake_warmup_cooldown_allowance,fd_flamenco fd_funk fd_ballet fd_util)
$(call run-unit-test,test_stake_warmup_cooldown_allowance)
endif

$(call add-hdrs,fd_vote_states.h)
$(call add-objs,fd_vote_states,fd_flamenco)
ifdef FD_HAS_HOSTED
Expand Down
75 changes: 75 additions & 0 deletions src/flamenco/stakes/fd_stake_warmup_cooldown_allowance.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "fd_stake_warmup_cooldown_allowance.h"

#include "../../util/bits/fd_sat.h"

#if !FD_HAS_INT128
#error "fd_stake_warmup_cooldown_allowance requires FD_HAS_INT128"
#endif

/* https://github.com/solana-program/stake/pull/152
https://github.com/solana-program/stake/blob/9719141dc60e0f03f5865a5091136d3d3dcbebfa/interface/src/warmup_cooldown_allowance.rs#L8 */
ulong
fd_stake_warmup_cooldown_rate_bps( ulong epoch, ulong const * new_rate_activation_epoch ) {
return ( epoch < ( new_rate_activation_epoch ? *new_rate_activation_epoch : ULONG_MAX ) )
? FD_STAKE_ORIGINAL_WARMUP_COOLDOWN_RATE_BPS
: FD_STAKE_TOWER_WARMUP_COOLDOWN_RATE_BPS;
}

/* https://github.com/solana-program/stake/pull/152
https://github.com/solana-program/stake/blob/9719141dc60e0f03f5865a5091136d3d3dcbebfa/interface/src/warmup_cooldown_allowance.rs#L55 */
static inline ulong
rate_limited_stake_change( ulong epoch,
ulong account_portion,
ulong cluster_portion,
ulong cluster_effective,
ulong const * new_rate_activation_epoch ) {
if( FD_UNLIKELY( !account_portion || !cluster_portion || !cluster_effective ) ) return 0UL;

ulong rate_bps = fd_stake_warmup_cooldown_rate_bps( epoch, new_rate_activation_epoch );

/* change = (account_portion * cluster_effective * rate_bps) /
(cluster_portion * BASIS_POINTS_PER_UNIT)
Saturating u128 multiply chain in Rust:
https://github.com/solana-program/stake/blob/9719141dc60e0f03f5865a5091136d3d3dcbebfa/interface/src/warmup_cooldown_allowance.rs#L69 */
__uint128_t numerator =
fd_uint128_sat_mul( fd_uint128_sat_mul( (__uint128_t)account_portion, (__uint128_t)cluster_effective ),
(__uint128_t)rate_bps );

__uint128_t denominator =
fd_uint128_sat_mul( (__uint128_t)cluster_portion, (__uint128_t)FD_STAKE_BASIS_POINTS_PER_UNIT );

if( FD_UNLIKELY( !denominator ) ) return 0UL;

__uint128_t delta = numerator / denominator;
if( delta > (__uint128_t)account_portion ) delta = (__uint128_t)account_portion;

return (ulong)delta;
}

/* https://github.com/solana-program/stake/pull/152
https://github.com/solana-program/stake/blob/9719141dc60e0f03f5865a5091136d3d3dcbebfa/interface/src/warmup_cooldown_allowance.rs#L20 */
ulong
fd_stake_calculate_activation_allowance( ulong current_epoch,
ulong account_activating_stake,
fd_stake_history_entry_t const * prev_epoch_cluster_state,
ulong const * new_rate_activation_epoch ) {
return rate_limited_stake_change( current_epoch,
account_activating_stake,
prev_epoch_cluster_state->activating,
prev_epoch_cluster_state->effective,
new_rate_activation_epoch );
}

/* https://github.com/solana-program/stake/pull/152
https://github.com/solana-program/stake/blob/9719141dc60e0f03f5865a5091136d3d3dcbebfa/interface/src/warmup_cooldown_allowance.rs#L39 */
ulong
fd_stake_calculate_deactivation_allowance( ulong current_epoch,
ulong account_deactivating_stake,
fd_stake_history_entry_t const * prev_epoch_cluster_state,
ulong const * new_rate_activation_epoch ) {
return rate_limited_stake_change( current_epoch,
account_deactivating_stake,
prev_epoch_cluster_state->deactivating,
prev_epoch_cluster_state->effective,
new_rate_activation_epoch );
}
33 changes: 33 additions & 0 deletions src/flamenco/stakes/fd_stake_warmup_cooldown_allowance.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef HEADER_fd_src_flamenco_stakes_fd_stake_warmup_cooldown_allowance_h
#define HEADER_fd_src_flamenco_stakes_fd_stake_warmup_cooldown_allowance_h

#include "../types/fd_types.h"

/* Port of stake warmup/cooldown allowance calculations
https://github.com/solana-program/stake/pull/152
https://github.com/solana-program/stake/blob/9719141dc60e0f03f5865a5091136d3d3dcbebfa/interface/src/warmup_cooldown_allowance.rs */

#define FD_STAKE_BASIS_POINTS_PER_UNIT (10000UL)
#define FD_STAKE_ORIGINAL_WARMUP_COOLDOWN_RATE_BPS (2500UL) /* 25% */
#define FD_STAKE_TOWER_WARMUP_COOLDOWN_RATE_BPS (900UL) /* 9% */

FD_PROTOTYPES_BEGIN

ulong
fd_stake_warmup_cooldown_rate_bps( ulong epoch, ulong const * new_rate_activation_epoch );

ulong
fd_stake_calculate_activation_allowance( ulong current_epoch,
ulong account_activating_stake,
fd_stake_history_entry_t const * prev_epoch_cluster_state,
ulong const * new_rate_activation_epoch );

ulong
fd_stake_calculate_deactivation_allowance( ulong current_epoch,
ulong account_deactivating_stake,
fd_stake_history_entry_t const * prev_epoch_cluster_state,
ulong const * new_rate_activation_epoch );

FD_PROTOTYPES_END

#endif /* HEADER_fd_src_flamenco_stakes_fd_stake_warmup_cooldown_allowance_h */
Loading