Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 67 additions & 1 deletion vote-interface/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use {
super::state::TowerSync,
crate::state::{
Vote, VoteAuthorize, VoteAuthorizeCheckedWithSeedArgs, VoteAuthorizeWithSeedArgs, VoteInit,
VoteStateUpdate, VoteStateV4,
VoteInitV2, VoteStateUpdate, VoteStateV4,
},
solana_clock::{Slot, UnixTimestamp},
solana_hash::Hash,
Expand Down Expand Up @@ -40,6 +40,9 @@ pub enum VoteInstruction {
/// 0. `[WRITE]` Vote account to be updated with the Pubkey for authorization
/// 1. `[]` Clock sysvar
/// 2. `[SIGNER]` Vote or withdraw authority
///
/// When SIMD-0387 is enabled, the `VoteAuthorize::Voter` variant is
/// disallowed for any vote accounts whose BLS pubkey is set to `Some`.
Authorize(Pubkey, VoteAuthorize),

/// A Vote instruction with recent votes
Expand Down Expand Up @@ -93,6 +96,9 @@ pub enum VoteInstruction {
/// 1. `[]` Clock sysvar
/// 2. `[SIGNER]` Vote or withdraw authority
/// 3. `[SIGNER]` New vote or withdraw authority
///
/// When SIMD-0387 is enabled, the `VoteAuthorize::Voter` variant is
/// disallowed for any vote accounts whose BLS pubkey is set to `Some`.
AuthorizeChecked(VoteAuthorize),

/// Update the onchain vote state for the signer.
Expand All @@ -117,6 +123,10 @@ pub enum VoteInstruction {
/// 0. `[Write]` Vote account to be updated
/// 1. `[]` Clock sysvar
/// 2. `[SIGNER]` Base key of current Voter or Withdrawer authority's derived key
///
/// When SIMD-0387 is enabled, the `VoteAuthorize::Voter` variant in
/// `authorization_type` is disallowed for any vote accounts whose BLS
/// pubkey is set to `Some`.
AuthorizeWithSeed(VoteAuthorizeWithSeedArgs),

/// Given that the current Voter or Withdrawer authority is a derived key,
Expand All @@ -131,6 +141,10 @@ pub enum VoteInstruction {
/// 1. `[]` Clock sysvar
/// 2. `[SIGNER]` Base key of current Voter or Withdrawer authority's derived key
/// 3. `[SIGNER]` New vote or withdraw authority
///
/// When SIMD-0387 is enabled, the `VoteAuthorize::Voter` variant in
/// `authorization_type` is disallowed for any vote accounts whose BLS
/// pubkey is set to `Some`.
AuthorizeCheckedWithSeed(VoteAuthorizeCheckedWithSeedArgs),

/// Update the onchain vote state for the signer.
Expand Down Expand Up @@ -169,6 +183,13 @@ pub enum VoteInstruction {
#[cfg_attr(feature = "serde", serde(with = "serde_tower_sync"))] TowerSync,
Hash,
),

// Initialize a vote account using VoteInitV2
///
/// # Account references
/// 0. `[WRITE]` Uninitialized vote account
/// 1. `[SIGNER]` New validator identity (node_pubkey)
InitializeAccountV2(VoteInitV2),
}

impl VoteInstruction {
Expand Down Expand Up @@ -265,6 +286,20 @@ fn initialize_account(vote_pubkey: &Pubkey, vote_init: &VoteInit) -> Instruction
)
}

#[cfg(feature = "bincode")]
fn initialize_account_v2(vote_pubkey: &Pubkey, vote_init: &VoteInitV2) -> Instruction {
let account_metas = vec![
AccountMeta::new(*vote_pubkey, false),
AccountMeta::new_readonly(vote_init.node_pubkey, true),
];

Instruction::new_with_bincode(
id(),
&VoteInstruction::InitializeAccountV2(*vote_init),
account_metas,
)
}

pub struct CreateVoteAccountConfig<'a> {
pub space: u64,
pub with_seed: Option<(&'a Pubkey, &'a str)>,
Expand Down Expand Up @@ -311,6 +346,37 @@ pub fn create_account_with_config(
vec![create_ix, init_ix]
}

#[cfg(feature = "bincode")]
pub fn create_account_with_config_v2(
from_pubkey: &Pubkey,
vote_pubkey: &Pubkey,
vote_init: &VoteInitV2,
lamports: u64,
config: CreateVoteAccountConfig,
) -> Vec<Instruction> {
let create_ix = if let Some((base, seed)) = config.with_seed {
solana_system_interface::instruction::create_account_with_seed(
from_pubkey,
vote_pubkey,
base,
seed,
lamports,
config.space,
&id(),
)
} else {
solana_system_interface::instruction::create_account(
from_pubkey,
vote_pubkey,
lamports,
config.space,
&id(),
)
};
let init_ix = initialize_account_v2(vote_pubkey, vote_init);
vec![create_ix, init_ix]
}

#[cfg(feature = "bincode")]
pub fn authorize(
vote_pubkey: &Pubkey,
Expand Down
3 changes: 3 additions & 0 deletions vote-interface/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ pub(crate) mod vote_state_deserialize;
/// Size of a BLS public key in a compressed point representation
pub const BLS_PUBLIC_KEY_COMPRESSED_SIZE: usize = 48;

/// Size of a BLS signature in a compressed point representation
pub const BLS_SIGNATURE_COMPRESSED_SIZE: usize = 96;

// Maximum number of votes to keep around, tightly coupled with epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
pub const MAX_LOCKOUT_HISTORY: usize = 31;
pub const INITIAL_LOCKOUT: usize = 2;
Expand Down
70 changes: 67 additions & 3 deletions vote-interface/src/state/vote_instruction_data.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
#[cfg(feature = "serde")]
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "frozen-abi")]
use solana_frozen_abi_macro::{frozen_abi, AbiExample};
use {
crate::state::{Lockout, MAX_LOCKOUT_HISTORY},
crate::state::{
Lockout, BLS_PUBLIC_KEY_COMPRESSED_SIZE, BLS_SIGNATURE_COMPRESSED_SIZE, MAX_LOCKOUT_HISTORY,
},
solana_clock::{Slot, UnixTimestamp},
solana_hash::Hash,
solana_pubkey::Pubkey,
std::{collections::VecDeque, fmt::Debug},
};
#[cfg(feature = "serde")]
use {
serde_derive::{Deserialize, Serialize},
serde_with::serde_as,
};

#[cfg_attr(
feature = "frozen-abi",
Expand Down Expand Up @@ -201,11 +206,70 @@ pub struct VoteInit {
pub commission: u8,
}

#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_as)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct VoteInitV2 {
pub node_pubkey: Pubkey,
pub authorized_voter: Pubkey,
#[cfg_attr(
feature = "serde",
serde_as(as = "[_; BLS_PUBLIC_KEY_COMPRESSED_SIZE]")
)]
pub authorized_voter_bls_pubkey: [u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
#[cfg_attr(feature = "serde", serde_as(as = "[_; BLS_SIGNATURE_COMPRESSED_SIZE]"))]
pub authorized_voter_bls_proof_of_possession: [u8; BLS_SIGNATURE_COMPRESSED_SIZE],
pub authorized_withdrawer: Pubkey,
pub inflation_rewards_commission_bps: u16,
pub inflation_rewards_collector: Pubkey,
pub block_revenue_commission_bps: u16,
pub block_revenue_collector: Pubkey,
}

