From 46b1f9a3d5ebca4a32292c215fbd90989b825399 Mon Sep 17 00:00:00 2001 From: Kevin Heavey Date: Sun, 19 Jan 2025 13:09:55 +0000 Subject: [PATCH] extract vote-interface crate (#4482) * extract vote-interface crate * remove thiserror * fmt * update digests * update digests * update digest * trigger ci * trigger ci --- Cargo.lock | 31 +++++ Cargo.toml | 2 + core/src/consensus.rs | 2 +- core/src/consensus/tower1_14_11.rs | 2 +- core/src/consensus/tower1_7_14.rs | 2 +- programs/sbf/Cargo.lock | 23 ++++ programs/vote/src/vote_state/mod.rs | 2 +- sdk/program/Cargo.toml | 1 + sdk/program/src/lib.rs | 3 +- sdk/program/src/vote/error.rs | 112 ------------------ sdk/vote-interface/Cargo.toml | 78 ++++++++++++ .../src}/authorized_voters.rs | 16 ++- sdk/vote-interface/src/error.rs | 111 +++++++++++++++++ .../src}/instruction.rs | 71 +++++++---- .../vote/mod.rs => vote-interface/src/lib.rs} | 2 + .../vote => vote-interface/src}/state/mod.rs | 108 ++++++++++------- .../src}/state/vote_state_0_23_5.rs | 8 +- .../src}/state/vote_state_1_14_11.rs | 9 +- .../src}/state/vote_state_deserialize.rs | 17 +-- .../src}/state/vote_state_versions.rs | 20 +++- svm/examples/Cargo.lock | 23 ++++ 21 files changed, 433 insertions(+), 210 deletions(-) delete mode 100644 sdk/program/src/vote/error.rs create mode 100644 sdk/vote-interface/Cargo.toml rename sdk/{program/src/vote => vote-interface/src}/authorized_voters.rs (91%) create mode 100644 sdk/vote-interface/src/error.rs rename sdk/{program/src/vote => vote-interface/src}/instruction.rs (91%) rename sdk/{program/src/vote/mod.rs => vote-interface/src/lib.rs} (70%) rename sdk/{program/src/vote => vote-interface/src}/state/mod.rs (95%) rename sdk/{program/src/vote => vote-interface/src}/state/vote_state_0_23_5.rs (93%) rename sdk/{program/src/vote => vote-interface/src}/state/vote_state_1_14_11.rs (93%) rename sdk/{program/src/vote => vote-interface/src}/state/vote_state_deserialize.rs (92%) rename sdk/{program/src/vote => vote-interface/src}/state/vote_state_versions.rs (87%) diff --git a/Cargo.lock b/Cargo.lock index f9d5338e616747..b018f55fc1a365 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8354,6 +8354,7 @@ dependencies = [ "solana-system-interface", "solana-sysvar", "solana-sysvar-id", + "solana-vote-interface", "thiserror 2.0.11", "wasm-bindgen", ] @@ -10362,6 +10363,36 @@ dependencies = [ "thiserror 2.0.11", ] +[[package]] +name = "solana-vote-interface" +version = "2.2.0" +dependencies = [ + "arbitrary", + "bincode", + "itertools 0.12.1", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "solana-clock", + "solana-decode-error", + "solana-epoch-schedule", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-hash", + "solana-instruction", + "solana-logger", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-serde-varint", + "solana-serialize-utils", + "solana-short-vec", + "solana-system-interface", + "solana-vote-interface", +] + [[package]] name = "solana-vote-program" version = "2.2.0" diff --git a/Cargo.toml b/Cargo.toml index 1dead9e61e8869..686eb2a7decc3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -198,6 +198,7 @@ members = [ "sdk/transaction-context", "sdk/transaction-error", "sdk/validator-exit", + "sdk/vote-interface", "send-transaction-service", "stake-accounts", "storage-bigtable", @@ -626,6 +627,7 @@ solana-udp-client = { path = "udp-client", version = "=2.2.0" } solana-validator-exit = { path = "sdk/validator-exit", version = "=2.2.0" } solana-version = { path = "version", version = "=2.2.0" } solana-vote = { path = "vote", version = "=2.2.0" } +solana-vote-interface = { path = "sdk/vote-interface", version = "=2.2.0" } solana-vote-program = { path = "programs/vote", version = "=2.2.0", default-features = false } solana-wen-restart = { path = "wen-restart", version = "=2.2.0" } solana-zk-elgamal-proof-program = { path = "programs/zk-elgamal-proof", version = "=2.2.0" } diff --git a/core/src/consensus.rs b/core/src/consensus.rs index d8065db6986c05..1a4712e674c6a9 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -239,7 +239,7 @@ pub(crate) enum BlockhashStatus { #[cfg_attr( feature = "frozen-abi", derive(AbiExample), - frozen_abi(digest = "9ziHa1vA7WG5RCvXiE3g1f2qjSTNa47FB7e2czo7en7a") + frozen_abi(digest = "FcHteDgmzjrtyFD9D6EQ2hY9FRz42gs2S7eJ1DyHWP7s") )] #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Tower { diff --git a/core/src/consensus/tower1_14_11.rs b/core/src/consensus/tower1_14_11.rs index 2c90bd1fd62926..2b3a9ccd9eb4e0 100644 --- a/core/src/consensus/tower1_14_11.rs +++ b/core/src/consensus/tower1_14_11.rs @@ -9,7 +9,7 @@ use { #[cfg_attr( feature = "frozen-abi", derive(AbiExample), - frozen_abi(digest = "6VhLW7DSHNzrcswtxbNo4cb47oGrKLcKuDmCWVpUMLLM") + frozen_abi(digest = "6Z9SDTJAihx2mVbdcifTvNN96keT4DyJ9BKGazgVUkzD") )] #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Tower1_14_11 { diff --git a/core/src/consensus/tower1_7_14.rs b/core/src/consensus/tower1_7_14.rs index e792d510587abe..e4e192af9e6f2a 100644 --- a/core/src/consensus/tower1_7_14.rs +++ b/core/src/consensus/tower1_7_14.rs @@ -11,7 +11,7 @@ use { #[cfg_attr( feature = "frozen-abi", derive(AbiExample), - frozen_abi(digest = "5bwSGBqA1BVmgNtnTenfYtEt123cciEzpfqt6bUX1dJo") + frozen_abi(digest = "CL1BKbtF3yMkpPnVi8sGnveybhnzf16nBqCqC8TKVNX") )] #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Tower1_7_14 { diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 62aca34a99e6df..088475fa4be053 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -6581,6 +6581,7 @@ dependencies = [ "solana-system-interface", "solana-sysvar", "solana-sysvar-id", + "solana-vote-interface", "thiserror 2.0.11", "wasm-bindgen", ] @@ -8568,6 +8569,28 @@ dependencies = [ "thiserror 2.0.11", ] +[[package]] +name = "solana-vote-interface" +version = "2.2.0" +dependencies = [ + "bincode", + "num-derive", + "num-traits", + "serde", + "serde_derive", + "solana-clock", + "solana-decode-error", + "solana-hash", + "solana-instruction", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-serde-varint", + "solana-serialize-utils", + "solana-short-vec", + "solana-system-interface", +] + [[package]] name = "solana-vote-program" version = "2.2.0" diff --git a/programs/vote/src/vote_state/mod.rs b/programs/vote/src/vote_state/mod.rs index cdc7398b5f9d5e..c53feb1bd45f68 100644 --- a/programs/vote/src/vote_state/mod.rs +++ b/programs/vote/src/vote_state/mod.rs @@ -27,7 +27,7 @@ use { #[cfg_attr( feature = "frozen-abi", derive(AbiExample, AbiEnumVisitor), - frozen_abi(digest = "3dbyMxwfCN43orGKa5YiyY1EqN2K97pTicNhKYTZSUQH") + frozen_abi(digest = "4BdRo6We16yDbjz69H1oFq6C4nXUZKDchZR76TvvGmBi") )] #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub enum VoteTransaction { diff --git a/sdk/program/Cargo.toml b/sdk/program/Cargo.toml index 6388b976538855..0362a149c82a28 100644 --- a/sdk/program/Cargo.toml +++ b/sdk/program/Cargo.toml @@ -79,6 +79,7 @@ solana-stable-layout = { workspace = true } solana-system-interface = { workspace = true, features = ["bincode"] } solana-sysvar = { workspace = true, features = ["bincode", "bytemuck"] } solana-sysvar-id = { workspace = true } +solana-vote-interface = { workspace = true, features = ["bincode"] } thiserror = { workspace = true } # This is currently needed to build on-chain programs reliably. diff --git a/sdk/program/src/lib.rs b/sdk/program/src/lib.rs index 6a454b8922ebda..43025220096808 100644 --- a/sdk/program/src/lib.rs +++ b/sdk/program/src/lib.rs @@ -502,7 +502,6 @@ pub mod syscalls; pub mod system_instruction; pub mod system_program; pub mod sysvar; -pub mod vote; pub mod wasm; #[deprecated(since = "2.2.0", note = "Use `solana-big-mod-exp` crate instead")] @@ -549,6 +548,8 @@ pub use solana_short_vec as short_vec; pub use solana_stable_layout as stable_layout; #[cfg(not(target_os = "solana"))] pub use solana_sysvar::program_stubs; +#[deprecated(since = "2.2.0", note = "Use `solana-vote-interface` crate instead")] +pub use solana_vote_interface as vote; #[cfg(target_arch = "wasm32")] pub use wasm_bindgen::prelude::wasm_bindgen; pub use { diff --git a/sdk/program/src/vote/error.rs b/sdk/program/src/vote/error.rs deleted file mode 100644 index 1883186f6e2b65..00000000000000 --- a/sdk/program/src/vote/error.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! Vote program errors - -use { - num_derive::{FromPrimitive, ToPrimitive}, - solana_decode_error::DecodeError, - thiserror::Error, -}; - -/// Reasons the vote might have had an error -#[derive(Error, Debug, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)] -pub enum VoteError { - #[error("vote already recorded or not in slot hashes history")] - VoteTooOld, - - #[error("vote slots do not match bank history")] - SlotsMismatch, - - #[error("vote hash does not match bank hash")] - SlotHashMismatch, - - #[error("vote has no slots, invalid")] - EmptySlots, - - #[error("vote timestamp not recent")] - TimestampTooOld, - - #[error("authorized voter has already been changed this epoch")] - TooSoonToReauthorize, - - // TODO: figure out how to migrate these new errors - #[error("Old state had vote which should not have been popped off by vote in new state")] - LockoutConflict, - - #[error("Proposed state had earlier slot which should have been popped off by later vote")] - NewVoteStateLockoutMismatch, - - #[error("Vote slots are not ordered")] - SlotsNotOrdered, - - #[error("Confirmations are not ordered")] - ConfirmationsNotOrdered, - - #[error("Zero confirmations")] - ZeroConfirmations, - - #[error("Confirmation exceeds limit")] - ConfirmationTooLarge, - - #[error("Root rolled back")] - RootRollBack, - - #[error("Confirmations for same vote were smaller in new proposed state")] - ConfirmationRollBack, - - #[error("New state contained a vote slot smaller than the root")] - SlotSmallerThanRoot, - - #[error("New state contained too many votes")] - TooManyVotes, - - #[error("every slot in the vote was older than the SlotHashes history")] - VotesTooOldAllFiltered, - - #[error("Proposed root is not in slot hashes")] - RootOnDifferentFork, - - #[error("Cannot close vote account unless it stopped voting at least one full epoch ago")] - ActiveVoteAccountClose, - - #[error("Cannot update commission at this point in the epoch")] - CommissionUpdateTooLate, - - #[error("Assertion failed")] - AssertionFailed, -} - -impl DecodeError for VoteError { - fn type_of() -> &'static str { - "VoteError" - } -} - -#[cfg(test)] -mod tests { - use {super::*, crate::instruction::InstructionError}; - - #[test] - fn test_custom_error_decode() { - use num_traits::FromPrimitive; - fn pretty_err(err: InstructionError) -> String - where - T: 'static + std::error::Error + DecodeError + FromPrimitive, - { - if let InstructionError::Custom(code) = err { - let specific_error: T = T::decode_custom_error_to_enum(code).unwrap(); - format!( - "{:?}: {}::{:?} - {}", - err, - T::type_of(), - specific_error, - specific_error, - ) - } else { - "".to_string() - } - } - assert_eq!( - "Custom(0): VoteError::VoteTooOld - vote already recorded or not in slot hashes history", - pretty_err::(VoteError::VoteTooOld.into()) - ) - } -} diff --git a/sdk/vote-interface/Cargo.toml b/sdk/vote-interface/Cargo.toml new file mode 100644 index 00000000000000..917d71315e834a --- /dev/null +++ b/sdk/vote-interface/Cargo.toml @@ -0,0 +1,78 @@ +[package] +name = "solana-vote-interface" +description = "Solana vote interface." +documentation = "https://docs.rs/solana-vote-interface" +version = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[dependencies] +bincode = { workspace = true, optional = true } +num-derive = { workspace = true } +num-traits = { workspace = true } +serde = { workspace = true, optional = true } +serde_derive = { workspace = true, optional = true } +solana-clock = { workspace = true } +solana-decode-error = { workspace = true } +solana-frozen-abi = { workspace = true, features = [ + "frozen-abi", +], optional = true } +solana-frozen-abi-macro = { workspace = true, features = [ + "frozen-abi", +], optional = true } +solana-hash = { workspace = true } +solana-instruction = { workspace = true, features = ["std"] } +solana-pubkey = { workspace = true } +solana-rent = { workspace = true } +solana-sdk-ids = { workspace = true } +solana-serde-varint = { workspace = true, optional = true } +solana-serialize-utils = { workspace = true, optional = true } +solana-short-vec = { workspace = true, optional = true } +solana-system-interface = { workspace = true, features = ["bincode"], optional = true } + +[target.'cfg(target_os = "solana")'.dependencies] +solana-serialize-utils = { workspace = true } + +[dev-dependencies] +arbitrary = { workspace = true, features = ["derive"] } +itertools = { workspace = true } +rand = { workspace = true } +solana-epoch-schedule = { workspace = true } +solana-logger = { workspace = true } +solana-pubkey = { workspace = true, features = ["dev-context-only-utils"] } +solana-vote-interface = { path = ".", features = ["dev-context-only-utils"] } + +[features] +bincode = [ + "dep:bincode", + "dep:solana-serialize-utils", + "dep:solana-system-interface", + "serde" +] +dev-context-only-utils = ["bincode"] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "serde", + "solana-hash/frozen-abi", + "solana-pubkey/frozen-abi" +] +serde = [ + "dep:serde", + "dep:serde_derive", + "dep:solana-serde-varint", + "dep:solana-short-vec", + "solana-hash/serde", + "solana-pubkey/serde" +] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +all-features = true +rustdoc-args = ["--cfg=docsrs"] + +[lints] +workspace = true diff --git a/sdk/program/src/vote/authorized_voters.rs b/sdk/vote-interface/src/authorized_voters.rs similarity index 91% rename from sdk/program/src/vote/authorized_voters.rs rename to sdk/vote-interface/src/authorized_voters.rs index 69f1a8b4828b1f..4a367bc1eb121f 100644 --- a/sdk/program/src/vote/authorized_voters.rs +++ b/sdk/vote-interface/src/authorized_voters.rs @@ -1,14 +1,12 @@ #[cfg(test)] use arbitrary::Arbitrary; -use { - crate::pubkey::Pubkey, - serde_derive::{Deserialize, Serialize}, - solana_clock::Epoch, - std::collections::BTreeMap, -}; - -#[cfg_attr(feature = "frozen-abi", derive(AbiExample))] -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[cfg(feature = "serde")] +use serde_derive::{Deserialize, Serialize}; +use {solana_clock::Epoch, solana_pubkey::Pubkey, std::collections::BTreeMap}; + +#[cfg_attr(feature = "frozen-abi", derive(solana_frozen_abi_macro::AbiExample))] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, Default, PartialEq, Eq, Clone)] #[cfg_attr(test, derive(Arbitrary))] pub struct AuthorizedVoters { authorized_voters: BTreeMap, diff --git a/sdk/vote-interface/src/error.rs b/sdk/vote-interface/src/error.rs new file mode 100644 index 00000000000000..35ab73fb23f8b2 --- /dev/null +++ b/sdk/vote-interface/src/error.rs @@ -0,0 +1,111 @@ +//! Vote program errors + +use { + core::fmt, + num_derive::{FromPrimitive, ToPrimitive}, + solana_decode_error::DecodeError, +}; + +/// Reasons the vote might have had an error +#[derive(Debug, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)] +pub enum VoteError { + VoteTooOld, + SlotsMismatch, + SlotHashMismatch, + EmptySlots, + TimestampTooOld, + TooSoonToReauthorize, + // TODO: figure out how to migrate these new errors + LockoutConflict, + NewVoteStateLockoutMismatch, + SlotsNotOrdered, + ConfirmationsNotOrdered, + ZeroConfirmations, + ConfirmationTooLarge, + RootRollBack, + ConfirmationRollBack, + SlotSmallerThanRoot, + TooManyVotes, + VotesTooOldAllFiltered, + RootOnDifferentFork, + ActiveVoteAccountClose, + CommissionUpdateTooLate, + AssertionFailed, +} + +impl std::error::Error for VoteError {} + +impl fmt::Display for VoteError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(match self { + Self::VoteTooOld => "vote already recorded or not in slot hashes history", + Self::SlotsMismatch => "vote slots do not match bank history", + Self::SlotHashMismatch => "vote hash does not match bank hash", + Self::EmptySlots => "vote has no slots, invalid", + Self::TimestampTooOld => "vote timestamp not recent", + Self::TooSoonToReauthorize => "authorized voter has already been changed this epoch", + Self::LockoutConflict => { + "Old state had vote which should not have been popped off by vote in new state" + } + Self::NewVoteStateLockoutMismatch => { + "Proposed state had earlier slot which should have been popped off by later vote" + } + Self::SlotsNotOrdered => "Vote slots are not ordered", + Self::ConfirmationsNotOrdered => "Confirmations are not ordered", + Self::ZeroConfirmations => "Zero confirmations", + Self::ConfirmationTooLarge => "Confirmation exceeds limit", + Self::RootRollBack => "Root rolled back", + Self::ConfirmationRollBack => { + "Confirmations for same vote were smaller in new proposed state" + } + Self::SlotSmallerThanRoot => "New state contained a vote slot smaller than the root", + Self::TooManyVotes => "New state contained too many votes", + Self::VotesTooOldAllFiltered => { + "every slot in the vote was older than the SlotHashes history" + } + Self::RootOnDifferentFork => "Proposed root is not in slot hashes", + Self::ActiveVoteAccountClose => { + "Cannot close vote account unless it stopped voting at least one full epoch ago" + } + Self::CommissionUpdateTooLate => "Cannot update commission at this point in the epoch", + Self::AssertionFailed => "Assertion failed", + }) + } +} + +impl DecodeError for VoteError { + fn type_of() -> &'static str { + "VoteError" + } +} + +#[cfg(test)] +mod tests { + use {super::*, solana_instruction::error::InstructionError}; + + #[test] + fn test_custom_error_decode() { + use num_traits::FromPrimitive; + fn pretty_err(err: InstructionError) -> String + where + T: 'static + std::error::Error + DecodeError + FromPrimitive, + { + if let InstructionError::Custom(code) = err { + let specific_error: T = T::decode_custom_error_to_enum(code).unwrap(); + format!( + "{:?}: {}::{:?} - {}", + err, + T::type_of(), + specific_error, + specific_error, + ) + } else { + "".to_string() + } + } + assert_eq!( + "Custom(0): VoteError::VoteTooOld - vote already recorded or not in slot hashes history", + pretty_err::(VoteError::VoteTooOld.into()) + ) + } +} diff --git a/sdk/program/src/vote/instruction.rs b/sdk/vote-interface/src/instruction.rs similarity index 91% rename from sdk/program/src/vote/instruction.rs rename to sdk/vote-interface/src/instruction.rs index 2c998950dc2fe6..7a3399ad8b9bc0 100644 --- a/sdk/program/src/vote/instruction.rs +++ b/sdk/vote-interface/src/instruction.rs @@ -2,25 +2,28 @@ use { super::state::TowerSync, - crate::{ - hash::Hash, - instruction::{AccountMeta, Instruction}, - pubkey::Pubkey, - system_instruction, sysvar, - vote::{ - program::id, - state::{ - serde_compact_vote_state_update, serde_tower_sync, Vote, VoteAuthorize, - VoteAuthorizeCheckedWithSeedArgs, VoteAuthorizeWithSeedArgs, VoteInit, - VoteStateUpdate, VoteStateVersions, - }, - }, + crate::state::{ + Vote, VoteAuthorize, VoteAuthorizeCheckedWithSeedArgs, VoteAuthorizeWithSeedArgs, VoteInit, + VoteStateUpdate, VoteStateVersions, }, - serde_derive::{Deserialize, Serialize}, solana_clock::{Slot, UnixTimestamp}, + solana_hash::Hash, + solana_pubkey::Pubkey, +}; +#[cfg(feature = "bincode")] +use { + crate::program::id, + solana_instruction::{AccountMeta, Instruction}, + solana_sdk_ids::sysvar, +}; +#[cfg(feature = "serde")] +use { + crate::state::{serde_compact_vote_state_update, serde_tower_sync}, + serde_derive::{Deserialize, Serialize}, }; -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum VoteInstruction { /// Initialize a vote account /// @@ -135,7 +138,7 @@ pub enum VoteInstruction { /// # Account references /// 0. `[Write]` Vote account to vote with /// 1. `[SIGNER]` Vote authority - #[serde(with = "serde_compact_vote_state_update")] + #[cfg_attr(feature = "serde", serde(with = "serde_compact_vote_state_update"))] CompactUpdateVoteState(VoteStateUpdate), /// Update the onchain vote state for the signer along with a switching proof. @@ -144,7 +147,8 @@ pub enum VoteInstruction { /// 0. `[Write]` Vote account to vote with /// 1. `[SIGNER]` Vote authority CompactUpdateVoteStateSwitch( - #[serde(with = "serde_compact_vote_state_update")] VoteStateUpdate, + #[cfg_attr(feature = "serde", serde(with = "serde_compact_vote_state_update"))] + VoteStateUpdate, Hash, ), @@ -153,7 +157,7 @@ pub enum VoteInstruction { /// # Account references /// 0. `[Write]` Vote account to vote with /// 1. `[SIGNER]` Vote authority - #[serde(with = "serde_tower_sync")] + #[cfg_attr(feature = "serde", serde(with = "serde_tower_sync"))] TowerSync(TowerSync), /// Sync the onchain vote state with local tower along with a switching proof @@ -161,7 +165,10 @@ pub enum VoteInstruction { /// # Account references /// 0. `[Write]` Vote account to vote with /// 1. `[SIGNER]` Vote authority - TowerSyncSwitch(#[serde(with = "serde_tower_sync")] TowerSync, Hash), + TowerSyncSwitch( + #[cfg_attr(feature = "serde", serde(with = "serde_tower_sync"))] TowerSync, + Hash, + ), } impl VoteInstruction { @@ -241,6 +248,7 @@ impl VoteInstruction { } } +#[cfg(feature = "bincode")] fn initialize_account(vote_pubkey: &Pubkey, vote_init: &VoteInit) -> Instruction { let account_metas = vec![ AccountMeta::new(*vote_pubkey, false), @@ -270,6 +278,7 @@ impl Default for CreateVoteAccountConfig<'_> { } } +#[cfg(feature = "bincode")] pub fn create_account_with_config( from_pubkey: &Pubkey, vote_pubkey: &Pubkey, @@ -277,12 +286,18 @@ pub fn create_account_with_config( lamports: u64, config: CreateVoteAccountConfig, ) -> Vec { - let create_ix = - system_instruction::create_account(from_pubkey, vote_pubkey, lamports, config.space, &id()); + let create_ix = solana_system_interface::instruction::create_account( + from_pubkey, + vote_pubkey, + lamports, + config.space, + &id(), + ); let init_ix = initialize_account(vote_pubkey, vote_init); vec![create_ix, init_ix] } +#[cfg(feature = "bincode")] pub fn authorize( vote_pubkey: &Pubkey, authorized_pubkey: &Pubkey, // currently authorized @@ -302,6 +317,7 @@ pub fn authorize( ) } +#[cfg(feature = "bincode")] pub fn authorize_checked( vote_pubkey: &Pubkey, authorized_pubkey: &Pubkey, // currently authorized @@ -322,6 +338,7 @@ pub fn authorize_checked( ) } +#[cfg(feature = "bincode")] pub fn authorize_with_seed( vote_pubkey: &Pubkey, current_authority_base_key: &Pubkey, @@ -348,6 +365,7 @@ pub fn authorize_with_seed( ) } +#[cfg(feature = "bincode")] pub fn authorize_checked_with_seed( vote_pubkey: &Pubkey, current_authority_base_key: &Pubkey, @@ -374,6 +392,7 @@ pub fn authorize_checked_with_seed( ) } +#[cfg(feature = "bincode")] pub fn update_validator_identity( vote_pubkey: &Pubkey, authorized_withdrawer_pubkey: &Pubkey, @@ -392,6 +411,7 @@ pub fn update_validator_identity( ) } +#[cfg(feature = "bincode")] pub fn update_commission( vote_pubkey: &Pubkey, authorized_withdrawer_pubkey: &Pubkey, @@ -409,6 +429,7 @@ pub fn update_commission( ) } +#[cfg(feature = "bincode")] pub fn vote(vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, vote: Vote) -> Instruction { let account_metas = vec![ AccountMeta::new(*vote_pubkey, false), @@ -420,6 +441,7 @@ pub fn vote(vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, vote: Vote) Instruction::new_with_bincode(id(), &VoteInstruction::Vote(vote), account_metas) } +#[cfg(feature = "bincode")] pub fn vote_switch( vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, @@ -440,6 +462,7 @@ pub fn vote_switch( ) } +#[cfg(feature = "bincode")] pub fn update_vote_state( vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, @@ -457,6 +480,7 @@ pub fn update_vote_state( ) } +#[cfg(feature = "bincode")] pub fn update_vote_state_switch( vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, @@ -475,6 +499,7 @@ pub fn update_vote_state_switch( ) } +#[cfg(feature = "bincode")] pub fn compact_update_vote_state( vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, @@ -492,6 +517,7 @@ pub fn compact_update_vote_state( ) } +#[cfg(feature = "bincode")] pub fn compact_update_vote_state_switch( vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, @@ -510,6 +536,7 @@ pub fn compact_update_vote_state_switch( ) } +#[cfg(feature = "bincode")] pub fn tower_sync( vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, @@ -523,6 +550,7 @@ pub fn tower_sync( Instruction::new_with_bincode(id(), &VoteInstruction::TowerSync(tower_sync), account_metas) } +#[cfg(feature = "bincode")] pub fn tower_sync_switch( vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, @@ -541,6 +569,7 @@ pub fn tower_sync_switch( ) } +#[cfg(feature = "bincode")] pub fn withdraw( vote_pubkey: &Pubkey, authorized_withdrawer_pubkey: &Pubkey, diff --git a/sdk/program/src/vote/mod.rs b/sdk/vote-interface/src/lib.rs similarity index 70% rename from sdk/program/src/vote/mod.rs rename to sdk/vote-interface/src/lib.rs index b1417990321b36..1826ed54a35b57 100644 --- a/sdk/program/src/vote/mod.rs +++ b/sdk/vote-interface/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(feature = "frozen-abi", feature(min_specialization))] //! The [vote native program][np]. //! //! [np]: https://docs.solanalabs.com/runtime/programs#vote-program diff --git a/sdk/program/src/vote/state/mod.rs b/sdk/vote-interface/src/state/mod.rs similarity index 95% rename from sdk/program/src/vote/state/mod.rs rename to sdk/vote-interface/src/state/mod.rs index 9fc72c41fc882f..14859c99003ce8 100644 --- a/sdk/program/src/vote/state/mod.rs +++ b/sdk/vote-interface/src/state/mod.rs @@ -1,37 +1,34 @@ //! Vote state -#[cfg(not(target_os = "solana"))] +#[cfg(all(not(target_os = "solana"), feature = "bincode"))] use bincode::deserialize; -#[cfg(test)] +#[cfg(feature = "bincode")] +use bincode::{serialize_into, ErrorKind}; +#[cfg(feature = "serde")] +use serde_derive::{Deserialize, Serialize}; +#[cfg(feature = "frozen-abi")] +use solana_frozen_abi_macro::{frozen_abi, AbiExample}; use { - crate::epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET, - arbitrary::{Arbitrary, Unstructured}, + crate::{authorized_voters::AuthorizedVoters, error::VoteError}, + solana_clock::{Clock, Epoch, Slot, UnixTimestamp}, + solana_hash::Hash, + solana_instruction::error::InstructionError, + solana_pubkey::Pubkey, + solana_rent::Rent, + std::{collections::VecDeque, fmt::Debug}, }; +#[cfg(test)] use { - crate::{ - hash::Hash, - instruction::InstructionError, - pubkey::Pubkey, - rent::Rent, - serialize_utils::cursor::read_u32, - sysvar::clock::Clock, - vote::{authorized_voters::AuthorizedVoters, error::VoteError}, - }, - bincode::{serialize_into, ErrorKind}, - serde_derive::{Deserialize, Serialize}, - solana_clock::{Epoch, Slot, UnixTimestamp}, - std::{ - collections::VecDeque, - fmt::Debug, - io::Cursor, - mem::{self, MaybeUninit}, - }, + arbitrary::{Arbitrary, Unstructured}, + solana_epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET, }; mod vote_state_0_23_5; pub mod vote_state_1_14_11; pub use vote_state_1_14_11::*; +#[cfg(any(target_os = "solana", feature = "bincode"))] mod vote_state_deserialize; +#[cfg(any(target_os = "solana", feature = "bincode"))] use vote_state_deserialize::deserialize_vote_state_into; pub mod vote_state_versions; pub use vote_state_versions::*; @@ -57,7 +54,8 @@ pub const VOTE_CREDITS_MAXIMUM_PER_SLOT: u8 = 16; frozen_abi(digest = "GvUzgtcxhKVVxPAjSntXGPqjLZK5ovgZzCiUP1tDpB9q"), derive(AbiExample) )] -#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Default, Debug, PartialEq, Eq, Clone)] pub struct Vote { /// A stack of votes starting with the oldest vote pub slots: Vec, @@ -82,7 +80,8 @@ impl Vote { } #[cfg_attr(feature = "frozen-abi", derive(AbiExample))] -#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Copy, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)] #[cfg_attr(test, derive(Arbitrary))] pub struct Lockout { slot: Slot, @@ -131,7 +130,8 @@ impl Lockout { } #[cfg_attr(feature = "frozen-abi", derive(AbiExample))] -#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Copy, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)] #[cfg_attr(test, derive(Arbitrary))] pub struct LandedVote { // Latency is the difference in slot number between the slot that was voted on (lockout.slot) and the slot in @@ -168,10 +168,11 @@ impl From for LandedVote { #[cfg_attr( feature = "frozen-abi", - frozen_abi(digest = "DRKTb72wifCUcCTSJs6PqWrQQK5Pfis4SCLEvXqWnDaL"), + frozen_abi(digest = "CxyuwbaEdzP7jDCZyxjgQvLGXadBUZF3LoUvbSpQ6tYN"), derive(AbiExample) )] -#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Default, Debug, PartialEq, Eq, Clone)] pub struct VoteStateUpdate { /// The proposed tower pub lockouts: VecDeque, @@ -221,10 +222,11 @@ impl VoteStateUpdate { #[cfg_attr( feature = "frozen-abi", - frozen_abi(digest = "5PFw9pyF1UG1DXVsw7gpjHegNyRycAAxWf2GA9wUXPs5"), + frozen_abi(digest = "6UDiQMH4wbNwkMHosPMtekMYu2Qa6CHPZ2ymK4mc6FGu"), derive(AbiExample) )] -#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Default, Debug, PartialEq, Eq, Clone)] pub struct TowerSync { /// The proposed tower pub lockouts: VecDeque, @@ -316,7 +318,8 @@ impl TowerSync { } } -#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] pub struct VoteInit { pub node_pubkey: Pubkey, pub authorized_voter: Pubkey, @@ -324,13 +327,15 @@ pub struct VoteInit { pub commission: u8, } -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum VoteAuthorize { Voter, Withdrawer, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, PartialEq, Eq, Clone)] pub struct VoteAuthorizeWithSeedArgs { pub authorization_type: VoteAuthorize, pub current_authority_derived_key_owner: Pubkey, @@ -338,7 +343,8 @@ pub struct VoteAuthorizeWithSeedArgs { pub new_authority: Pubkey, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, PartialEq, Eq, Clone)] pub struct VoteAuthorizeCheckedWithSeedArgs { pub authorization_type: VoteAuthorize, pub current_authority_derived_key_owner: Pubkey, @@ -346,7 +352,8 @@ pub struct VoteAuthorizeCheckedWithSeedArgs { } #[cfg_attr(feature = "frozen-abi", derive(AbiExample))] -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, Default, PartialEq, Eq, Clone)] #[cfg_attr(test, derive(Arbitrary))] pub struct BlockTimestamp { pub slot: Slot, @@ -356,8 +363,9 @@ pub struct BlockTimestamp { // this is how many epochs a voter can be remembered for slashing const MAX_ITEMS: usize = 32; +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "frozen-abi", derive(AbiExample))] -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] #[cfg_attr(test, derive(Arbitrary))] pub struct CircBuf { buf: [I; MAX_ITEMS], @@ -406,10 +414,11 @@ impl CircBuf { #[cfg_attr( feature = "frozen-abi", - frozen_abi(digest = "87ULMjjHnMsPmCTEyzj4KPn2u5gdX1rmgtSdycpbSaLs"), + frozen_abi(digest = "BRwozbypfYXsHqFVj9w3iH5x1ak2NWHqCCn6pr3gHBkG"), derive(AbiExample) )] -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, Default, PartialEq, Eq, Clone)] #[cfg_attr(test, derive(Arbitrary))] pub struct VoteState { /// the node that votes in this account @@ -499,6 +508,7 @@ impl VoteState { // conversion of V0_23_5 to current must be handled specially, however // because it inserts a null voter into `authorized_voters` // which `VoteStateVersions::is_uninitialized` erroneously reports as initialized + #[cfg(any(target_os = "solana", feature = "bincode"))] pub fn deserialize(input: &[u8]) -> Result { #[cfg(not(target_os = "solana"))] { @@ -521,6 +531,7 @@ impl VoteState { /// /// On success, `vote_state` reflects the state of the input data. On failure, `vote_state` is /// reset to `VoteState::default()`. + #[cfg(any(target_os = "solana", feature = "bincode"))] pub fn deserialize_into( input: &[u8], vote_state: &mut VoteState, @@ -564,7 +575,7 @@ impl VoteState { let res = VoteState::deserialize_into_ptr(input, vote_state); if res.is_ok() { - mem::forget(guard); + std::mem::forget(guard); } res @@ -579,20 +590,22 @@ impl VoteState { /// On success, `vote_state` is fully initialized and can be converted to `VoteState` using /// [MaybeUninit::assume_init]. On failure, `vote_state` may still be uninitialized and must not /// be converted to `VoteState`. + #[cfg(any(target_os = "solana", feature = "bincode"))] pub fn deserialize_into_uninit( input: &[u8], - vote_state: &mut MaybeUninit, + vote_state: &mut std::mem::MaybeUninit, ) -> Result<(), InstructionError> { VoteState::deserialize_into_ptr(input, vote_state.as_mut_ptr()) } + #[cfg(any(target_os = "solana", feature = "bincode"))] fn deserialize_into_ptr( input: &[u8], vote_state: *mut VoteState, ) -> Result<(), InstructionError> { - let mut cursor = Cursor::new(input); + let mut cursor = std::io::Cursor::new(input); - let variant = read_u32(&mut cursor)?; + let variant = solana_serialize_utils::cursor::read_u32(&mut cursor)?; match variant { // V0_23_5. not supported for bpf targets; these should not exist on mainnet // supported for non-bpf targets for backwards compatibility @@ -626,6 +639,7 @@ impl VoteState { Ok(()) } + #[cfg(feature = "bincode")] pub fn serialize( versioned: &VoteStateVersions, output: &mut [u8], @@ -970,10 +984,11 @@ impl VoteState { } } +#[cfg(feature = "serde")] pub mod serde_compact_vote_state_update { use { super::*, - crate::vote::state::Lockout, + crate::state::Lockout, serde::{Deserialize, Deserializer, Serialize, Serializer}, solana_serde_varint as serde_varint, solana_short_vec as short_vec, }; @@ -1064,10 +1079,11 @@ pub mod serde_compact_vote_state_update { } } +#[cfg(feature = "serde")] pub mod serde_tower_sync { use { super::*, - crate::vote::state::Lockout, + crate::state::Lockout, serde::{Deserialize, Deserializer, Serialize, Serializer}, solana_serde_varint as serde_varint, solana_short_vec as short_vec, }; @@ -1161,7 +1177,9 @@ pub mod serde_tower_sync { #[cfg(test)] mod tests { - use {super::*, bincode::serialized_size, itertools::Itertools, rand::Rng}; + use { + super::*, bincode::serialized_size, core::mem::MaybeUninit, itertools::Itertools, rand::Rng, + }; #[test] fn test_vote_serialize() { @@ -1766,7 +1784,7 @@ mod tests { #[test] fn test_minimum_balance() { - let rent = solana_program::rent::Rent::default(); + let rent = solana_rent::Rent::default(); let minimum_balance = rent.minimum_balance(VoteState::size_of()); // golden, may need updating when vote_state grows assert!(minimum_balance as f64 / 10f64.powf(9.0) < 0.04) diff --git a/sdk/program/src/vote/state/vote_state_0_23_5.rs b/sdk/vote-interface/src/state/vote_state_0_23_5.rs similarity index 93% rename from sdk/program/src/vote/state/vote_state_0_23_5.rs rename to sdk/vote-interface/src/state/vote_state_0_23_5.rs index efc3e89bcf0e37..c3977ae5db6e2c 100644 --- a/sdk/program/src/vote/state/vote_state_0_23_5.rs +++ b/sdk/vote-interface/src/state/vote_state_0_23_5.rs @@ -5,7 +5,8 @@ use arbitrary::{Arbitrary, Unstructured}; const MAX_ITEMS: usize = 32; -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, Default, PartialEq, Eq, Clone)] #[cfg_attr(test, derive(Arbitrary))] pub struct VoteState0_23_5 { /// the node that votes in this account @@ -37,7 +38,8 @@ pub struct VoteState0_23_5 { pub last_timestamp: BlockTimestamp, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, PartialEq, Eq, Clone)] #[cfg_attr(test, derive(Arbitrary))] pub struct CircBuf { pub buf: [I; MAX_ITEMS], @@ -66,7 +68,7 @@ impl CircBuf { #[cfg(test)] mod tests { - use super::*; + use {super::*, core::mem::MaybeUninit}; #[test] fn test_vote_deserialize_0_23_5() { diff --git a/sdk/program/src/vote/state/vote_state_1_14_11.rs b/sdk/vote-interface/src/state/vote_state_1_14_11.rs similarity index 93% rename from sdk/program/src/vote/state/vote_state_1_14_11.rs rename to sdk/vote-interface/src/state/vote_state_1_14_11.rs index 2e0877ab3924eb..6a010d4757d4ef 100644 --- a/sdk/program/src/vote/state/vote_state_1_14_11.rs +++ b/sdk/vote-interface/src/state/vote_state_1_14_11.rs @@ -7,10 +7,11 @@ const DEFAULT_PRIOR_VOTERS_OFFSET: usize = 82; #[cfg_attr( feature = "frozen-abi", - frozen_abi(digest = "64duaG8iUgwmgMM9y1Pdi8S9jBGoPcjS5HrE8RRfsxJJ"), - derive(AbiExample) + solana_frozen_abi_macro::frozen_abi(digest = "HF4NfshaLg9e93RURYWTJRowtRrpLf5mWiF4G2Gnfu2r"), + derive(solana_frozen_abi_macro::AbiExample) )] -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[derive(Debug, Default, PartialEq, Eq, Clone)] #[cfg_attr(test, derive(Arbitrary))] pub struct VoteState1_14_11 { /// the node that votes in this account @@ -85,7 +86,7 @@ impl From for VoteState1_14_11 { #[cfg(test)] mod tests { - use super::*; + use {super::*, core::mem::MaybeUninit}; #[test] fn test_vote_deserialize_1_14_11() { diff --git a/sdk/program/src/vote/state/vote_state_deserialize.rs b/sdk/vote-interface/src/state/vote_state_deserialize.rs similarity index 92% rename from sdk/program/src/vote/state/vote_state_deserialize.rs rename to sdk/vote-interface/src/state/vote_state_deserialize.rs index 268341513a72b8..514ade1567b33f 100644 --- a/sdk/program/src/vote/state/vote_state_deserialize.rs +++ b/sdk/vote-interface/src/state/vote_state_deserialize.rs @@ -1,14 +1,15 @@ use { super::{MAX_EPOCH_CREDITS_HISTORY, MAX_LOCKOUT_HISTORY}, crate::{ - clock::Epoch, - instruction::InstructionError, - pubkey::Pubkey, - serialize_utils::cursor::*, - vote::{ - authorized_voters::AuthorizedVoters, - state::{BlockTimestamp, LandedVote, Lockout, VoteState, MAX_ITEMS}, - }, + authorized_voters::AuthorizedVoters, + state::{BlockTimestamp, LandedVote, Lockout, VoteState, MAX_ITEMS}, + }, + solana_clock::Epoch, + solana_instruction::error::InstructionError, + solana_pubkey::Pubkey, + solana_serialize_utils::cursor::{ + read_bool, read_i64, read_option_u64, read_pubkey, read_pubkey_into, read_u32, read_u64, + read_u8, }, std::{collections::VecDeque, io::Cursor, ptr::addr_of_mut}, }; diff --git a/sdk/program/src/vote/state/vote_state_versions.rs b/sdk/vote-interface/src/state/vote_state_versions.rs similarity index 87% rename from sdk/program/src/vote/state/vote_state_versions.rs rename to sdk/vote-interface/src/state/vote_state_versions.rs index 58d63d15def379..74afac088391da 100644 --- a/sdk/program/src/vote/state/vote_state_versions.rs +++ b/sdk/vote-interface/src/state/vote_state_versions.rs @@ -1,8 +1,22 @@ -use super::{vote_state_0_23_5::VoteState0_23_5, vote_state_1_14_11::VoteState1_14_11, *}; #[cfg(test)] use arbitrary::{Arbitrary, Unstructured}; - -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +use { + crate::{ + authorized_voters::AuthorizedVoters, + state::{ + vote_state_0_23_5::VoteState0_23_5, vote_state_1_14_11::VoteState1_14_11, CircBuf, + LandedVote, Lockout, VoteState, + }, + }, + solana_pubkey::Pubkey, + std::collections::VecDeque, +}; + +#[cfg_attr( + feature = "serde", + derive(serde_derive::Deserialize, serde_derive::Serialize) +)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum VoteStateVersions { V0_23_5(Box), V1_14_11(Box), diff --git a/svm/examples/Cargo.lock b/svm/examples/Cargo.lock index 1980544bf5f292..62c12a624076a9 100644 --- a/svm/examples/Cargo.lock +++ b/svm/examples/Cargo.lock @@ -6411,6 +6411,7 @@ dependencies = [ "solana-system-interface", "solana-sysvar", "solana-sysvar-id", + "solana-vote-interface", "thiserror 2.0.11", "wasm-bindgen", ] @@ -7914,6 +7915,28 @@ dependencies = [ "thiserror 2.0.11", ] +[[package]] +name = "solana-vote-interface" +version = "2.2.0" +dependencies = [ + "bincode", + "num-derive", + "num-traits", + "serde", + "serde_derive", + "solana-clock", + "solana-decode-error", + "solana-hash", + "solana-instruction", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-serde-varint", + "solana-serialize-utils", + "solana-short-vec", + "solana-system-interface", +] + [[package]] name = "solana-vote-program" version = "2.2.0"