Skip to main content

solana_vote_interface/
instruction.rs

1//! Vote program instructions
2
3use {
4    super::state::TowerSync,
5    crate::state::{
6        Vote, VoteAuthorize, VoteAuthorizeCheckedWithSeedArgs, VoteAuthorizeWithSeedArgs, VoteInit,
7        VoteInitV2, VoteStateUpdate, VoteStateV4,
8    },
9    solana_clock::{Slot, UnixTimestamp},
10    solana_hash::Hash,
11    solana_pubkey::Pubkey,
12};
13#[cfg(feature = "bincode")]
14use {
15    crate::program::id,
16    solana_instruction::{AccountMeta, Instruction},
17    solana_sdk_ids::sysvar,
18};
19#[cfg(feature = "serde")]
20use {
21    crate::state::{serde_compact_vote_state_update, serde_tower_sync},
22    serde_derive::{Deserialize, Serialize},
23};
24
25#[repr(u8)]
26#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
27#[derive(Debug, PartialEq, Eq, Clone)]
28pub enum CommissionKind {
29    InflationRewards = 0,
30    BlockRevenue = 1,
31}
32
33#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
34#[derive(Debug, PartialEq, Eq, Clone)]
35pub enum VoteInstruction {
36    /// Initialize a vote account
37    ///
38    /// # Account references
39    ///   0. `[WRITE]` Uninitialized vote account
40    ///   1. `[]` Rent sysvar
41    ///   2. `[]` Clock sysvar
42    ///   3. `[SIGNER]` New validator identity (node_pubkey)
43    InitializeAccount(VoteInit),
44
45    /// Authorize a key to send votes or issue a withdrawal
46    ///
47    /// # Account references
48    ///   0. `[WRITE]` Vote account to be updated with the Pubkey for authorization
49    ///   1. `[]` Clock sysvar
50    ///   2. `[SIGNER]` Vote or withdraw authority
51    ///
52    /// When SIMD-0387 is enabled, the `VoteAuthorize::Voter` variant is
53    /// disallowed for any vote accounts whose BLS pubkey is set to `Some`.
54    Authorize(Pubkey, VoteAuthorize),
55
56    /// A Vote instruction with recent votes
57    ///
58    /// # Account references
59    ///   0. `[WRITE]` Vote account to vote with
60    ///   1. `[]` Slot hashes sysvar
61    ///   2. `[]` Clock sysvar
62    ///   3. `[SIGNER]` Vote authority
63    Vote(Vote),
64
65    /// Withdraw some amount of funds
66    ///
67    /// # Account references
68    ///   0. `[WRITE]` Vote account to withdraw from
69    ///   1. `[WRITE]` Recipient account
70    ///   2. `[SIGNER]` Withdraw authority
71    Withdraw(u64),
72
73    /// Update the vote account's validator identity (node_pubkey)
74    ///
75    /// # Account references
76    ///   0. `[WRITE]` Vote account to be updated with the given authority public key
77    ///   1. `[SIGNER]` New validator identity (node_pubkey)
78    ///   2. `[SIGNER]` Withdraw authority
79    UpdateValidatorIdentity,
80
81    /// Update the commission for the vote account
82    ///
83    /// # Account references
84    ///   0. `[WRITE]` Vote account to be updated
85    ///   1. `[SIGNER]` Withdraw authority
86    UpdateCommission(u8),
87
88    /// A Vote instruction with recent votes
89    ///
90    /// # Account references
91    ///   0. `[WRITE]` Vote account to vote with
92    ///   1. `[]` Slot hashes sysvar
93    ///   2. `[]` Clock sysvar
94    ///   3. `[SIGNER]` Vote authority
95    VoteSwitch(Vote, Hash),
96
97    /// Authorize a key to send votes or issue a withdrawal
98    ///
99    /// This instruction behaves like `Authorize` with the additional requirement that the new vote
100    /// or withdraw authority must also be a signer.
101    ///
102    /// # Account references
103    ///   0. `[WRITE]` Vote account to be updated with the Pubkey for authorization
104    ///   1. `[]` Clock sysvar
105    ///   2. `[SIGNER]` Vote or withdraw authority
106    ///   3. `[SIGNER]` New vote or withdraw authority
107    ///
108    /// When SIMD-0387 is enabled, the `VoteAuthorize::Voter` variant is
109    /// disallowed for any vote accounts whose BLS pubkey is set to `Some`.
110    AuthorizeChecked(VoteAuthorize),
111
112    /// Update the onchain vote state for the signer.
113    ///
114    /// # Account references
115    ///   0. `[Write]` Vote account to vote with
116    ///   1. `[SIGNER]` Vote authority
117    UpdateVoteState(VoteStateUpdate),
118
119    /// Update the onchain vote state for the signer along with a switching proof.
120    ///
121    /// # Account references
122    ///   0. `[Write]` Vote account to vote with
123    ///   1. `[SIGNER]` Vote authority
124    UpdateVoteStateSwitch(VoteStateUpdate, Hash),
125
126    /// Given that the current Voter or Withdrawer authority is a derived key,
127    /// this instruction allows someone who can sign for that derived key's
128    /// base key to authorize a new Voter or Withdrawer for a vote account.
129    ///
130    /// # Account references
131    ///   0. `[Write]` Vote account to be updated
132    ///   1. `[]` Clock sysvar
133    ///   2. `[SIGNER]` Base key of current Voter or Withdrawer authority's derived key
134    ///
135    /// When SIMD-0387 is enabled, the `VoteAuthorize::Voter` variant in
136    /// `authorization_type` is disallowed for any vote accounts whose BLS
137    /// pubkey is set to `Some`.
138    AuthorizeWithSeed(VoteAuthorizeWithSeedArgs),
139
140    /// Given that the current Voter or Withdrawer authority is a derived key,
141    /// this instruction allows someone who can sign for that derived key's
142    /// base key to authorize a new Voter or Withdrawer for a vote account.
143    ///
144    /// This instruction behaves like `AuthorizeWithSeed` with the additional requirement
145    /// that the new vote or withdraw authority must also be a signer.
146    ///
147    /// # Account references
148    ///   0. `[Write]` Vote account to be updated
149    ///   1. `[]` Clock sysvar
150    ///   2. `[SIGNER]` Base key of current Voter or Withdrawer authority's derived key
151    ///   3. `[SIGNER]` New vote or withdraw authority
152    ///
153    /// When SIMD-0387 is enabled, the `VoteAuthorize::Voter` variant in
154    /// `authorization_type` is disallowed for any vote accounts whose BLS
155    /// pubkey is set to `Some`.
156    AuthorizeCheckedWithSeed(VoteAuthorizeCheckedWithSeedArgs),
157
158    /// Update the onchain vote state for the signer.
159    ///
160    /// # Account references
161    ///   0. `[Write]` Vote account to vote with
162    ///   1. `[SIGNER]` Vote authority
163    #[cfg_attr(feature = "serde", serde(with = "serde_compact_vote_state_update"))]
164    CompactUpdateVoteState(VoteStateUpdate),
165
166    /// Update the onchain vote state for the signer along with a switching proof.
167    ///
168    /// # Account references
169    ///   0. `[Write]` Vote account to vote with
170    ///   1. `[SIGNER]` Vote authority
171    CompactUpdateVoteStateSwitch(
172        #[cfg_attr(feature = "serde", serde(with = "serde_compact_vote_state_update"))]
173        VoteStateUpdate,
174        Hash,
175    ),
176
177    /// Sync the onchain vote state with local tower
178    ///
179    /// # Account references
180    ///   0. `[Write]` Vote account to vote with
181    ///   1. `[SIGNER]` Vote authority
182    #[cfg_attr(feature = "serde", serde(with = "serde_tower_sync"))]
183    TowerSync(TowerSync),
184
185    /// Sync the onchain vote state with local tower along with a switching proof
186    ///
187    /// # Account references
188    ///   0. `[Write]` Vote account to vote with
189    ///   1. `[SIGNER]` Vote authority
190    TowerSyncSwitch(
191        #[cfg_attr(feature = "serde", serde(with = "serde_tower_sync"))] TowerSync,
192        Hash,
193    ),
194
195    /// Initialize a vote account with all vote state v4 fields, including
196    /// BLS public key and collector accounts.
197    ///
198    /// The vote program performs BLS proof-of-possession verification on the
199    /// submitted BLS public key (per SIMD-0387). For each collector account
200    /// (indices 2 and 3), the program performs the same validation as
201    /// `UpdateCommissionCollector` (per SIMD-0232): if the collector is not
202    /// the vote account itself, it must be system-program owned, rent-exempt,
203    /// and writable (not a reserved account).
204    ///
205    /// # Account references
206    ///   0. `[WRITE]` Uninitialized vote account
207    ///   1. `[SIGNER]` New validator identity (node_pubkey)
208    ///   2. `[WRITE]` Inflation rewards collector
209    ///   3. `[WRITE]` Block revenue collector
210    InitializeAccountV2(VoteInitV2),
211
212    /// Update the commission collector for the vote account
213    ///
214    /// # Account references
215    ///   0. `[WRITE]` Vote account to be updated with the new collector public key
216    ///   1. `[WRITE]` New collector account. Must be set to the vote account or
217    ///      a system program owned account. Must be writable to ensure the
218    ///      account is not reserved.
219    ///   2. `[SIGNER]` Vote account withdraw authority
220    UpdateCommissionCollector(CommissionKind),
221
222    /// Update the commission rate in basis points for the specified commission
223    /// rate kind in a vote account.
224    ///
225    /// # Account references
226    ///   0. `[WRITE]` Vote account to be updated with the new commission
227    ///   1. `[SIGNER]` Vote account withdraw authority
228    UpdateCommissionBps {
229        commission_bps: u16,
230        kind: CommissionKind,
231    },
232
233    /// Deposit lamports for distribution to stake delegators
234    ///
235    /// # Account references
236    ///   0. `[WRITE]` Vote account to be updated with the deposit
237    ///   1. `[SIGNER, WRITE]` Source account for deposit funds
238    DepositDelegatorRewards { deposit: u64 },
239}
240
241impl VoteInstruction {
242    pub fn is_simple_vote(&self) -> bool {
243        matches!(
244            self,
245            Self::Vote(_)
246                | Self::VoteSwitch(_, _)
247                | Self::UpdateVoteState(_)
248                | Self::UpdateVoteStateSwitch(_, _)
249                | Self::CompactUpdateVoteState(_)
250                | Self::CompactUpdateVoteStateSwitch(_, _)
251                | Self::TowerSync(_)
252                | Self::TowerSyncSwitch(_, _),
253        )
254    }
255
256    pub fn is_single_vote_state_update(&self) -> bool {
257        matches!(
258            self,
259            Self::UpdateVoteState(_)
260                | Self::UpdateVoteStateSwitch(_, _)
261                | Self::CompactUpdateVoteState(_)
262                | Self::CompactUpdateVoteStateSwitch(_, _)
263                | Self::TowerSync(_)
264                | Self::TowerSyncSwitch(_, _),
265        )
266    }
267
268    /// Only to be used on vote instructions (guard with is_simple_vote),  panics otherwise
269    pub fn last_voted_slot(&self) -> Option<Slot> {
270        assert!(self.is_simple_vote());
271        match self {
272            Self::Vote(v) | Self::VoteSwitch(v, _) => v.last_voted_slot(),
273            Self::UpdateVoteState(vote_state_update)
274            | Self::UpdateVoteStateSwitch(vote_state_update, _)
275            | Self::CompactUpdateVoteState(vote_state_update)
276            | Self::CompactUpdateVoteStateSwitch(vote_state_update, _) => {
277                vote_state_update.last_voted_slot()
278            }
279            Self::TowerSync(tower_sync) | Self::TowerSyncSwitch(tower_sync, _) => {
280                tower_sync.last_voted_slot()
281            }
282            _ => panic!("Tried to get slot on non simple vote instruction"),
283        }
284    }
285
286    /// Only to be used on vote instructions (guard with is_simple_vote), panics otherwise
287    pub fn hash(&self) -> Hash {
288        assert!(self.is_simple_vote());
289        let hash = match self {
290            Self::Vote(v) | Self::VoteSwitch(v, _) => &v.hash,
291            Self::UpdateVoteState(vote_state_update)
292            | Self::UpdateVoteStateSwitch(vote_state_update, _)
293            | Self::CompactUpdateVoteState(vote_state_update)
294            | Self::CompactUpdateVoteStateSwitch(vote_state_update, _) => &vote_state_update.hash,
295            Self::TowerSync(tower_sync) | Self::TowerSyncSwitch(tower_sync, _) => &tower_sync.hash,
296            _ => panic!("Tried to get hash on non simple vote instruction"),
297        };
298        Hash::new_from_array(hash.to_bytes())
299    }
300    /// Only to be used on vote instructions (guard with is_simple_vote),  panics otherwise
301    pub fn timestamp(&self) -> Option<UnixTimestamp> {
302        assert!(self.is_simple_vote());
303        match self {
304            Self::Vote(v) | Self::VoteSwitch(v, _) => v.timestamp,
305            Self::UpdateVoteState(vote_state_update)
306            | Self::UpdateVoteStateSwitch(vote_state_update, _)
307            | Self::CompactUpdateVoteState(vote_state_update)
308            | Self::CompactUpdateVoteStateSwitch(vote_state_update, _) => {
309                vote_state_update.timestamp
310            }
311            Self::TowerSync(tower_sync) | Self::TowerSyncSwitch(tower_sync, _) => {
312                tower_sync.timestamp
313            }
314            _ => panic!("Tried to get timestamp on non simple vote instruction"),
315        }
316    }
317}
318
319#[cfg(feature = "bincode")]
320fn initialize_account(vote_pubkey: &Pubkey, vote_init: &VoteInit) -> Instruction {
321    let account_metas = vec![
322        AccountMeta::new(*vote_pubkey, false),
323        AccountMeta::new_readonly(sysvar::rent::id(), false),
324        AccountMeta::new_readonly(sysvar::clock::id(), false),
325        AccountMeta::new_readonly(vote_init.node_pubkey, true),
326    ];
327
328    Instruction::new_with_bincode(
329        id(),
330        &VoteInstruction::InitializeAccount(*vote_init),
331        account_metas,
332    )
333}
334
335#[cfg(feature = "bincode")]
336fn initialize_account_v2(
337    vote_pubkey: &Pubkey,
338    vote_init: &VoteInitV2,
339    inflation_rewards_collector: &Pubkey,
340    block_revenue_collector: &Pubkey,
341) -> Instruction {
342    let account_metas = vec![
343        AccountMeta::new(*vote_pubkey, false),
344        AccountMeta::new_readonly(vote_init.node_pubkey, true),
345        AccountMeta::new(*inflation_rewards_collector, false),
346        AccountMeta::new(*block_revenue_collector, false),
347    ];
348
349    Instruction::new_with_bincode(
350        id(),
351        &VoteInstruction::InitializeAccountV2(*vote_init),
352        account_metas,
353    )
354}
355
356pub struct CreateVoteAccountConfig<'a> {
357    pub space: u64,
358    pub with_seed: Option<(&'a Pubkey, &'a str)>,
359}
360
361impl Default for CreateVoteAccountConfig<'_> {
362    fn default() -> Self {
363        Self {
364            // Create new vote accounts with size for V4.
365            space: VoteStateV4::size_of() as u64,
366            with_seed: None,
367        }
368    }
369}
370
371#[cfg(feature = "bincode")]
372pub fn create_account_with_config(
373    from_pubkey: &Pubkey,
374    vote_pubkey: &Pubkey,
375    vote_init: &VoteInit,
376    lamports: u64,
377    config: CreateVoteAccountConfig,
378) -> Vec<Instruction> {
379    let create_ix = if let Some((base, seed)) = config.with_seed {
380        solana_system_interface::instruction::create_account_with_seed(
381            from_pubkey,
382            vote_pubkey,
383            base,
384            seed,
385            lamports,
386            config.space,
387            &id(),
388        )
389    } else {
390        solana_system_interface::instruction::create_account(
391            from_pubkey,
392            vote_pubkey,
393            lamports,
394            config.space,
395            &id(),
396        )
397    };
398    let init_ix = initialize_account(vote_pubkey, vote_init);
399    vec![create_ix, init_ix]
400}
401
402#[cfg(feature = "bincode")]
403pub fn create_account_with_config_v2(
404    from_pubkey: &Pubkey,
405    vote_pubkey: &Pubkey,
406    vote_init: &VoteInitV2,
407    inflation_rewards_collector: &Pubkey,
408    block_revenue_collector: &Pubkey,
409    lamports: u64,
410    config: CreateVoteAccountConfig,
411) -> Vec<Instruction> {
412    let create_ix = if let Some((base, seed)) = config.with_seed {
413        solana_system_interface::instruction::create_account_with_seed(
414            from_pubkey,
415            vote_pubkey,
416            base,
417            seed,
418            lamports,
419            config.space,
420            &id(),
421        )
422    } else {
423        solana_system_interface::instruction::create_account(
424            from_pubkey,
425            vote_pubkey,
426            lamports,
427            config.space,
428            &id(),
429        )
430    };
431    let init_ix = initialize_account_v2(
432        vote_pubkey,
433        vote_init,
434        inflation_rewards_collector,
435        block_revenue_collector,
436    );
437    vec![create_ix, init_ix]
438}
439
440#[cfg(feature = "bincode")]
441pub fn authorize(
442    vote_pubkey: &Pubkey,
443    authorized_pubkey: &Pubkey, // currently authorized
444    new_authorized_pubkey: &Pubkey,
445    vote_authorize: VoteAuthorize,
446) -> Instruction {
447    let account_metas = vec![
448        AccountMeta::new(*vote_pubkey, false),
449        AccountMeta::new_readonly(sysvar::clock::id(), false),
450        AccountMeta::new_readonly(*authorized_pubkey, true),
451    ];
452
453    Instruction::new_with_bincode(
454        id(),
455        &VoteInstruction::Authorize(*new_authorized_pubkey, vote_authorize),
456        account_metas,
457    )
458}
459
460#[cfg(feature = "bincode")]
461pub fn authorize_checked(
462    vote_pubkey: &Pubkey,
463    authorized_pubkey: &Pubkey, // currently authorized
464    new_authorized_pubkey: &Pubkey,
465    vote_authorize: VoteAuthorize,
466) -> Instruction {
467    let account_metas = vec![
468        AccountMeta::new(*vote_pubkey, false),
469        AccountMeta::new_readonly(sysvar::clock::id(), false),
470        AccountMeta::new_readonly(*authorized_pubkey, true),
471        AccountMeta::new_readonly(*new_authorized_pubkey, true),
472    ];
473
474    Instruction::new_with_bincode(
475        id(),
476        &VoteInstruction::AuthorizeChecked(vote_authorize),
477        account_metas,
478    )
479}
480
481#[cfg(feature = "bincode")]
482pub fn authorize_with_seed(
483    vote_pubkey: &Pubkey,
484    current_authority_base_key: &Pubkey,
485    current_authority_derived_key_owner: &Pubkey,
486    current_authority_derived_key_seed: &str,
487    new_authority: &Pubkey,
488    authorization_type: VoteAuthorize,
489) -> Instruction {
490    let account_metas = vec![
491        AccountMeta::new(*vote_pubkey, false),
492        AccountMeta::new_readonly(sysvar::clock::id(), false),
493        AccountMeta::new_readonly(*current_authority_base_key, true),
494    ];
495
496    Instruction::new_with_bincode(
497        id(),
498        &VoteInstruction::AuthorizeWithSeed(VoteAuthorizeWithSeedArgs {
499            authorization_type,
500            current_authority_derived_key_owner: *current_authority_derived_key_owner,
501            current_authority_derived_key_seed: current_authority_derived_key_seed.to_string(),
502            new_authority: *new_authority,
503        }),
504        account_metas,
505    )
506}
507
508#[cfg(feature = "bincode")]
509pub fn authorize_checked_with_seed(
510    vote_pubkey: &Pubkey,
511    current_authority_base_key: &Pubkey,
512    current_authority_derived_key_owner: &Pubkey,
513    current_authority_derived_key_seed: &str,
514    new_authority: &Pubkey,
515    authorization_type: VoteAuthorize,
516) -> Instruction {
517    let account_metas = vec![
518        AccountMeta::new(*vote_pubkey, false),
519        AccountMeta::new_readonly(sysvar::clock::id(), false),
520        AccountMeta::new_readonly(*current_authority_base_key, true),
521        AccountMeta::new_readonly(*new_authority, true),
522    ];
523
524    Instruction::new_with_bincode(
525        id(),
526        &VoteInstruction::AuthorizeCheckedWithSeed(VoteAuthorizeCheckedWithSeedArgs {
527            authorization_type,
528            current_authority_derived_key_owner: *current_authority_derived_key_owner,
529            current_authority_derived_key_seed: current_authority_derived_key_seed.to_string(),
530        }),
531        account_metas,
532    )
533}
534
535#[cfg(feature = "bincode")]
536pub fn update_validator_identity(
537    vote_pubkey: &Pubkey,
538    authorized_withdrawer_pubkey: &Pubkey,
539    node_pubkey: &Pubkey,
540) -> Instruction {
541    let account_metas = vec![
542        AccountMeta::new(*vote_pubkey, false),
543        AccountMeta::new_readonly(*node_pubkey, true),
544        AccountMeta::new_readonly(*authorized_withdrawer_pubkey, true),
545    ];
546
547    Instruction::new_with_bincode(
548        id(),
549        &VoteInstruction::UpdateValidatorIdentity,
550        account_metas,
551    )
552}
553
554#[cfg(feature = "bincode")]
555pub fn update_commission(
556    vote_pubkey: &Pubkey,
557    authorized_withdrawer_pubkey: &Pubkey,
558    commission: u8,
559) -> Instruction {
560    let account_metas = vec![
561        AccountMeta::new(*vote_pubkey, false),
562        AccountMeta::new_readonly(*authorized_withdrawer_pubkey, true),
563    ];
564
565    Instruction::new_with_bincode(
566        id(),
567        &VoteInstruction::UpdateCommission(commission),
568        account_metas,
569    )
570}
571
572#[cfg(feature = "bincode")]
573pub fn update_commission_collector(
574    vote_pubkey: &Pubkey,
575    authorized_withdrawer_pubkey: &Pubkey,
576    new_collector_pubkey: &Pubkey,
577    kind: CommissionKind,
578) -> Instruction {
579    let account_metas = vec![
580        AccountMeta::new(*vote_pubkey, false),
581        AccountMeta::new(*new_collector_pubkey, false),
582        AccountMeta::new_readonly(*authorized_withdrawer_pubkey, true),
583    ];
584
585    Instruction::new_with_bincode(
586        id(),
587        &VoteInstruction::UpdateCommissionCollector(kind),
588        account_metas,
589    )
590}
591
592#[cfg(feature = "bincode")]
593pub fn update_commission_bps(
594    vote_pubkey: &Pubkey,
595    authorized_withdrawer_pubkey: &Pubkey,
596    kind: CommissionKind,
597    commission_bps: u16,
598) -> Instruction {
599    let account_metas = vec![
600        AccountMeta::new(*vote_pubkey, false),
601        AccountMeta::new_readonly(*authorized_withdrawer_pubkey, true),
602    ];
603
604    Instruction::new_with_bincode(
605        id(),
606        &VoteInstruction::UpdateCommissionBps {
607            kind,
608            commission_bps,
609        },
610        account_metas,
611    )
612}
613
614#[cfg(feature = "bincode")]
615pub fn deposit_delegator_rewards(
616    vote_pubkey: &Pubkey,
617    source_pubkey: &Pubkey,
618    deposit: u64,
619) -> Instruction {
620    let account_metas = vec![
621        AccountMeta::new(*vote_pubkey, false),
622        AccountMeta::new(*source_pubkey, true),
623    ];
624
625    Instruction::new_with_bincode(
626        id(),
627        &VoteInstruction::DepositDelegatorRewards { deposit },
628        account_metas,
629    )
630}
631
632#[cfg(feature = "bincode")]
633pub fn vote(vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, vote: Vote) -> Instruction {
634    let account_metas = vec![
635        AccountMeta::new(*vote_pubkey, false),
636        AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
637        AccountMeta::new_readonly(sysvar::clock::id(), false),
638        AccountMeta::new_readonly(*authorized_voter_pubkey, true),
639    ];
640
641    Instruction::new_with_bincode(id(), &VoteInstruction::Vote(vote), account_metas)
642}
643
644#[cfg(feature = "bincode")]
645pub fn vote_switch(
646    vote_pubkey: &Pubkey,
647    authorized_voter_pubkey: &Pubkey,
648    vote: Vote,
649    proof_hash: Hash,
650) -> Instruction {
651    let account_metas = vec![
652        AccountMeta::new(*vote_pubkey, false),
653        AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
654        AccountMeta::new_readonly(sysvar::clock::id(), false),
655        AccountMeta::new_readonly(*authorized_voter_pubkey, true),
656    ];
657
658    Instruction::new_with_bincode(
659        id(),
660        &VoteInstruction::VoteSwitch(vote, proof_hash),
661        account_metas,
662    )
663}
664
665#[cfg(feature = "bincode")]
666pub fn update_vote_state(
667    vote_pubkey: &Pubkey,
668    authorized_voter_pubkey: &Pubkey,
669    vote_state_update: VoteStateUpdate,
670) -> Instruction {
671    let account_metas = vec![
672        AccountMeta::new(*vote_pubkey, false),
673        AccountMeta::new_readonly(*authorized_voter_pubkey, true),
674    ];
675
676    Instruction::new_with_bincode(
677        id(),
678        &VoteInstruction::UpdateVoteState(vote_state_update),
679        account_metas,
680    )
681}
682
683#[cfg(feature = "bincode")]
684pub fn update_vote_state_switch(
685    vote_pubkey: &Pubkey,
686    authorized_voter_pubkey: &Pubkey,
687    vote_state_update: VoteStateUpdate,
688    proof_hash: Hash,
689) -> Instruction {
690    let account_metas = vec![
691        AccountMeta::new(*vote_pubkey, false),
692        AccountMeta::new_readonly(*authorized_voter_pubkey, true),
693    ];
694
695    Instruction::new_with_bincode(
696        id(),
697        &VoteInstruction::UpdateVoteStateSwitch(vote_state_update, proof_hash),
698        account_metas,
699    )
700}
701
702#[cfg(feature = "bincode")]
703pub fn compact_update_vote_state(
704    vote_pubkey: &Pubkey,
705    authorized_voter_pubkey: &Pubkey,
706    vote_state_update: VoteStateUpdate,
707) -> Instruction {
708    let account_metas = vec![
709        AccountMeta::new(*vote_pubkey, false),
710        AccountMeta::new_readonly(*authorized_voter_pubkey, true),
711    ];
712
713    Instruction::new_with_bincode(
714        id(),
715        &VoteInstruction::CompactUpdateVoteState(vote_state_update),
716        account_metas,
717    )
718}
719
720#[cfg(feature = "bincode")]
721pub fn compact_update_vote_state_switch(
722    vote_pubkey: &Pubkey,
723    authorized_voter_pubkey: &Pubkey,
724    vote_state_update: VoteStateUpdate,
725    proof_hash: Hash,
726) -> Instruction {
727    let account_metas = vec![
728        AccountMeta::new(*vote_pubkey, false),
729        AccountMeta::new_readonly(*authorized_voter_pubkey, true),
730    ];
731
732    Instruction::new_with_bincode(
733        id(),
734        &VoteInstruction::CompactUpdateVoteStateSwitch(vote_state_update, proof_hash),
735        account_metas,
736    )
737}
738
739#[cfg(feature = "bincode")]
740pub fn tower_sync(
741    vote_pubkey: &Pubkey,
742    authorized_voter_pubkey: &Pubkey,
743    tower_sync: TowerSync,
744) -> Instruction {
745    let account_metas = vec![
746        AccountMeta::new(*vote_pubkey, false),
747        AccountMeta::new_readonly(*authorized_voter_pubkey, true),
748    ];
749
750    Instruction::new_with_bincode(id(), &VoteInstruction::TowerSync(tower_sync), account_metas)
751}
752
753#[cfg(feature = "bincode")]
754pub fn tower_sync_switch(
755    vote_pubkey: &Pubkey,
756    authorized_voter_pubkey: &Pubkey,
757    tower_sync: TowerSync,
758    proof_hash: Hash,
759) -> Instruction {
760    let account_metas = vec![
761        AccountMeta::new(*vote_pubkey, false),
762        AccountMeta::new_readonly(*authorized_voter_pubkey, true),
763    ];
764
765    Instruction::new_with_bincode(
766        id(),
767        &VoteInstruction::TowerSyncSwitch(tower_sync, proof_hash),
768        account_metas,
769    )
770}
771
772#[cfg(feature = "bincode")]
773pub fn withdraw(
774    vote_pubkey: &Pubkey,
775    authorized_withdrawer_pubkey: &Pubkey,
776    lamports: u64,
777    to_pubkey: &Pubkey,
778) -> Instruction {
779    let account_metas = vec![
780        AccountMeta::new(*vote_pubkey, false),
781        AccountMeta::new(*to_pubkey, false),
782        AccountMeta::new_readonly(*authorized_withdrawer_pubkey, true),
783    ];
784
785    Instruction::new_with_bincode(id(), &VoteInstruction::Withdraw(lamports), account_metas)
786}