1use {
4 crate::{
5 clock::Slot,
6 hash::Hash,
7 instruction::{AccountMeta, Instruction},
8 pubkey::Pubkey,
9 system_instruction, sysvar,
10 vote::{
11 program::id,
12 state::{
13 serde_compact_vote_state_update, Vote, VoteAuthorize,
14 VoteAuthorizeCheckedWithSeedArgs, VoteAuthorizeWithSeedArgs, VoteInit, VoteState,
15 VoteStateUpdate,
16 },
17 },
18 },
19 serde_derive::{Deserialize, Serialize},
20};
21
22#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
23pub enum VoteInstruction {
24 InitializeAccount(VoteInit),
32
33 Authorize(Pubkey, VoteAuthorize),
40
41 Vote(Vote),
49
50 Withdraw(u64),
57
58 UpdateValidatorIdentity,
65
66 UpdateCommission(u8),
72
73 VoteSwitch(Vote, Hash),
81
82 AuthorizeChecked(VoteAuthorize),
93
94 UpdateVoteState(VoteStateUpdate),
100
101 UpdateVoteStateSwitch(VoteStateUpdate, Hash),
107
108 AuthorizeWithSeed(VoteAuthorizeWithSeedArgs),
117
118 AuthorizeCheckedWithSeed(VoteAuthorizeCheckedWithSeedArgs),
131
132 #[serde(with = "serde_compact_vote_state_update")]
138 CompactUpdateVoteState(VoteStateUpdate),
139
140 CompactUpdateVoteStateSwitch(
146 #[serde(with = "serde_compact_vote_state_update")] VoteStateUpdate,
147 Hash,
148 ),
149}
150
151impl VoteInstruction {
152 pub fn is_simple_vote(&self) -> bool {
153 matches!(
154 self,
155 Self::Vote(_)
156 | Self::VoteSwitch(_, _)
157 | Self::UpdateVoteState(_)
158 | Self::UpdateVoteStateSwitch(_, _)
159 | Self::CompactUpdateVoteState(_)
160 | Self::CompactUpdateVoteStateSwitch(_, _),
161 )
162 }
163
164 pub fn is_single_vote_state_update(&self) -> bool {
165 matches!(
166 self,
167 Self::UpdateVoteState(_)
168 | Self::UpdateVoteStateSwitch(_, _)
169 | Self::CompactUpdateVoteState(_)
170 | Self::CompactUpdateVoteStateSwitch(_, _),
171 )
172 }
173
174 pub fn last_voted_slot(&self) -> Option<Slot> {
176 assert!(self.is_simple_vote());
177 match self {
178 Self::Vote(v) | Self::VoteSwitch(v, _) => v.last_voted_slot(),
179 Self::UpdateVoteState(vote_state_update)
180 | Self::UpdateVoteStateSwitch(vote_state_update, _)
181 | Self::CompactUpdateVoteState(vote_state_update)
182 | Self::CompactUpdateVoteStateSwitch(vote_state_update, _) => {
183 vote_state_update.last_voted_slot()
184 }
185 _ => panic!("Tried to get slot on non simple vote instruction"),
186 }
187 }
188}
189
190fn initialize_account(vote_pubkey: &Pubkey, vote_init: &VoteInit) -> Instruction {
191 let account_metas = vec![
192 AccountMeta::new(*vote_pubkey, false),
193 AccountMeta::new_readonly(sysvar::rent::id(), false),
194 AccountMeta::new_readonly(sysvar::clock::id(), false),
195 AccountMeta::new_readonly(vote_init.node_pubkey, true),
196 ];
197
198 Instruction::new_with_bincode(
199 id(),
200 &VoteInstruction::InitializeAccount(*vote_init),
201 account_metas,
202 )
203}
204
205pub fn create_account(
206 from_pubkey: &Pubkey,
207 vote_pubkey: &Pubkey,
208 vote_init: &VoteInit,
209 scoobies: u64,
210) -> Vec<Instruction> {
211 let space = VoteState::size_of() as u64;
212 let create_ix =
213 system_instruction::create_account(from_pubkey, vote_pubkey, scoobies, space, &id());
214 let init_ix = initialize_account(vote_pubkey, vote_init);
215 vec![create_ix, init_ix]
216}
217
218pub fn create_account_with_seed(
219 from_pubkey: &Pubkey,
220 vote_pubkey: &Pubkey,
221 base: &Pubkey,
222 seed: &str,
223 vote_init: &VoteInit,
224 scoobies: u64,
225) -> Vec<Instruction> {
226 let space = VoteState::size_of() as u64;
227 let create_ix = system_instruction::create_account_with_seed(
228 from_pubkey,
229 vote_pubkey,
230 base,
231 seed,
232 scoobies,
233 space,
234 &id(),
235 );
236 let init_ix = initialize_account(vote_pubkey, vote_init);
237 vec![create_ix, init_ix]
238}
239
240pub fn authorize(
241 vote_pubkey: &Pubkey,
242 authorized_pubkey: &Pubkey, new_authorized_pubkey: &Pubkey,
244 vote_authorize: VoteAuthorize,
245) -> Instruction {
246 let account_metas = vec![
247 AccountMeta::new(*vote_pubkey, false),
248 AccountMeta::new_readonly(sysvar::clock::id(), false),
249 AccountMeta::new_readonly(*authorized_pubkey, true),
250 ];
251
252 Instruction::new_with_bincode(
253 id(),
254 &VoteInstruction::Authorize(*new_authorized_pubkey, vote_authorize),
255 account_metas,
256 )
257}
258
259pub fn authorize_checked(
260 vote_pubkey: &Pubkey,
261 authorized_pubkey: &Pubkey, new_authorized_pubkey: &Pubkey,
263 vote_authorize: VoteAuthorize,
264) -> Instruction {
265 let account_metas = vec![
266 AccountMeta::new(*vote_pubkey, false),
267 AccountMeta::new_readonly(sysvar::clock::id(), false),
268 AccountMeta::new_readonly(*authorized_pubkey, true),
269 AccountMeta::new_readonly(*new_authorized_pubkey, true),
270 ];
271
272 Instruction::new_with_bincode(
273 id(),
274 &VoteInstruction::AuthorizeChecked(vote_authorize),
275 account_metas,
276 )
277}
278
279pub fn authorize_with_seed(
280 vote_pubkey: &Pubkey,
281 current_authority_base_key: &Pubkey,
282 current_authority_derived_key_owner: &Pubkey,
283 current_authority_derived_key_seed: &str,
284 new_authority: &Pubkey,
285 authorization_type: VoteAuthorize,
286) -> Instruction {
287 let account_metas = vec![
288 AccountMeta::new(*vote_pubkey, false),
289 AccountMeta::new_readonly(sysvar::clock::id(), false),
290 AccountMeta::new_readonly(*current_authority_base_key, true),
291 ];
292
293 Instruction::new_with_bincode(
294 id(),
295 &VoteInstruction::AuthorizeWithSeed(VoteAuthorizeWithSeedArgs {
296 authorization_type,
297 current_authority_derived_key_owner: *current_authority_derived_key_owner,
298 current_authority_derived_key_seed: current_authority_derived_key_seed.to_string(),
299 new_authority: *new_authority,
300 }),
301 account_metas,
302 )
303}
304
305pub fn authorize_checked_with_seed(
306 vote_pubkey: &Pubkey,
307 current_authority_base_key: &Pubkey,
308 current_authority_derived_key_owner: &Pubkey,
309 current_authority_derived_key_seed: &str,
310 new_authority: &Pubkey,
311 authorization_type: VoteAuthorize,
312) -> Instruction {
313 let account_metas = vec![
314 AccountMeta::new(*vote_pubkey, false),
315 AccountMeta::new_readonly(sysvar::clock::id(), false),
316 AccountMeta::new_readonly(*current_authority_base_key, true),
317 AccountMeta::new_readonly(*new_authority, true),
318 ];
319
320 Instruction::new_with_bincode(
321 id(),
322 &VoteInstruction::AuthorizeCheckedWithSeed(VoteAuthorizeCheckedWithSeedArgs {
323 authorization_type,
324 current_authority_derived_key_owner: *current_authority_derived_key_owner,
325 current_authority_derived_key_seed: current_authority_derived_key_seed.to_string(),
326 }),
327 account_metas,
328 )
329}
330
331pub fn update_validator_identity(
332 vote_pubkey: &Pubkey,
333 authorized_withdrawer_pubkey: &Pubkey,
334 node_pubkey: &Pubkey,
335) -> Instruction {
336 let account_metas = vec![
337 AccountMeta::new(*vote_pubkey, false),
338 AccountMeta::new_readonly(*node_pubkey, true),
339 AccountMeta::new_readonly(*authorized_withdrawer_pubkey, true),
340 ];
341
342 Instruction::new_with_bincode(
343 id(),
344 &VoteInstruction::UpdateValidatorIdentity,
345 account_metas,
346 )
347}
348
349pub fn update_commission(
350 vote_pubkey: &Pubkey,
351 authorized_withdrawer_pubkey: &Pubkey,
352 commission: u8,
353) -> Instruction {
354 let account_metas = vec![
355 AccountMeta::new(*vote_pubkey, false),
356 AccountMeta::new_readonly(*authorized_withdrawer_pubkey, true),
357 ];
358
359 Instruction::new_with_bincode(
360 id(),
361 &VoteInstruction::UpdateCommission(commission),
362 account_metas,
363 )
364}
365
366pub fn vote(vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, vote: Vote) -> Instruction {
367 let account_metas = vec![
368 AccountMeta::new(*vote_pubkey, false),
369 AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
370 AccountMeta::new_readonly(sysvar::clock::id(), false),
371 AccountMeta::new_readonly(*authorized_voter_pubkey, true),
372 ];
373
374 Instruction::new_with_bincode(id(), &VoteInstruction::Vote(vote), account_metas)
375}
376
377pub fn vote_switch(
378 vote_pubkey: &Pubkey,
379 authorized_voter_pubkey: &Pubkey,
380 vote: Vote,
381 proof_hash: Hash,
382) -> Instruction {
383 let account_metas = vec![
384 AccountMeta::new(*vote_pubkey, false),
385 AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
386 AccountMeta::new_readonly(sysvar::clock::id(), false),
387 AccountMeta::new_readonly(*authorized_voter_pubkey, true),
388 ];
389
390 Instruction::new_with_bincode(
391 id(),
392 &VoteInstruction::VoteSwitch(vote, proof_hash),
393 account_metas,
394 )
395}
396
397pub fn update_vote_state(
398 vote_pubkey: &Pubkey,
399 authorized_voter_pubkey: &Pubkey,
400 vote_state_update: VoteStateUpdate,
401) -> Instruction {
402 let account_metas = vec![
403 AccountMeta::new(*vote_pubkey, false),
404 AccountMeta::new_readonly(*authorized_voter_pubkey, true),
405 ];
406
407 Instruction::new_with_bincode(
408 id(),
409 &VoteInstruction::UpdateVoteState(vote_state_update),
410 account_metas,
411 )
412}
413
414pub fn update_vote_state_switch(
415 vote_pubkey: &Pubkey,
416 authorized_voter_pubkey: &Pubkey,
417 vote_state_update: VoteStateUpdate,
418 proof_hash: Hash,
419) -> Instruction {
420 let account_metas = vec![
421 AccountMeta::new(*vote_pubkey, false),
422 AccountMeta::new_readonly(*authorized_voter_pubkey, true),
423 ];
424
425 Instruction::new_with_bincode(
426 id(),
427 &VoteInstruction::UpdateVoteStateSwitch(vote_state_update, proof_hash),
428 account_metas,
429 )
430}
431
432pub fn compact_update_vote_state(
433 vote_pubkey: &Pubkey,
434 authorized_voter_pubkey: &Pubkey,
435 vote_state_update: VoteStateUpdate,
436) -> Instruction {
437 let account_metas = vec![
438 AccountMeta::new(*vote_pubkey, false),
439 AccountMeta::new_readonly(*authorized_voter_pubkey, true),
440 ];
441
442 Instruction::new_with_bincode(
443 id(),
444 &VoteInstruction::CompactUpdateVoteState(vote_state_update),
445 account_metas,
446 )
447}
448
449pub fn compact_update_vote_state_switch(
450 vote_pubkey: &Pubkey,
451 authorized_voter_pubkey: &Pubkey,
452 vote_state_update: VoteStateUpdate,
453 proof_hash: Hash,
454) -> Instruction {
455 let account_metas = vec![
456 AccountMeta::new(*vote_pubkey, false),
457 AccountMeta::new_readonly(*authorized_voter_pubkey, true),
458 ];
459
460 Instruction::new_with_bincode(
461 id(),
462 &VoteInstruction::CompactUpdateVoteStateSwitch(vote_state_update, proof_hash),
463 account_metas,
464 )
465}
466
467pub fn withdraw(
468 vote_pubkey: &Pubkey,
469 authorized_withdrawer_pubkey: &Pubkey,
470 scoobies: u64,
471 to_pubkey: &Pubkey,
472) -> Instruction {
473 let account_metas = vec![
474 AccountMeta::new(*vote_pubkey, false),
475 AccountMeta::new(*to_pubkey, false),
476 AccountMeta::new_readonly(*authorized_withdrawer_pubkey, true),
477 ];
478
479 Instruction::new_with_bincode(id(), &VoteInstruction::Withdraw(scoobies), account_metas)
480}