From 9077a94dfecfd85a11c1dd27db040d8fc8ca3d73 Mon Sep 17 00:00:00 2001 From: Rob Walker Date: Tue, 3 Dec 2019 22:50:08 -0800 Subject: [PATCH] vote update node_id (#7253) * vote update node_id * un-break binary 'contract' --- programs/vote/src/vote_instruction.rs | 29 +++++++++++++++++++++ programs/vote/src/vote_state.rs | 37 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/programs/vote/src/vote_instruction.rs b/programs/vote/src/vote_instruction.rs index 70f4d3902d..090e7d9958 100644 --- a/programs/vote/src/vote_instruction.rs +++ b/programs/vote/src/vote_instruction.rs @@ -54,6 +54,9 @@ pub enum VoteInstruction { /// Withdraw some amount of funds Withdraw(u64), + + /// Update the vote account's node id + UpdateNode(Pubkey), } fn initialize_account(vote_pubkey: &Pubkey, vote_init: &VoteInit) -> Instruction { @@ -96,6 +99,20 @@ pub fn authorize( ) } +pub fn update_node( + vote_pubkey: &Pubkey, // vote account + authorized_pubkey: &Pubkey, // currently authorized + node_pubkey: &Pubkey, +) -> Instruction { + let account_metas = vec![AccountMeta::new(*vote_pubkey, false)].with_signer(authorized_pubkey); + + Instruction::new( + id(), + &VoteInstruction::UpdateNode(*node_pubkey), + account_metas, + ) +} + pub fn vote(vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, vote: Vote) -> Instruction { let account_metas = vec![ AccountMeta::new(*vote_pubkey, false), @@ -145,6 +162,9 @@ pub fn process_instruction( VoteInstruction::Authorize(voter_pubkey, vote_authorize) => { vote_state::authorize(me, &voter_pubkey, vote_authorize, &signers) } + VoteInstruction::UpdateNode(node_pubkey) => { + vote_state::update_node(me, &node_pubkey, &signers) + } VoteInstruction::Vote(vote) => { datapoint_debug!("vote-native", ("count", 1, i64)); vote_state::process_vote( @@ -237,6 +257,15 @@ mod tests { )), Err(InstructionError::InvalidAccountData), ); + assert_eq!( + process_instruction(&update_node( + &Pubkey::default(), + &Pubkey::default(), + &Pubkey::default(), + )), + Err(InstructionError::InvalidAccountData), + ); + assert_eq!( process_instruction(&withdraw( &Pubkey::default(), diff --git a/programs/vote/src/vote_state.rs b/programs/vote/src/vote_state.rs index ba7882bbfd..f7d24d2eff 100644 --- a/programs/vote/src/vote_state.rs +++ b/programs/vote/src/vote_state.rs @@ -367,6 +367,22 @@ pub fn authorize( vote_account.set_state(&vote_state) } +/// Update the node_pubkey, requires signature of the authorized voter +pub fn update_node( + vote_account: &mut KeyedAccount, + node_pubkey: &Pubkey, + signers: &HashSet, +) -> Result<(), InstructionError> { + let mut vote_state: VoteState = vote_account.state()?; + + // current authorized voter must say "yay" + verify_authorized_signer(&vote_state.authorized_voter, signers)?; + + vote_state.node_pubkey = *node_pubkey; + + vote_account.set_state(&vote_state) +} + fn verify_authorized_signer( authorized: &Pubkey, signers: &HashSet, @@ -621,6 +637,27 @@ mod tests { ); } + #[test] + fn test_vote_update_node_id() { + let (vote_pubkey, mut vote_account) = create_test_account(); + + let node_pubkey = Pubkey::new_rand(); + + let keyed_accounts = &mut [KeyedAccount::new(&vote_pubkey, false, &mut vote_account)]; + let signers = get_signers(keyed_accounts); + let res = update_node(&mut keyed_accounts[0], &node_pubkey, &signers); + assert_eq!(res, Err(InstructionError::MissingRequiredSignature)); + let vote_state: VoteState = vote_account.state().unwrap(); + assert!(vote_state.node_pubkey != node_pubkey); + + let keyed_accounts = &mut [KeyedAccount::new(&vote_pubkey, true, &mut vote_account)]; + let signers = get_signers(keyed_accounts); + let res = update_node(&mut keyed_accounts[0], &node_pubkey, &signers); + assert_eq!(res, Ok(())); + let vote_state: VoteState = vote_account.state().unwrap(); + assert_eq!(vote_state.node_pubkey, node_pubkey); + } + #[test] fn test_vote_signature() { let (vote_pubkey, mut vote_account) = create_test_account();