impl Default for VoteInitV2 {
fn default() -> Self {
Self {
node_pubkey: Pubkey::default(),
authorized_voter: Pubkey::default(),
authorized_voter_bls_pubkey: [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
authorized_voter_bls_proof_of_possession: [0u8; BLS_SIGNATURE_COMPRESSED_SIZE],
authorized_withdrawer: Pubkey::default(),
inflation_rewards_commission_bps: 0,
inflation_rewards_collector: Pubkey::default(),
block_revenue_commission_bps: 0,
block_revenue_collector: Pubkey::default(),
}
}
}

#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_as)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct VoterWithBLSArgs {
#[cfg_attr(
feature = "serde",
serde_as(as = "[_; BLS_PUBLIC_KEY_COMPRESSED_SIZE]")
)]
pub bls_pub_key: [u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
#[cfg_attr(feature = "serde", serde_as(as = "[_; BLS_SIGNATURE_COMPRESSED_SIZE]"))]
pub bls_proof_of_possession: [u8; BLS_SIGNATURE_COMPRESSED_SIZE],
}

impl Default for VoterWithBLSArgs {
fn default() -> Self {
Self {
bls_pub_key: [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
bls_proof_of_possession: [0u8; BLS_SIGNATURE_COMPRESSED_SIZE],
}
}
}

#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum VoteAuthorize {
Voter,
Withdrawer,
VoterWithBLS(VoterWithBLSArgs),
}

#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
Expand Down
18 changes: 16 additions & 2 deletions vote-interface/src/state/vote_state_v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use solana_frozen_abi_macro::{frozen_abi, AbiExample};
#[cfg(any(target_os = "solana", feature = "bincode"))]
use solana_instruction::error::InstructionError;
use {
super::{BlockTimestamp, LandedVote, VoteInit, BLS_PUBLIC_KEY_COMPRESSED_SIZE},
super::{BlockTimestamp, LandedVote, VoteInit, VoteInitV2, BLS_PUBLIC_KEY_COMPRESSED_SIZE},
crate::authorized_voters::AuthorizedVoters,
solana_clock::{Clock, Epoch, Slot},
solana_pubkey::Pubkey,
Expand Down Expand Up @@ -77,7 +77,7 @@ impl VoteStateV4 {
3762 // Same size as V3 to avoid account resizing
}

pub fn new(vote_pubkey: &Pubkey, vote_init: &VoteInit, clock: &Clock) -> Self {
pub fn new_with_defaults(vote_pubkey: &Pubkey, vote_init: &VoteInit, clock: &Clock) -> Self {
Self {
node_pubkey: vote_init.node_pubkey,
authorized_voters: AuthorizedVoters::new(clock.epoch, vote_init.authorized_voter),
Expand All @@ -92,6 +92,20 @@ impl VoteStateV4 {
}
}

pub fn new(vote_init: &VoteInitV2, clock: &Clock) -> Self {
Self {
node_pubkey: vote_init.node_pubkey,
authorized_voters: AuthorizedVoters::new(clock.epoch, vote_init.authorized_voter),
bls_pubkey_compressed: Some(vote_init.authorized_voter_bls_pubkey),
authorized_withdrawer: vote_init.authorized_withdrawer,
inflation_rewards_commission_bps: vote_init.inflation_rewards_commission_bps,
inflation_rewards_collector: vote_init.inflation_rewards_collector,
block_revenue_commission_bps: vote_init.block_revenue_commission_bps,
block_revenue_collector: vote_init.block_revenue_collector,
..Self::default()
}
}

#[cfg(any(target_os = "solana", feature = "bincode"))]
pub fn deserialize(input: &[u8], vote_pubkey: &Pubkey) -> Result<Self, InstructionError> {
let mut vote_state = Self::default();
Expand Down