From 6d34aa6899c77320086992016f3b5b4f2ee9ee0f Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Tue, 4 Jun 2024 16:58:24 -0400 Subject: [PATCH 01/16] Admin methods for testing --- .../instructions/close_steward_accounts.rs | 39 +++++++++++ programs/steward/src/instructions/mod.rs | 4 ++ .../src/instructions/reset_steward_state.rs | 66 +++++++++++++++++++ programs/steward/src/lib.rs | 14 ++++ 4 files changed, 123 insertions(+) create mode 100644 programs/steward/src/instructions/close_steward_accounts.rs create mode 100644 programs/steward/src/instructions/reset_steward_state.rs diff --git a/programs/steward/src/instructions/close_steward_accounts.rs b/programs/steward/src/instructions/close_steward_accounts.rs new file mode 100644 index 00000000..bbf00776 --- /dev/null +++ b/programs/steward/src/instructions/close_steward_accounts.rs @@ -0,0 +1,39 @@ +use crate::{ + state::{Config, StewardStateAccount}, + utils::get_config_authority, + Staker, +}; +use anchor_lang::prelude::*; + +#[derive(Accounts)] +pub struct CloseStewardAccounts<'info> { + pub config: AccountLoader<'info, Config>, + + #[account( + mut, + close = authority, + seeds = [Staker::SEED, config.key().as_ref()], + bump, + )] + staker: Account<'info, Staker>, + + #[account( + mut, + close = authority, + seeds = [StewardStateAccount::SEED, config.key().as_ref()], + bump + )] + pub state_account: AccountLoader<'info, StewardStateAccount>, + + #[account(mut, address = get_config_authority(&config)?)] + pub authority: Signer<'info>, +} + +/* + Closes Steward PDA accounts associated with a given Config (StewardStateAccount, and Staker). + Config is not closed as it is a Keypair, so lamports can simply be withdrawn. + Reclaims lamports to authority +*/ +pub const fn handler(_ctx: Context) -> Result<()> { + Ok(()) +} diff --git a/programs/steward/src/instructions/mod.rs b/programs/steward/src/instructions/mod.rs index 4ca9674e..ec849977 100644 --- a/programs/steward/src/instructions/mod.rs +++ b/programs/steward/src/instructions/mod.rs @@ -2,6 +2,7 @@ pub mod add_validator_to_blacklist; pub mod auto_add_validator_to_pool; pub mod auto_remove_validator_from_pool; +pub mod close_steward_accounts; pub mod compute_delegations; pub mod compute_instant_unstake; pub mod compute_score; @@ -12,6 +13,7 @@ pub mod pause_steward; pub mod realloc_state; pub mod rebalance; pub mod remove_validator_from_blacklist; +pub mod reset_steward_state; pub mod resume_steward; pub mod set_new_authority; pub mod spl_passthrough; @@ -20,6 +22,7 @@ pub mod update_parameters; pub use add_validator_to_blacklist::*; pub use auto_add_validator_to_pool::*; pub use auto_remove_validator_from_pool::*; +pub use close_steward_accounts::*; pub use compute_delegations::*; pub use compute_instant_unstake::*; pub use compute_score::*; @@ -30,6 +33,7 @@ pub use pause_steward::*; pub use realloc_state::*; pub use rebalance::*; pub use remove_validator_from_blacklist::*; +pub use reset_steward_state::*; pub use resume_steward::*; pub use set_new_authority::*; pub use spl_passthrough::*; diff --git a/programs/steward/src/instructions/reset_steward_state.rs b/programs/steward/src/instructions/reset_steward_state.rs new file mode 100644 index 00000000..a2f84542 --- /dev/null +++ b/programs/steward/src/instructions/reset_steward_state.rs @@ -0,0 +1,66 @@ +use crate::{ + constants::{MAX_VALIDATORS, SORTED_INDEX_DEFAULT}, + errors::StewardError, + state::{Config, StewardStateAccount}, + utils::{get_config_authority, get_stake_pool, StakePool}, + BitMask, Delegation, StewardStateEnum, +}; +use anchor_lang::prelude::*; +use spl_stake_pool::state::ValidatorListHeader; + +#[derive(Accounts)] +pub struct ResetStewardState<'info> { + #[account( + mut, + seeds = [StewardStateAccount::SEED, config.key().as_ref()], + bump + )] + pub state_account: AccountLoader<'info, StewardStateAccount>, + + pub config: AccountLoader<'info, Config>, + + pub system_program: Program<'info, System>, + + #[account(address = get_stake_pool(&config)?)] + pub stake_pool: Account<'info, StakePool>, + + #[account(address = stake_pool.validator_list)] + pub validator_list: AccountInfo<'info>, + + #[account(mut, address = get_config_authority(&config)?)] + pub authority: Signer<'info>, +} + +/* + Resets steward state account to its initial state. +*/ +pub fn handler(ctx: Context) -> Result<()> { + let mut state_account = ctx.accounts.state_account.load_mut()?; + + let clock = Clock::get()?; + state_account.is_initialized = true.into(); + state_account.bump = ctx.bumps.state_account; + + let config = ctx.accounts.config.load()?; + let validator_list_data = &mut ctx.accounts.validator_list.try_borrow_mut_data()?; + let (_, validator_list) = ValidatorListHeader::deserialize_vec(validator_list_data)?; + + state_account.state.state_tag = StewardStateEnum::ComputeScores; + state_account.state.num_pool_validators = validator_list.len() as usize; + state_account.state.scores = [0; MAX_VALIDATORS]; + state_account.state.sorted_score_indices = [SORTED_INDEX_DEFAULT; MAX_VALIDATORS]; + state_account.state.yield_scores = [0; MAX_VALIDATORS]; + state_account.state.sorted_yield_score_indices = [SORTED_INDEX_DEFAULT; MAX_VALIDATORS]; + state_account.state.progress = BitMask::default(); + state_account.state.current_epoch = clock.epoch; + state_account.state.next_cycle_epoch = clock + .epoch + .checked_add(config.parameters.num_epochs_between_scoring) + .ok_or(StewardError::ArithmeticError)?; + state_account.state.delegations = [Delegation::default(); MAX_VALIDATORS]; + state_account.state.rebalance_completed = false.into(); + state_account.state.instant_unstake = BitMask::default(); + state_account.state.start_computing_scores_slot = clock.slot; + state_account.state._padding0 = [0; 6 + MAX_VALIDATORS * 8]; + Ok(()) +} diff --git a/programs/steward/src/lib.rs b/programs/steward/src/lib.rs index c668bc0b..a73132ec 100644 --- a/programs/steward/src/lib.rs +++ b/programs/steward/src/lib.rs @@ -160,6 +160,20 @@ pub mod steward { instructions::update_parameters::handler(ctx, &update_parameters_args) } + /* TEMPORARY ADMIN INSTRUCTIONS for testing */ + + /// Resets steward state account to its initial state. + pub fn reset_steward_state(ctx: Context) -> Result<()> { + instructions::reset_steward_state::handler(ctx) + } + + /// Closes Steward PDA accounts associated with a given Config (StewardStateAccount, and Staker). + /// Config is not closed as it is a Keypair, so lamports can simply be withdrawn. + /// Reclaims lamports to authority + pub fn close_steward_accounts(ctx: Context) -> Result<()> { + instructions::close_steward_accounts::handler(ctx) + } + /* Passthrough instructions to spl-stake-pool, where the signer is Staker. Must be invoked by `config.authority` */ pub fn set_staker(ctx: Context) -> Result<()> { From f78ef0686cb7214714ad10a2a0a13d60d5b86cbf Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Wed, 5 Jun 2024 16:53:49 -0400 Subject: [PATCH 02/16] new program id --- Anchor.toml | 2 +- programs/steward/src/instructions/reset_steward_state.rs | 2 -- programs/steward/src/lib.rs | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Anchor.toml b/Anchor.toml index c99a48ce..970e14b9 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -3,7 +3,7 @@ resolution = false skip-lint = false [programs.localnet] validator_history = "HistoryJTGbKQD2mRgLZ3XhqHnN811Qpez8X9kCcGHoa" -steward = "Stewardf95sJbmtcZsyagb2dg4Mo8eVQho8gpECvLx8" +steward = "sssh4zkKhX8jXTNQz1xDHyGpygzgu2UhcRcUvZihBjP" [workspace] members = [ diff --git a/programs/steward/src/instructions/reset_steward_state.rs b/programs/steward/src/instructions/reset_steward_state.rs index a2f84542..6b9bdfa2 100644 --- a/programs/steward/src/instructions/reset_steward_state.rs +++ b/programs/steward/src/instructions/reset_steward_state.rs @@ -19,8 +19,6 @@ pub struct ResetStewardState<'info> { pub config: AccountLoader<'info, Config>, - pub system_program: Program<'info, System>, - #[account(address = get_stake_pool(&config)?)] pub stake_pool: Account<'info, StakePool>, diff --git a/programs/steward/src/lib.rs b/programs/steward/src/lib.rs index a73132ec..c23ab419 100644 --- a/programs/steward/src/lib.rs +++ b/programs/steward/src/lib.rs @@ -15,7 +15,7 @@ pub mod utils; pub use state::*; -declare_id!("Stewardf95sJbmtcZsyagb2dg4Mo8eVQho8gpECvLx8"); +declare_id!("sssh4zkKhX8jXTNQz1xDHyGpygzgu2UhcRcUvZihBjP"); /* This program manages the selection of validators and delegation of stake for a SPL Stake Pool. From 0410fd227893cfdf27f02a31448cefed12cae9af Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Mon, 10 Jun 2024 13:12:28 -0400 Subject: [PATCH 03/16] IDL WIP --- Cargo.lock | 355 +++++++++++++++--- programs/steward/Cargo.toml | 5 +- programs/steward/src/delegation.rs | 8 +- .../auto_add_validator_to_pool.rs | 4 +- .../auto_remove_validator_from_pool.rs | 4 +- .../steward/src/instructions/realloc_state.rs | 2 +- .../steward/src/instructions/rebalance.rs | 4 +- .../src/instructions/reset_steward_state.rs | 4 +- .../src/instructions/spl_passthrough.rs | 18 +- programs/steward/src/lib.rs | 23 +- programs/steward/src/score.rs | 3 +- programs/steward/src/state/accounts.rs | 2 +- programs/steward/src/state/parameters.rs | 8 +- programs/steward/src/state/steward_state.rs | 63 ++-- programs/steward/src/utils.rs | 28 +- programs/validator-history/Cargo.toml | 1 + 16 files changed, 421 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41bb3bf2..aaf133e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -243,6 +243,7 @@ dependencies = [ "anchor-derive-accounts", "anchor-derive-serde", "anchor-derive-space", + "anchor-lang-idl", "arrayref", "base64 0.21.7", "bincode", @@ -259,11 +260,28 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b29da81eae478b1bb846749b06b8a2cb9c6f9ed26ca793b0c916793fdf36adab" dependencies = [ + "anchor-syn", "anyhow", + "regex", "serde", "serde_json", ] +[[package]] +name = "anchor-spl" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dcee54a30b27ea8317ca647759b5d9701a8c7caaaa0c922c6d3c306a7278a7a" +dependencies = [ + "anchor-lang", + "spl-associated-token-account 3.0.2", + "spl-pod 0.2.2", + "spl-token", + "spl-token-2022 3.0.2", + "spl-token-group-interface 0.2.3", + "spl-token-metadata-interface 0.3.3", +] + [[package]] name = "anchor-syn" version = "0.30.0" @@ -272,6 +290,7 @@ checksum = "ac53f2378bc08e89e20c2b893c01986ffd34cfbc69a17e35bd6f754753e9fdad" dependencies = [ "anyhow", "bs58 0.5.0", + "cargo_toml", "heck 0.3.3", "proc-macro2", "quote", @@ -1012,9 +1031,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.14.2" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" +checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" dependencies = [ "bytemuck_derive", ] @@ -1073,6 +1092,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cargo_toml" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" +dependencies = [ + "serde", + "toml 0.8.12", +] + [[package]] name = "cc" version = "1.0.83" @@ -2507,6 +2536,7 @@ name = "jito-steward" version = "0.1.0" dependencies = [ "anchor-lang", + "anchor-spl", "bincode", "blake3", "borsh 0.10.3", @@ -2515,7 +2545,7 @@ dependencies = [ "semver", "serde", "serde_derive", - "spl-pod", + "spl-pod 0.1.0", "spl-stake-pool", "static_assertions", "thiserror", @@ -3514,7 +3544,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" dependencies = [ - "toml", + "toml 0.5.11", ] [[package]] @@ -4219,6 +4249,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4428,8 +4467,8 @@ dependencies = [ "solana-sdk", "spl-token", "spl-token-2022 1.0.0", - "spl-token-group-interface", - "spl-token-metadata-interface", + "spl-token-group-interface 0.1.0", + "spl-token-metadata-interface 0.2.0", "thiserror", "zstd", ] @@ -5624,7 +5663,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-sdk", - "spl-associated-token-account", + "spl-associated-token-account 2.3.0", "spl-memo", "spl-token", "spl-token-2022 1.0.0", @@ -5803,6 +5842,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "spl-associated-token-account" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2e688554bac5838217ffd1fab7845c573ff106b6336bf7d290db7c98d5a8efd" +dependencies = [ + "assert_matches", + "borsh 1.4.0", + "num-derive 0.4.2", + "num-traits", + "solana-program", + "spl-token", + "spl-token-2022 3.0.2", + "thiserror", +] + [[package]] name = "spl-discriminator" version = "0.1.0" @@ -5811,7 +5866,18 @@ checksum = "cce5d563b58ef1bb2cdbbfe0dfb9ffdc24903b10ae6a4df2d8f425ece375033f" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator-derive", + "spl-discriminator-derive 0.1.2", +] + +[[package]] +name = "spl-discriminator" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34d1814406e98b08c5cd02c1126f83fd407ad084adce0b05fda5730677822eac" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator-derive 0.2.0", ] [[package]] @@ -5821,7 +5887,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07fd7858fc4ff8fb0e34090e41d7eb06a823e1057945c26d480bfc21d2338a93" dependencies = [ "quote", - "spl-discriminator-syn", + "spl-discriminator-syn 0.1.2", + "syn 2.0.48", +] + +[[package]] +name = "spl-discriminator-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" +dependencies = [ + "quote", + "spl-discriminator-syn 0.2.0", "syn 2.0.48", ] @@ -5838,6 +5915,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "spl-discriminator-syn" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f05593b7ca9eac7caca309720f2eafb96355e037e6d373b909a80fe7b69b9" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.48", + "thiserror", +] + [[package]] name = "spl-math" version = "0.2.0" @@ -5871,7 +5961,20 @@ dependencies = [ "bytemuck", "solana-program", "solana-zk-token-sdk", - "spl-program-error", + "spl-program-error 0.3.0", +] + +[[package]] +name = "spl-pod" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046ce669f48cf2eca1ec518916d8725596bfb655beb1c74374cf71dc6cb773c9" +dependencies = [ + "borsh 1.4.0", + "bytemuck", + "solana-program", + "solana-zk-token-sdk", + "spl-program-error 0.4.1", ] [[package]] @@ -5883,7 +5986,20 @@ dependencies = [ "num-derive 0.4.2", "num-traits", "solana-program", - "spl-program-error-derive", + "spl-program-error-derive 0.3.2", + "thiserror", +] + +[[package]] +name = "spl-program-error" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49065093ea91f57b9b2bd81493ff705e2ad4e64507a07dbc02b085778e02770e" +dependencies = [ + "num-derive 0.4.2", + "num-traits", + "solana-program", + "spl-program-error-derive 0.4.1", "thiserror", ] @@ -5899,6 +6015,18 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "spl-program-error-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.48", +] + [[package]] name = "spl-stake-pool" version = "1.0.0" @@ -5917,7 +6045,7 @@ dependencies = [ "solana-program", "solana-security-txt", "spl-math", - "spl-pod", + "spl-pod 0.1.0", "spl-token-2022 0.9.0", "thiserror", ] @@ -5930,10 +6058,10 @@ checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", + "spl-type-length-value 0.3.0", ] [[package]] @@ -5944,10 +6072,24 @@ checksum = "56f335787add7fa711819f9e7c573f8145a5358a709446fe2d24bf2a88117c90" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", + "spl-type-length-value 0.3.0", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cace91ba08984a41556efe49cbf2edca4db2f577b649da7827d3621161784bf8" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator 0.2.2", + "spl-pod 0.2.2", + "spl-program-error 0.4.1", + "spl-type-length-value 0.4.3", ] [[package]] @@ -5979,11 +6121,11 @@ dependencies = [ "solana-program", "solana-zk-token-sdk", "spl-memo", - "spl-pod", + "spl-pod 0.1.0", "spl-token", - "spl-token-metadata-interface", + "spl-token-metadata-interface 0.2.0", "spl-transfer-hook-interface 0.3.0", - "spl-type-length-value", + "spl-type-length-value 0.3.0", "thiserror", ] @@ -6002,12 +6144,36 @@ dependencies = [ "solana-security-txt", "solana-zk-token-sdk", "spl-memo", - "spl-pod", + "spl-pod 0.1.0", "spl-token", - "spl-token-group-interface", - "spl-token-metadata-interface", + "spl-token-group-interface 0.1.0", + "spl-token-metadata-interface 0.2.0", "spl-transfer-hook-interface 0.4.1", - "spl-type-length-value", + "spl-type-length-value 0.3.0", + "thiserror", +] + +[[package]] +name = "spl-token-2022" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5412f99ae7ee6e0afde00defaa354e6228e47e30c0e3adf553e2e01e6abb584" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.4.2", + "num-traits", + "num_enum 0.7.2", + "solana-program", + "solana-security-txt", + "solana-zk-token-sdk", + "spl-memo", + "spl-pod 0.2.2", + "spl-token", + "spl-token-group-interface 0.2.3", + "spl-token-metadata-interface 0.3.3", + "spl-transfer-hook-interface 0.6.3", + "spl-type-length-value 0.4.3", "thiserror", ] @@ -6019,9 +6185,22 @@ checksum = "b889509d49fa74a4a033ca5dae6c2307e9e918122d97e58562f5c4ffa795c75d" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d419b5cfa3ee8e0f2386fd7e02a33b3ec8a7db4a9c7064a2ea24849dc4a273b6" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator 0.2.2", + "spl-pod 0.2.2", + "spl-program-error 0.4.1", ] [[package]] @@ -6032,10 +6211,24 @@ checksum = "4c16ce3ba6979645fb7627aa1e435576172dd63088dc7848cb09aa331fa1fe4f" dependencies = [ "borsh 0.10.3", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", + "spl-type-length-value 0.3.0", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30179c47e93625680dabb620c6e7931bd12d62af390f447bc7beb4a3a9b5feee" +dependencies = [ + "borsh 1.4.0", + "solana-program", + "spl-discriminator 0.2.2", + "spl-pod 0.2.2", + "spl-program-error 0.4.1", + "spl-type-length-value 0.4.3", ] [[package]] @@ -6047,11 +6240,11 @@ dependencies = [ "arrayref", "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", "spl-tlv-account-resolution 0.4.0", - "spl-type-length-value", + "spl-type-length-value 0.3.0", ] [[package]] @@ -6063,11 +6256,27 @@ dependencies = [ "arrayref", "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", "spl-tlv-account-resolution 0.5.2", - "spl-type-length-value", + "spl-type-length-value 0.3.0", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a98359769cd988f7b35c02558daa56d496a7e3bd8626e61f90a7c757eedb9b" +dependencies = [ + "arrayref", + "bytemuck", + "solana-program", + "spl-discriminator 0.2.2", + "spl-pod 0.2.2", + "spl-program-error 0.4.1", + "spl-tlv-account-resolution 0.6.3", + "spl-type-length-value 0.4.3", ] [[package]] @@ -6078,9 +6287,22 @@ checksum = "a468e6f6371f9c69aae760186ea9f1a01c2908351b06a5e0026d21cfc4d7ecac" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", +] + +[[package]] +name = "spl-type-length-value" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "422ce13429dbd41d2cee8a73931c05fda0b0c8ca156a8b0c19445642550bb61a" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator 0.2.2", + "spl-pod 0.2.2", + "spl-program-error 0.4.1", ] [[package]] @@ -6337,7 +6559,7 @@ dependencies = [ "solana-program-test", "solana-sdk", "solana-version", - "spl-associated-token-account", + "spl-associated-token-account 2.3.0", "spl-stake-pool", "spl-token", "validator-history", @@ -6594,11 +6816,26 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.12", +] + [[package]] name = "toml_datetime" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -6608,7 +6845,7 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap 2.2.2", "toml_datetime", - "winnow", + "winnow 0.5.39", ] [[package]] @@ -6619,7 +6856,20 @@ checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap 2.2.2", "toml_datetime", - "winnow", + "winnow 0.5.39", +] + +[[package]] +name = "toml_edit" +version = "0.22.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" +dependencies = [ + "indexmap 2.2.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.12", ] [[package]] @@ -7351,6 +7601,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ff33f391015ecab21cd092389215eb265ef9496a9a07b6bee7d3529831deda" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/programs/steward/Cargo.toml b/programs/steward/Cargo.toml index 5560b02f..b9ce8b71 100644 --- a/programs/steward/Cargo.toml +++ b/programs/steward/Cargo.toml @@ -17,10 +17,11 @@ no-log-ix-name = [] cpi = ["no-entrypoint"] default = ["custom-heap"] custom-heap = [] -# idl-build = ["anchor-lang/idl-build"] +idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] [dependencies] -anchor-lang = "0.30.0" +anchor-lang = { features = ["idl-build"], version = "0.30.0" } +anchor-spl = { features = ["idl-build"], version = "0.30.0" } bincode = "1.3.3" blake3 = "1.3.1" borsh = "0.10.0" diff --git a/programs/steward/src/delegation.rs b/programs/steward/src/delegation.rs index fc333a76..2ea078ae 100644 --- a/programs/steward/src/delegation.rs +++ b/programs/steward/src/delegation.rs @@ -39,7 +39,7 @@ pub fn decrease_stake_calculation( minimum_delegation: u64, stake_rent: u64, ) -> Result { - if target_index >= state.num_pool_validators { + if target_index >= state.num_pool_validators as usize { return Err(StewardError::ValidatorIndexOutOfBounds.into()); } @@ -47,7 +47,7 @@ pub fn decrease_stake_calculation( .checked_add(stake_rent) .ok_or(StewardError::ArithmeticError)?; - for idx in state.sorted_yield_score_indices[..state.num_pool_validators] + for idx in state.sorted_yield_score_indices[..state.num_pool_validators as usize] .iter() .rev() { @@ -115,7 +115,7 @@ pub fn increase_stake_calculation( minimum_delegation: u64, stake_rent: u64, ) -> Result { - if target_index >= state.num_pool_validators { + if target_index >= state.num_pool_validators as usize { return Err(StewardError::ValidatorIndexOutOfBounds.into()); } let target_lamports: u64 = @@ -126,7 +126,7 @@ pub fn increase_stake_calculation( .ok_or(StewardError::ArithmeticError)?; if current_lamports < target_lamports { - for idx in state.sorted_score_indices[..state.num_pool_validators].iter() { + for idx in state.sorted_score_indices[..state.num_pool_validators as usize].iter() { let temp_index = *idx as usize; let lamports = if state.delegations[temp_index].numerator > 0 && !state.instant_unstake.get(temp_index)? 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 99b405c1..c31715dc 100644 --- a/programs/steward/src/instructions/auto_add_validator_to_pool.rs +++ b/programs/steward/src/instructions/auto_add_validator_to_pool.rs @@ -1,7 +1,7 @@ use crate::constants::{MAX_VALIDATORS, STAKE_POOL_WITHDRAW_SEED}; use crate::errors::StewardError; use crate::state::{Config, Staker}; -use crate::utils::{get_stake_pool, StakePool}; +use crate::utils::{get_stake_pool_address, StakePool}; use anchor_lang::prelude::*; use anchor_lang::solana_program::{program::invoke_signed, stake, sysvar, vote}; use spl_stake_pool::find_stake_program_address; @@ -28,7 +28,7 @@ pub struct AutoAddValidator<'info> { #[account( mut, - address = get_stake_pool(&config)? + address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, 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 27c1cb09..2ab2f379 100644 --- a/programs/steward/src/instructions/auto_remove_validator_from_pool.rs +++ b/programs/steward/src/instructions/auto_remove_validator_from_pool.rs @@ -3,7 +3,7 @@ use std::num::NonZeroU32; use crate::constants::STAKE_POOL_WITHDRAW_SEED; use crate::errors::StewardError; use crate::state::{Config, Staker}; -use crate::utils::{get_stake_pool, get_validator_stake_info_at_index, StakePool}; +use crate::utils::{get_stake_pool_address, get_validator_stake_info_at_index, StakePool}; use crate::StewardStateAccount; use anchor_lang::solana_program::{program::invoke_signed, stake, sysvar, vote}; use anchor_lang::{prelude::*, system_program}; @@ -39,7 +39,7 @@ pub struct AutoRemoveValidator<'info> { #[account( mut, - address = get_stake_pool(&config)? + address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, diff --git a/programs/steward/src/instructions/realloc_state.rs b/programs/steward/src/instructions/realloc_state.rs index e7b94a62..394ffd90 100644 --- a/programs/steward/src/instructions/realloc_state.rs +++ b/programs/steward/src/instructions/realloc_state.rs @@ -73,7 +73,7 @@ pub fn handler(ctx: Context) -> Result<()> { let (_, validator_list) = ValidatorListHeader::deserialize_vec(validator_list_data)?; state_account.state.state_tag = StewardStateEnum::ComputeScores; - state_account.state.num_pool_validators = validator_list.len() as usize; + state_account.state.num_pool_validators = validator_list.len() as u64; state_account.state.scores = [0; MAX_VALIDATORS]; state_account.state.sorted_score_indices = [SORTED_INDEX_DEFAULT; MAX_VALIDATORS]; state_account.state.yield_scores = [0; MAX_VALIDATORS]; diff --git a/programs/steward/src/instructions/rebalance.rs b/programs/steward/src/instructions/rebalance.rs index 9befdd26..e073cdb2 100644 --- a/programs/steward/src/instructions/rebalance.rs +++ b/programs/steward/src/instructions/rebalance.rs @@ -20,7 +20,7 @@ use crate::{ delegation::RebalanceType, errors::StewardError, maybe_transition_and_emit, - utils::{get_stake_pool, get_validator_stake_info_at_index, StakePool}, + utils::{get_stake_pool_address, get_validator_stake_info_at_index, StakePool}, Config, Staker, StewardStateAccount, }; @@ -47,7 +47,7 @@ pub struct Rebalance<'info> { #[account(address = spl_stake_pool::ID)] pub stake_pool_program: AccountInfo<'info>, - #[account(address = get_stake_pool(&config)?)] + #[account(address = get_stake_pool_address(&config)?)] pub stake_pool: Account<'info, StakePool>, #[account( diff --git a/programs/steward/src/instructions/reset_steward_state.rs b/programs/steward/src/instructions/reset_steward_state.rs index 6b9bdfa2..4005abb9 100644 --- a/programs/steward/src/instructions/reset_steward_state.rs +++ b/programs/steward/src/instructions/reset_steward_state.rs @@ -2,7 +2,7 @@ use crate::{ constants::{MAX_VALIDATORS, SORTED_INDEX_DEFAULT}, errors::StewardError, state::{Config, StewardStateAccount}, - utils::{get_config_authority, get_stake_pool, StakePool}, + utils::{get_config_authority, get_stake_pool_address, StakePool}, BitMask, Delegation, StewardStateEnum, }; use anchor_lang::prelude::*; @@ -19,7 +19,7 @@ pub struct ResetStewardState<'info> { pub config: AccountLoader<'info, Config>, - #[account(address = get_stake_pool(&config)?)] + #[account(address = get_stake_pool_address(&config)?)] pub stake_pool: Account<'info, StakePool>, #[account(address = stake_pool.validator_list)] diff --git a/programs/steward/src/instructions/spl_passthrough.rs b/programs/steward/src/instructions/spl_passthrough.rs index 741a63c6..95b15d2b 100644 --- a/programs/steward/src/instructions/spl_passthrough.rs +++ b/programs/steward/src/instructions/spl_passthrough.rs @@ -8,7 +8,7 @@ use crate::constants::MAX_VALIDATORS; use crate::errors::StewardError; use crate::state::{Config, Staker}; use crate::utils::{ - get_config_authority, get_stake_pool, get_validator_stake_info_at_index, StakePool, + get_config_authority, get_stake_pool_address, get_validator_stake_info_at_index, StakePool, ValidatorList, }; use crate::StewardStateAccount; @@ -30,7 +30,7 @@ pub struct AddValidatorToPool<'info> { pub stake_pool_program: AccountInfo<'info>, #[account( mut, - address = get_stake_pool(&config)? + address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, #[account( @@ -133,7 +133,7 @@ pub struct RemoveValidatorFromPool<'info> { pub stake_pool_program: AccountInfo<'info>, #[account( mut, - address = get_stake_pool(&config)? + address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, #[account( @@ -225,7 +225,7 @@ pub struct SetPreferredValidator<'info> { pub stake_pool_program: AccountInfo<'info>, #[account( mut, - address = get_stake_pool(&config)? + address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, #[account( @@ -290,7 +290,7 @@ pub struct IncreaseValidatorStake<'info> { pub stake_pool_program: AccountInfo<'info>, #[account( mut, - address = get_stake_pool(&config)? + address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, #[account( @@ -418,7 +418,7 @@ pub struct DecreaseValidatorStake<'info> { pub stake_pool_program: AccountInfo<'info>, #[account( mut, - address = get_stake_pool(&config)? + address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, #[account( @@ -539,7 +539,7 @@ pub struct IncreaseAdditionalValidatorStake<'info> { )] pub stake_pool_program: AccountInfo<'info>, #[account( - address = get_stake_pool(&config)? + address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, #[account( @@ -672,7 +672,7 @@ pub struct DecreaseAdditionalValidatorStake<'info> { /// CHECK: CPI program pub stake_pool_program: AccountInfo<'info>, #[account( - address = get_stake_pool(&config)? + address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, #[account( @@ -778,7 +778,7 @@ pub struct SetStaker<'info> { )] pub stake_pool_program: AccountInfo<'info>, #[account( - mut, address = get_stake_pool(&config)? + mut, address = get_stake_pool_address(&config)? )] pub stake_pool: Account<'info, StakePool>, #[account( diff --git a/programs/steward/src/lib.rs b/programs/steward/src/lib.rs index c23ab419..0ddfaf35 100644 --- a/programs/steward/src/lib.rs +++ b/programs/steward/src/lib.rs @@ -85,14 +85,14 @@ pub mod steward { /// Removes a validator from the pool if its stake account is inactive or the vote account has closed pub fn auto_remove_validator_from_pool( ctx: Context, - validator_list_index: usize, + validator_list_index: u64, ) -> Result<()> { - instructions::auto_remove_validator_from_pool::handler(ctx, validator_list_index) + instructions::auto_remove_validator_from_pool::handler(ctx, validator_list_index as usize) } /// Computes score for a the validator at `validator_list_index` for the current cycle. - pub fn compute_score(ctx: Context, validator_list_index: usize) -> Result<()> { - instructions::compute_score::handler(ctx, validator_list_index) + pub fn compute_score(ctx: Context, validator_list_index: u64) -> Result<()> { + instructions::compute_score::handler(ctx, validator_list_index as usize) } /// Computes delegation for a validator for the current cycle. @@ -109,15 +109,15 @@ pub mod steward { /// Checks if a validator at `validator_list_index` should be instant unstaked, and marks it if so pub fn compute_instant_unstake( ctx: Context, - validator_list_index: usize, + validator_list_index: u64, ) -> Result<()> { - instructions::compute_instant_unstake::handler(ctx, validator_list_index) + instructions::compute_instant_unstake::handler(ctx, validator_list_index as usize) } /// Increases or decreases stake for a validator at `validator_list_index` to match the target stake, /// given constraints on increase/decrease priority, reserve balance, and unstaking caps - pub fn rebalance(ctx: Context, validator_list_index: usize) -> Result<()> { - instructions::rebalance::handler(ctx, validator_list_index) + pub fn rebalance(ctx: Context, validator_list_index: u64) -> Result<()> { + instructions::rebalance::handler(ctx, validator_list_index as usize) } /* Admin instructions */ @@ -189,9 +189,12 @@ pub mod steward { pub fn remove_validator_from_pool( ctx: Context, - validator_list_index: usize, + validator_list_index: u64, ) -> Result<()> { - instructions::spl_passthrough::remove_validator_from_pool_handler(ctx, validator_list_index) + instructions::spl_passthrough::remove_validator_from_pool_handler( + ctx, + validator_list_index as usize, + ) } pub fn set_preferred_validator( diff --git a/programs/steward/src/score.rs b/programs/steward/src/score.rs index 762344aa..d0e04e2c 100644 --- a/programs/steward/src/score.rs +++ b/programs/steward/src/score.rs @@ -1,5 +1,6 @@ use anchor_lang::{ - prelude::event, solana_program::pubkey::Pubkey, AnchorDeserialize, AnchorSerialize, Result, + prelude::event, solana_program::pubkey::Pubkey, AnchorDeserialize, AnchorSerialize, IdlBuild, + Result, }; use validator_history::{ClusterHistory, ValidatorHistory}; diff --git a/programs/steward/src/state/accounts.rs b/programs/steward/src/state/accounts.rs index ee252adc..4cb5dc7e 100644 --- a/programs/steward/src/state/accounts.rs +++ b/programs/steward/src/state/accounts.rs @@ -1,6 +1,6 @@ use std::mem::size_of; -use anchor_lang::prelude::*; +use anchor_lang::{prelude::*, IdlBuild}; use borsh::BorshSerialize; use type_layout::TypeLayout; diff --git a/programs/steward/src/state/parameters.rs b/programs/steward/src/state/parameters.rs index 0bfaa01f..b2100db1 100644 --- a/programs/steward/src/state/parameters.rs +++ b/programs/steward/src/state/parameters.rs @@ -1,4 +1,4 @@ -use anchor_lang::{prelude::Result, zero_copy}; +use anchor_lang::{prelude::Result, zero_copy, IdlBuild}; use borsh::{BorshDeserialize, BorshSerialize}; use validator_history::utils::cast_epoch; @@ -28,7 +28,7 @@ pub struct UpdateParametersArgs { pub stake_deposit_unstake_cap_bps: Option, // State machine parameters pub instant_unstake_epoch_progress: Option, - pub compute_score_slot_range: Option, + pub compute_score_slot_range: Option, pub instant_unstake_inputs_epoch_progress: Option, pub num_epochs_between_scoring: Option, pub minimum_stake_lamports: Option, @@ -82,7 +82,7 @@ pub struct Parameters { /////// State machine operation parameters /////// /// Number of slots that scoring must be completed in - pub compute_score_slot_range: usize, + pub compute_score_slot_range: u64, /// Progress in epoch before instant unstake is allowed pub instant_unstake_epoch_progress: f64, @@ -288,7 +288,7 @@ impl Parameters { return Err(StewardError::InvalidParameterValue.into()); } - if !(COMPUTE_SCORE_SLOT_RANGE_MIN..=slots_per_epoch as usize) + if !(COMPUTE_SCORE_SLOT_RANGE_MIN as u64..=slots_per_epoch) .contains(&self.compute_score_slot_range) { return Err(StewardError::InvalidParameterValue.into()); diff --git a/programs/steward/src/state/steward_state.rs b/programs/steward/src/state/steward_state.rs index 60c975d0..a17d6771 100644 --- a/programs/steward/src/state/steward_state.rs +++ b/programs/steward/src/state/steward_state.rs @@ -13,7 +13,7 @@ use crate::{ utils::{epoch_progress, get_target_lamports, stake_lamports_at_validator_list_index, U8Bool}, Config, Parameters, }; -use anchor_lang::prelude::*; +use anchor_lang::{prelude::*, IdlBuild}; use bytemuck::{Pod, Zeroable}; use spl_stake_pool::big_vec::BigVec; @@ -98,7 +98,7 @@ pub struct StewardState { /// Number of validators in the stake pool, used to determine the number of validators to be scored. /// Updated at the start of each cycle and when validators are removed. - pub num_pool_validators: usize, + pub num_pool_validators: u64, /// Total lamports that have been due to scoring this cycle pub scoring_unstake_total: u64, @@ -191,6 +191,16 @@ impl Display for StewardStateEnum { } } +// impl IdlBuild for StewardStateEnum { +// #[cfg(feature = "idl-build")] +// fn create_type() -> Option { +// Some(IdlTypeDef { +// name: "StewardStateEnum".into(), +// ty: IdlTypeDef:: +// }) +// } +// } + impl StewardState { /// Top level transition method. Tries to transition to a new state based on current state and epoch conditions pub fn transition( @@ -247,7 +257,10 @@ impl StewardState { current_slot, num_epochs_between_scoring, )?; - } else if self.progress.is_complete(self.num_pool_validators)? { + } else if self + .progress + .is_complete(self.num_pool_validators as usize)? + { self.state_tag = StewardStateEnum::ComputeDelegations; self.progress = BitMask::default(); self.delegations = [Delegation::default(); MAX_VALIDATORS]; @@ -322,7 +335,10 @@ impl StewardState { self.current_epoch = current_epoch; self.instant_unstake = BitMask::default(); self.progress = BitMask::default(); - } else if self.progress.is_complete(self.num_pool_validators)? { + } else if self + .progress + .is_complete(self.num_pool_validators as usize)? + { self.state_tag = StewardStateEnum::Rebalance; self.progress = BitMask::default(); } @@ -348,7 +364,10 @@ impl StewardState { self.current_epoch = current_epoch; self.progress = BitMask::default(); self.rebalance_completed = false.into(); - } else if self.progress.is_complete(self.num_pool_validators)? { + } else if self + .progress + .is_complete(self.num_pool_validators as usize)? + { self.state_tag = StewardStateEnum::Idle; self.current_epoch = current_epoch; self.rebalance_completed = true.into(); @@ -390,7 +409,7 @@ impl StewardState { .ok_or(StewardError::ArithmeticError)?; // Shift all validator state to the left - for i in index..self.num_pool_validators { + for i in index..self.num_pool_validators as usize { let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; self.validator_lamport_balances[i] = self.validator_lamport_balances[next_i]; self.scores[i] = self.scores[next_i]; @@ -412,17 +431,17 @@ impl StewardState { .position(|&i| i == index as u16) .ok_or(StewardError::ValidatorIndexOutOfBounds)?; - for i in yield_score_index..self.num_pool_validators { + for i in yield_score_index..self.num_pool_validators as usize { let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; self.sorted_yield_score_indices[i] = self.sorted_yield_score_indices[next_i]; } - for i in score_index..self.num_pool_validators { + for i in score_index..self.num_pool_validators as usize { let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; self.sorted_score_indices[i] = self.sorted_score_indices[next_i]; } - for i in 0..self.num_pool_validators { + for i in 0..self.num_pool_validators as usize { if self.sorted_yield_score_indices[i] as usize > index { self.sorted_yield_score_indices[i] = self.sorted_yield_score_indices[i] .checked_sub(1) @@ -436,14 +455,16 @@ impl StewardState { } // Clear values on empty last index - self.validator_lamport_balances[self.num_pool_validators] = 0; - self.scores[self.num_pool_validators] = 0; - self.yield_scores[self.num_pool_validators] = 0; - self.sorted_score_indices[self.num_pool_validators] = SORTED_INDEX_DEFAULT; - self.sorted_yield_score_indices[self.num_pool_validators] = SORTED_INDEX_DEFAULT; - self.delegations[self.num_pool_validators] = Delegation::default(); - self.instant_unstake.set(self.num_pool_validators, false)?; - self.progress.set(self.num_pool_validators, false)?; + self.validator_lamport_balances[self.num_pool_validators as usize] = 0; + self.scores[self.num_pool_validators as usize] = 0; + self.yield_scores[self.num_pool_validators as usize] = 0; + self.sorted_score_indices[self.num_pool_validators as usize] = SORTED_INDEX_DEFAULT; + self.sorted_yield_score_indices[self.num_pool_validators as usize] = SORTED_INDEX_DEFAULT; + self.delegations[self.num_pool_validators as usize] = Delegation::default(); + self.instant_unstake + .set(self.num_pool_validators as usize, false)?; + self.progress + .set(self.num_pool_validators as usize, false)?; Ok(()) } @@ -463,7 +484,7 @@ impl StewardState { index: usize, cluster: &ClusterHistory, config: &Config, - num_pool_validators: usize, + num_pool_validators: u64, ) -> Result<()> { if matches!(self.state_tag, StewardStateEnum::ComputeScores) { let current_epoch = clock.epoch; @@ -552,8 +573,8 @@ impl StewardState { } let validators_to_delegate = select_validators_to_delegate( - &self.scores[..self.num_pool_validators], - &self.sorted_score_indices[..self.num_pool_validators], + &self.scores[..self.num_pool_validators as usize], + &self.sorted_score_indices[..self.num_pool_validators as usize], config.parameters.num_delegation_validators as usize, ); @@ -815,7 +836,7 @@ impl StewardState { } let next_i = index.checked_add(1).ok_or(StewardError::ArithmeticError)?; - for i in next_i..self.num_pool_validators { + for i in next_i..self.num_pool_validators as usize { if self.delegations[i].numerator > 0 { self.delegations[i].denominator = self.delegations[i].denominator.saturating_sub(1).max(1); diff --git a/programs/steward/src/utils.rs b/programs/steward/src/utils.rs index 6d6436de..d2fde003 100644 --- a/programs/steward/src/utils.rs +++ b/programs/steward/src/utils.rs @@ -1,6 +1,6 @@ use std::ops::{Deref, Not}; -use anchor_lang::prelude::*; +use anchor_lang::{prelude::*, IdlBuild}; use borsh::{BorshDeserialize, BorshSerialize}; use spl_pod::{bytemuck::pod_from_bytes, primitives::PodU64, solana_program::program_pack::Pack}; use spl_stake_pool::{ @@ -10,7 +10,7 @@ use spl_stake_pool::{ use crate::{errors::StewardError, Config, Delegation}; -pub fn get_stake_pool(account: &AccountLoader) -> Result { +pub fn get_stake_pool_address(account: &AccountLoader) -> Result { let config = account.load()?; Ok(config.stake_pool) } @@ -121,6 +121,30 @@ impl From for bool { } } +pub fn deserialize_stake_pool( + account_info: &AccountInfo, +) -> Result { + if account_info.owner != &spl_stake_pool::ID { + return Err(ProgramError::InvalidAccountOwner.into()); + } + let data = account_info.try_borrow_data()?; + Ok(spl_stake_pool::state::StakePool::deserialize( + &mut data.as_ref(), + )?) +} + +pub fn deserialize_validator_list( + account_info: &AccountInfo, +) -> Result { + if account_info.owner != &spl_stake_pool::ID { + return Err(ProgramError::InvalidAccountOwner.into()); + } + let data = account_info.try_borrow_data()?; + Ok(spl_stake_pool::state::ValidatorList::deserialize( + &mut data.as_ref(), + )?) +} + #[derive(Clone)] pub struct StakePool(spl_stake_pool::state::StakePool); diff --git a/programs/validator-history/Cargo.toml b/programs/validator-history/Cargo.toml index c252075f..df04b7c4 100644 --- a/programs/validator-history/Cargo.toml +++ b/programs/validator-history/Cargo.toml @@ -21,6 +21,7 @@ cpi = ["no-entrypoint"] default = ["custom-heap"] custom-heap = [] # idl-build = ["anchor-lang/idl-build"] +idl-build = [] [dependencies] anchor-lang = "0.30.0" From 57081b898382f45c9a5c69a9e44dc9762134ab24 Mon Sep 17 00:00:00 2001 From: Coach Chuck <169060940+coachchucksol@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:13:06 -0600 Subject: [PATCH 04/16] FIX: Skip reordering scored indexes if index DNE (#45) Co-authored-by: Christian --- programs/steward/src/state/steward_state.rs | 23 ++++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/programs/steward/src/state/steward_state.rs b/programs/steward/src/state/steward_state.rs index 60c975d0..1486f965 100644 --- a/programs/steward/src/state/steward_state.rs +++ b/programs/steward/src/state/steward_state.rs @@ -400,26 +400,29 @@ impl StewardState { .set(i, self.instant_unstake.get(next_i)?)?; self.progress.set(i, self.progress.get(next_i)?)?; } + // Update score indices let yield_score_index = self .sorted_yield_score_indices .iter() - .position(|&i| i == index as u16) - .ok_or(StewardError::ValidatorIndexOutOfBounds)?; + .position(|&i| i == index as u16); let score_index = self .sorted_score_indices .iter() - .position(|&i| i == index as u16) - .ok_or(StewardError::ValidatorIndexOutOfBounds)?; + .position(|&i| i == index as u16); - for i in yield_score_index..self.num_pool_validators { - let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; - self.sorted_yield_score_indices[i] = self.sorted_yield_score_indices[next_i]; + if let Some(yield_score_index) = yield_score_index { + for i in yield_score_index..self.num_pool_validators { + let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; + self.sorted_yield_score_indices[i] = self.sorted_yield_score_indices[next_i]; + } } - for i in score_index..self.num_pool_validators { - let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; - self.sorted_score_indices[i] = self.sorted_score_indices[next_i]; + if let Some(score_index) = score_index { + for i in score_index..self.num_pool_validators { + let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; + self.sorted_score_indices[i] = self.sorted_score_indices[next_i]; + } } for i in 0..self.num_pool_validators { From ee7a39a9edf723c9aeb7e223488b316c2edaa085 Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Tue, 11 Jun 2024 12:05:59 -0400 Subject: [PATCH 05/16] more WIP --- .../auto_add_validator_to_pool.rs | 11 +- .../auto_remove_validator_from_pool.rs | 19 +-- .../instructions/compute_instant_unstake.rs | 1 + .../steward/src/instructions/compute_score.rs | 3 +- .../src/instructions/initialize_config.rs | 12 +- .../steward/src/instructions/realloc_state.rs | 1 + .../steward/src/instructions/rebalance.rs | 20 ++-- .../src/instructions/reset_steward_state.rs | 10 +- .../src/instructions/spl_passthrough.rs | 58 +++++---- programs/steward/src/lib.rs | 5 +- programs/steward/src/state/parameters.rs | 112 +++++++++++++++++- programs/steward/src/state/steward_state.rs | 47 ++++++-- programs/steward/src/utils.rs | 43 ++++++- programs/validator-history/Cargo.toml | 2 +- test | 5 + 15 files changed, 280 insertions(+), 69 deletions(-) create mode 100755 test 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 c31715dc..8ecb5b47 100644 --- a/programs/steward/src/instructions/auto_add_validator_to_pool.rs +++ b/programs/steward/src/instructions/auto_add_validator_to_pool.rs @@ -1,7 +1,7 @@ use crate::constants::{MAX_VALIDATORS, STAKE_POOL_WITHDRAW_SEED}; use crate::errors::StewardError; use crate::state::{Config, Staker}; -use crate::utils::{get_stake_pool_address, StakePool}; +use crate::utils::{deserialize_stake_pool, get_stake_pool_address}; use anchor_lang::prelude::*; use anchor_lang::solana_program::{program::invoke_signed, stake, sysvar, vote}; use spl_stake_pool::find_stake_program_address; @@ -26,11 +26,12 @@ pub struct AutoAddValidator<'info> { )] pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], @@ -39,7 +40,7 @@ pub struct AutoAddValidator<'info> { pub staker: Account<'info, Staker>, /// CHECK: passing through, checks are done by spl-stake-pool - #[account(mut, address = stake_pool.reserve_stake)] + #[account(mut, address = deserialize_stake_pool(&stake_pool)?.reserve_stake)] pub reserve_stake: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool @@ -49,12 +50,12 @@ pub struct AutoAddValidator<'info> { STAKE_POOL_WITHDRAW_SEED ], seeds::program = spl_stake_pool::ID, - bump = stake_pool.stake_withdraw_bump_seed + bump = deserialize_stake_pool(&stake_pool)?.stake_withdraw_bump_seed )] pub withdraw_authority: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool - #[account(mut, address = stake_pool.validator_list)] + #[account(mut, address = deserialize_stake_pool(&stake_pool)?.validator_list)] pub validator_list: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool 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 2ab2f379..bec46b49 100644 --- a/programs/steward/src/instructions/auto_remove_validator_from_pool.rs +++ b/programs/steward/src/instructions/auto_remove_validator_from_pool.rs @@ -3,7 +3,9 @@ use std::num::NonZeroU32; use crate::constants::STAKE_POOL_WITHDRAW_SEED; use crate::errors::StewardError; use crate::state::{Config, Staker}; -use crate::utils::{get_stake_pool_address, get_validator_stake_info_at_index, StakePool}; +use crate::utils::{ + deserialize_stake_pool, get_stake_pool_address, get_validator_stake_info_at_index, StakePool, +}; use crate::StewardStateAccount; use anchor_lang::solana_program::{program::invoke_signed, stake, sysvar, vote}; use anchor_lang::{prelude::*, system_program}; @@ -13,7 +15,7 @@ use spl_stake_pool::{find_stake_program_address, find_transient_stake_program_ad use validator_history::state::ValidatorHistory; #[derive(Accounts)] -#[instruction(validator_list_index: usize)] +#[instruction(validator_list_index: u64)] pub struct AutoRemoveValidator<'info> { #[account( seeds = [ValidatorHistory::SEED, vote_account.key().as_ref()], @@ -37,11 +39,12 @@ pub struct AutoRemoveValidator<'info> { )] pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], @@ -50,7 +53,7 @@ pub struct AutoRemoveValidator<'info> { pub staker: Account<'info, Staker>, /// CHECK: passing through, checks are done by spl-stake-pool - #[account(mut, address = stake_pool.reserve_stake)] + #[account(mut, address = deserialize_stake_pool(&stake_pool)?.reserve_stake)] pub reserve_stake: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool @@ -60,12 +63,12 @@ pub struct AutoRemoveValidator<'info> { STAKE_POOL_WITHDRAW_SEED ], seeds::program = spl_stake_pool::ID, - bump = stake_pool.stake_withdraw_bump_seed + bump = deserialize_stake_pool(&stake_pool)?.stake_withdraw_bump_seed )] pub withdraw_authority: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool - #[account(mut, address = stake_pool.validator_list)] + #[account(mut, address = deserialize_stake_pool(&stake_pool)?.validator_list)] pub validator_list: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool @@ -77,7 +80,7 @@ pub struct AutoRemoveValidator<'info> { &stake_pool.key(), NonZeroU32::new( u32::from( - get_validator_stake_info_at_index(&validator_list, validator_list_index)? + get_validator_stake_info_at_index(&validator_list, validator_list_index as usize)? .validator_seed_suffix ) ) @@ -94,7 +97,7 @@ pub struct AutoRemoveValidator<'info> { &spl_stake_pool::id(), &vote_account.key(), &stake_pool.key(), - get_validator_stake_info_at_index(&validator_list, validator_list_index)?.transient_seed_suffix.into() + get_validator_stake_info_at_index(&validator_list, validator_list_index as usize)?.transient_seed_suffix.into() ).0 )] pub transient_stake_account: AccountInfo<'info>, diff --git a/programs/steward/src/instructions/compute_instant_unstake.rs b/programs/steward/src/instructions/compute_instant_unstake.rs index a87b7fcb..a5a294ac 100644 --- a/programs/steward/src/instructions/compute_instant_unstake.rs +++ b/programs/steward/src/instructions/compute_instant_unstake.rs @@ -18,6 +18,7 @@ pub struct ComputeInstantUnstake<'info> { pub validator_history: AccountLoader<'info, ValidatorHistory>, + /// CHECK: TODO #[account(owner = spl_stake_pool::id())] pub validator_list: AccountInfo<'info>, diff --git a/programs/steward/src/instructions/compute_score.rs b/programs/steward/src/instructions/compute_score.rs index a9a32e9d..79b6b359 100644 --- a/programs/steward/src/instructions/compute_score.rs +++ b/programs/steward/src/instructions/compute_score.rs @@ -20,6 +20,7 @@ pub struct ComputeScore<'info> { pub validator_history: AccountLoader<'info, ValidatorHistory>, + /// CHECK: TODO #[account(owner = spl_stake_pool::id())] pub validator_list: AccountInfo<'info>, @@ -53,7 +54,7 @@ pub fn handler(ctx: Context, validator_list_index: usize) -> Resul let num_pool_validators = { let mut validator_list_data = validator_list.try_borrow_mut_data()?; let (_, validator_list) = ValidatorListHeader::deserialize_vec(&mut validator_list_data)?; - validator_list.len() as usize + validator_list.len() as u64 }; if config.is_paused() { diff --git a/programs/steward/src/instructions/initialize_config.rs b/programs/steward/src/instructions/initialize_config.rs index 7b22765c..3311a63e 100644 --- a/programs/steward/src/instructions/initialize_config.rs +++ b/programs/steward/src/instructions/initialize_config.rs @@ -1,6 +1,9 @@ use anchor_lang::{prelude::*, solana_program::program::invoke}; -use crate::{utils::StakePool, Config, Staker, UpdateParametersArgs}; +use crate::{ + utils::{deserialize_stake_pool, StakePool}, + Config, Staker, UpdateParametersArgs, +}; #[derive(Accounts)] pub struct InitializeConfig<'info> { @@ -23,8 +26,9 @@ pub struct InitializeConfig<'info> { )] pub staker: Account<'info, Staker>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account(mut)] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, /// CHECK: CPI program #[account(address = spl_stake_pool::ID)] @@ -34,7 +38,7 @@ pub struct InitializeConfig<'info> { #[account( mut, - address = stake_pool.staker + address = deserialize_stake_pool(&stake_pool)?.staker )] pub signer: Signer<'info>, } @@ -44,6 +48,8 @@ pub fn handler( authority: Pubkey, update_parameters_args: &UpdateParametersArgs, ) -> Result<()> { + // Confirm that the stake pool is valid + let _ = deserialize_stake_pool(&ctx.accounts.stake_pool)?; let mut config = ctx.accounts.config.load_init()?; config.stake_pool = ctx.accounts.stake_pool.key(); config.authority = authority; diff --git a/programs/steward/src/instructions/realloc_state.rs b/programs/steward/src/instructions/realloc_state.rs index 394ffd90..2d706ca9 100644 --- a/programs/steward/src/instructions/realloc_state.rs +++ b/programs/steward/src/instructions/realloc_state.rs @@ -43,6 +43,7 @@ pub struct ReallocState<'info> { pub config: AccountLoader<'info, Config>, + /// CHECK: TODO #[account( owner = spl_stake_pool::ID, )] diff --git a/programs/steward/src/instructions/rebalance.rs b/programs/steward/src/instructions/rebalance.rs index e073cdb2..92ef5a46 100644 --- a/programs/steward/src/instructions/rebalance.rs +++ b/programs/steward/src/instructions/rebalance.rs @@ -20,12 +20,12 @@ use crate::{ delegation::RebalanceType, errors::StewardError, maybe_transition_and_emit, - utils::{get_stake_pool_address, get_validator_stake_info_at_index, StakePool}, + utils::{deserialize_stake_pool, get_stake_pool_address, get_validator_stake_info_at_index}, Config, Staker, StewardStateAccount, }; #[derive(Accounts)] -#[instruction(validator_list_index: usize)] +#[instruction(validator_list_index: u64)] pub struct Rebalance<'info> { pub config: AccountLoader<'info, Config>, @@ -47,8 +47,9 @@ pub struct Rebalance<'info> { #[account(address = spl_stake_pool::ID)] pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account(address = get_stake_pool_address(&config)?)] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( mut, @@ -64,21 +65,21 @@ pub struct Rebalance<'info> { STAKE_POOL_WITHDRAW_SEED ], seeds::program = spl_stake_pool::ID, - bump = stake_pool.stake_withdraw_bump_seed + bump = deserialize_stake_pool(&stake_pool)?.stake_withdraw_bump_seed )] pub withdraw_authority: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, - address = stake_pool.validator_list + address = deserialize_stake_pool(&stake_pool)?.validator_list )] pub validator_list: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, - address = stake_pool.reserve_stake + address = deserialize_stake_pool(&stake_pool)?.reserve_stake )] pub reserve_stake: AccountInfo<'info>, @@ -91,7 +92,7 @@ pub struct Rebalance<'info> { &stake_pool.key(), NonZeroU32::new( u32::from( - get_validator_stake_info_at_index(&validator_list, validator_list_index)? + get_validator_stake_info_at_index(&validator_list, validator_list_index as usize)? .validator_seed_suffix ) ) @@ -108,7 +109,7 @@ pub struct Rebalance<'info> { &spl_stake_pool::id(), &vote_account.key(), &stake_pool.key(), - get_validator_stake_info_at_index(&validator_list, validator_list_index)?.transient_seed_suffix.into() + get_validator_stake_info_at_index(&validator_list, validator_list_index as usize)?.transient_seed_suffix.into() ).0 )] pub transient_stake_account: AccountInfo<'info>, @@ -171,7 +172,8 @@ pub fn handler(ctx: Context, validator_list_index: usize) -> Result<( let validator_list_data = &mut ctx.accounts.validator_list.try_borrow_mut_data()?; let (_, validator_list) = ValidatorListHeader::deserialize_vec(validator_list_data)?; - let stake_pool_lamports_with_fixed_cost = ctx.accounts.stake_pool.total_lamports; + let stake_pool_lamports_with_fixed_cost = + deserialize_stake_pool(&ctx.accounts.stake_pool)?.total_lamports; let reserve_lamports_with_rent = ctx.accounts.reserve_stake.lamports(); state_account.state.rebalance( diff --git a/programs/steward/src/instructions/reset_steward_state.rs b/programs/steward/src/instructions/reset_steward_state.rs index 4005abb9..5a24699f 100644 --- a/programs/steward/src/instructions/reset_steward_state.rs +++ b/programs/steward/src/instructions/reset_steward_state.rs @@ -2,7 +2,7 @@ use crate::{ constants::{MAX_VALIDATORS, SORTED_INDEX_DEFAULT}, errors::StewardError, state::{Config, StewardStateAccount}, - utils::{get_config_authority, get_stake_pool_address, StakePool}, + utils::{deserialize_stake_pool, get_config_authority, get_stake_pool_address, StakePool}, BitMask, Delegation, StewardStateEnum, }; use anchor_lang::prelude::*; @@ -19,10 +19,12 @@ pub struct ResetStewardState<'info> { pub config: AccountLoader<'info, Config>, + /// CHECK: TODO #[account(address = get_stake_pool_address(&config)?)] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, - #[account(address = stake_pool.validator_list)] + /// CHECK: TODO + #[account(address = deserialize_stake_pool(&stake_pool)?.validator_list)] pub validator_list: AccountInfo<'info>, #[account(mut, address = get_config_authority(&config)?)] @@ -44,7 +46,7 @@ pub fn handler(ctx: Context) -> Result<()> { let (_, validator_list) = ValidatorListHeader::deserialize_vec(validator_list_data)?; state_account.state.state_tag = StewardStateEnum::ComputeScores; - state_account.state.num_pool_validators = validator_list.len() as usize; + state_account.state.num_pool_validators = validator_list.len() as u64; state_account.state.scores = [0; MAX_VALIDATORS]; state_account.state.sorted_score_indices = [SORTED_INDEX_DEFAULT; MAX_VALIDATORS]; state_account.state.yield_scores = [0; MAX_VALIDATORS]; diff --git a/programs/steward/src/instructions/spl_passthrough.rs b/programs/steward/src/instructions/spl_passthrough.rs index 95b15d2b..db239852 100644 --- a/programs/steward/src/instructions/spl_passthrough.rs +++ b/programs/steward/src/instructions/spl_passthrough.rs @@ -8,8 +8,8 @@ use crate::constants::MAX_VALIDATORS; use crate::errors::StewardError; use crate::state::{Config, Staker}; use crate::utils::{ - get_config_authority, get_stake_pool_address, get_validator_stake_info_at_index, StakePool, - ValidatorList, + deserialize_stake_pool, get_config_authority, get_stake_pool_address, + get_validator_stake_info_at_index, StakePool, ValidatorList, }; use crate::StewardStateAccount; use anchor_lang::prelude::*; @@ -32,7 +32,8 @@ pub struct AddValidatorToPool<'info> { mut, address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + /// CHECK: passing through, checks are done by spl-stake-pool + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], bump = staker.bump @@ -44,7 +45,7 @@ pub struct AddValidatorToPool<'info> { /// CHECK: passing through, checks are done by spl-stake-pool pub withdraw_authority: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool - #[account(mut, address = stake_pool.validator_list)] + #[account(mut, address = deserialize_stake_pool(&stake_pool)?.validator_list)] pub validator_list: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool #[account(mut)] @@ -131,11 +132,12 @@ pub struct RemoveValidatorFromPool<'info> { address = spl_stake_pool::ID )] pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], bump = staker.bump @@ -143,8 +145,9 @@ pub struct RemoveValidatorFromPool<'info> { pub staker: Account<'info, Staker>, /// CHECK: passing through, checks are done by spl-stake-pool pub withdraw_authority: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account(mut)] - pub validator_list: Account<'info, ValidatorList>, + pub validator_list: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool #[account(mut)] pub stake_account: AccountInfo<'info>, @@ -166,7 +169,7 @@ pub fn remove_validator_from_pool_handler( ) -> Result<()> { let mut state_account = ctx.accounts.steward_state.load_mut()?; - if validator_list_index < state_account.state.num_pool_validators { + if validator_list_index < state_account.state.num_pool_validators as usize { let validator_list_stake_info = get_validator_stake_info_at_index( &ctx.accounts.validator_list.to_account_info(), validator_list_index, @@ -223,25 +226,27 @@ pub struct SetPreferredValidator<'info> { address = spl_stake_pool::ID )] pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], bump = staker.bump )] pub staker: Account<'info, Staker>, - #[account(address = stake_pool.validator_list)] - pub validator_list: Account<'info, ValidatorList>, + /// CHECK: passing through, checks are done by spl-stake-pool + #[account(address = deserialize_stake_pool(&stake_pool)?.validator_list)] + pub validator_list: AccountInfo<'info>, #[account(mut, address = get_config_authority(&config)?)] pub signer: Signer<'info>, } pub fn set_preferred_validator_handler( ctx: Context, - validator_type: PreferredValidatorType, + validator_type: &PreferredValidatorType, validator: Option, ) -> Result<()> { invoke_signed( @@ -250,7 +255,7 @@ pub fn set_preferred_validator_handler( &ctx.accounts.stake_pool.key(), &ctx.accounts.staker.key(), &ctx.accounts.validator_list.key(), - validator_type, + validator_type.clone(), validator, ), &[ @@ -288,11 +293,12 @@ pub struct IncreaseValidatorStake<'info> { address = spl_stake_pool::ID )] pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], bump = staker.bump @@ -306,7 +312,7 @@ pub struct IncreaseValidatorStake<'info> { /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, - address = stake_pool.reserve_stake + address = deserialize_stake_pool(&stake_pool)?.reserve_stake )] pub reserve_stake: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool @@ -416,11 +422,12 @@ pub struct DecreaseValidatorStake<'info> { address = spl_stake_pool::ID )] pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], bump = staker.bump @@ -434,7 +441,7 @@ pub struct DecreaseValidatorStake<'info> { /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, - address = stake_pool.reserve_stake + address = deserialize_stake_pool(&stake_pool)?.reserve_stake )] pub reserve_stake: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool @@ -538,10 +545,11 @@ pub struct IncreaseAdditionalValidatorStake<'info> { address = spl_stake_pool::ID )] pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account( address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], bump = staker.bump @@ -549,8 +557,9 @@ pub struct IncreaseAdditionalValidatorStake<'info> { pub staker: Account<'info, Staker>, /// CHECK: passing through, checks are done by spl-stake-pool pub withdraw_authority: AccountInfo<'info>, - #[account(mut, address = stake_pool.validator_list)] - pub validator_list: Account<'info, ValidatorList>, + /// CHECK: passing through, checks are done by spl-stake-pool + #[account(mut, address = deserialize_stake_pool(&stake_pool)?.validator_list)] + pub validator_list: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool #[account(mut)] pub reserve_stake: AccountInfo<'info>, @@ -671,10 +680,11 @@ pub struct DecreaseAdditionalValidatorStake<'info> { )] /// CHECK: CPI program pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account( address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], bump = staker.bump @@ -682,8 +692,9 @@ pub struct DecreaseAdditionalValidatorStake<'info> { pub staker: Account<'info, Staker>, /// CHECK: passing through, checks are done by spl-stake-pool pub withdraw_authority: AccountInfo<'info>, - #[account(mut, address = stake_pool.validator_list)] - pub validator_list: Account<'info, ValidatorList>, + /// CHECK: passing through, checks are done by spl-stake-pool + #[account(mut, address = deserialize_stake_pool(&stake_pool)?.validator_list)] + pub validator_list: AccountInfo<'info>, /// CHECK: passing through, checks are done by spl-stake-pool #[account(mut)] pub reserve_stake: AccountInfo<'info>, @@ -777,10 +788,11 @@ pub struct SetStaker<'info> { address = spl_stake_pool::ID )] pub stake_pool_program: AccountInfo<'info>, + /// CHECK: passing through, checks are done by spl-stake-pool #[account( mut, address = get_stake_pool_address(&config)? )] - pub stake_pool: Account<'info, StakePool>, + pub stake_pool: AccountInfo<'info>, #[account( seeds = [Staker::SEED, config.key().as_ref()], bump = staker.bump diff --git a/programs/steward/src/lib.rs b/programs/steward/src/lib.rs index 0ddfaf35..bed7bea1 100644 --- a/programs/steward/src/lib.rs +++ b/programs/steward/src/lib.rs @@ -1,8 +1,9 @@ #![allow(clippy::redundant_pub_crate)] use anchor_lang::prelude::*; +use anchor_lang::IdlBuild; use instructions::*; -use spl_stake_pool::instruction::PreferredValidatorType; +use crate::utils::PreferredValidatorType; mod allocator; pub mod constants; @@ -204,7 +205,7 @@ pub mod steward { ) -> Result<()> { instructions::spl_passthrough::set_preferred_validator_handler( ctx, - validator_type, + validator_type.as_ref(), validator, ) } diff --git a/programs/steward/src/state/parameters.rs b/programs/steward/src/state/parameters.rs index b2100db1..79ff507f 100644 --- a/programs/steward/src/state/parameters.rs +++ b/programs/steward/src/state/parameters.rs @@ -1,4 +1,7 @@ -use anchor_lang::{prelude::Result, zero_copy, IdlBuild}; +// #[cfg(feature = "idl-build")] +use anchor_lang::idl::types::*; +use anchor_lang::idl::*; +use anchor_lang::{prelude::Result, zero_copy}; use borsh::{BorshDeserialize, BorshSerialize}; use validator_history::utils::cast_epoch; @@ -35,6 +38,113 @@ pub struct UpdateParametersArgs { pub minimum_voting_epochs: Option, } +// #[cfg(feature = "idl-build")] +impl IdlBuild for UpdateParametersArgs { + fn create_type() -> Option { + Some(IdlTypeDef { + name: "UpdateParametersArgs".to_string(), + ty: IdlTypeDefTy::Struct { + fields: Some(IdlDefinedFields::Named(vec![ + IdlField { + name: "mev_commission_range".to_string(), + ty: IdlType::Option(Box::new(IdlType::U16)), + docs: Default::default(), + }, + IdlField { + name: "epoch_credits_range".to_string(), + ty: IdlType::Option(Box::new(IdlType::U16)), + docs: Default::default(), + }, + IdlField { + name: "commission_range".to_string(), + ty: IdlType::Option(Box::new(IdlType::U16)), + docs: Default::default(), + }, + IdlField { + name: "scoring_delinquency_threshold_ratio".to_string(), + ty: IdlType::Option(Box::new(IdlType::F64)), + docs: Default::default(), + }, + IdlField { + name: "instant_unstake_delinquency_threshold_ratio".to_string(), + ty: IdlType::Option(Box::new(IdlType::F64)), + docs: Default::default(), + }, + IdlField { + name: "mev_commission_bps_threshold".to_string(), + ty: IdlType::Option(Box::new(IdlType::U16)), + docs: Default::default(), + }, + IdlField { + name: "commission_threshold".to_string(), + ty: IdlType::Option(Box::new(IdlType::U8)), + docs: Default::default(), + }, + IdlField { + name: "historical_commission_threshold".to_string(), + ty: IdlType::Option(Box::new(IdlType::U8)), + docs: Default::default(), + }, + IdlField { + name: "num_delegation_validators".to_string(), + ty: IdlType::Option(Box::new(IdlType::U32)), + docs: Default::default(), + }, + IdlField { + name: "scoring_unstake_cap_bps".to_string(), + ty: IdlType::Option(Box::new(IdlType::U32)), + docs: Default::default(), + }, + IdlField { + name: "instant_unstake_cap_bps".to_string(), + ty: IdlType::Option(Box::new(IdlType::U32)), + docs: Default::default(), + }, + IdlField { + name: "stake_deposit_unstake_cap_bps".to_string(), + ty: IdlType::Option(Box::new(IdlType::U32)), + docs: Default::default(), + }, + IdlField { + name: "instant_unstake_epoch_progress".to_string(), + ty: IdlType::Option(Box::new(IdlType::F64)), + docs: Default::default(), + }, + IdlField { + name: "compute_score_slot_range".to_string(), + ty: IdlType::Option(Box::new(IdlType::U64)), + docs: Default::default(), + }, + IdlField { + name: "instant_unstake_inputs_epoch_progress".to_string(), + ty: IdlType::Option(Box::new(IdlType::F64)), + docs: Default::default(), + }, + IdlField { + name: "num_epochs_between_scoring".to_string(), + ty: IdlType::Option(Box::new(IdlType::U64)), + docs: Default::default(), + }, + IdlField { + name: "minimum_stake_lamports".to_string(), + ty: IdlType::Option(Box::new(IdlType::U64)), + docs: Default::default(), + }, + IdlField { + name: "minimum_voting_epochs".to_string(), + ty: IdlType::Option(Box::new(IdlType::U64)), + docs: Default::default(), + }, + ])), + }, + docs: Default::default(), + generics: Default::default(), + serialization: Default::default(), + repr: Default::default(), + }) + } +} + #[derive(BorshSerialize, Default)] #[zero_copy] pub struct Parameters { diff --git a/programs/steward/src/state/steward_state.rs b/programs/steward/src/state/steward_state.rs index 7e126099..4b2db54e 100644 --- a/programs/steward/src/state/steward_state.rs +++ b/programs/steward/src/state/steward_state.rs @@ -13,6 +13,7 @@ use crate::{ utils::{epoch_progress, get_target_lamports, stake_lamports_at_validator_list_index, U8Bool}, Config, Parameters, }; +use anchor_lang::idl::types::*; use anchor_lang::{prelude::*, IdlBuild}; use bytemuck::{Pod, Zeroable}; @@ -21,7 +22,7 @@ use validator_history::{ClusterHistory, ValidatorHistory}; // Tests will fail here - comment out msg! to pass fn invalid_state_error(expected: String, actual: String) -> Error { - msg!("Invalid state. Expected {}, Actual {}", expected, actual); + // msg!("Invalid state. Expected {}, Actual {}", expected, actual); StewardError::InvalidState.into() } @@ -191,15 +192,41 @@ impl Display for StewardStateEnum { } } -// impl IdlBuild for StewardStateEnum { -// #[cfg(feature = "idl-build")] -// fn create_type() -> Option { -// Some(IdlTypeDef { -// name: "StewardStateEnum".into(), -// ty: IdlTypeDef:: -// }) -// } -// } +impl IdlBuild for StewardStateEnum { + fn create_type() -> Option { + Some(IdlTypeDef { + name: "StewardStateEnum".to_string(), + ty: IdlTypeDefTy::Enum { + variants: vec![ + IdlEnumVariant { + name: "ComputeScores".to_string(), + fields: None, + }, + IdlEnumVariant { + name: "ComputeDelegations".to_string(), + fields: None, + }, + IdlEnumVariant { + name: "Idle".to_string(), + fields: None, + }, + IdlEnumVariant { + name: "ComputeInstantUnstake".to_string(), + fields: None, + }, + IdlEnumVariant { + name: "Rebalance".to_string(), + fields: None, + }, + ], + }, + docs: Default::default(), + generics: Default::default(), + serialization: Default::default(), + repr: Default::default(), + }) + } +} impl StewardState { /// Top level transition method. Tries to transition to a new state based on current state and epoch conditions diff --git a/programs/steward/src/utils.rs b/programs/steward/src/utils.rs index d2fde003..484f64ca 100644 --- a/programs/steward/src/utils.rs +++ b/programs/steward/src/utils.rs @@ -1,11 +1,11 @@ use std::ops::{Deref, Not}; -use anchor_lang::{prelude::*, IdlBuild}; +use anchor_lang::{idl::types::*, prelude::*}; use borsh::{BorshDeserialize, BorshSerialize}; use spl_pod::{bytemuck::pod_from_bytes, primitives::PodU64, solana_program::program_pack::Pack}; use spl_stake_pool::{ big_vec::BigVec, - state::{ValidatorListHeader, ValidatorStakeInfo}, + state::{StakePool as SPLStakePool, ValidatorListHeader, ValidatorStakeInfo}, }; use crate::{errors::StewardError, Config, Delegation}; @@ -145,6 +145,45 @@ pub fn deserialize_validator_list( )?) } +#[derive(BorshDeserialize, BorshSerialize)] +pub struct PreferredValidatorType(spl_stake_pool::instruction::PreferredValidatorType); + +impl AsRef for PreferredValidatorType { + fn as_ref(&self) -> &spl_stake_pool::instruction::PreferredValidatorType { + &self.0 + } +} + +impl From for PreferredValidatorType { + fn from(val: spl_stake_pool::instruction::PreferredValidatorType) -> Self { + Self(val) + } +} + +impl IdlBuild for PreferredValidatorType { + fn create_type() -> Option { + Some(IdlTypeDef { + name: "PreferredValidatorType".to_string(), + ty: IdlTypeDefTy::Enum { + variants: vec![ + IdlEnumVariant { + name: "Deposit".to_string(), + fields: None, + }, + IdlEnumVariant { + name: "Withdraw".to_string(), + fields: None, + }, + ], + }, + docs: Default::default(), + generics: Default::default(), + serialization: Default::default(), + repr: Default::default(), + }) + } +} + #[derive(Clone)] pub struct StakePool(spl_stake_pool::state::StakePool); diff --git a/programs/validator-history/Cargo.toml b/programs/validator-history/Cargo.toml index df04b7c4..82c69153 100644 --- a/programs/validator-history/Cargo.toml +++ b/programs/validator-history/Cargo.toml @@ -24,7 +24,7 @@ custom-heap = [] idl-build = [] [dependencies] -anchor-lang = "0.30.0" +anchor-lang = { features = ["idl-build"], version = "0.30.0" } bincode = "1.3.3" bytemuck = { version = "1.13.1", features = ["derive", "min_const_generics"] } cfg-if = "1.0.0" diff --git a/test b/test new file mode 100755 index 00000000..a3e5f723 --- /dev/null +++ b/test @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +cargo-build-sbf && \ + RUST_LOG=DEBUG \ + SBF_OUT_DIR=/Users/evanbatsell/jito/stakenet/target/sbf-solana-solana/release \ + cargo test-sbf From e87f09871dd073af8fb9cd7a3697d2efa92b1209 Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Tue, 11 Jun 2024 12:37:57 -0400 Subject: [PATCH 06/16] More stuff --- tests/tests/steward/test_integration.rs | 25 ++++++++++--------- tests/tests/steward/test_parameters.rs | 6 ++--- tests/tests/steward/test_spl_passthrough.rs | 6 ++--- tests/tests/steward/test_state_methods.rs | 2 +- tests/tests/steward/test_state_transitions.rs | 6 ++--- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/tests/tests/steward/test_integration.rs b/tests/tests/steward/test_integration.rs index b1a231ad..8e158ef6 100644 --- a/tests/tests/steward/test_integration.rs +++ b/tests/tests/steward/test_integration.rs @@ -80,7 +80,7 @@ async fn test_compute_delegations() { steward_state_account.state.sorted_yield_score_indices[i] = yield_score_vec[i].0 as u16; } - steward_state_account.state.num_pool_validators = MAX_VALIDATORS; + steward_state_account.state.num_pool_validators = MAX_VALIDATORS as u64; steward_state_account.state.state_tag = jito_steward::state::StewardStateEnum::ComputeDelegations; steward_state_account.state.current_epoch = clock.epoch; @@ -176,7 +176,8 @@ async fn test_compute_scores() { fixture.initialize_config(None).await; fixture.initialize_steward_state().await; - let epoch_credits = vec![(0, 1, 0), (1, 2, 1), (2, 3, 2), (3, 4, 3), (4, 5, 4)]; + let epoch_credits: Vec<(u64, u64, u64)> = + vec![(0, 1, 0), (1, 2, 1), (2, 3, 2), (3, 4, 3), (4, 5, 4)]; let vote_account = Pubkey::new_unique(); let validator_history_account = Pubkey::find_program_address( &[ValidatorHistory::SEED, vote_account.as_ref()], @@ -239,7 +240,7 @@ async fn test_compute_scores() { fixture.load_and_deserialize(&fixture.steward_state).await; // Basic state setup - steward_state_account.state.num_pool_validators = MAX_VALIDATORS; + steward_state_account.state.num_pool_validators = MAX_VALIDATORS as u64; steward_state_account.state.state_tag = jito_steward::state::StewardStateEnum::ComputeScores; steward_state_account.state.current_epoch = clock.epoch; steward_state_account.state.next_cycle_epoch = @@ -296,7 +297,7 @@ async fn test_compute_scores() { } .to_account_metas(None), data: jito_steward::instruction::ComputeScore { - validator_list_index: validator_history.index as usize, + validator_list_index: validator_history.index as u64, } .data(), }; @@ -578,7 +579,7 @@ async fn test_compute_instant_unstake() { } .to_account_metas(None), data: jito_steward::instruction::ComputeInstantUnstake { - validator_list_index: validator_history.index as usize, + validator_list_index: validator_history.index as u64, } .data(), }; @@ -676,7 +677,7 @@ async fn test_idle() { steward_state_account.state.state_tag = StewardStateEnum::Idle; steward_state_account.state.next_cycle_epoch = epoch_schedule.first_normal_epoch + 10; steward_state_account.state.current_epoch = epoch_schedule.first_normal_epoch; - steward_state_account.state.num_pool_validators = MAX_VALIDATORS; + steward_state_account.state.num_pool_validators = MAX_VALIDATORS as u64; ctx.borrow_mut().set_account( &fixture.steward_state, @@ -806,7 +807,7 @@ async fn test_rebalance_increase() { steward_config.parameters.stake_deposit_unstake_cap_bps = 0; steward_config.parameters.minimum_voting_epochs = 1; steward_state_account.state.state_tag = StewardStateEnum::Rebalance; - steward_state_account.state.num_pool_validators = MAX_VALIDATORS - 1; + steward_state_account.state.num_pool_validators = MAX_VALIDATORS as u64 - 1; steward_state_account.state.next_cycle_epoch = epoch_schedule.first_normal_epoch + 10; steward_state_account.state.current_epoch = epoch_schedule.first_normal_epoch; @@ -964,7 +965,7 @@ async fn test_rebalance_increase() { } .to_account_metas(None), data: jito_steward::instruction::Rebalance { - validator_list_index: MAX_VALIDATORS - 1, + validator_list_index: MAX_VALIDATORS as u64 - 1, } .data(), }; @@ -1047,7 +1048,7 @@ async fn test_rebalance_decrease() { steward_config.parameters.minimum_voting_epochs = 1; steward_state_account.state.state_tag = StewardStateEnum::Rebalance; - steward_state_account.state.num_pool_validators = MAX_VALIDATORS - 1; + steward_state_account.state.num_pool_validators = MAX_VALIDATORS as u64 - 1; steward_state_account.state.next_cycle_epoch = epoch_schedule.first_normal_epoch + 10; steward_state_account.state.current_epoch = epoch_schedule.first_normal_epoch; @@ -1273,7 +1274,7 @@ async fn test_rebalance_decrease() { } .to_account_metas(None), data: jito_steward::instruction::Rebalance { - validator_list_index: MAX_VALIDATORS - 1, + validator_list_index: MAX_VALIDATORS as u64 - 1, } .data(), }; @@ -1450,7 +1451,7 @@ async fn test_rebalance_other_cases() { } .to_account_metas(None), data: jito_steward::instruction::Rebalance { - validator_list_index: MAX_VALIDATORS - 1, + validator_list_index: MAX_VALIDATORS as u64 - 1, } .data(), }; @@ -1469,7 +1470,7 @@ async fn test_rebalance_other_cases() { fixture.load_and_deserialize(&fixture.steward_state).await; steward_state_account.state.state_tag = StewardStateEnum::Idle; - steward_state_account.state.num_pool_validators = MAX_VALIDATORS; + steward_state_account.state.num_pool_validators = MAX_VALIDATORS as u64; steward_state_account.state.next_cycle_epoch = epoch_schedule.first_normal_epoch + 10; steward_state_account.state.current_epoch = epoch_schedule.first_normal_epoch; steward_config.set_paused(false); diff --git a/tests/tests/steward/test_parameters.rs b/tests/tests/steward/test_parameters.rs index b9861af9..4bfe8d6f 100644 --- a/tests/tests/steward/test_parameters.rs +++ b/tests/tests/steward/test_parameters.rs @@ -825,7 +825,7 @@ fn test_compute_score_slot_range() { // Cannot be below min_slots_per_epoch let new_value = min_slots_per_epoch - 1; let update_parameters = UpdateParametersArgs { - compute_score_slot_range: Some(new_value), + compute_score_slot_range: Some(new_value as u64), ..UpdateParametersArgs::default() }; let result = _test_parameter(&update_parameters, None, Some(slots_per_epoch), None); @@ -836,7 +836,7 @@ fn test_compute_score_slot_range() { // Cannot be above slots_per_epoch let new_value = slots_per_epoch + 1; let update_parameters = UpdateParametersArgs { - compute_score_slot_range: Some(new_value as usize), + compute_score_slot_range: Some(new_value), ..UpdateParametersArgs::default() }; let result = _test_parameter(&update_parameters, None, Some(slots_per_epoch), None); @@ -845,7 +845,7 @@ fn test_compute_score_slot_range() { { // In range - let new_value = COMPUTE_SCORE_SLOT_RANGE_MIN + 1; + let new_value = COMPUTE_SCORE_SLOT_RANGE_MIN as u64 + 1; let update_parameters = UpdateParametersArgs { compute_score_slot_range: Some(new_value), ..UpdateParametersArgs::default() diff --git a/tests/tests/steward/test_spl_passthrough.rs b/tests/tests/steward/test_spl_passthrough.rs index 8347119b..a3448572 100644 --- a/tests/tests/steward/test_spl_passthrough.rs +++ b/tests/tests/steward/test_spl_passthrough.rs @@ -98,7 +98,7 @@ async fn _setup_test_steward_state( steward_config.parameters.instant_unstake_cap_bps = 0; steward_config.parameters.stake_deposit_unstake_cap_bps = 0; steward_state_account.state.state_tag = StewardStateEnum::Idle; - steward_state_account.state.num_pool_validators = validators_to_add - 1; + steward_state_account.state.num_pool_validators = validators_to_add as u64 - 1; steward_state_account.state.next_cycle_epoch = epoch_schedule.first_normal_epoch + 10; steward_state_account.state.current_epoch = epoch_schedule.first_normal_epoch; @@ -232,7 +232,7 @@ async fn _set_and_check_preferred_validator( } .to_account_metas(None), data: jito_steward::instruction::SetPreferredValidator { - validator_type: preferred_validator_type.clone(), + validator_type: preferred_validator_type.clone().into(), validator, } .data(), @@ -559,7 +559,7 @@ async fn test_remove_validator_from_pool() { } .to_account_metas(None), data: jito_steward::instruction::RemoveValidatorFromPool { - validator_list_index, + validator_list_index: validator_list_index as u64, } .data(), }; diff --git a/tests/tests/steward/test_state_methods.rs b/tests/tests/steward/test_state_methods.rs index 6ec24a1e..69436925 100644 --- a/tests/tests/steward/test_state_methods.rs +++ b/tests/tests/steward/test_state_methods.rs @@ -58,7 +58,7 @@ fn test_compute_scores() { } assert!(state .progress - .is_complete(state.num_pool_validators) + .is_complete(state.num_pool_validators as usize) .unwrap()); assert!(state.scores[0..3] == [1_000_000_000, 0, 950_000_000]); assert!(state.sorted_score_indices[0..3] == [0, 2, 1]); diff --git a/tests/tests/steward/test_state_transitions.rs b/tests/tests/steward/test_state_transitions.rs index c05bc3a9..d2ab9486 100644 --- a/tests/tests/steward/test_state_transitions.rs +++ b/tests/tests/steward/test_state_transitions.rs @@ -35,7 +35,7 @@ pub fn test_compute_scores_to_compute_delegations() { assert!(state .progress - .is_complete(state.num_pool_validators) + .is_complete(state.num_pool_validators as usize) .unwrap()); let res = state.transition(clock, parameters, epoch_schedule); @@ -261,7 +261,7 @@ pub fn test_compute_instant_unstake_to_rebalance() { .unwrap(); assert!(state .progress - .is_complete(state.num_pool_validators) + .is_complete(state.num_pool_validators as usize) .unwrap()); let res = state.transition(clock, parameters, epoch_schedule); @@ -338,7 +338,7 @@ pub fn test_rebalance_to_idle() { state.state_tag = StewardStateEnum::Rebalance; - for i in 0..state.num_pool_validators { + for i in 0..state.num_pool_validators as usize { let _ = state.progress.set(i, true); assert!(matches!(state.state_tag, StewardStateEnum::Rebalance)); } From 701fae83a59378d090a21cdd34f0f93db40ad286 Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Wed, 12 Jun 2024 12:07:47 -0400 Subject: [PATCH 07/16] last bits to build idl --- Cargo.lock | 285 ++++---------------------- programs/steward/Cargo.toml | 6 +- programs/validator-history/Cargo.toml | 5 +- 3 files changed, 48 insertions(+), 248 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aaf133e8..13282434 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -267,21 +267,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "anchor-spl" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dcee54a30b27ea8317ca647759b5d9701a8c7caaaa0c922c6d3c306a7278a7a" -dependencies = [ - "anchor-lang", - "spl-associated-token-account 3.0.2", - "spl-pod 0.2.2", - "spl-token", - "spl-token-2022 3.0.2", - "spl-token-group-interface 0.2.3", - "spl-token-metadata-interface 0.3.3", -] - [[package]] name = "anchor-syn" version = "0.30.0" @@ -2536,7 +2521,6 @@ name = "jito-steward" version = "0.1.0" dependencies = [ "anchor-lang", - "anchor-spl", "bincode", "blake3", "borsh 0.10.3", @@ -2545,7 +2529,7 @@ dependencies = [ "semver", "serde", "serde_derive", - "spl-pod 0.1.0", + "spl-pod", "spl-stake-pool", "static_assertions", "thiserror", @@ -4467,8 +4451,8 @@ dependencies = [ "solana-sdk", "spl-token", "spl-token-2022 1.0.0", - "spl-token-group-interface 0.1.0", - "spl-token-metadata-interface 0.2.0", + "spl-token-group-interface", + "spl-token-metadata-interface", "thiserror", "zstd", ] @@ -5663,7 +5647,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-sdk", - "spl-associated-token-account 2.3.0", + "spl-associated-token-account", "spl-memo", "spl-token", "spl-token-2022 1.0.0", @@ -5842,22 +5826,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "spl-associated-token-account" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2e688554bac5838217ffd1fab7845c573ff106b6336bf7d290db7c98d5a8efd" -dependencies = [ - "assert_matches", - "borsh 1.4.0", - "num-derive 0.4.2", - "num-traits", - "solana-program", - "spl-token", - "spl-token-2022 3.0.2", - "thiserror", -] - [[package]] name = "spl-discriminator" version = "0.1.0" @@ -5866,18 +5834,7 @@ checksum = "cce5d563b58ef1bb2cdbbfe0dfb9ffdc24903b10ae6a4df2d8f425ece375033f" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator-derive 0.1.2", -] - -[[package]] -name = "spl-discriminator" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d1814406e98b08c5cd02c1126f83fd407ad084adce0b05fda5730677822eac" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator-derive 0.2.0", + "spl-discriminator-derive", ] [[package]] @@ -5887,18 +5844,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07fd7858fc4ff8fb0e34090e41d7eb06a823e1057945c26d480bfc21d2338a93" dependencies = [ "quote", - "spl-discriminator-syn 0.1.2", - "syn 2.0.48", -] - -[[package]] -name = "spl-discriminator-derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" -dependencies = [ - "quote", - "spl-discriminator-syn 0.2.0", + "spl-discriminator-syn", "syn 2.0.48", ] @@ -5915,19 +5861,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "spl-discriminator-syn" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f05593b7ca9eac7caca309720f2eafb96355e037e6d373b909a80fe7b69b9" -dependencies = [ - "proc-macro2", - "quote", - "sha2 0.10.8", - "syn 2.0.48", - "thiserror", -] - [[package]] name = "spl-math" version = "0.2.0" @@ -5961,20 +5894,7 @@ dependencies = [ "bytemuck", "solana-program", "solana-zk-token-sdk", - "spl-program-error 0.3.0", -] - -[[package]] -name = "spl-pod" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046ce669f48cf2eca1ec518916d8725596bfb655beb1c74374cf71dc6cb773c9" -dependencies = [ - "borsh 1.4.0", - "bytemuck", - "solana-program", - "solana-zk-token-sdk", - "spl-program-error 0.4.1", + "spl-program-error", ] [[package]] @@ -5986,20 +5906,7 @@ dependencies = [ "num-derive 0.4.2", "num-traits", "solana-program", - "spl-program-error-derive 0.3.2", - "thiserror", -] - -[[package]] -name = "spl-program-error" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49065093ea91f57b9b2bd81493ff705e2ad4e64507a07dbc02b085778e02770e" -dependencies = [ - "num-derive 0.4.2", - "num-traits", - "solana-program", - "spl-program-error-derive 0.4.1", + "spl-program-error-derive", "thiserror", ] @@ -6015,18 +5922,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "spl-program-error-derive" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" -dependencies = [ - "proc-macro2", - "quote", - "sha2 0.10.8", - "syn 2.0.48", -] - [[package]] name = "spl-stake-pool" version = "1.0.0" @@ -6045,7 +5940,7 @@ dependencies = [ "solana-program", "solana-security-txt", "spl-math", - "spl-pod 0.1.0", + "spl-pod", "spl-token-2022 0.9.0", "thiserror", ] @@ -6058,10 +5953,10 @@ checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator 0.1.0", - "spl-pod 0.1.0", - "spl-program-error 0.3.0", - "spl-type-length-value 0.3.0", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", ] [[package]] @@ -6072,24 +5967,10 @@ checksum = "56f335787add7fa711819f9e7c573f8145a5358a709446fe2d24bf2a88117c90" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator 0.1.0", - "spl-pod 0.1.0", - "spl-program-error 0.3.0", - "spl-type-length-value 0.3.0", -] - -[[package]] -name = "spl-tlv-account-resolution" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cace91ba08984a41556efe49cbf2edca4db2f577b649da7827d3621161784bf8" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator 0.2.2", - "spl-pod 0.2.2", - "spl-program-error 0.4.1", - "spl-type-length-value 0.4.3", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", ] [[package]] @@ -6121,11 +6002,11 @@ dependencies = [ "solana-program", "solana-zk-token-sdk", "spl-memo", - "spl-pod 0.1.0", + "spl-pod", "spl-token", - "spl-token-metadata-interface 0.2.0", + "spl-token-metadata-interface", "spl-transfer-hook-interface 0.3.0", - "spl-type-length-value 0.3.0", + "spl-type-length-value", "thiserror", ] @@ -6144,36 +6025,12 @@ dependencies = [ "solana-security-txt", "solana-zk-token-sdk", "spl-memo", - "spl-pod 0.1.0", + "spl-pod", "spl-token", - "spl-token-group-interface 0.1.0", - "spl-token-metadata-interface 0.2.0", + "spl-token-group-interface", + "spl-token-metadata-interface", "spl-transfer-hook-interface 0.4.1", - "spl-type-length-value 0.3.0", - "thiserror", -] - -[[package]] -name = "spl-token-2022" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5412f99ae7ee6e0afde00defaa354e6228e47e30c0e3adf553e2e01e6abb584" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.4.2", - "num-traits", - "num_enum 0.7.2", - "solana-program", - "solana-security-txt", - "solana-zk-token-sdk", - "spl-memo", - "spl-pod 0.2.2", - "spl-token", - "spl-token-group-interface 0.2.3", - "spl-token-metadata-interface 0.3.3", - "spl-transfer-hook-interface 0.6.3", - "spl-type-length-value 0.4.3", + "spl-type-length-value", "thiserror", ] @@ -6185,22 +6042,9 @@ checksum = "b889509d49fa74a4a033ca5dae6c2307e9e918122d97e58562f5c4ffa795c75d" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator 0.1.0", - "spl-pod 0.1.0", - "spl-program-error 0.3.0", -] - -[[package]] -name = "spl-token-group-interface" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d419b5cfa3ee8e0f2386fd7e02a33b3ec8a7db4a9c7064a2ea24849dc4a273b6" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator 0.2.2", - "spl-pod 0.2.2", - "spl-program-error 0.4.1", + "spl-discriminator", + "spl-pod", + "spl-program-error", ] [[package]] @@ -6211,24 +6055,10 @@ checksum = "4c16ce3ba6979645fb7627aa1e435576172dd63088dc7848cb09aa331fa1fe4f" dependencies = [ "borsh 0.10.3", "solana-program", - "spl-discriminator 0.1.0", - "spl-pod 0.1.0", - "spl-program-error 0.3.0", - "spl-type-length-value 0.3.0", -] - -[[package]] -name = "spl-token-metadata-interface" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30179c47e93625680dabb620c6e7931bd12d62af390f447bc7beb4a3a9b5feee" -dependencies = [ - "borsh 1.4.0", - "solana-program", - "spl-discriminator 0.2.2", - "spl-pod 0.2.2", - "spl-program-error 0.4.1", - "spl-type-length-value 0.4.3", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", ] [[package]] @@ -6240,11 +6070,11 @@ dependencies = [ "arrayref", "bytemuck", "solana-program", - "spl-discriminator 0.1.0", - "spl-pod 0.1.0", - "spl-program-error 0.3.0", + "spl-discriminator", + "spl-pod", + "spl-program-error", "spl-tlv-account-resolution 0.4.0", - "spl-type-length-value 0.3.0", + "spl-type-length-value", ] [[package]] @@ -6256,27 +6086,11 @@ dependencies = [ "arrayref", "bytemuck", "solana-program", - "spl-discriminator 0.1.0", - "spl-pod 0.1.0", - "spl-program-error 0.3.0", + "spl-discriminator", + "spl-pod", + "spl-program-error", "spl-tlv-account-resolution 0.5.2", - "spl-type-length-value 0.3.0", -] - -[[package]] -name = "spl-transfer-hook-interface" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a98359769cd988f7b35c02558daa56d496a7e3bd8626e61f90a7c757eedb9b" -dependencies = [ - "arrayref", - "bytemuck", - "solana-program", - "spl-discriminator 0.2.2", - "spl-pod 0.2.2", - "spl-program-error 0.4.1", - "spl-tlv-account-resolution 0.6.3", - "spl-type-length-value 0.4.3", + "spl-type-length-value", ] [[package]] @@ -6287,22 +6101,9 @@ checksum = "a468e6f6371f9c69aae760186ea9f1a01c2908351b06a5e0026d21cfc4d7ecac" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator 0.1.0", - "spl-pod 0.1.0", - "spl-program-error 0.3.0", -] - -[[package]] -name = "spl-type-length-value" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422ce13429dbd41d2cee8a73931c05fda0b0c8ca156a8b0c19445642550bb61a" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator 0.2.2", - "spl-pod 0.2.2", - "spl-program-error 0.4.1", + "spl-discriminator", + "spl-pod", + "spl-program-error", ] [[package]] @@ -6559,7 +6360,7 @@ dependencies = [ "solana-program-test", "solana-sdk", "solana-version", - "spl-associated-token-account 2.3.0", + "spl-associated-token-account", "spl-stake-pool", "spl-token", "validator-history", diff --git a/programs/steward/Cargo.toml b/programs/steward/Cargo.toml index b9ce8b71..b07145a8 100644 --- a/programs/steward/Cargo.toml +++ b/programs/steward/Cargo.toml @@ -15,13 +15,13 @@ no-entrypoint = [] no-idl = [] no-log-ix-name = [] cpi = ["no-entrypoint"] -default = ["custom-heap"] +default = ["custom-heap", "no-entrypoint"] custom-heap = [] -idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] +idl-build = ["anchor-lang/idl-build"] [dependencies] anchor-lang = { features = ["idl-build"], version = "0.30.0" } -anchor-spl = { features = ["idl-build"], version = "0.30.0" } +# anchor-spl = { features = ["idl-build"], version = "0.30.0" } bincode = "1.3.3" blake3 = "1.3.1" borsh = "0.10.0" diff --git a/programs/validator-history/Cargo.toml b/programs/validator-history/Cargo.toml index 82c69153..9e816262 100644 --- a/programs/validator-history/Cargo.toml +++ b/programs/validator-history/Cargo.toml @@ -18,10 +18,9 @@ no-entrypoint = [] no-idl = [] no-log-ix-name = [] cpi = ["no-entrypoint"] -default = ["custom-heap"] +default = ["custom-heap", "no-entrypoint"] custom-heap = [] -# idl-build = ["anchor-lang/idl-build"] -idl-build = [] +idl-build = ["anchor-lang/idl-build"] [dependencies] anchor-lang = { features = ["idl-build"], version = "0.30.0" } From f1bb39513d5e0a806bf57aca37fb487a169907d0 Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Wed, 12 Jun 2024 20:28:49 -0400 Subject: [PATCH 08/16] Cleaning up stuff --- .github/workflows/build.yaml | 21 +- programs/steward/Cargo.toml | 5 +- programs/steward/idl/steward.json | 3295 +++++++++++------ programs/steward/src/constants.rs | 2 +- programs/steward/src/state/accounts.rs | 2 +- programs/steward/src/state/bitmask.rs | 3 +- programs/steward/src/state/parameters.rs | 3 +- programs/steward/src/state/steward_state.rs | 45 +- programs/steward/src/utils.rs | 2 +- programs/validator-history/Cargo.toml | 4 +- .../idl/validator_history.json | 1154 +++--- test | 5 - tests/tests/steward/test_state_methods.rs | 2 +- tests/tests/steward/test_state_transitions.rs | 4 +- 14 files changed, 2801 insertions(+), 1746 deletions(-) delete mode 100755 test diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 6dc936b8..fcbf6ba8 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -81,9 +81,9 @@ jobs: run: echo "/home/runner/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH # build the program and IDL; exit if error - - run: anchor build --no-idl - # - name: Check for diff on IDL - # run: git diff --exit-code + - run: anchor build --idl idl + - name: Check for diff on IDL + run: git diff --exit-code # run verified build - run: solana-verify build --library-name validator_history @@ -100,11 +100,16 @@ jobs: with: name: jito_steward.so path: target/deploy/jito_steward.so - # - name: Upload IDL - # uses: actions/upload-artifact@v4 - # with: - # name: validator_history.json - # path: programs/validator-history/idl/validator_history.json + - name: Upload Validator History IDL + uses: actions/upload-artifact@v4 + with: + name: validator_history.json + path: programs/validator-history/idl/validator_history.json + - name: Upload Jito Steward IDL + uses: actions/upload-artifact@v4 + with: + name: jito_steward.json + path: programs/steward/idl/jito_steward.json # tests run on verified build test: diff --git a/programs/steward/Cargo.toml b/programs/steward/Cargo.toml index b07145a8..874bfcfe 100644 --- a/programs/steward/Cargo.toml +++ b/programs/steward/Cargo.toml @@ -15,13 +15,12 @@ no-entrypoint = [] no-idl = [] no-log-ix-name = [] cpi = ["no-entrypoint"] -default = ["custom-heap", "no-entrypoint"] +default = ["custom-heap"] custom-heap = [] -idl-build = ["anchor-lang/idl-build"] +idl-build = ["anchor-lang/idl-build", "no-entrypoint"] [dependencies] anchor-lang = { features = ["idl-build"], version = "0.30.0" } -# anchor-spl = { features = ["idl-build"], version = "0.30.0" } bincode = "1.3.3" blake3 = "1.3.1" borsh = "0.10.0" diff --git a/programs/steward/idl/steward.json b/programs/steward/idl/steward.json index 642b84c2..20cfff35 100644 --- a/programs/steward/idl/steward.json +++ b/programs/steward/idl/steward.json @@ -1,1477 +1,1726 @@ { - "version": "0.1.0", - "name": "steward", + "address": "sssh4zkKhX8jXTNQz1xDHyGpygzgu2UhcRcUvZihBjP", + "metadata": { + "name": "steward", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Program for permissionlessly managing an SPL Stake Pool" + }, "instructions": [ { - "name": "initializeConfig", + "name": "add_validator_to_blacklist", + "docs": [ + "Adds the validator at `index` to the blacklist. It will be instant unstaked and never receive delegations" + ], + "discriminator": [ + 18, + 30, + 248, + 201, + 28, + 196, + 137, + 118 + ], "accounts": [ { "name": "config", - "isMut": true, - "isSigner": true + "writable": true }, { - "name": "staker", - "isMut": true, - "isSigner": false + "name": "authority", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "index", + "type": "u32" + } + ] + }, + { + "name": "add_validator_to_pool", + "discriminator": [ + 181, + 6, + 29, + 25, + 192, + 211, + 190, + 187 + ], + "accounts": [ + { + "name": "config" }, { - "name": "stakePool", - "isMut": true, - "isSigner": false + "name": "stake_pool_program" }, { - "name": "validatorHistoryConfig", - "isMut": false, - "isSigner": false + "name": "stake_pool", + "writable": true }, { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "name": "staker" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "reserve_stake", + "writable": true }, { - "name": "signer", - "isMut": true, - "isSigner": true - } - ], - "args": [ + "name": "withdraw_authority" + }, { - "name": "authority", - "type": "publicKey" - } - ] - }, - { - "name": "initializeState", - "accounts": [ + "name": "validator_list", + "writable": true + }, { - "name": "stateAccount", - "isMut": true, - "isSigner": false + "name": "stake_account", + "writable": true }, { - "name": "config", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "rent" }, { - "name": "signer", - "isMut": true, - "isSigner": true - } - ], - "args": [] - }, - { - "name": "reallocState", - "accounts": [ + "name": "clock" + }, { - "name": "stateAccount", - "isMut": true, - "isSigner": false + "name": "stake_history" }, { - "name": "config", - "isMut": false, - "isSigner": false + "name": "stake_config" }, { - "name": "validatorHistoryConfig", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "stake_program" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], - "args": [] + "args": [ + { + "name": "validator_seed", + "type": { + "option": "u32" + } + } + ] }, { - "name": "autoAddValidatorToPool", + "name": "auto_add_validator_to_pool", + "docs": [ + "Adds a validator to the pool if it has a validator history account, matches stake_minimum, and is not yet in the pool" + ], + "discriminator": [ + 166, + 226, + 7, + 8, + 169, + 239, + 220, + 69 + ], "accounts": [ { - "name": "validatorHistoryAccount", - "isMut": false, - "isSigner": false + "name": "validator_history_account" }, { - "name": "config", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "name": "stake_pool_program" }, { - "name": "stakePool", - "isMut": true, - "isSigner": false + "name": "stake_pool", + "writable": true }, { - "name": "staker", - "isMut": false, - "isSigner": false + "name": "staker" }, { - "name": "reserveStake", - "isMut": true, - "isSigner": false + "name": "reserve_stake", + "writable": true }, { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false + "name": "withdraw_authority" }, { - "name": "validatorList", - "isMut": true, - "isSigner": false + "name": "validator_list", + "writable": true }, { - "name": "stakeAccount", - "isMut": true, - "isSigner": false + "name": "stake_account", + "writable": true }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { - "name": "rent", - "isMut": false, - "isSigner": false + "name": "rent" }, { - "name": "clock", - "isMut": false, - "isSigner": false + "name": "clock" }, { - "name": "stakeHistory", - "isMut": false, - "isSigner": false + "name": "stake_history" }, { - "name": "stakeConfig", - "isMut": false, - "isSigner": false + "name": "stake_config" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "stake_program" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [] }, { - "name": "computeScore", + "name": "auto_remove_validator_from_pool", + "docs": [ + "Removes a validator from the pool if its stake account is inactive or the vote account has closed" + ], + "discriminator": [ + 65, + 39, + 73, + 213, + 52, + 34, + 181, + 94 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false + "name": "validator_history_account" + }, + { + "name": "config" + }, + { + "name": "state_account", + "writable": true + }, + { + "name": "stake_pool_program" + }, + { + "name": "stake_pool", + "writable": true + }, + { + "name": "staker" }, { - "name": "stateAccount", - "isMut": true, - "isSigner": false + "name": "reserve_stake", + "writable": true }, { - "name": "validatorHistory", - "isMut": false, - "isSigner": false + "name": "withdraw_authority" }, { - "name": "validatorHistoryConfig", - "isMut": false, - "isSigner": false + "name": "validator_list", + "writable": true }, { - "name": "clusterHistory", - "isMut": false, - "isSigner": false + "name": "stake_account", + "writable": true + }, + { + "name": "transient_stake_account", + "docs": [ + "Account may not exist yet so no owner check done" + ], + "writable": true + }, + { + "name": "vote_account" + }, + { + "name": "rent" + }, + { + "name": "clock" + }, + { + "name": "stake_history" + }, + { + "name": "stake_config" + }, + { + "name": "system_program" + }, + { + "name": "stake_program" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], - "args": [] + "args": [ + { + "name": "validator_list_index", + "type": "u64" + } + ] }, { - "name": "computeDelegations", + "name": "close_steward_accounts", + "docs": [ + "Closes Steward PDA accounts associated with a given Config (StewardStateAccount, and Staker).", + "Config is not closed as it is a Keypair, so lamports can simply be withdrawn.", + "Reclaims lamports to authority" + ], + "discriminator": [ + 172, + 171, + 212, + 186, + 90, + 10, + 181, + 24 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "stateAccount", - "isMut": true, - "isSigner": false + "name": "staker", + "writable": true }, { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "state_account", + "writable": true }, { - "name": "signer", - "isMut": true, - "isSigner": true + "name": "authority", + "writable": true, + "signer": true } ], "args": [] }, { - "name": "idle", + "name": "compute_delegations", + "docs": [ + "Computes delegation for a validator for the current cycle.", + "All validators must have delegations computed before stake can be delegated" + ], + "discriminator": [ + 249, + 138, + 49, + 247, + 69, + 32, + 11, + 175 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "stateAccount", - "isMut": true, - "isSigner": false + "name": "state_account", + "writable": true }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [] }, { - "name": "computeInstantUnstake", + "name": "compute_instant_unstake", + "docs": [ + "Checks if a validator at `validator_list_index` should be instant unstaked, and marks it if so" + ], + "discriminator": [ + 172, + 220, + 51, + 183, + 2, + 94, + 253, + 251 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false + "name": "config" + }, + { + "name": "state_account", + "writable": true }, { - "name": "stateAccount", - "isMut": true, - "isSigner": false + "name": "validator_history" }, { - "name": "validatorHistory", - "isMut": false, - "isSigner": false + "name": "validator_list" }, { - "name": "clusterHistory", - "isMut": false, - "isSigner": false + "name": "cluster_history" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], - "args": [] + "args": [ + { + "name": "validator_list_index", + "type": "u64" + } + ] }, { - "name": "recomputeDelegations", + "name": "compute_score", + "docs": [ + "Computes score for a the validator at `validator_list_index` for the current cycle." + ], + "discriminator": [ + 161, + 101, + 4, + 93, + 120, + 62, + 41, + 20 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false + "name": "config" + }, + { + "name": "state_account", + "writable": true }, { - "name": "stateAccount", - "isMut": true, - "isSigner": false + "name": "validator_history" }, { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "validator_list" }, { - "name": "validatorList", - "isMut": false, - "isSigner": false + "name": "cluster_history" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], - "args": [] + "args": [ + { + "name": "validator_list_index", + "type": "u64" + } + ] }, { - "name": "unstake", + "name": "decrease_additional_validator_stake", + "discriminator": [ + 90, + 22, + 113, + 73, + 21, + 229, + 33, + 83 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "stateAccount", - "isMut": true, - "isSigner": false + "name": "steward_state", + "writable": true }, { - "name": "validatorHistory", - "isMut": false, - "isSigner": false + "name": "validator_history", + "writable": true }, { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "stake_pool_program" }, { - "name": "staker", - "isMut": false, - "isSigner": false + "name": "stake_pool" }, { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false + "name": "staker" }, { - "name": "validatorList", - "isMut": false, - "isSigner": false + "name": "withdraw_authority" }, { - "name": "stakeAccount", - "isMut": false, - "isSigner": false + "name": "validator_list", + "writable": true }, { - "name": "transientStakeAccount", - "isMut": false, - "isSigner": false + "name": "reserve_stake", + "writable": true }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "stake_account", + "writable": true }, { - "name": "clock", - "isMut": false, - "isSigner": false + "name": "ephemeral_stake_account", + "writable": true }, { - "name": "rent", - "isMut": false, - "isSigner": false + "name": "transient_stake_account", + "writable": true }, { - "name": "stakeHistory", - "isMut": false, - "isSigner": false + "name": "clock" }, { - "name": "stakeConfig", - "isMut": false, - "isSigner": false + "name": "stake_history" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "stake_program" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [ { - "name": "validatorListIndex", - "type": { - "defined": "usize" - } + "name": "lamports", + "type": "u64" + }, + { + "name": "transient_seed", + "type": "u64" + }, + { + "name": "ephemeral_seed", + "type": "u64" } ] }, { - "name": "delegate", + "name": "decrease_validator_stake", + "discriminator": [ + 145, + 203, + 107, + 123, + 71, + 63, + 35, + 225 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false - }, - { - "name": "stateAccount", - "isMut": true, - "isSigner": false + "name": "config" }, { - "name": "validatorHistory", - "isMut": false, - "isSigner": false + "name": "steward_state", + "writable": true }, { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "name": "validator_history", + "writable": true }, { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "stake_pool_program" }, { - "name": "staker", - "isMut": false, - "isSigner": false + "name": "stake_pool", + "writable": true }, { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false + "name": "staker" }, { - "name": "validatorList", - "isMut": false, - "isSigner": false + "name": "withdraw_authority" }, { - "name": "reserveStake", - "isMut": false, - "isSigner": false + "name": "validator_list", + "writable": true }, { - "name": "transientStakeAccount", - "isMut": false, - "isSigner": false + "name": "reserve_stake", + "writable": true }, { - "name": "stakeAccount", - "isMut": false, - "isSigner": false + "name": "stake_account", + "writable": true }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "transient_stake_account", + "writable": true }, { - "name": "clock", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { - "name": "rent", - "isMut": false, - "isSigner": false + "name": "clock" }, { - "name": "stakeHistory", - "isMut": false, - "isSigner": false + "name": "rent" }, { - "name": "stakeConfig", - "isMut": false, - "isSigner": false + "name": "stake_history" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "stake_program" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [ { - "name": "validatorListIndex", - "type": { - "defined": "usize" - } + "name": "lamports", + "type": "u64" + }, + { + "name": "transient_seed", + "type": "u64" } ] }, { - "name": "setNewAuthority", + "name": "idle", + "docs": [ + "Idle state, waiting for epoch progress before transitioning to next state" + ], + "discriminator": [ + 200, + 79, + 16, + 41, + 251, + 91, + 239, + 83 + ], "accounts": [ { - "name": "config", - "isMut": true, - "isSigner": false + "name": "config" }, { - "name": "newAuthority", - "isMut": false, - "isSigner": false + "name": "state_account", + "writable": true }, { - "name": "authority", - "isMut": true, - "isSigner": true + "name": "signer", + "writable": true, + "signer": true } ], "args": [] }, { - "name": "pauseSteward", + "name": "increase_additional_validator_stake", + "discriminator": [ + 93, + 136, + 94, + 230, + 32, + 54, + 167, + 242 + ], "accounts": [ { - "name": "config", - "isMut": true, - "isSigner": false + "name": "config" }, { - "name": "authority", - "isMut": true, - "isSigner": true - } - ], - "args": [] - }, - { - "name": "resumeSteward", - "accounts": [ + "name": "steward_state", + "writable": true + }, { - "name": "config", - "isMut": true, - "isSigner": false + "name": "validator_history", + "writable": true }, { - "name": "authority", - "isMut": true, - "isSigner": true - } - ], - "args": [] - }, - { - "name": "addValidatorToBlacklist", - "accounts": [ + "name": "stake_pool_program" + }, { - "name": "config", - "isMut": true, - "isSigner": false + "name": "stake_pool" }, { - "name": "authority", - "isMut": true, - "isSigner": true - } - ], - "args": [ + "name": "staker" + }, { - "name": "index", - "type": "u32" - } - ] - }, - { - "name": "removeValidatorFromBlacklist", - "accounts": [ + "name": "withdraw_authority" + }, { - "name": "config", - "isMut": true, - "isSigner": false + "name": "validator_list", + "writable": true }, { - "name": "authority", - "isMut": true, - "isSigner": true - } - ], - "args": [ + "name": "reserve_stake", + "writable": true + }, { - "name": "index", - "type": "u32" - } - ] - }, - { - "name": "updateParameters", - "accounts": [ + "name": "ephemeral_stake_account", + "writable": true + }, { - "name": "config", - "isMut": true, - "isSigner": false + "name": "transient_stake_account", + "writable": true }, { - "name": "authority", - "isMut": true, - "isSigner": true - } - ], - "args": [ + "name": "stake_account" + }, { - "name": "updateParametersArgs", - "type": { - "defined": "UpdateParametersArgs" - } - } - ] - }, - { - "name": "setStaker", - "accounts": [ + "name": "vote_account" + }, { - "name": "config", - "isMut": false, - "isSigner": false + "name": "clock" }, { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "name": "stake_history" }, { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "stake_config" }, { - "name": "staker", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "newStaker", - "isMut": false, - "isSigner": false + "name": "stake_program" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], - "args": [] + "args": [ + { + "name": "lamports", + "type": "u64" + }, + { + "name": "transient_seed", + "type": "u64" + }, + { + "name": "ephemeral_seed", + "type": "u64" + } + ] }, { - "name": "addValidatorToPool", + "name": "increase_validator_stake", + "discriminator": [ + 5, + 121, + 50, + 243, + 14, + 159, + 97, + 6 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "name": "steward_state", + "writable": true }, { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "validator_history", + "writable": true }, { - "name": "staker", - "isMut": false, - "isSigner": false + "name": "stake_pool_program" + }, + { + "name": "stake_pool", + "writable": true + }, + { + "name": "staker" }, { - "name": "reserveStake", - "isMut": false, - "isSigner": false + "name": "withdraw_authority" }, { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false + "name": "validator_list", + "writable": true }, { - "name": "validatorList", - "isMut": false, - "isSigner": false + "name": "reserve_stake", + "writable": true }, { - "name": "stakeAccount", - "isMut": false, - "isSigner": false + "name": "transient_stake_account", + "writable": true }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "stake_account", + "writable": true }, { - "name": "rent", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { - "name": "clock", - "isMut": false, - "isSigner": false + "name": "clock" }, { - "name": "stakeHistory", - "isMut": false, - "isSigner": false + "name": "rent" }, { - "name": "stakeConfig", - "isMut": false, - "isSigner": false + "name": "stake_history" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "stake_config" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "system_program" + }, + { + "name": "stake_program" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [ { - "name": "validatorSeed", - "type": { - "option": "u32" - } + "name": "lamports", + "type": "u64" + }, + { + "name": "transient_seed", + "type": "u64" } ] }, { - "name": "removeValidatorFromPool", + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], "accounts": [ { "name": "config", - "isMut": false, - "isSigner": false - }, - { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "stakePool", - "isMut": false, - "isSigner": false + "writable": true, + "signer": true }, { "name": "staker", - "isMut": false, - "isSigner": false - }, - { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "validatorList", - "isMut": false, - "isSigner": false - }, - { - "name": "stakeAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "transientStakeAccount", - "isMut": false, - "isSigner": false + "writable": true }, { - "name": "clock", - "isMut": false, - "isSigner": false + "name": "stake_pool", + "writable": true }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "stake_pool_program" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "system_program" }, { "name": "signer", - "isMut": true, - "isSigner": true - } - ], - "args": [] - }, - { - "name": "setPreferredValidator", - "accounts": [ - { - "name": "config", - "isMut": false, - "isSigner": false - }, - { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "stakePool", - "isMut": false, - "isSigner": false - }, - { - "name": "staker", - "isMut": false, - "isSigner": false - }, - { - "name": "validatorList", - "isMut": false, - "isSigner": false - }, - { - "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [ { - "name": "validatorType", - "type": { - "defined": "PreferredValidatorType" - } + "name": "authority", + "type": "pubkey" }, { - "name": "validator", + "name": "update_parameters_args", "type": { - "option": "publicKey" + "defined": { + "name": "UpdateParametersArgs" + } } } ] }, { - "name": "increaseValidatorStake", + "name": "initialize_state", + "docs": [ + "Creates state account" + ], + "discriminator": [ + 190, + 171, + 224, + 219, + 217, + 72, + 199, + 176 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false + "name": "state_account", + "writable": true }, { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "staker", - "isMut": false, - "isSigner": false - }, + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "pause_steward", + "discriminator": [ + 214, + 85, + 52, + 67, + 192, + 238, + 178, + 102 + ], + "accounts": [ { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false + "name": "config", + "writable": true }, { - "name": "validatorList", - "isMut": false, - "isSigner": false - }, + "name": "authority", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "realloc_state", + "docs": [ + "Increases state account by 10KiB each ix until it reaches StewardStateAccount::SIZE" + ], + "discriminator": [ + 67, + 181, + 233, + 214, + 215, + 148, + 245, + 126 + ], + "accounts": [ { - "name": "reserveStake", - "isMut": false, - "isSigner": false + "name": "state_account", + "writable": true }, { - "name": "transientStakeAccount", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "stakeAccount", - "isMut": false, - "isSigner": false + "name": "validator_list" }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "clock", - "isMut": false, - "isSigner": false - }, + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "rebalance", + "docs": [ + "Increases or decreases stake for a validator at `validator_list_index` to match the target stake,", + "given constraints on increase/decrease priority, reserve balance, and unstaking caps" + ], + "discriminator": [ + 108, + 158, + 77, + 9, + 210, + 52, + 88, + 62 + ], + "accounts": [ { - "name": "rent", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "stakeHistory", - "isMut": false, - "isSigner": false + "name": "state_account", + "writable": true }, { - "name": "stakeConfig", - "isMut": false, - "isSigner": false + "name": "validator_history" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "stake_pool_program" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "stake_pool" }, { - "name": "signer", - "isMut": true, - "isSigner": true - } - ], - "args": [ - { - "name": "lamports", - "type": "u64" + "name": "staker", + "writable": true }, { - "name": "transientSeed", - "type": "u64" - } - ] - }, - { - "name": "decreaseValidatorStake", - "accounts": [ - { - "name": "config", - "isMut": false, - "isSigner": false + "name": "withdraw_authority" }, { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "name": "validator_list", + "writable": true }, { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "reserve_stake", + "writable": true }, { - "name": "staker", - "isMut": false, - "isSigner": false + "name": "stake_account", + "writable": true }, { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false + "name": "transient_stake_account", + "docs": [ + "Account may not exist yet so no owner check done" + ], + "writable": true }, { - "name": "validatorList", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { - "name": "stakeAccount", - "isMut": false, - "isSigner": false + "name": "clock" }, { - "name": "transientStakeAccount", - "isMut": false, - "isSigner": false + "name": "rent" }, { - "name": "clock", - "isMut": false, - "isSigner": false + "name": "stake_history" }, { - "name": "rent", - "isMut": false, - "isSigner": false + "name": "stake_config" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "stake_program" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [ { - "name": "lamports", - "type": "u64" - }, - { - "name": "transientSeed", + "name": "validator_list_index", "type": "u64" } ] }, { - "name": "increaseAdditionalValidatorStake", + "name": "remove_validator_from_blacklist", + "docs": [ + "Removes the validator at `index` from the blacklist" + ], + "discriminator": [ + 253, + 48, + 101, + 237, + 109, + 14, + 153, + 208 + ], "accounts": [ { "name": "config", - "isMut": false, - "isSigner": false - }, - { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "writable": true }, { - "name": "stakePool", - "isMut": false, - "isSigner": false - }, + "name": "authority", + "writable": true, + "signer": true + } + ], + "args": [ { - "name": "staker", - "isMut": false, - "isSigner": false - }, + "name": "index", + "type": "u32" + } + ] + }, + { + "name": "remove_validator_from_pool", + "discriminator": [ + 161, + 32, + 213, + 239, + 221, + 15, + 181, + 114 + ], + "accounts": [ { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "validatorList", - "isMut": false, - "isSigner": false + "name": "steward_state", + "writable": true }, { - "name": "reserveStake", - "isMut": false, - "isSigner": false + "name": "stake_pool_program" }, { - "name": "ephemeralStakeAccount", - "isMut": false, - "isSigner": false + "name": "stake_pool", + "writable": true }, { - "name": "transientStakeAccount", - "isMut": false, - "isSigner": false + "name": "staker" }, { - "name": "stakeAccount", - "isMut": false, - "isSigner": false + "name": "withdraw_authority" }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "validator_list", + "writable": true }, { - "name": "clock", - "isMut": false, - "isSigner": false + "name": "stake_account", + "writable": true }, { - "name": "stakeHistory", - "isMut": false, - "isSigner": false + "name": "transient_stake_account", + "writable": true }, { - "name": "stakeConfig", - "isMut": false, - "isSigner": false + "name": "clock" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "stake_program" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [ { - "name": "lamports", - "type": "u64" - }, - { - "name": "transientSeed", - "type": "u64" - }, - { - "name": "ephemeralSeed", + "name": "validator_list_index", "type": "u64" } ] }, { - "name": "decreaseAdditionalValidatorStake", + "name": "reset_steward_state", + "docs": [ + "Resets steward state account to its initial state." + ], + "discriminator": [ + 84, + 248, + 158, + 46, + 200, + 205, + 234, + 86 + ], "accounts": [ { - "name": "config", - "isMut": false, - "isSigner": false - }, - { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "state_account", + "writable": true }, { - "name": "staker", - "isMut": false, - "isSigner": false - }, - { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "validatorList", - "isMut": false, - "isSigner": false - }, - { - "name": "stakeAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "ephemeralStakeAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "transientStakeAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "clock", - "isMut": false, - "isSigner": false - }, - { - "name": "stakeHistory", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "stake_pool" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "validator_list" }, { - "name": "signer", - "isMut": true, - "isSigner": true + "name": "authority", + "writable": true, + "signer": true } ], - "args": [ - { - "name": "lamports", - "type": "u64" - }, + "args": [] + }, + { + "name": "resume_steward", + "discriminator": [ + 25, + 71, + 153, + 183, + 197, + 197, + 187, + 3 + ], + "accounts": [ { - "name": "transientSeed", - "type": "u64" + "name": "config", + "writable": true }, { - "name": "ephemeralSeed", - "type": "u64" + "name": "authority", + "writable": true, + "signer": true } - ] + ], + "args": [] }, { - "name": "redelegate", + "name": "set_new_authority", + "discriminator": [ + 94, + 40, + 220, + 124, + 122, + 142, + 142, + 98 + ], "accounts": [ { "name": "config", - "isMut": false, - "isSigner": false - }, - { - "name": "stakePoolProgram", - "isMut": false, - "isSigner": false + "writable": true }, { - "name": "stakePool", - "isMut": false, - "isSigner": false + "name": "new_authority" }, { - "name": "staker", - "isMut": false, - "isSigner": false - }, + "name": "authority", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "set_preferred_validator", + "discriminator": [ + 114, + 42, + 19, + 98, + 212, + 97, + 109, + 13 + ], + "accounts": [ { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "validatorList", - "isMut": false, - "isSigner": false + "name": "stake_pool_program" }, { - "name": "sourceStakeAccount", - "isMut": false, - "isSigner": false + "name": "stake_pool", + "writable": true }, { - "name": "sourceEphemeralStakeAccount", - "isMut": false, - "isSigner": false + "name": "staker" }, { - "name": "sourceTransientStakeAccount", - "isMut": false, - "isSigner": false + "name": "validator_list" }, { - "name": "destinationTransientStakeAccount", - "isMut": false, - "isSigner": false - }, + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ { - "name": "destinationStakeAccount", - "isMut": false, - "isSigner": false + "name": "validator_type", + "type": { + "defined": { + "name": "PreferredValidatorType" + } + } }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false - }, + "name": "validator", + "type": { + "option": "pubkey" + } + } + ] + }, + { + "name": "set_staker", + "discriminator": [ + 149, + 203, + 114, + 28, + 80, + 138, + 17, + 131 + ], + "accounts": [ { - "name": "clock", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "stakeHistory", - "isMut": false, - "isSigner": false + "name": "stake_pool_program" }, { - "name": "stakeConfig", - "isMut": false, - "isSigner": false + "name": "stake_pool", + "writable": true }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "staker" }, { - "name": "stakeProgram", - "isMut": false, - "isSigner": false + "name": "new_staker" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], - "args": [ - { - "name": "lamports", - "type": "u64" - }, + "args": [] + }, + { + "name": "update_parameters", + "docs": [ + "For parameters that are present in args, the instruction checks that they are within sensible bounds and saves them to config struct" + ], + "discriminator": [ + 116, + 107, + 24, + 207, + 101, + 49, + 213, + 77 + ], + "accounts": [ { - "name": "sourceTransientStakeSeed", - "type": "u64" + "name": "config", + "writable": true }, { - "name": "ephemeralStakeSeed", - "type": "u64" - }, + "name": "authority", + "writable": true, + "signer": true + } + ], + "args": [ { - "name": "destinationTransientSeed", - "type": "u64" + "name": "update_parameters_args", + "type": { + "defined": { + "name": "UpdateParametersArgs" + } + } } ] } ], "accounts": [ + { + "name": "ClusterHistory", + "discriminator": [ + 41, + 154, + 241, + 80, + 135, + 88, + 85, + 252 + ] + }, { "name": "Config", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stakePool", - "type": "publicKey" - }, - { - "name": "authority", - "type": "publicKey" - }, - { - "name": "minimumStakeLamports", - "type": "u64" - }, - { - "name": "blacklist", - "type": { - "defined": "BitMask" - } - }, - { - "name": "parameters", - "type": { - "defined": "Parameters" - } - }, - { - "name": "paused", - "type": "u8" - }, - { - "name": "padding1", - "type": { - "array": [ - "u8", - 1023 - ] - } - } - ] - } + "discriminator": [ + 155, + 12, + 170, + 224, + 30, + 250, + 204, + 130 + ] }, { "name": "Staker", - "type": { - "kind": "struct", - "fields": [ - { - "name": "bump", - "type": "u8" - } - ] - } + "discriminator": [ + 171, + 229, + 193, + 85, + 67, + 177, + 151, + 4 + ] }, { "name": "StewardStateAccount", - "type": { - "kind": "struct", - "fields": [ - { - "name": "state", - "type": { - "defined": "StewardState" + "discriminator": [ + 55, + 216, + 46, + 49, + 148, + 67, + 228, + 29 + ] + }, + { + "name": "ValidatorHistory", + "discriminator": [ + 205, + 25, + 8, + 221, + 253, + 131, + 2, + 146 + ] + } + ], + "events": [ + { + "name": "DecreaseComponents", + "discriminator": [ + 129, + 8, + 124, + 12, + 11, + 140, + 0, + 8 + ] + }, + { + "name": "InstantUnstakeComponents", + "discriminator": [ + 217, + 80, + 196, + 114, + 226, + 11, + 127, + 77 + ] + }, + { + "name": "ScoreComponents", + "discriminator": [ + 218, + 204, + 53, + 7, + 22, + 2, + 217, + 251 + ] + }, + { + "name": "StateTransition", + "discriminator": [ + 106, + 9, + 120, + 247, + 169, + 106, + 206, + 233 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "ScoringNotComplete", + "msg": "Scoring must be completed before any other steps can be taken" + }, + { + "code": 6001, + "name": "ValidatorNotInList", + "msg": "Validator does not exist at the ValidatorList index provided" + }, + { + "code": 6002, + "name": "AddValidatorsNotComplete", + "msg": "Add validators step must be completed before any other steps can be taken" + }, + { + "code": 6003, + "name": "EpochNotOver", + "msg": "Cannot reset state before epoch is over" + }, + { + "code": 6004, + "name": "Unauthorized", + "msg": "Unauthorized to perform this action" + }, + { + "code": 6005, + "name": "BitmaskOutOfBounds", + "msg": "Bitmask index out of bounds" + }, + { + "code": 6006, + "name": "StateNotReset", + "msg": "Epoch state not reset" + }, + { + "code": 6007, + "name": "ValidatorOutOfRange", + "msg": "Validator History created after epoch start, out of range" + }, + { + "code": 6008, + "name": "InvalidState" + }, + { + "code": 6009, + "name": "ValidatorBelowStakeMinimum", + "msg": "Validator not eligible to be added to the pool. Must meet stake minimum" + }, + { + "code": 6010, + "name": "ValidatorBelowLivenessMinimum", + "msg": "Validator not eligible to be added to the pool. Must meet recent voting minimum" + }, + { + "code": 6011, + "name": "VoteHistoryNotRecentEnough", + "msg": "Validator History vote data not recent enough to be used for scoring. Must be updated this epoch" + }, + { + "code": 6012, + "name": "StakeHistoryNotRecentEnough", + "msg": "Validator History stake data not recent enough to be used for scoring. Must be updated this epoch" + }, + { + "code": 6013, + "name": "ClusterHistoryNotRecentEnough", + "msg": "Cluster History data not recent enough to be used for scoring. Must be updated this epoch" + }, + { + "code": 6014, + "name": "StateMachinePaused", + "msg": "Steward State Machine is paused. No state machine actions can be taken" + }, + { + "code": 6015, + "name": "InvalidParameterValue", + "msg": "Config parameter is out of range or otherwise invalid" + }, + { + "code": 6016, + "name": "InstantUnstakeNotReady", + "msg": "Instant unstake cannot be performed yet." + }, + { + "code": 6017, + "name": "ValidatorIndexOutOfBounds", + "msg": "Validator index out of bounds of state machine" + }, + { + "code": 6018, + "name": "ValidatorListTypeMismatch", + "msg": "ValidatorList account type mismatch" + }, + { + "code": 6019, + "name": "ArithmeticError", + "msg": "An operation caused an overflow/underflow" + }, + { + "code": 6020, + "name": "ValidatorNotRemovable", + "msg": "Validator not eligible for removal. Must be delinquent or have closed vote account" + }, + { + "code": 6021, + "name": "MaxValidatorsReached", + "msg": "Max validators reached" + }, + { + "code": 6022, + "name": "ValidatorHistoryMismatch", + "msg": "Validator history account does not match vote account" + } + ], + "types": [ + { + "name": "BitMask", + "docs": [ + "Data structure used to efficiently pack a binary array, primarily used to store all validators.", + "Each validator has an index (its index in the spl_stake_pool::ValidatorList), corresponding to a bit in the bitmask.", + "When an operation is executed on a validator, the bit corresponding to that validator's index is set to 1.", + "When all bits are 1, the operation is complete." + ], + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "values", + "type": { + "array": [ + "u64", + 79 + ] + } + } + ] + } + }, + { + "name": "CircBuf", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "idx", + "type": "u64" + }, + { + "name": "is_empty", + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 7 + ] } }, { - "name": "bump", + "name": "arr", + "type": { + "array": [ + { + "defined": { + "name": "ValidatorHistoryEntry" + } + }, + 512 + ] + } + } + ] + } + }, + { + "name": "CircBufCluster", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "idx", + "type": "u64" + }, + { + "name": "is_empty", "type": "u8" }, { @@ -1482,23 +1731,799 @@ 7 ] } + }, + { + "name": "arr", + "type": { + "array": [ + { + "defined": { + "name": "ClusterHistoryEntry" + } + }, + 512 + ] + } } ] } - } - ], - "types": [ + }, { - "name": "BitMask", + "name": "ClientVersion", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { "kind": "struct", "fields": [ { - "name": "values", + "name": "major", + "type": "u8" + }, + { + "name": "minor", + "type": "u8" + }, + { + "name": "patch", + "type": "u16" + } + ] + } + }, + { + "name": "ClusterHistory", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "struct_version", + "type": "u64" + }, + { + "name": "bump", + "type": "u8" + }, + { + "name": "_padding0", + "type": { + "array": [ + "u8", + 7 + ] + } + }, + { + "name": "cluster_history_last_update_slot", + "type": "u64" + }, + { + "name": "_padding1", + "type": { + "array": [ + "u8", + 232 + ] + } + }, + { + "name": "history", + "type": { + "defined": { + "name": "CircBufCluster" + } + } + } + ] + } + }, + { + "name": "ClusterHistoryEntry", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "total_blocks", + "type": "u32" + }, + { + "name": "epoch", + "type": "u16" + }, + { + "name": "padding0", + "type": { + "array": [ + "u8", + 2 + ] + } + }, + { + "name": "epoch_start_timestamp", + "type": "u64" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 240 + ] + } + } + ] + } + }, + { + "name": "Config", + "docs": [ + "Config is a user-provided keypair.", + "This is so there can be multiple configs per stake pool, and one party can't", + "squat a config address for another party's stake pool." + ], + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "stake_pool", + "docs": [ + "SPL Stake Pool address that this program is managing" + ], + "type": "pubkey" + }, + { + "name": "authority", + "docs": [ + "Authority for pool stewardship, can execute SPL Staker commands and adjust Delegation parameters" + ], + "type": "pubkey" + }, + { + "name": "blacklist", + "docs": [ + "Bitmask representing index of validators that are not allowed delegation" + ], + "type": { + "defined": { + "name": "BitMask" + } + } + }, + { + "name": "parameters", + "docs": [ + "Parameters for scoring, delegation, and state machine" + ], + "type": { + "defined": { + "name": "Parameters" + } + } + }, + { + "name": "_padding", + "docs": [ + "Padding for future governance parameters" + ], + "type": { + "array": [ + "u8", + 1023 + ] + } + }, + { + "name": "paused", + "docs": [ + "Halts any state machine progress" + ], + "type": { + "defined": { + "name": "U8Bool" + } + } + } + ] + } + }, + { + "name": "DecreaseComponents", + "type": { + "kind": "struct", + "fields": [ + { + "name": "scoring_unstake_lamports", + "type": "u64" + }, + { + "name": "instant_unstake_lamports", + "type": "u64" + }, + { + "name": "stake_deposit_unstake_lamports", + "type": "u64" + }, + { + "name": "total_unstake_lamports", + "type": "u64" + } + ] + } + }, + { + "name": "Delegation", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "numerator", + "type": "u32" + }, + { + "name": "denominator", + "type": "u32" + } + ] + } + }, + { + "name": "InstantUnstakeComponents", + "type": { + "kind": "struct", + "fields": [ + { + "name": "instant_unstake", + "docs": [ + "Aggregate of all checks" + ], + "type": "bool" + }, + { + "name": "delinquency_check", + "docs": [ + "Checks if validator has missed > instant_unstake_delinquency_threshold_ratio of votes this epoch" + ], + "type": "bool" + }, + { + "name": "commission_check", + "docs": [ + "Checks if validator has increased commission > commission_threshold" + ], + "type": "bool" + }, + { + "name": "mev_commission_check", + "docs": [ + "Checks if validator has increased MEV commission > mev_commission_bps_threshold" + ], + "type": "bool" + }, + { + "name": "is_blacklisted", + "docs": [ + "Checks if validator was added to blacklist blacklisted" + ], + "type": "bool" + }, + { + "name": "vote_account", + "type": "pubkey" + }, + { + "name": "epoch", + "type": "u16" + } + ] + } + }, + { + "name": "Parameters", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "mev_commission_range", + "docs": [ + "Number of epochs to consider for MEV commission" + ], + "type": "u16" + }, + { + "name": "epoch_credits_range", + "docs": [ + "Number of epochs to consider for epoch credits" + ], + "type": "u16" + }, + { + "name": "commission_range", + "docs": [ + "Number of epochs to consider for commission" + ], + "type": "u16" + }, + { + "name": "mev_commission_bps_threshold", + "docs": [ + "Highest MEV commission rate allowed in bps" + ], + "type": "u16" + }, + { + "name": "scoring_delinquency_threshold_ratio", + "docs": [ + "Proportion of delinquent slots to total slots to trigger delinquency measurement in scoring" + ], + "type": "f64" + }, + { + "name": "instant_unstake_delinquency_threshold_ratio", + "docs": [ + "Proportion of delinquent slots to total slots to trigger instant unstake" + ], + "type": "f64" + }, + { + "name": "commission_threshold", + "docs": [ + "Highest commission rate allowed in commission_range epochs, in percent" + ], + "type": "u8" + }, + { + "name": "historical_commission_threshold", + "docs": [ + "Highest commission rate allowed in tracked history" + ], + "type": "u8" + }, + { + "name": "padding0", + "docs": [ + "Required so that the struct is 8-byte aligned", + "https://doc.rust-lang.org/reference/type-layout.html#reprc-structs" + ], + "type": { + "array": [ + "u8", + 6 + ] + } + }, + { + "name": "num_delegation_validators", + "docs": [ + "Number of validators to delegate to" + ], + "type": "u32" + }, + { + "name": "scoring_unstake_cap_bps", + "docs": [ + "Maximum amount of the pool to be unstaked in a cycle for scoring (in basis points)" + ], + "type": "u32" + }, + { + "name": "instant_unstake_cap_bps", + "type": "u32" + }, + { + "name": "stake_deposit_unstake_cap_bps", + "docs": [ + "Maximum amount of the pool to be unstaked in a cycle from stake deposits (in basis points)" + ], + "type": "u32" + }, + { + "name": "compute_score_slot_range", + "docs": [ + "Number of slots that scoring must be completed in" + ], + "type": "u64" + }, + { + "name": "instant_unstake_epoch_progress", + "docs": [ + "Progress in epoch before instant unstake is allowed" + ], + "type": "f64" + }, + { + "name": "instant_unstake_inputs_epoch_progress", + "docs": [ + "Validator history copy_vote_account and Cluster History must be updated past this epoch progress before calculating instant unstake" + ], + "type": "f64" + }, + { + "name": "num_epochs_between_scoring", + "docs": [ + "Number of epochs a given validator set will be delegated to before recomputing scores" + ], + "type": "u64" + }, + { + "name": "minimum_stake_lamports", + "docs": [ + "Minimum stake required to be added to pool ValidatorList and eligible for delegation" + ], + "type": "u64" + }, + { + "name": "minimum_voting_epochs", + "docs": [ + "Minimum epochs voting required to be in the pool ValidatorList and eligible for delegation" + ], + "type": "u64" + } + ] + } + }, + { + "name": "PreferredValidatorType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Deposit" + }, + { + "name": "Withdraw" + } + ] + } + }, + { + "name": "ScoreComponents", + "type": { + "kind": "struct", + "fields": [ + { + "name": "score", + "docs": [ + "Product of all scoring components" + ], + "type": "f64" + }, + { + "name": "yield_score", + "docs": [ + "vote_credits_ratio * (1 - commission)" + ], + "type": "f64" + }, + { + "name": "mev_commission_score", + "docs": [ + "If max mev commission in mev_commission_range epochs is less than threshold, score is 1.0, else 0" + ], + "type": "f64" + }, + { + "name": "blacklisted_score", + "docs": [ + "If validator is blacklisted, score is 0.0, else 1.0" + ], + "type": "f64" + }, + { + "name": "superminority_score", + "docs": [ + "If validator is not in the superminority, score is 1.0, else 0.0" + ], + "type": "f64" + }, + { + "name": "delinquency_score", + "docs": [ + "If delinquency is not > threshold in any epoch, score is 1.0, else 0.0" + ], + "type": "f64" + }, + { + "name": "running_jito_score", + "docs": [ + "If validator has a mev commission in the last 10 epochs, score is 1.0, else 0.0" + ], + "type": "f64" + }, + { + "name": "commission_score", + "docs": [ + "If max commission in commission_range epochs is less than commission_threshold, score is 1.0, else 0.0" + ], + "type": "f64" + }, + { + "name": "historical_commission_score", + "docs": [ + "If max commission in all validator history epochs is less than historical_commission_threshold, score is 1.0, else 0.0" + ], + "type": "f64" + }, + { + "name": "vote_credits_ratio", + "docs": [ + "Average vote credits in last epoch_credits_range epochs / average blocks in last epoch_credits_range epochs", + "Excluding current epoch" + ], + "type": "f64" + }, + { + "name": "vote_account", + "type": "pubkey" + }, + { + "name": "epoch", + "type": "u16" + } + ] + } + }, + { + "name": "Staker", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "StateTransition", + "type": { + "kind": "struct", + "fields": [ + { + "name": "epoch", + "type": "u64" + }, + { + "name": "slot", + "type": "u64" + }, + { + "name": "previous_state", + "type": "string" + }, + { + "name": "new_state", + "type": "string" + } + ] + } + }, + { + "name": "StewardState", + "docs": [ + "Tracks state of the stake pool.", + "Follow state transitions here: [TODO add link to github diagram]" + ], + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "state_tag", + "docs": [ + "Current state of the Steward" + ], + "type": { + "defined": { + "name": "StewardStateEnum" + } + } + }, + { + "name": "validator_lamport_balances", + "docs": [ + "Internal lamport balance of each validator, used to track stake deposits that need to be unstaked,", + "so not always equal to the stake account balance." + ], + "type": { + "array": [ + "u64", + 5000 + ] + } + }, + { + "name": "scores", + "docs": [ + "Overall score of validator, used to determine delegates and order for delegation." + ], + "type": { + "array": [ + "u32", + 5000 + ] + } + }, + { + "name": "sorted_score_indices", + "docs": [ + "Indices of validators, sorted by score descending" + ], + "type": { + "array": [ + "u16", + 5000 + ] + } + }, + { + "name": "yield_scores", + "docs": [ + "Yield component of the score. Used as secondary priority, to determine order for unstaking." + ], + "type": { + "array": [ + "u32", + 5000 + ] + } + }, + { + "name": "sorted_yield_score_indices", + "docs": [ + "Indices of validators, sorted by yield score descending" + ], + "type": { + "array": [ + "u16", + 5000 + ] + } + }, + { + "name": "delegations", + "docs": [ + "Target share of pool represented as a proportion, indexed by spl_stake_pool::ValidatorList index" + ], + "type": { + "array": [ + { + "defined": { + "name": "Delegation" + } + }, + 5000 + ] + } + }, + { + "name": "instant_unstake", + "docs": [ + "Each bit represents a validator, true if validator should be unstaked" + ], + "type": { + "defined": { + "name": "BitMask" + } + } + }, + { + "name": "progress", + "docs": [ + "Tracks progress of states that require one instruction per validator" + ], + "type": { + "defined": { + "name": "BitMask" + } + } + }, + { + "name": "start_computing_scores_slot", + "docs": [ + "Slot of the first ComputeScores instruction in the current cycle" + ], + "type": "u64" + }, + { + "name": "current_epoch", + "docs": [ + "Internal current epoch, for tracking when epoch has changed" + ], + "type": "u64" + }, + { + "name": "next_cycle_epoch", + "docs": [ + "Next cycle start" + ], + "type": "u64" + }, + { + "name": "num_pool_validators", + "docs": [ + "Number of validators in the stake pool, used to determine the number of validators to be scored.", + "Updated at the start of each cycle and when validators are removed." + ], + "type": "u64" + }, + { + "name": "scoring_unstake_total", + "docs": [ + "Total lamports that have been due to scoring this cycle" + ], + "type": "u64" + }, + { + "name": "instant_unstake_total", + "docs": [ + "Total lamports that have been due to instant unstaking this cycle" + ], + "type": "u64" + }, + { + "name": "stake_deposit_unstake_total", + "docs": [ + "Total lamports that have been due to stake deposits this cycle" + ], + "type": "u64" + }, + { + "name": "compute_delegations_completed", + "docs": [ + "Tracks whether delegation computation has been completed" + ], + "type": { + "defined": { + "name": "U8Bool" + } + } + }, + { + "name": "rebalance_completed", + "docs": [ + "Tracks whether unstake and delegate steps have completed" + ], + "type": { + "defined": { + "name": "U8Bool" + } + } + }, + { + "name": "_padding0", + "docs": [ + "Future state and #[repr(C)] alignment" + ], "type": { "array": [ - "u64", - 157 + "u8", + 40006 ] } } @@ -1506,76 +2531,84 @@ } }, { - "name": "Parameters", + "name": "StewardStateAccount", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { "kind": "struct", "fields": [ { - "name": "mevCommissionRange", - "type": "u16" - }, - { - "name": "epochCreditsRange", - "type": "u16" - }, - { - "name": "commissionRange", - "type": "u16" - }, - { - "name": "mevCommissionBpsThreshold", - "type": "u16" - }, - { - "name": "scoringDelinquencyThresholdRatio", - "type": "f64" + "name": "state", + "type": { + "defined": { + "name": "StewardState" + } + } }, { - "name": "instantUnstakeDelinquencyThresholdRatio", - "type": "f64" + "name": "is_initialized", + "type": { + "defined": { + "name": "U8Bool" + } + } }, { - "name": "commissionThreshold", + "name": "bump", "type": "u8" }, { - "name": "padding0", + "name": "_padding", "type": { "array": [ "u8", - 7 + 6 ] } - }, - { - "name": "minPerfScore", - "type": "f64" - }, + } + ] + } + }, + { + "name": "StewardStateEnum", + "type": { + "kind": "enum", + "variants": [ { - "name": "minStakeAmount", - "type": "f64" + "name": "ComputeScores" }, { - "name": "computeScoreSlotRange", - "type": { - "defined": "usize" - } + "name": "ComputeDelegations" }, { - "name": "instantUnstakeEpochProgress", - "type": "f64" + "name": "Idle" }, { - "name": "clusterHistoryUpdateEpochProgress", - "type": "f64" + "name": "ComputeInstantUnstake" }, { - "name": "voteAccountUpdateEpochProgress", - "type": "f64" - }, + "name": "Rebalance" + } + ] + } + }, + { + "name": "U8Bool", + "docs": [ + "A boolean type stored as a u8." + ], + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ { - "name": "numEpochsBetweenScoring", - "type": "u64" + "name": "value", + "type": "u8" } ] } @@ -1586,87 +2619,109 @@ "kind": "struct", "fields": [ { - "name": "mevCommissionRange", + "name": "mev_commission_range", "type": { "option": "u16" } }, { - "name": "epochCreditsRange", + "name": "epoch_credits_range", "type": { "option": "u16" } }, { - "name": "commissionRange", + "name": "commission_range", "type": { "option": "u16" } }, { - "name": "scoringDelinquencyThresholdRatio", + "name": "scoring_delinquency_threshold_ratio", "type": { "option": "f64" } }, { - "name": "instantUnstakeDelinquencyThresholdRatio", + "name": "instant_unstake_delinquency_threshold_ratio", "type": { "option": "f64" } }, { - "name": "mevCommissionBpsThreshold", + "name": "mev_commission_bps_threshold", "type": { "option": "u16" } }, { - "name": "commissionThreshold", + "name": "commission_threshold", "type": { "option": "u8" } }, { - "name": "minPerfScore", + "name": "historical_commission_threshold", "type": { - "option": "f64" + "option": "u8" } }, { - "name": "minStakeAmount", + "name": "num_delegation_validators", "type": { - "option": "f64" + "option": "u32" } }, { - "name": "instantUnstakeEpochProgress", + "name": "scoring_unstake_cap_bps", "type": { - "option": "f64" + "option": "u32" } }, { - "name": "computeScoreSlotRange", + "name": "instant_unstake_cap_bps", "type": { - "option": { - "defined": "usize" - } + "option": "u32" + } + }, + { + "name": "stake_deposit_unstake_cap_bps", + "type": { + "option": "u32" } }, { - "name": "clusterHistoryUpdateEpochProgress", + "name": "instant_unstake_epoch_progress", "type": { "option": "f64" } }, { - "name": "voteAccountUpdateEpochProgress", + "name": "compute_score_slot_range", + "type": { + "option": "u64" + } + }, + { + "name": "instant_unstake_inputs_epoch_progress", "type": { "option": "f64" } }, { - "name": "numEpochsBetweenScoring", + "name": "num_epochs_between_scoring", + "type": { + "option": "u64" + } + }, + { + "name": "minimum_stake_lamports", + "type": { + "option": "u64" + } + }, + { + "name": "minimum_voting_epochs", "type": { "option": "u64" } @@ -1675,126 +2730,148 @@ } }, { - "name": "StewardStateEnum", + "name": "ValidatorHistory", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { - "kind": "enum", - "variants": [ + "kind": "struct", + "fields": [ { - "name": "ComputeScores" + "name": "struct_version", + "type": "u32" }, { - "name": "ComputeDelegations" + "name": "vote_account", + "type": "pubkey" }, { - "name": "Idle" + "name": "index", + "type": "u32" }, { - "name": "ComputeInstantUnstake" + "name": "bump", + "type": "u8" + }, + { + "name": "_padding0", + "type": { + "array": [ + "u8", + 7 + ] + } + }, + { + "name": "last_ip_timestamp", + "type": "u64" }, { - "name": "RecomputeDelegations" + "name": "last_version_timestamp", + "type": "u64" }, { - "name": "Unstake" + "name": "_padding1", + "type": { + "array": [ + "u8", + 232 + ] + } }, { - "name": "Delegate" + "name": "history", + "type": { + "defined": { + "name": "CircBuf" + } + } } ] } - } - ], - "events": [ - { - "name": "StateTransition", - "fields": [ - { - "name": "previousState", - "type": "string", - "index": false - }, - { - "name": "newState", - "type": "string", - "index": false - } - ] - } - ], - "errors": [ - { - "code": 6000, - "name": "ScoringNotComplete", - "msg": "Scoring must be completed before any other steps can be taken" - }, - { - "code": 6001, - "name": "ValidatorNotInList", - "msg": "Validator does not exist at the ValidatorList index provided" - }, - { - "code": 6002, - "name": "AddValidatorsNotComplete", - "msg": "Add validators step must be completed before any other steps can be taken" - }, - { - "code": 6003, - "name": "EpochNotOver", - "msg": "Cannot reset state before epoch is over" - }, - { - "code": 6004, - "name": "Unauthorized", - "msg": "Unauthorized to perform this action" - }, - { - "code": 6005, - "name": "BitmaskOutOfBounds", - "msg": "Bitmask index out of bounds" - }, - { - "code": 6006, - "name": "StateNotReset", - "msg": "Epoch state not reset" - }, - { - "code": 6007, - "name": "ValidatorOutOfRange", - "msg": "Validator History created after epoch start, out of range" - }, - { - "code": 6008, - "name": "InvalidState" - }, - { - "code": 6009, - "name": "ValidatorBelowStakeMinimum", - "msg": "Validator not eligible to be added to the pool. Must meet stake minimum" - }, - { - "code": 6010, - "name": "ValidatorBelowLivenessMinimum", - "msg": "Validator not eligible to be added to the pool. Must meet recent voting minimum" - }, - { - "code": 6011, - "name": "ValidatorHistoryNotRecentEnough", - "msg": "Validator History data not recent enough to be used for scoring. Must be updated this epoch" - }, - { - "code": 6012, - "name": "ClusterHistoryNotRecentEnough", - "msg": "Cluster History data not recent enough to be used for scoring. Must be updated this epoch" }, { - "code": 6013, - "name": "StateMachinePaused", - "msg": "Steward State Machine is paused. No state machine actions can be taken" - }, - { - "code": 6014, - "name": "InvalidParameterValue", - "msg": "Config parameter is out of range or otherwise invalid" + "name": "ValidatorHistoryEntry", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "activated_stake_lamports", + "type": "u64" + }, + { + "name": "epoch", + "type": "u16" + }, + { + "name": "mev_commission", + "type": "u16" + }, + { + "name": "epoch_credits", + "type": "u32" + }, + { + "name": "commission", + "type": "u8" + }, + { + "name": "client_type", + "type": "u8" + }, + { + "name": "version", + "type": { + "defined": { + "name": "ClientVersion" + } + } + }, + { + "name": "ip", + "type": { + "array": [ + "u8", + 4 + ] + } + }, + { + "name": "padding0", + "type": "u8" + }, + { + "name": "is_superminority", + "type": "u8" + }, + { + "name": "rank", + "type": "u32" + }, + { + "name": "vote_account_last_update_slot", + "type": "u64" + }, + { + "name": "mev_earned", + "type": "u32" + }, + { + "name": "padding1", + "type": { + "array": [ + "u8", + 84 + ] + } + } + ] + } } ] } \ No newline at end of file diff --git a/programs/steward/src/constants.rs b/programs/steward/src/constants.rs index 8957cf82..5edfca33 100644 --- a/programs/steward/src/constants.rs +++ b/programs/steward/src/constants.rs @@ -10,7 +10,7 @@ pub const EPOCH_PROGRESS_MAX: f64 = 0.99; // Cannot go more than 100 epochs without scoring pub const NUM_EPOCHS_BETWEEN_SCORING_MAX: u64 = 100; // Cannot score validators in under 100 slots, to submit 1 instruction per validator -pub const COMPUTE_SCORE_SLOT_RANGE_MIN: usize = 100; +pub const COMPUTE_SCORE_SLOT_RANGE_MIN: u64 = 100; #[cfg(feature = "mainnet-beta")] pub const VALIDATOR_HISTORY_FIRST_RELIABLE_EPOCH: usize = 520; #[cfg(not(feature = "mainnet-beta"))] diff --git a/programs/steward/src/state/accounts.rs b/programs/steward/src/state/accounts.rs index 4cb5dc7e..ee252adc 100644 --- a/programs/steward/src/state/accounts.rs +++ b/programs/steward/src/state/accounts.rs @@ -1,6 +1,6 @@ use std::mem::size_of; -use anchor_lang::{prelude::*, IdlBuild}; +use anchor_lang::prelude::*; use borsh::BorshSerialize; use type_layout::TypeLayout; diff --git a/programs/steward/src/state/bitmask.rs b/programs/steward/src/state/bitmask.rs index 9d82f2d9..529cfe64 100644 --- a/programs/steward/src/state/bitmask.rs +++ b/programs/steward/src/state/bitmask.rs @@ -72,7 +72,8 @@ impl BitMask { } #[allow(clippy::integer_division)] - pub fn is_complete(&self, num_validators: usize) -> Result { + pub fn is_complete(&self, num_validators: u64) -> Result { + let num_validators = num_validators as usize; if num_validators > MAX_VALIDATORS { return Err(StewardError::BitmaskOutOfBounds.into()); } diff --git a/programs/steward/src/state/parameters.rs b/programs/steward/src/state/parameters.rs index 79ff507f..f7c233c7 100644 --- a/programs/steward/src/state/parameters.rs +++ b/programs/steward/src/state/parameters.rs @@ -1,4 +1,3 @@ -// #[cfg(feature = "idl-build")] use anchor_lang::idl::types::*; use anchor_lang::idl::*; use anchor_lang::{prelude::Result, zero_copy}; @@ -398,7 +397,7 @@ impl Parameters { return Err(StewardError::InvalidParameterValue.into()); } - if !(COMPUTE_SCORE_SLOT_RANGE_MIN as u64..=slots_per_epoch) + if !(COMPUTE_SCORE_SLOT_RANGE_MIN..=slots_per_epoch) .contains(&self.compute_score_slot_range) { return Err(StewardError::InvalidParameterValue.into()); diff --git a/programs/steward/src/state/steward_state.rs b/programs/steward/src/state/steward_state.rs index 4b2db54e..bd7b52de 100644 --- a/programs/steward/src/state/steward_state.rs +++ b/programs/steward/src/state/steward_state.rs @@ -1,4 +1,5 @@ use borsh::BorshSerialize; +use core::num; use std::fmt::Display; use crate::{ @@ -284,10 +285,7 @@ impl StewardState { current_slot, num_epochs_between_scoring, )?; - } else if self - .progress - .is_complete(self.num_pool_validators as usize)? - { + } else if self.progress.is_complete(self.num_pool_validators)? { self.state_tag = StewardStateEnum::ComputeDelegations; self.progress = BitMask::default(); self.delegations = [Delegation::default(); MAX_VALIDATORS]; @@ -362,10 +360,7 @@ impl StewardState { self.current_epoch = current_epoch; self.instant_unstake = BitMask::default(); self.progress = BitMask::default(); - } else if self - .progress - .is_complete(self.num_pool_validators as usize)? - { + } else if self.progress.is_complete(self.num_pool_validators)? { self.state_tag = StewardStateEnum::Rebalance; self.progress = BitMask::default(); } @@ -391,10 +386,7 @@ impl StewardState { self.current_epoch = current_epoch; self.progress = BitMask::default(); self.rebalance_completed = false.into(); - } else if self - .progress - .is_complete(self.num_pool_validators as usize)? - { + } else if self.progress.is_complete(self.num_pool_validators)? { self.state_tag = StewardStateEnum::Idle; self.current_epoch = current_epoch; self.rebalance_completed = true.into(); @@ -434,9 +426,10 @@ impl StewardState { .num_pool_validators .checked_sub(1) .ok_or(StewardError::ArithmeticError)?; + let num_pool_validators = self.num_pool_validators as usize; // Shift all validator state to the left - for i in index..self.num_pool_validators as usize { + for i in index..num_pool_validators { let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; self.validator_lamport_balances[i] = self.validator_lamport_balances[next_i]; self.scores[i] = self.scores[next_i]; @@ -458,20 +451,20 @@ impl StewardState { .position(|&i| i == index as u16); if let Some(yield_score_index) = yield_score_index { - for i in yield_score_index..self.num_pool_validators as usize { + for i in yield_score_index..num_pool_validators { let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; self.sorted_yield_score_indices[i] = self.sorted_yield_score_indices[next_i]; } } if let Some(score_index) = score_index { - for i in score_index..self.num_pool_validators as usize { + for i in score_index..num_pool_validators { let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; self.sorted_score_indices[i] = self.sorted_score_indices[next_i]; } } - for i in 0..self.num_pool_validators as usize { + for i in 0..num_pool_validators { if self.sorted_yield_score_indices[i] as usize > index { self.sorted_yield_score_indices[i] = self.sorted_yield_score_indices[i] .checked_sub(1) @@ -485,16 +478,14 @@ impl StewardState { } // Clear values on empty last index - self.validator_lamport_balances[self.num_pool_validators as usize] = 0; - self.scores[self.num_pool_validators as usize] = 0; - self.yield_scores[self.num_pool_validators as usize] = 0; - self.sorted_score_indices[self.num_pool_validators as usize] = SORTED_INDEX_DEFAULT; - self.sorted_yield_score_indices[self.num_pool_validators as usize] = SORTED_INDEX_DEFAULT; - self.delegations[self.num_pool_validators as usize] = Delegation::default(); - self.instant_unstake - .set(self.num_pool_validators as usize, false)?; - self.progress - .set(self.num_pool_validators as usize, false)?; + self.validator_lamport_balances[num_pool_validators] = 0; + self.scores[num_pool_validators] = 0; + self.yield_scores[num_pool_validators] = 0; + self.sorted_score_indices[num_pool_validators] = SORTED_INDEX_DEFAULT; + self.sorted_yield_score_indices[num_pool_validators] = SORTED_INDEX_DEFAULT; + self.delegations[num_pool_validators] = Delegation::default(); + self.instant_unstake.set(num_pool_validators, false)?; + self.progress.set(num_pool_validators, false)?; Ok(()) } @@ -546,7 +537,7 @@ impl StewardState { .ok_or(StewardError::ArithmeticError)?; if self.progress.is_empty() || current_epoch > self.current_epoch - || slots_since_scoring_started > config.parameters.compute_score_slot_range as u64 + || slots_since_scoring_started > config.parameters.compute_score_slot_range { self.reset_state_for_new_cycle( clock.epoch, diff --git a/programs/steward/src/utils.rs b/programs/steward/src/utils.rs index 484f64ca..96f281fd 100644 --- a/programs/steward/src/utils.rs +++ b/programs/steward/src/utils.rs @@ -5,7 +5,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use spl_pod::{bytemuck::pod_from_bytes, primitives::PodU64, solana_program::program_pack::Pack}; use spl_stake_pool::{ big_vec::BigVec, - state::{StakePool as SPLStakePool, ValidatorListHeader, ValidatorStakeInfo}, + state::{ValidatorListHeader, ValidatorStakeInfo}, }; use crate::{errors::StewardError, Config, Delegation}; diff --git a/programs/validator-history/Cargo.toml b/programs/validator-history/Cargo.toml index 9e816262..6ed95c8c 100644 --- a/programs/validator-history/Cargo.toml +++ b/programs/validator-history/Cargo.toml @@ -18,9 +18,9 @@ no-entrypoint = [] no-idl = [] no-log-ix-name = [] cpi = ["no-entrypoint"] -default = ["custom-heap", "no-entrypoint"] +default = ["custom-heap"] custom-heap = [] -idl-build = ["anchor-lang/idl-build"] +idl-build = ["anchor-lang/idl-build", "no-entrypoint"] [dependencies] anchor-lang = { features = ["idl-build"], version = "0.30.0" } diff --git a/programs/validator-history/idl/validator_history.json b/programs/validator-history/idl/validator_history.json index 0b8bf879..0de57d0a 100644 --- a/programs/validator-history/idl/validator_history.json +++ b/programs/validator-history/idl/validator_history.json @@ -1,163 +1,147 @@ { - "version": "0.1.0", - "name": "validator_history", + "address": "HistoryJTGbKQD2mRgLZ3XhqHnN811Qpez8X9kCcGHoa", + "metadata": { + "name": "validator_history", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Program for tracking validator metrics on chain" + }, "instructions": [ { - "name": "initializeValidatorHistoryAccount", + "name": "backfill_total_blocks", + "discriminator": [ + 223, + 59, + 120, + 117, + 34, + 248, + 117, + 220 + ], "accounts": [ { - "name": "validatorHistoryAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "cluster_history_account", + "writable": true }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "signer", - "isMut": true, - "isSigner": true + "name": "oracle_authority", + "writable": true, + "signer": true } ], - "args": [] - }, - { - "name": "reallocValidatorHistoryAccount", - "accounts": [ - { - "name": "validatorHistoryAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "config", - "isMut": true, - "isSigner": false - }, - { - "name": "voteAccount", - "isMut": false, - "isSigner": false, - "docs": [ - "Used to read validator commission." - ] - }, + "args": [ { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "epoch", + "type": "u64" }, { - "name": "signer", - "isMut": true, - "isSigner": true + "name": "blocks_in_epoch", + "type": "u32" } - ], - "args": [] + ] }, { - "name": "initializeClusterHistoryAccount", + "name": "copy_cluster_info", + "discriminator": [ + 124, + 126, + 139, + 134, + 126, + 230, + 100, + 37 + ], "accounts": [ { - "name": "clusterHistoryAccount", - "isMut": true, - "isSigner": false + "name": "cluster_history_account", + "writable": true }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "slot_history" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [] }, { - "name": "reallocClusterHistoryAccount", + "name": "copy_gossip_contact_info", + "discriminator": [ + 246, + 174, + 228, + 249, + 28, + 209, + 69, + 85 + ], "accounts": [ { - "name": "clusterHistoryAccount", - "isMut": true, - "isSigner": false + "name": "validator_history_account", + "writable": true }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { - "name": "signer", - "isMut": true, - "isSigner": true - } - ], - "args": [] - }, - { - "name": "copyVoteAccount", - "accounts": [ - { - "name": "validatorHistoryAccount", - "isMut": true, - "isSigner": false + "name": "instructions" }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "signer", - "isMut": true, - "isSigner": true + "name": "oracle_authority", + "writable": true, + "signer": true } ], "args": [] }, { - "name": "copyTipDistributionAccount", + "name": "copy_tip_distribution_account", + "discriminator": [ + 208, + 213, + 185, + 210, + 103, + 124, + 128, + 173 + ], "accounts": [ { - "name": "validatorHistoryAccount", - "isMut": true, - "isSigner": false + "name": "validator_history_account", + "writable": true }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false, + "name": "vote_account", "docs": [ "Used to read validator commission." ] }, { - "name": "config", - "isMut": false, - "isSigner": false + "name": "config" }, { - "name": "tipDistributionAccount", - "isMut": false, - "isSigner": false, + "name": "tip_distribution_account", "docs": [ "`owner = config.tip_distribution_program.key()` here is sufficient." ] }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], "args": [ @@ -168,206 +152,299 @@ ] }, { - "name": "initializeConfig", + "name": "copy_vote_account", + "discriminator": [ + 171, + 204, + 73, + 59, + 129, + 63, + 134, + 61 + ], "accounts": [ { - "name": "config", - "isMut": true, - "isSigner": false + "name": "validator_history_account", + "writable": true }, { - "name": "systemProgram", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { "name": "signer", - "isMut": true, - "isSigner": true + "writable": true, + "signer": true } ], - "args": [ - { - "name": "authority", - "type": "publicKey" - } - ] + "args": [] }, { - "name": "setNewTipDistributionProgram", + "name": "initialize_cluster_history_account", + "discriminator": [ + 8, + 204, + 21, + 27, + 253, + 9, + 10, + 78 + ], "accounts": [ { - "name": "config", - "isMut": true, - "isSigner": false + "name": "cluster_history_account", + "writable": true }, { - "name": "newTipDistributionProgram", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "admin", - "isMut": false, - "isSigner": true + "name": "signer", + "writable": true, + "signer": true } ], "args": [] }, { - "name": "setNewAdmin", + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], "accounts": [ { "name": "config", - "isMut": true, - "isSigner": false + "writable": true }, { - "name": "newAdmin", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "admin", - "isMut": false, - "isSigner": true + "name": "signer", + "writable": true, + "signer": true } ], - "args": [] + "args": [ + { + "name": "authority", + "type": "pubkey" + } + ] }, { - "name": "setNewOracleAuthority", + "name": "initialize_validator_history_account", + "discriminator": [ + 61, + 152, + 10, + 77, + 196, + 242, + 89, + 36 + ], "accounts": [ { - "name": "config", - "isMut": true, - "isSigner": false + "name": "validator_history_account", + "writable": true }, { - "name": "newOracleAuthority", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { - "name": "admin", - "isMut": false, - "isSigner": true + "name": "system_program" + }, + { + "name": "signer", + "writable": true, + "signer": true } ], "args": [] }, { - "name": "updateStakeHistory", + "name": "realloc_cluster_history_account", + "discriminator": [ + 249, + 51, + 161, + 22, + 107, + 40, + 129, + 104 + ], "accounts": [ { - "name": "validatorHistoryAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "cluster_history_account", + "writable": true }, { - "name": "config", - "isMut": false, - "isSigner": false + "name": "system_program" }, { - "name": "oracleAuthority", - "isMut": true, - "isSigner": true + "name": "signer", + "writable": true, + "signer": true } ], - "args": [ + "args": [] + }, + { + "name": "realloc_validator_history_account", + "discriminator": [ + 196, + 17, + 33, + 140, + 174, + 130, + 33, + 12 + ], + "accounts": [ { - "name": "epoch", - "type": "u64" + "name": "validator_history_account", + "writable": true }, { - "name": "lamports", - "type": "u64" + "name": "config", + "writable": true }, { - "name": "rank", - "type": "u32" + "name": "vote_account", + "docs": [ + "Used to read validator commission." + ] }, { - "name": "isSuperminority", - "type": "bool" + "name": "system_program" + }, + { + "name": "signer", + "writable": true, + "signer": true } - ] + ], + "args": [] }, { - "name": "copyGossipContactInfo", + "name": "set_new_admin", + "discriminator": [ + 62, + 156, + 4, + 148, + 79, + 162, + 148, + 252 + ], "accounts": [ { - "name": "validatorHistoryAccount", - "isMut": true, - "isSigner": false + "name": "config", + "writable": true }, { - "name": "voteAccount", - "isMut": false, - "isSigner": false + "name": "new_admin" }, { - "name": "instructions", - "isMut": false, - "isSigner": false - }, + "name": "admin", + "signer": true + } + ], + "args": [] + }, + { + "name": "set_new_oracle_authority", + "discriminator": [ + 70, + 73, + 21, + 170, + 82, + 128, + 144, + 56 + ], + "accounts": [ { "name": "config", - "isMut": false, - "isSigner": false + "writable": true + }, + { + "name": "new_oracle_authority" }, { - "name": "oracleAuthority", - "isMut": true, - "isSigner": true + "name": "admin", + "signer": true } ], "args": [] }, { - "name": "copyClusterInfo", + "name": "set_new_tip_distribution_program", + "discriminator": [ + 200, + 69, + 235, + 182, + 178, + 62, + 130, + 217 + ], "accounts": [ { - "name": "clusterHistoryAccount", - "isMut": true, - "isSigner": false + "name": "config", + "writable": true }, { - "name": "slotHistory", - "isMut": false, - "isSigner": false + "name": "new_tip_distribution_program" }, { - "name": "signer", - "isMut": true, - "isSigner": true + "name": "admin", + "signer": true } ], "args": [] }, { - "name": "backfillTotalBlocks", + "name": "update_stake_history", + "discriminator": [ + 213, + 212, + 103, + 144, + 8, + 212, + 173, + 232 + ], "accounts": [ { - "name": "clusterHistoryAccount", - "isMut": true, - "isSigner": false + "name": "validator_history_account", + "writable": true }, { - "name": "config", - "isMut": false, - "isSigner": false + "name": "vote_account" }, { - "name": "signer", - "isMut": true, - "isSigner": true + "name": "config" + }, + { + "name": "oracle_authority", + "writable": true, + "signer": true } ], "args": [ @@ -376,64 +453,148 @@ "type": "u64" }, { - "name": "blocksInEpoch", + "name": "lamports", + "type": "u64" + }, + { + "name": "rank", "type": "u32" + }, + { + "name": "is_superminority", + "type": "bool" } ] } ], "accounts": [ + { + "name": "ClusterHistory", + "discriminator": [ + 41, + 154, + 241, + 80, + 135, + 88, + 85, + 252 + ] + }, { "name": "Config", - "type": { - "kind": "struct", - "fields": [ - { - "name": "tipDistributionProgram", - "type": "publicKey" - }, - { - "name": "admin", - "type": "publicKey" - }, - { - "name": "oracleAuthority", - "type": "publicKey" - }, - { - "name": "counter", - "type": "u32" - }, - { - "name": "bump", - "type": "u8" - } - ] - } + "discriminator": [ + 155, + 12, + 170, + 224, + 30, + 250, + 204, + 130 + ] }, { "name": "ValidatorHistory", + "discriminator": [ + 205, + 25, + 8, + 221, + 253, + 131, + 2, + 146 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "AccountFullySized", + "msg": "Account already reached proper size, no more allocations allowed" + }, + { + "code": 6001, + "name": "InvalidEpochCredits", + "msg": "Invalid epoch credits, credits must exist and each value must be greater than previous credits" + }, + { + "code": 6002, + "name": "EpochOutOfRange", + "msg": "Epoch is out of range of history" + }, + { + "code": 6003, + "name": "NotSigVerified", + "msg": "Gossip Signature Verification not performed" + }, + { + "code": 6004, + "name": "GossipDataInvalid", + "msg": "Gossip Data Invalid" + }, + { + "code": 6005, + "name": "UnsupportedIpFormat", + "msg": "Unsupported IP Format, only IpAddr::V4 is supported" + }, + { + "code": 6006, + "name": "NotEnoughVotingHistory", + "msg": "Not enough voting history to create account. Minimum 5 epochs required" + }, + { + "code": 6007, + "name": "GossipDataTooOld", + "msg": "Gossip data too old. Data cannot be older than the last recorded timestamp for a field" + }, + { + "code": 6008, + "name": "GossipDataInFuture", + "msg": "Gossip timestamp too far in the future" + }, + { + "code": 6009, + "name": "ArithmeticError", + "msg": "Arithmetic Error (overflow/underflow)" + }, + { + "code": 6010, + "name": "SlotHistoryOutOfDate", + "msg": "Slot history sysvar is not containing expected slots" + }, + { + "code": 6011, + "name": "EpochTooLarge", + "msg": "Epoch larger than 65535, cannot be stored" + }, + { + "code": 6012, + "name": "DuplicateEpoch", + "msg": "Inserting duplicate epoch" + } + ], + "types": [ + { + "name": "CircBuf", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { "kind": "struct", "fields": [ { - "name": "structVersion", - "type": "u32" - }, - { - "name": "voteAccount", - "type": "publicKey" - }, - { - "name": "index", - "type": "u32" + "name": "idx", + "type": "u64" }, { - "name": "bump", + "name": "is_empty", "type": "u8" }, { - "name": "padding0", + "name": "padding", "type": { "array": [ "u8", @@ -442,46 +603,40 @@ } }, { - "name": "lastIpTimestamp", - "type": "u64" - }, - { - "name": "lastVersionTimestamp", - "type": "u64" - }, - { - "name": "padding1", + "name": "arr", "type": { "array": [ - "u8", - 232 + { + "defined": { + "name": "ValidatorHistoryEntry" + } + }, + 512 ] } - }, - { - "name": "history", - "type": { - "defined": "CircBuf" - } } ] } }, { - "name": "ClusterHistory", + "name": "CircBufCluster", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { "kind": "struct", "fields": [ { - "name": "structVersion", + "name": "idx", "type": "u64" }, { - "name": "bump", + "name": "is_empty", "type": "u8" }, { - "name": "padding0", + "name": "padding", "type": { "array": [ "u8", @@ -490,99 +645,15 @@ } }, { - "name": "clusterHistoryLastUpdateSlot", - "type": "u64" - }, - { - "name": "padding1", - "type": { - "array": [ - "u8", - 232 - ] - } - }, - { - "name": "history", - "type": { - "defined": "CircBufCluster" - } - } - ] - } - } - ], - "types": [ - { - "name": "ValidatorHistoryEntry", - "type": { - "kind": "struct", - "fields": [ - { - "name": "activatedStakeLamports", - "type": "u64" - }, - { - "name": "epoch", - "type": "u16" - }, - { - "name": "mevCommission", - "type": "u16" - }, - { - "name": "epochCredits", - "type": "u32" - }, - { - "name": "commission", - "type": "u8" - }, - { - "name": "clientType", - "type": "u8" - }, - { - "name": "version", - "type": { - "defined": "ClientVersion" - } - }, - { - "name": "ip", - "type": { - "array": [ - "u8", - 4 - ] - } - }, - { - "name": "padding0", - "type": "u8" - }, - { - "name": "isSuperminority", - "type": "u8" - }, - { - "name": "rank", - "type": "u32" - }, - { - "name": "voteAccountLastUpdateSlot", - "type": "u64" - }, - { - "name": "mevEarned", - "type": "u32" - }, - { - "name": "padding1", + "name": "arr", "type": { "array": [ - "u8", - 84 + { + "defined": { + "name": "ClusterHistoryEntry" + } + }, + 512 ] } } @@ -591,6 +662,10 @@ }, { "name": "ClientVersion", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { "kind": "struct", "fields": [ @@ -610,20 +685,24 @@ } }, { - "name": "CircBuf", + "name": "ClusterHistory", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { "kind": "struct", "fields": [ { - "name": "idx", + "name": "struct_version", "type": "u64" }, { - "name": "isEmpty", + "name": "bump", "type": "u8" }, { - "name": "padding", + "name": "_padding0", "type": { "array": [ "u8", @@ -632,26 +711,40 @@ } }, { - "name": "arr", + "name": "cluster_history_last_update_slot", + "type": "u64" + }, + { + "name": "_padding1", "type": { "array": [ - { - "defined": "ValidatorHistoryEntry" - }, - 512 + "u8", + 232 ] } + }, + { + "name": "history", + "type": { + "defined": { + "name": "CircBufCluster" + } + } } ] } }, { "name": "ClusterHistoryEntry", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { "kind": "struct", "fields": [ { - "name": "totalBlocks", + "name": "total_blocks", "type": "u32" }, { @@ -668,7 +761,7 @@ } }, { - "name": "epochStartTimestamp", + "name": "epoch_start_timestamp", "type": "u64" }, { @@ -684,281 +777,176 @@ } }, { - "name": "CircBufCluster", + "name": "Config", "type": { "kind": "struct", "fields": [ { - "name": "idx", - "type": "u64" + "name": "tip_distribution_program", + "type": "pubkey" }, { - "name": "isEmpty", - "type": "u8" + "name": "admin", + "type": "pubkey" }, { - "name": "padding", - "type": { - "array": [ - "u8", - 7 - ] - } + "name": "oracle_authority", + "type": "pubkey" }, { - "name": "arr", - "type": { - "array": [ - { - "defined": "ClusterHistoryEntry" - }, - 512 - ] - } + "name": "counter", + "type": "u32" + }, + { + "name": "bump", + "type": "u8" } ] } }, { - "name": "CrdsData", - "docs": [ - "CrdsData that defines the different types of items CrdsValues can hold", - "* Merge Strategy - Latest wallclock is picked", - "* LowestSlot index is deprecated" - ], + "name": "ValidatorHistory", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { - "kind": "enum", - "variants": [ - { - "name": "LegacyContactInfo", - "fields": [ - { - "defined": "LegacyContactInfo" - } - ] - }, - { - "name": "Vote" - }, - { - "name": "LowestSlot" - }, + "kind": "struct", + "fields": [ { - "name": "LegacySnapshotHashes" + "name": "struct_version", + "type": "u32" }, { - "name": "AccountsHashes" + "name": "vote_account", + "type": "pubkey" }, { - "name": "EpochSlots" + "name": "index", + "type": "u32" }, { - "name": "LegacyVersion", - "fields": [ - { - "defined": "LegacyVersion" - } - ] + "name": "bump", + "type": "u8" }, { - "name": "Version", - "fields": [ - { - "defined": "Version2" - } - ] + "name": "_padding0", + "type": { + "array": [ + "u8", + 7 + ] + } }, { - "name": "NodeInstance" + "name": "last_ip_timestamp", + "type": "u64" }, { - "name": "DuplicateShred" + "name": "last_version_timestamp", + "type": "u64" }, { - "name": "SnapshotHashes" + "name": "_padding1", + "type": { + "array": [ + "u8", + 232 + ] + } }, { - "name": "ContactInfo", - "fields": [ - { - "defined": "ContactInfo" + "name": "history", + "type": { + "defined": { + "name": "CircBuf" } - ] + } } ] } }, { - "name": "Error", + "name": "ValidatorHistoryEntry", + "serialization": "bytemuck", + "repr": { + "kind": "c" + }, "type": { - "kind": "enum", - "variants": [ + "kind": "struct", + "fields": [ { - "name": "DuplicateIpAddr", - "fields": [ - { - "defined": "IpAddr" - } - ] - }, - { - "name": "DuplicateSocket", - "fields": [ - "u8" - ] - }, - { - "name": "InvalidIpAddrIndex", - "fields": [ - { - "name": "index", - "type": "u8" - }, - { - "name": "numAddrs", - "type": { - "defined": "usize" - } - } - ] - }, - { - "name": "InvalidPort", - "fields": [ - "u16" - ] - }, - { - "name": "InvalidQuicSocket", - "fields": [ - { - "option": { - "defined": "SocketAddr" - } - }, - { - "option": { - "defined": "SocketAddr" - } - } - ] + "name": "activated_stake_lamports", + "type": "u64" }, { - "name": "IpAddrsSaturated" + "name": "epoch", + "type": "u16" }, { - "name": "MulticastIpAddr", - "fields": [ - { - "defined": "IpAddr" - } - ] + "name": "mev_commission", + "type": "u16" }, { - "name": "PortOffsetsOverflow" + "name": "epoch_credits", + "type": "u32" }, { - "name": "SocketNotFound", - "fields": [ - "u8" - ] + "name": "commission", + "type": "u8" }, { - "name": "UnspecifiedIpAddr", - "fields": [ - { - "defined": "IpAddr" - } - ] + "name": "client_type", + "type": "u8" }, { - "name": "UnusedIpAddr", - "fields": [ - { - "defined": "IpAddr" + "name": "version", + "type": { + "defined": { + "name": "ClientVersion" } - ] - } - ] - } - }, - { - "name": "ValidatorHistoryVersion", - "type": { - "kind": "enum", - "variants": [ + } + }, + { + "name": "ip", + "type": { + "array": [ + "u8", + 4 + ] + } + }, + { + "name": "padding0", + "type": "u8" + }, + { + "name": "is_superminority", + "type": "u8" + }, + { + "name": "rank", + "type": "u32" + }, + { + "name": "vote_account_last_update_slot", + "type": "u64" + }, + { + "name": "mev_earned", + "type": "u32" + }, { - "name": "V0" + "name": "padding1", + "type": { + "array": [ + "u8", + 84 + ] + } } ] } } - ], - "errors": [ - { - "code": 6000, - "name": "AccountFullySized", - "msg": "Account already reached proper size, no more allocations allowed" - }, - { - "code": 6001, - "name": "InvalidEpochCredits", - "msg": "Invalid epoch credits, credits must exist and each value must be greater than previous credits" - }, - { - "code": 6002, - "name": "EpochOutOfRange", - "msg": "Epoch is out of range of history" - }, - { - "code": 6003, - "name": "NotSigVerified", - "msg": "Gossip Signature Verification not performed" - }, - { - "code": 6004, - "name": "GossipDataInvalid", - "msg": "Gossip Data Invalid" - }, - { - "code": 6005, - "name": "UnsupportedIpFormat", - "msg": "Unsupported IP Format, only IpAddr::V4 is supported" - }, - { - "code": 6006, - "name": "NotEnoughVotingHistory", - "msg": "Not enough voting history to create account. Minimum 5 epochs required" - }, - { - "code": 6007, - "name": "GossipDataTooOld", - "msg": "Gossip data too old. Data cannot be older than the last recorded timestamp for a field" - }, - { - "code": 6008, - "name": "GossipDataInFuture", - "msg": "Gossip timestamp too far in the future" - }, - { - "code": 6009, - "name": "ArithmeticError", - "msg": "Arithmetic Error (overflow/underflow)" - }, - { - "code": 6010, - "name": "SlotHistoryOutOfDate", - "msg": "Slot history sysvar is not containing expected slots" - }, - { - "code": 6011, - "name": "EpochTooLarge", - "msg": "Epoch larger than 65535, cannot be stored" - }, - { - "code": 6012, - "name": "DuplicateEpoch", - "msg": "Inserting duplicate epoch" - } ] } \ No newline at end of file diff --git a/test b/test deleted file mode 100755 index a3e5f723..00000000 --- a/test +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -cargo-build-sbf && \ - RUST_LOG=DEBUG \ - SBF_OUT_DIR=/Users/evanbatsell/jito/stakenet/target/sbf-solana-solana/release \ - cargo test-sbf diff --git a/tests/tests/steward/test_state_methods.rs b/tests/tests/steward/test_state_methods.rs index 69436925..6ec24a1e 100644 --- a/tests/tests/steward/test_state_methods.rs +++ b/tests/tests/steward/test_state_methods.rs @@ -58,7 +58,7 @@ fn test_compute_scores() { } assert!(state .progress - .is_complete(state.num_pool_validators as usize) + .is_complete(state.num_pool_validators) .unwrap()); assert!(state.scores[0..3] == [1_000_000_000, 0, 950_000_000]); assert!(state.sorted_score_indices[0..3] == [0, 2, 1]); diff --git a/tests/tests/steward/test_state_transitions.rs b/tests/tests/steward/test_state_transitions.rs index d2ab9486..75e3eea8 100644 --- a/tests/tests/steward/test_state_transitions.rs +++ b/tests/tests/steward/test_state_transitions.rs @@ -35,7 +35,7 @@ pub fn test_compute_scores_to_compute_delegations() { assert!(state .progress - .is_complete(state.num_pool_validators as usize) + .is_complete(state.num_pool_validators) .unwrap()); let res = state.transition(clock, parameters, epoch_schedule); @@ -261,7 +261,7 @@ pub fn test_compute_instant_unstake_to_rebalance() { .unwrap(); assert!(state .progress - .is_complete(state.num_pool_validators as usize) + .is_complete(state.num_pool_validators) .unwrap()); let res = state.transition(clock, parameters, epoch_schedule); From e68d25bb3601b2efbd14624d81ea57c1f29bacec Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Mon, 17 Jun 2024 11:01:15 -0400 Subject: [PATCH 09/16] updates for merging to master --- .../instructions/close_steward_accounts.rs | 39 ----------- .../steward/src/instructions/compute_score.rs | 2 +- programs/steward/src/instructions/mod.rs | 4 -- .../steward/src/instructions/realloc_state.rs | 2 +- .../src/instructions/reset_steward_state.rs | 66 ------------------- programs/steward/src/lib.rs | 14 ---- programs/steward/src/state/steward_state.rs | 22 +++---- 7 files changed, 12 insertions(+), 137 deletions(-) delete mode 100644 programs/steward/src/instructions/close_steward_accounts.rs delete mode 100644 programs/steward/src/instructions/reset_steward_state.rs diff --git a/programs/steward/src/instructions/close_steward_accounts.rs b/programs/steward/src/instructions/close_steward_accounts.rs deleted file mode 100644 index bbf00776..00000000 --- a/programs/steward/src/instructions/close_steward_accounts.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::{ - state::{Config, StewardStateAccount}, - utils::get_config_authority, - Staker, -}; -use anchor_lang::prelude::*; - -#[derive(Accounts)] -pub struct CloseStewardAccounts<'info> { - pub config: AccountLoader<'info, Config>, - - #[account( - mut, - close = authority, - seeds = [Staker::SEED, config.key().as_ref()], - bump, - )] - staker: Account<'info, Staker>, - - #[account( - mut, - close = authority, - seeds = [StewardStateAccount::SEED, config.key().as_ref()], - bump - )] - pub state_account: AccountLoader<'info, StewardStateAccount>, - - #[account(mut, address = get_config_authority(&config)?)] - pub authority: Signer<'info>, -} - -/* - Closes Steward PDA accounts associated with a given Config (StewardStateAccount, and Staker). - Config is not closed as it is a Keypair, so lamports can simply be withdrawn. - Reclaims lamports to authority -*/ -pub const fn handler(_ctx: Context) -> Result<()> { - Ok(()) -} diff --git a/programs/steward/src/instructions/compute_score.rs b/programs/steward/src/instructions/compute_score.rs index 79b6b359..81125003 100644 --- a/programs/steward/src/instructions/compute_score.rs +++ b/programs/steward/src/instructions/compute_score.rs @@ -20,7 +20,7 @@ pub struct ComputeScore<'info> { pub validator_history: AccountLoader<'info, ValidatorHistory>, - /// CHECK: TODO + /// CHECK: Account owner checked, account type checked in get_validator_stake_info_at_index #[account(owner = spl_stake_pool::id())] pub validator_list: AccountInfo<'info>, diff --git a/programs/steward/src/instructions/mod.rs b/programs/steward/src/instructions/mod.rs index ec849977..4ca9674e 100644 --- a/programs/steward/src/instructions/mod.rs +++ b/programs/steward/src/instructions/mod.rs @@ -2,7 +2,6 @@ pub mod add_validator_to_blacklist; pub mod auto_add_validator_to_pool; pub mod auto_remove_validator_from_pool; -pub mod close_steward_accounts; pub mod compute_delegations; pub mod compute_instant_unstake; pub mod compute_score; @@ -13,7 +12,6 @@ pub mod pause_steward; pub mod realloc_state; pub mod rebalance; pub mod remove_validator_from_blacklist; -pub mod reset_steward_state; pub mod resume_steward; pub mod set_new_authority; pub mod spl_passthrough; @@ -22,7 +20,6 @@ pub mod update_parameters; pub use add_validator_to_blacklist::*; pub use auto_add_validator_to_pool::*; pub use auto_remove_validator_from_pool::*; -pub use close_steward_accounts::*; pub use compute_delegations::*; pub use compute_instant_unstake::*; pub use compute_score::*; @@ -33,7 +30,6 @@ pub use pause_steward::*; pub use realloc_state::*; pub use rebalance::*; pub use remove_validator_from_blacklist::*; -pub use reset_steward_state::*; pub use resume_steward::*; pub use set_new_authority::*; pub use spl_passthrough::*; diff --git a/programs/steward/src/instructions/realloc_state.rs b/programs/steward/src/instructions/realloc_state.rs index 2d706ca9..fadaf40c 100644 --- a/programs/steward/src/instructions/realloc_state.rs +++ b/programs/steward/src/instructions/realloc_state.rs @@ -43,7 +43,7 @@ pub struct ReallocState<'info> { pub config: AccountLoader<'info, Config>, - /// CHECK: TODO + /// CHECK: TODO add validator_list address to config #[account( owner = spl_stake_pool::ID, )] diff --git a/programs/steward/src/instructions/reset_steward_state.rs b/programs/steward/src/instructions/reset_steward_state.rs deleted file mode 100644 index 5a24699f..00000000 --- a/programs/steward/src/instructions/reset_steward_state.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::{ - constants::{MAX_VALIDATORS, SORTED_INDEX_DEFAULT}, - errors::StewardError, - state::{Config, StewardStateAccount}, - utils::{deserialize_stake_pool, get_config_authority, get_stake_pool_address, StakePool}, - BitMask, Delegation, StewardStateEnum, -}; -use anchor_lang::prelude::*; -use spl_stake_pool::state::ValidatorListHeader; - -#[derive(Accounts)] -pub struct ResetStewardState<'info> { - #[account( - mut, - seeds = [StewardStateAccount::SEED, config.key().as_ref()], - bump - )] - pub state_account: AccountLoader<'info, StewardStateAccount>, - - pub config: AccountLoader<'info, Config>, - - /// CHECK: TODO - #[account(address = get_stake_pool_address(&config)?)] - pub stake_pool: AccountInfo<'info>, - - /// CHECK: TODO - #[account(address = deserialize_stake_pool(&stake_pool)?.validator_list)] - pub validator_list: AccountInfo<'info>, - - #[account(mut, address = get_config_authority(&config)?)] - pub authority: Signer<'info>, -} - -/* - Resets steward state account to its initial state. -*/ -pub fn handler(ctx: Context) -> Result<()> { - let mut state_account = ctx.accounts.state_account.load_mut()?; - - let clock = Clock::get()?; - state_account.is_initialized = true.into(); - state_account.bump = ctx.bumps.state_account; - - let config = ctx.accounts.config.load()?; - let validator_list_data = &mut ctx.accounts.validator_list.try_borrow_mut_data()?; - let (_, validator_list) = ValidatorListHeader::deserialize_vec(validator_list_data)?; - - state_account.state.state_tag = StewardStateEnum::ComputeScores; - state_account.state.num_pool_validators = validator_list.len() as u64; - state_account.state.scores = [0; MAX_VALIDATORS]; - state_account.state.sorted_score_indices = [SORTED_INDEX_DEFAULT; MAX_VALIDATORS]; - state_account.state.yield_scores = [0; MAX_VALIDATORS]; - state_account.state.sorted_yield_score_indices = [SORTED_INDEX_DEFAULT; MAX_VALIDATORS]; - state_account.state.progress = BitMask::default(); - state_account.state.current_epoch = clock.epoch; - state_account.state.next_cycle_epoch = clock - .epoch - .checked_add(config.parameters.num_epochs_between_scoring) - .ok_or(StewardError::ArithmeticError)?; - state_account.state.delegations = [Delegation::default(); MAX_VALIDATORS]; - state_account.state.rebalance_completed = false.into(); - state_account.state.instant_unstake = BitMask::default(); - state_account.state.start_computing_scores_slot = clock.slot; - state_account.state._padding0 = [0; 6 + MAX_VALIDATORS * 8]; - Ok(()) -} diff --git a/programs/steward/src/lib.rs b/programs/steward/src/lib.rs index bed7bea1..48194f37 100644 --- a/programs/steward/src/lib.rs +++ b/programs/steward/src/lib.rs @@ -161,20 +161,6 @@ pub mod steward { instructions::update_parameters::handler(ctx, &update_parameters_args) } - /* TEMPORARY ADMIN INSTRUCTIONS for testing */ - - /// Resets steward state account to its initial state. - pub fn reset_steward_state(ctx: Context) -> Result<()> { - instructions::reset_steward_state::handler(ctx) - } - - /// Closes Steward PDA accounts associated with a given Config (StewardStateAccount, and Staker). - /// Config is not closed as it is a Keypair, so lamports can simply be withdrawn. - /// Reclaims lamports to authority - pub fn close_steward_accounts(ctx: Context) -> Result<()> { - instructions::close_steward_accounts::handler(ctx) - } - /* Passthrough instructions to spl-stake-pool, where the signer is Staker. Must be invoked by `config.authority` */ pub fn set_staker(ctx: Context) -> Result<()> { diff --git a/programs/steward/src/state/steward_state.rs b/programs/steward/src/state/steward_state.rs index bd7b52de..74c4389c 100644 --- a/programs/steward/src/state/steward_state.rs +++ b/programs/steward/src/state/steward_state.rs @@ -444,24 +444,22 @@ impl StewardState { let yield_score_index = self .sorted_yield_score_indices .iter() - .position(|&i| i == index as u16); + .position(|&i| i == index as u16) + .ok_or(StewardError::ValidatorIndexOutOfBounds)?; let score_index = self .sorted_score_indices .iter() - .position(|&i| i == index as u16); + .position(|&i| i == index as u16) + .ok_or(StewardError::ValidatorIndexOutOfBounds)?; - if let Some(yield_score_index) = yield_score_index { - for i in yield_score_index..num_pool_validators { - let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; - self.sorted_yield_score_indices[i] = self.sorted_yield_score_indices[next_i]; - } + for i in yield_score_index..num_pool_validators { + let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; + self.sorted_yield_score_indices[i] = self.sorted_yield_score_indices[next_i]; } - if let Some(score_index) = score_index { - for i in score_index..num_pool_validators { - let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; - self.sorted_score_indices[i] = self.sorted_score_indices[next_i]; - } + for i in score_index..num_pool_validators { + let next_i = i.checked_add(1).ok_or(StewardError::ArithmeticError)?; + self.sorted_score_indices[i] = self.sorted_score_indices[next_i]; } for i in 0..num_pool_validators { From 5b27ef62acab56b29388e377ebd80ce856944d7e Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Mon, 17 Jun 2024 11:03:45 -0400 Subject: [PATCH 10/16] Lints --- programs/steward/idl/steward.json | 76 +------------------ .../auto_remove_validator_from_pool.rs | 2 +- .../src/instructions/initialize_config.rs | 5 +- .../src/instructions/spl_passthrough.rs | 2 +- programs/steward/src/lib.rs | 2 +- programs/steward/src/state/steward_state.rs | 3 +- 6 files changed, 6 insertions(+), 84 deletions(-) diff --git a/programs/steward/idl/steward.json b/programs/steward/idl/steward.json index 20cfff35..9ea51b4a 100644 --- a/programs/steward/idl/steward.json +++ b/programs/steward/idl/steward.json @@ -1,5 +1,5 @@ { - "address": "sssh4zkKhX8jXTNQz1xDHyGpygzgu2UhcRcUvZihBjP", + "address": "Stewardf95sJbmtcZsyagb2dg4Mo8eVQho8gpECvLx8", "metadata": { "name": "steward", "version": "0.1.0", @@ -285,43 +285,6 @@ } ] }, - { - "name": "close_steward_accounts", - "docs": [ - "Closes Steward PDA accounts associated with a given Config (StewardStateAccount, and Staker).", - "Config is not closed as it is a Keypair, so lamports can simply be withdrawn.", - "Reclaims lamports to authority" - ], - "discriminator": [ - 172, - 171, - 212, - 186, - 90, - 10, - 181, - 24 - ], - "accounts": [ - { - "name": "config" - }, - { - "name": "staker", - "writable": true - }, - { - "name": "state_account", - "writable": true - }, - { - "name": "authority", - "writable": true, - "signer": true - } - ], - "args": [] - }, { "name": "compute_delegations", "docs": [ @@ -1182,43 +1145,6 @@ } ] }, - { - "name": "reset_steward_state", - "docs": [ - "Resets steward state account to its initial state." - ], - "discriminator": [ - 84, - 248, - 158, - 46, - 200, - 205, - 234, - 86 - ], - "accounts": [ - { - "name": "state_account", - "writable": true - }, - { - "name": "config" - }, - { - "name": "stake_pool" - }, - { - "name": "validator_list" - }, - { - "name": "authority", - "writable": true, - "signer": true - } - ], - "args": [] - }, { "name": "resume_steward", "discriminator": [ 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 bec46b49..15b8b67d 100644 --- a/programs/steward/src/instructions/auto_remove_validator_from_pool.rs +++ b/programs/steward/src/instructions/auto_remove_validator_from_pool.rs @@ -4,7 +4,7 @@ use crate::constants::STAKE_POOL_WITHDRAW_SEED; use crate::errors::StewardError; use crate::state::{Config, Staker}; use crate::utils::{ - deserialize_stake_pool, get_stake_pool_address, get_validator_stake_info_at_index, StakePool, + deserialize_stake_pool, get_stake_pool_address, get_validator_stake_info_at_index, }; use crate::StewardStateAccount; use anchor_lang::solana_program::{program::invoke_signed, stake, sysvar, vote}; diff --git a/programs/steward/src/instructions/initialize_config.rs b/programs/steward/src/instructions/initialize_config.rs index 3311a63e..12a5ccaa 100644 --- a/programs/steward/src/instructions/initialize_config.rs +++ b/programs/steward/src/instructions/initialize_config.rs @@ -1,9 +1,6 @@ use anchor_lang::{prelude::*, solana_program::program::invoke}; -use crate::{ - utils::{deserialize_stake_pool, StakePool}, - Config, Staker, UpdateParametersArgs, -}; +use crate::{utils::deserialize_stake_pool, Config, Staker, UpdateParametersArgs}; #[derive(Accounts)] pub struct InitializeConfig<'info> { diff --git a/programs/steward/src/instructions/spl_passthrough.rs b/programs/steward/src/instructions/spl_passthrough.rs index db239852..ed4224a8 100644 --- a/programs/steward/src/instructions/spl_passthrough.rs +++ b/programs/steward/src/instructions/spl_passthrough.rs @@ -9,7 +9,7 @@ use crate::errors::StewardError; use crate::state::{Config, Staker}; use crate::utils::{ deserialize_stake_pool, get_config_authority, get_stake_pool_address, - get_validator_stake_info_at_index, StakePool, ValidatorList, + get_validator_stake_info_at_index, }; use crate::StewardStateAccount; use anchor_lang::prelude::*; diff --git a/programs/steward/src/lib.rs b/programs/steward/src/lib.rs index 48194f37..493e622e 100644 --- a/programs/steward/src/lib.rs +++ b/programs/steward/src/lib.rs @@ -16,7 +16,7 @@ pub mod utils; pub use state::*; -declare_id!("sssh4zkKhX8jXTNQz1xDHyGpygzgu2UhcRcUvZihBjP"); +declare_id!("Stewardf95sJbmtcZsyagb2dg4Mo8eVQho8gpECvLx8"); /* This program manages the selection of validators and delegation of stake for a SPL Stake Pool. diff --git a/programs/steward/src/state/steward_state.rs b/programs/steward/src/state/steward_state.rs index 74c4389c..e141a9ed 100644 --- a/programs/steward/src/state/steward_state.rs +++ b/programs/steward/src/state/steward_state.rs @@ -1,5 +1,4 @@ use borsh::BorshSerialize; -use core::num; use std::fmt::Display; use crate::{ @@ -22,7 +21,7 @@ use spl_stake_pool::big_vec::BigVec; use validator_history::{ClusterHistory, ValidatorHistory}; // Tests will fail here - comment out msg! to pass -fn invalid_state_error(expected: String, actual: String) -> Error { +fn invalid_state_error(_expected: String, _actual: String) -> Error { // msg!("Invalid state. Expected {}, Actual {}", expected, actual); StewardError::InvalidState.into() } From 8688a49ecc081c78578ae92c30a4600992f90278 Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Mon, 17 Jun 2024 11:04:06 -0400 Subject: [PATCH 11/16] Old address --- Anchor.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Anchor.toml b/Anchor.toml index 970e14b9..c99a48ce 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -3,7 +3,7 @@ resolution = false skip-lint = false [programs.localnet] validator_history = "HistoryJTGbKQD2mRgLZ3XhqHnN811Qpez8X9kCcGHoa" -steward = "sssh4zkKhX8jXTNQz1xDHyGpygzgu2UhcRcUvZihBjP" +steward = "Stewardf95sJbmtcZsyagb2dg4Mo8eVQho8gpECvLx8" [workspace] members = [ From 6ebbd6d95a15c46f997d8d03c64805fd69b13e91 Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Mon, 17 Jun 2024 11:19:40 -0400 Subject: [PATCH 12/16] clippies --- tests/src/spl_stake_pool_cli.rs | 2 ++ tests/tests/steward/test_algorithms.rs | 2 +- tests/tests/steward/test_parameters.rs | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/src/spl_stake_pool_cli.rs b/tests/src/spl_stake_pool_cli.rs index 930989b8..c9643c5a 100644 --- a/tests/src/spl_stake_pool_cli.rs +++ b/tests/src/spl_stake_pool_cli.rs @@ -30,6 +30,8 @@ macro_rules! unique_signers { } type Error = Box; + +#[allow(dead_code)] pub struct CliConfig { pub manager: Keypair, pub staker: Keypair, diff --git a/tests/tests/steward/test_algorithms.rs b/tests/tests/steward/test_algorithms.rs index c5c5ba6e..83e0b464 100644 --- a/tests/tests/steward/test_algorithms.rs +++ b/tests/tests/steward/test_algorithms.rs @@ -1028,7 +1028,7 @@ fn test_increase_stake_calculation() { &state, 0, u64::from(validator_list[0].active_stake_lamports) - minimum_delegation, - 2000 * LAMPORTS_PER_SOL - (state.num_pool_validators as u64 * minimum_delegation), + 2000 * LAMPORTS_PER_SOL - (state.num_pool_validators * minimum_delegation), &validator_list_bigvec, 1002 * LAMPORTS_PER_SOL, minimum_delegation, diff --git a/tests/tests/steward/test_parameters.rs b/tests/tests/steward/test_parameters.rs index 4bfe8d6f..591dce04 100644 --- a/tests/tests/steward/test_parameters.rs +++ b/tests/tests/steward/test_parameters.rs @@ -825,7 +825,7 @@ fn test_compute_score_slot_range() { // Cannot be below min_slots_per_epoch let new_value = min_slots_per_epoch - 1; let update_parameters = UpdateParametersArgs { - compute_score_slot_range: Some(new_value as u64), + compute_score_slot_range: Some(new_value), ..UpdateParametersArgs::default() }; let result = _test_parameter(&update_parameters, None, Some(slots_per_epoch), None); @@ -845,7 +845,7 @@ fn test_compute_score_slot_range() { { // In range - let new_value = COMPUTE_SCORE_SLOT_RANGE_MIN as u64 + 1; + let new_value = COMPUTE_SCORE_SLOT_RANGE_MIN + 1; let update_parameters = UpdateParametersArgs { compute_score_slot_range: Some(new_value), ..UpdateParametersArgs::default() From 31107757641a1c718693d50ec1da0159449cff51 Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Wed, 19 Jun 2024 15:37:06 -0400 Subject: [PATCH 13/16] PR feedback --- programs/steward/src/constants.rs | 4 ++-- programs/steward/src/instructions/compute_instant_unstake.rs | 2 +- programs/steward/src/state/parameters.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/programs/steward/src/constants.rs b/programs/steward/src/constants.rs index 5edfca33..1bacb9c5 100644 --- a/programs/steward/src/constants.rs +++ b/programs/steward/src/constants.rs @@ -12,6 +12,6 @@ pub const NUM_EPOCHS_BETWEEN_SCORING_MAX: u64 = 100; // Cannot score validators in under 100 slots, to submit 1 instruction per validator pub const COMPUTE_SCORE_SLOT_RANGE_MIN: u64 = 100; #[cfg(feature = "mainnet-beta")] -pub const VALIDATOR_HISTORY_FIRST_RELIABLE_EPOCH: usize = 520; +pub const VALIDATOR_HISTORY_FIRST_RELIABLE_EPOCH: u64 = 520; #[cfg(not(feature = "mainnet-beta"))] -pub const VALIDATOR_HISTORY_FIRST_RELIABLE_EPOCH: usize = 0; +pub const VALIDATOR_HISTORY_FIRST_RELIABLE_EPOCH: u64 = 0; diff --git a/programs/steward/src/instructions/compute_instant_unstake.rs b/programs/steward/src/instructions/compute_instant_unstake.rs index a5a294ac..9bcd64f4 100644 --- a/programs/steward/src/instructions/compute_instant_unstake.rs +++ b/programs/steward/src/instructions/compute_instant_unstake.rs @@ -18,7 +18,7 @@ pub struct ComputeInstantUnstake<'info> { pub validator_history: AccountLoader<'info, ValidatorHistory>, - /// CHECK: TODO + /// CHECK: TODO add validator list to config #[account(owner = spl_stake_pool::id())] pub validator_list: AccountInfo<'info>, diff --git a/programs/steward/src/state/parameters.rs b/programs/steward/src/state/parameters.rs index f7c233c7..eb4db0a8 100644 --- a/programs/steward/src/state/parameters.rs +++ b/programs/steward/src/state/parameters.rs @@ -327,11 +327,11 @@ impl Parameters { /// Validate reasonable bounds on parameters pub fn validate(&self, current_epoch: u64, slots_per_epoch: u64) -> Result<()> { // Cannot evaluate epochs before VALIDATOR_HISTORY_FIRST_RELIABLE_EPOCH or beyond the CircBuf length - let window_max = (current_epoch as usize) + let window_max = current_epoch .checked_sub(VALIDATOR_HISTORY_FIRST_RELIABLE_EPOCH) .ok_or(StewardError::ArithmeticError)? .min(validator_history::ValidatorHistory::MAX_ITEMS - 1); - let window_max = cast_epoch(window_max as u64)?; + let window_max = cast_epoch(window_max)?; if self.mev_commission_range > window_max { return Err(StewardError::InvalidParameterValue.into()); From 2d6b55d1d17eaeb98cc59e5935df35cb51ebf6fd Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Wed, 19 Jun 2024 15:48:19 -0400 Subject: [PATCH 14/16] Fix --- programs/steward/src/state/parameters.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/steward/src/state/parameters.rs b/programs/steward/src/state/parameters.rs index eb4db0a8..f1ccdb6c 100644 --- a/programs/steward/src/state/parameters.rs +++ b/programs/steward/src/state/parameters.rs @@ -330,7 +330,7 @@ impl Parameters { let window_max = current_epoch .checked_sub(VALIDATOR_HISTORY_FIRST_RELIABLE_EPOCH) .ok_or(StewardError::ArithmeticError)? - .min(validator_history::ValidatorHistory::MAX_ITEMS - 1); + .min(validator_history::ValidatorHistory::MAX_ITEMS as usize - 1); let window_max = cast_epoch(window_max)?; if self.mev_commission_range > window_max { From 83d645b01a24bb4d13358614a8a2a6fcefb75c2f Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Wed, 19 Jun 2024 15:52:56 -0400 Subject: [PATCH 15/16] Fix --- programs/steward/src/state/parameters.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/steward/src/state/parameters.rs b/programs/steward/src/state/parameters.rs index f1ccdb6c..1f287358 100644 --- a/programs/steward/src/state/parameters.rs +++ b/programs/steward/src/state/parameters.rs @@ -330,7 +330,7 @@ impl Parameters { let window_max = current_epoch .checked_sub(VALIDATOR_HISTORY_FIRST_RELIABLE_EPOCH) .ok_or(StewardError::ArithmeticError)? - .min(validator_history::ValidatorHistory::MAX_ITEMS as usize - 1); + .min(validator_history::ValidatorHistory::MAX_ITEMS as u64 - 1); let window_max = cast_epoch(window_max)?; if self.mev_commission_range > window_max { From 34f490e78f2240b8164981d4509289e42e6f4e0c Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Wed, 19 Jun 2024 19:03:56 -0400 Subject: [PATCH 16/16] curve25519-dalek crate with security warning, not updated in upstream 1.18. remove after solana updates --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index fcbf6ba8..0cf0cc76 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: uses: baptiste0928/cargo-install@v3 with: crate: cargo-audit - - run: cargo audit --ignore RUSTSEC-2022-0093 --ignore RUSTSEC-2023-0065 --ignore RUSTSEC-2024-0336 + - run: cargo audit --ignore RUSTSEC-2022-0093 --ignore RUSTSEC-2023-0065 --ignore RUSTSEC-2024-0336 --ignore RUSTSEC-2024-0344 lint: name: lint