From 0e15e60b1cc830a59c715b8ad0ff8f01780e6df0 Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Mon, 1 Jul 2024 16:38:14 -0400 Subject: [PATCH 1/2] More events emitted --- programs/steward/src/delegation.rs | 12 +-- programs/steward/src/events.rs | 93 +++++++++++++++++++ .../auto_add_validator_to_pool.rs | 15 ++- .../auto_remove_validator_from_pool.rs | 8 ++ .../src/instructions/epoch_maintenance.rs | 10 ++ .../steward/src/instructions/rebalance.rs | 50 +--------- programs/steward/src/lib.rs | 1 + programs/steward/src/state/steward_state.rs | 13 +-- tests/tests/steward/test_algorithms.rs | 4 +- 9 files changed, 131 insertions(+), 75 deletions(-) create mode 100644 programs/steward/src/events.rs diff --git a/programs/steward/src/delegation.rs b/programs/steward/src/delegation.rs index 14da68d6..5c4afdaa 100644 --- a/programs/steward/src/delegation.rs +++ b/programs/steward/src/delegation.rs @@ -1,8 +1,7 @@ -use anchor_lang::idl::*; use anchor_lang::prelude::*; -use borsh::BorshSerialize; use spl_stake_pool::big_vec::BigVec; +use crate::events::DecreaseComponents; use crate::{ errors::StewardError, utils::{get_target_lamports, stake_lamports_at_validator_list_index}, @@ -16,15 +15,6 @@ pub enum RebalanceType { None, } -#[event] -#[derive(Default, Debug, Clone, PartialEq, Eq)] -pub struct DecreaseComponents { - pub scoring_unstake_lamports: u64, - pub instant_unstake_lamports: u64, - pub stake_deposit_unstake_lamports: u64, - pub total_unstake_lamports: u64, -} - /// Given a target validator, determines how much stake to remove on this validator given the constraints of unstaking caps. /// Validators with lower yield_scores are prioritized for unstaking. We simulate unstaking movements on each validator, starting /// from the lowest yield_score validator, until we reach the target validator. If the target validator is reached and there is still diff --git a/programs/steward/src/events.rs b/programs/steward/src/events.rs new file mode 100644 index 00000000..c1f57228 --- /dev/null +++ b/programs/steward/src/events.rs @@ -0,0 +1,93 @@ +use anchor_lang::idl::{ + types::{IdlEnumVariant, IdlTypeDef, IdlTypeDefTy}, + IdlBuild, +}; +use anchor_lang::prelude::{event, AnchorDeserialize, AnchorSerialize}; +use anchor_lang::solana_program::pubkey::Pubkey; +use borsh::{BorshDeserialize, BorshSerialize}; + +#[event] +pub struct AutoRemoveValidatorEvent { + pub validator_list_index: u64, + pub vote_account: Pubkey, + pub vote_account_closed: bool, + pub stake_account_deactivated: bool, +} + +#[event] +pub struct AutoAddValidatorEvent { + pub validator_list_index: u64, + pub vote_account: Pubkey, +} + +#[event] +pub struct EpochMaintenanceEvent { + pub validator_index_to_remove: Option, + pub validator_list_length: u64, + pub num_pool_validators: u64, + pub validators_to_remove: u64, + pub validators_to_add: u64, + pub maintenance_complete: bool, +} + +#[event] +#[derive(Debug)] +pub struct StateTransition { + pub epoch: u64, + pub slot: u64, + pub previous_state: String, + pub new_state: String, +} + +#[event] +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct DecreaseComponents { + pub scoring_unstake_lamports: u64, + pub instant_unstake_lamports: u64, + pub stake_deposit_unstake_lamports: u64, + pub total_unstake_lamports: u64, +} + +#[event] +pub struct RebalanceEvent { + pub vote_account: Pubkey, + pub epoch: u16, + pub rebalance_type_tag: RebalanceTypeTag, + pub increase_lamports: u64, + pub decrease_components: DecreaseComponents, +} + +#[derive(BorshSerialize, BorshDeserialize, Debug)] +pub enum RebalanceTypeTag { + None, + Increase, + Decrease, +} + +impl IdlBuild for RebalanceTypeTag { + fn create_type() -> Option { + Some(IdlTypeDef { + name: "RebalanceTypeTag".to_string(), + ty: IdlTypeDefTy::Enum { + variants: vec![ + IdlEnumVariant { + name: "None".to_string(), + fields: None, + }, + IdlEnumVariant { + name: "Increase".to_string(), + fields: None, + }, + IdlEnumVariant { + name: "Decrease".to_string(), + fields: None, + }, + ], + }, + docs: Default::default(), + generics: Default::default(), + serialization: Default::default(), + repr: Default::default(), + }) + } +} diff --git a/programs/steward/src/instructions/auto_add_validator_to_pool.rs b/programs/steward/src/instructions/auto_add_validator_to_pool.rs index 49a57626..b9b2ff76 100644 --- a/programs/steward/src/instructions/auto_add_validator_to_pool.rs +++ b/programs/steward/src/instructions/auto_add_validator_to_pool.rs @@ -1,5 +1,6 @@ use crate::constants::{MAX_VALIDATORS, STAKE_POOL_WITHDRAW_SEED}; use crate::errors::StewardError; +use crate::events::AutoAddValidatorEvent; use crate::state::{Config, StewardStateAccount}; use crate::utils::{deserialize_stake_pool, get_stake_pool_address}; use anchor_lang::prelude::*; @@ -111,13 +112,14 @@ pub fn handler(ctx: Context) -> Result<()> { StewardError::EpochMaintenanceNotComplete ); - { + let validator_list_len = { let validator_list_data = &mut ctx.accounts.validator_list.try_borrow_mut_data()?; let (_, validator_list) = ValidatorListHeader::deserialize_vec(validator_list_data)?; - if validator_list.len().checked_add(1).unwrap() > MAX_VALIDATORS as u32 { - return Err(StewardError::MaxValidatorsReached.into()); - } + validator_list.len() + }; + if validator_list_len.checked_add(1).unwrap() > MAX_VALIDATORS as u32 { + return Err(StewardError::MaxValidatorsReached.into()); } let start_epoch = @@ -150,6 +152,11 @@ pub fn handler(ctx: Context) -> Result<()> { // Have to drop the state account before calling the CPI drop(state_account); + emit!(AutoAddValidatorEvent { + vote_account: ctx.accounts.vote_account.key(), + validator_list_index: validator_list_len as u64 + }); + invoke_signed( &spl_stake_pool::instruction::add_validator_to_pool( &ctx.accounts.stake_pool_program.key(), diff --git a/programs/steward/src/instructions/auto_remove_validator_from_pool.rs b/programs/steward/src/instructions/auto_remove_validator_from_pool.rs index e18422e4..70a205e1 100644 --- a/programs/steward/src/instructions/auto_remove_validator_from_pool.rs +++ b/programs/steward/src/instructions/auto_remove_validator_from_pool.rs @@ -2,6 +2,7 @@ use std::num::NonZeroU32; use crate::constants::STAKE_POOL_WITHDRAW_SEED; use crate::errors::StewardError; +use crate::events::AutoRemoveValidatorEvent; use crate::state::Config; use crate::utils::{ deserialize_stake_pool, get_stake_pool_address, get_validator_stake_info_at_index, @@ -167,6 +168,13 @@ pub fn handler(ctx: Context, validator_list_index: usize) - state_account .state .mark_validator_for_removal(validator_list_index)?; + + emit!(AutoRemoveValidatorEvent { + vote_account: ctx.accounts.vote_account.key(), + validator_list_index: validator_list_index as u64, + stake_account_deactivated, + vote_account_closed, + }); } invoke_signed( diff --git a/programs/steward/src/instructions/epoch_maintenance.rs b/programs/steward/src/instructions/epoch_maintenance.rs index ff538c94..95c9a40a 100644 --- a/programs/steward/src/instructions/epoch_maintenance.rs +++ b/programs/steward/src/instructions/epoch_maintenance.rs @@ -1,5 +1,6 @@ use crate::{ errors::StewardError, + events::EpochMaintenanceEvent, utils::{ check_validator_list_has_stake_status_other_than, deserialize_stake_pool, get_stake_pool_address, get_validator_list_length, @@ -94,6 +95,15 @@ pub fn handler( state_account.state.checked_validators_removed_from_list = false.into(); state_account.state.rebalance_completed = false.into(); } + + emit!(EpochMaintenanceEvent { + validator_index_to_remove: validator_index_to_remove.map(|x| x as u64), + validator_list_length: get_validator_list_length(&ctx.accounts.validator_list)? as u64, + num_pool_validators: state_account.state.num_pool_validators, + validators_to_remove: state_account.state.validators_to_remove.count() as u64, + validators_to_add: state_account.state.validators_added as u64, + maintenance_complete: okay_to_update, + }); } Ok(()) diff --git a/programs/steward/src/instructions/rebalance.rs b/programs/steward/src/instructions/rebalance.rs index ab338ad7..3bf09d4d 100644 --- a/programs/steward/src/instructions/rebalance.rs +++ b/programs/steward/src/instructions/rebalance.rs @@ -1,7 +1,6 @@ use std::num::NonZeroU32; use anchor_lang::{ - idl::types::*, idl::*, prelude::*, solana_program::{ @@ -10,7 +9,7 @@ use anchor_lang::{ system_program, sysvar, vote, }, }; -use borsh::{BorshDeserialize, BorshSerialize}; +use borsh::BorshDeserialize; use spl_pod::solana_program::stake::state::StakeStateV2; use spl_stake_pool::{ find_stake_program_address, find_transient_stake_program_address, minimum_delegation, @@ -20,8 +19,9 @@ use validator_history::ValidatorHistory; use crate::{ constants::STAKE_POOL_WITHDRAW_SEED, - delegation::{DecreaseComponents, RebalanceType}, + delegation::RebalanceType, errors::StewardError, + events::{DecreaseComponents, RebalanceEvent, RebalanceTypeTag}, maybe_transition_and_emit, utils::{deserialize_stake_pool, get_stake_pool_address, get_validator_stake_info_at_index}, Config, StewardStateAccount, @@ -287,15 +287,6 @@ pub fn handler(ctx: Context, validator_list_index: usize) -> Result<( Ok(()) } -#[event] -pub struct RebalanceEvent { - pub vote_account: Pubkey, - pub epoch: u16, - pub rebalance_type_tag: RebalanceTypeTag, - pub increase_lamports: u64, - pub decrease_components: DecreaseComponents, -} - fn rebalance_to_event( vote_account: Pubkey, epoch: u16, @@ -325,38 +316,3 @@ fn rebalance_to_event( }, } } - -#[derive(BorshSerialize, BorshDeserialize, Debug)] -pub enum RebalanceTypeTag { - None, - Increase, - Decrease, -} - -impl IdlBuild for RebalanceTypeTag { - fn create_type() -> Option { - Some(IdlTypeDef { - name: "RebalanceTypeTag".to_string(), - ty: IdlTypeDefTy::Enum { - variants: vec![ - IdlEnumVariant { - name: "None".to_string(), - fields: None, - }, - IdlEnumVariant { - name: "Increase".to_string(), - fields: None, - }, - IdlEnumVariant { - name: "Decrease".to_string(), - fields: None, - }, - ], - }, - docs: Default::default(), - generics: Default::default(), - serialization: Default::default(), - repr: Default::default(), - }) - } -} diff --git a/programs/steward/src/lib.rs b/programs/steward/src/lib.rs index 138daf11..74b8f938 100644 --- a/programs/steward/src/lib.rs +++ b/programs/steward/src/lib.rs @@ -9,6 +9,7 @@ mod allocator; pub mod constants; pub mod delegation; pub mod errors; +pub mod events; pub mod instructions; pub mod score; pub mod state; diff --git a/programs/steward/src/state/steward_state.rs b/programs/steward/src/state/steward_state.rs index 0c091fc9..41a81424 100644 --- a/programs/steward/src/state/steward_state.rs +++ b/programs/steward/src/state/steward_state.rs @@ -5,10 +5,10 @@ use crate::{ bitmask::BitMask, constants::{MAX_VALIDATORS, SORTED_INDEX_DEFAULT}, delegation::{ - decrease_stake_calculation, increase_stake_calculation, DecreaseComponents, RebalanceType, - UnstakeState, + decrease_stake_calculation, increase_stake_calculation, RebalanceType, UnstakeState, }, errors::StewardError, + events::{DecreaseComponents, StateTransition}, score::{ instant_unstake_validator, validator_score, InstantUnstakeComponents, ScoreComponents, }, @@ -28,15 +28,6 @@ fn invalid_state_error(_expected: String, _actual: String) -> Error { StewardError::InvalidState.into() } -#[event] -#[derive(Debug)] -pub struct StateTransition { - pub epoch: u64, - pub slot: u64, - pub previous_state: String, - pub new_state: String, -} - pub fn maybe_transition_and_emit( steward_state: &mut StewardState, clock: &Clock, diff --git a/tests/tests/steward/test_algorithms.rs b/tests/tests/steward/test_algorithms.rs index 901bf0b8..02bd60aa 100644 --- a/tests/tests/steward/test_algorithms.rs +++ b/tests/tests/steward/test_algorithms.rs @@ -3,10 +3,10 @@ use anchor_lang::AnchorSerialize; use jito_steward::{ constants::SORTED_INDEX_DEFAULT, delegation::{ - decrease_stake_calculation, increase_stake_calculation, DecreaseComponents, RebalanceType, - UnstakeState, + decrease_stake_calculation, increase_stake_calculation, RebalanceType, UnstakeState, }, errors::StewardError, + events::DecreaseComponents, insert_sorted_index, score::{ instant_unstake_validator, validator_score, InstantUnstakeComponents, ScoreComponents, From 34ee3b9972bbe3d2ca0256d1129380b974329d57 Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Mon, 1 Jul 2024 16:52:54 -0400 Subject: [PATCH 2/2] Idl --- programs/steward/idl/steward.json | 113 ++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/programs/steward/idl/steward.json b/programs/steward/idl/steward.json index 57e49a14..c385b4c4 100644 --- a/programs/steward/idl/steward.json +++ b/programs/steward/idl/steward.json @@ -1407,6 +1407,32 @@ } ], "events": [ + { + "name": "AutoAddValidatorEvent", + "discriminator": [ + 123, + 65, + 239, + 15, + 82, + 216, + 206, + 28 + ] + }, + { + "name": "AutoRemoveValidatorEvent", + "discriminator": [ + 211, + 46, + 52, + 163, + 17, + 38, + 197, + 186 + ] + }, { "name": "DecreaseComponents", "discriminator": [ @@ -1420,6 +1446,19 @@ 8 ] }, + { + "name": "EpochMaintenanceEvent", + "discriminator": [ + 255, + 149, + 70, + 161, + 199, + 176, + 9, + 42 + ] + }, { "name": "InstantUnstakeComponents", "discriminator": [ @@ -1661,6 +1700,46 @@ ] } }, + { + "name": "AutoAddValidatorEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "validator_list_index", + "type": "u64" + }, + { + "name": "vote_account", + "type": "pubkey" + } + ] + } + }, + { + "name": "AutoRemoveValidatorEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "validator_list_index", + "type": "u64" + }, + { + "name": "vote_account", + "type": "pubkey" + }, + { + "name": "vote_account_closed", + "type": "bool" + }, + { + "name": "stake_account_deactivated", + "type": "bool" + } + ] + } + }, { "name": "BitMask", "docs": [ @@ -2037,6 +2116,40 @@ ] } }, + { + "name": "EpochMaintenanceEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "validator_index_to_remove", + "type": { + "option": "u64" + } + }, + { + "name": "validator_list_length", + "type": "u64" + }, + { + "name": "num_pool_validators", + "type": "u64" + }, + { + "name": "validators_to_remove", + "type": "u64" + }, + { + "name": "validators_to_add", + "type": "u64" + }, + { + "name": "maintenance_complete", + "type": "bool" + } + ] + } + }, { "name": "InstantUnstakeComponents", "type": {