From 94b5835738d3976e79b6df099ce6e5f56f7af663 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 19 Mar 2019 15:25:48 -0600 Subject: [PATCH] Make AccountMeta a traditional struct instead of a tuple struct --- programs/budget_api/src/budget_instruction.rs | 22 +++++---- programs/config_api/src/config_instruction.rs | 4 +- .../rewards_api/src/rewards_instruction.rs | 5 +- programs/vote/tests/vote.rs | 2 +- programs/vote_api/src/vote_instruction.rs | 10 ++-- runtime/src/bank_client.rs | 2 +- runtime/src/system_program.rs | 4 +- sdk/src/script.rs | 47 ++++++++++--------- sdk/src/system_instruction.rs | 12 ++++- sdk/src/transaction.rs | 28 +++++++---- 10 files changed, 82 insertions(+), 54 deletions(-) diff --git a/programs/budget_api/src/budget_instruction.rs b/programs/budget_api/src/budget_instruction.rs index 7cd6f796c7..4b1b8825c0 100644 --- a/programs/budget_api/src/budget_instruction.rs +++ b/programs/budget_api/src/budget_instruction.rs @@ -31,9 +31,9 @@ impl BudgetInstruction { pub fn new_initialize_account(contract: &Pubkey, expr: BudgetExpr) -> Instruction { let mut keys = vec![]; if let BudgetExpr::Pay(payment) = &expr { - keys.push(AccountMeta(payment.to, false)); + keys.push(AccountMeta::new(payment.to, false)); } - keys.push(AccountMeta(*contract, false)); + keys.push(AccountMeta::new(*contract, false)); Instruction::new(id(), &BudgetInstruction::InitializeAccount(expr), keys) } @@ -43,18 +43,24 @@ impl BudgetInstruction { to: &Pubkey, dt: DateTime, ) -> Instruction { - let mut keys = vec![AccountMeta(*from, true), AccountMeta(*contract, false)]; + let mut account_metas = vec![ + AccountMeta::new(*from, true), + AccountMeta::new(*contract, false), + ]; if from != to { - keys.push(AccountMeta(*to, false)); + account_metas.push(AccountMeta::new(*to, false)); } - Instruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), keys) + Instruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), account_metas) } pub fn new_apply_signature(from: &Pubkey, contract: &Pubkey, to: &Pubkey) -> Instruction { - let mut keys = vec![AccountMeta(*from, true), AccountMeta(*contract, false)]; + let mut account_metas = vec![ + AccountMeta::new(*from, true), + AccountMeta::new(*contract, false), + ]; if from != to { - keys.push(AccountMeta(*to, false)); + account_metas.push(AccountMeta::new(*to, false)); } - Instruction::new(id(), &BudgetInstruction::ApplySignature, keys) + Instruction::new(id(), &BudgetInstruction::ApplySignature, account_metas) } } diff --git a/programs/config_api/src/config_instruction.rs b/programs/config_api/src/config_instruction.rs index 2953bfda79..f3fdca44de 100644 --- a/programs/config_api/src/config_instruction.rs +++ b/programs/config_api/src/config_instruction.rs @@ -29,8 +29,8 @@ impl ConfigInstruction { data: &T, ) -> Instruction { let account_metas = vec![ - AccountMeta(*from_account_pubkey, true), - AccountMeta(*config_account_pubkey, true), + AccountMeta::new(*from_account_pubkey, true), + AccountMeta::new(*config_account_pubkey, true), ]; Instruction::new(id(), data, account_metas) } diff --git a/programs/rewards_api/src/rewards_instruction.rs b/programs/rewards_api/src/rewards_instruction.rs index 6018b3297a..2ab10f9fb8 100644 --- a/programs/rewards_api/src/rewards_instruction.rs +++ b/programs/rewards_api/src/rewards_instruction.rs @@ -10,7 +10,10 @@ pub enum RewardsInstruction { impl RewardsInstruction { pub fn new_redeem_vote_credits(vote_id: &Pubkey, rewards_id: &Pubkey) -> Instruction { - let account_metas = vec![AccountMeta(*vote_id, true), AccountMeta(*rewards_id, false)]; + let account_metas = vec![ + AccountMeta::new(*vote_id, true), + AccountMeta::new(*rewards_id, false), + ]; Instruction::new(id(), &RewardsInstruction::RedeemVoteCredits, account_metas) } } diff --git a/programs/vote/tests/vote.rs b/programs/vote/tests/vote.rs index d313d0e8cf..5a07f3f013 100644 --- a/programs/vote/tests/vote.rs +++ b/programs/vote/tests/vote.rs @@ -114,7 +114,7 @@ fn test_vote_via_bank_with_no_signature() { let vote_ix = Instruction::new( solana_vote_api::id(), &VoteInstruction::Vote(Vote::new(0)), - vec![AccountMeta(vote_id, false)], // <--- attack!! No signature. + vec![AccountMeta::new(vote_id, false)], // <--- attack!! No signer required. ); // Sneak in an instruction so that the transaction is signed but diff --git a/programs/vote_api/src/vote_instruction.rs b/programs/vote_api/src/vote_instruction.rs index 13c13d5c79..e7b7642522 100644 --- a/programs/vote_api/src/vote_instruction.rs +++ b/programs/vote_api/src/vote_instruction.rs @@ -33,11 +33,11 @@ pub enum VoteInstruction { impl VoteInstruction { pub fn new_clear_credits(vote_id: &Pubkey) -> Instruction { - let account_metas = vec![AccountMeta(*vote_id, true)]; + let account_metas = vec![AccountMeta::new(*vote_id, true)]; Instruction::new(id(), &VoteInstruction::ClearCredits, account_metas) } pub fn new_delegate_stake(vote_id: &Pubkey, delegate_id: &Pubkey) -> Instruction { - let account_metas = vec![AccountMeta(*vote_id, true)]; + let account_metas = vec![AccountMeta::new(*vote_id, true)]; Instruction::new( id(), &VoteInstruction::DelegateStake(*delegate_id), @@ -45,7 +45,7 @@ impl VoteInstruction { ) } pub fn new_authorize_voter(vote_id: &Pubkey, authorized_voter_id: &Pubkey) -> Instruction { - let account_metas = vec![AccountMeta(*vote_id, true)]; + let account_metas = vec![AccountMeta::new(*vote_id, true)]; Instruction::new( id(), &VoteInstruction::AuthorizeVoter(*authorized_voter_id), @@ -53,11 +53,11 @@ impl VoteInstruction { ) } pub fn new_initialize_account(vote_id: &Pubkey) -> Instruction { - let account_metas = vec![AccountMeta(*vote_id, false)]; + let account_metas = vec![AccountMeta::new(*vote_id, false)]; Instruction::new(id(), &VoteInstruction::InitializeAccount, account_metas) } pub fn new_vote(vote_id: &Pubkey, vote: Vote) -> Instruction { - let account_metas = vec![AccountMeta(*vote_id, true)]; + let account_metas = vec![AccountMeta::new(*vote_id, true)]; Instruction::new(id(), &VoteInstruction::Vote(vote), account_metas) } } diff --git a/runtime/src/bank_client.rs b/runtime/src/bank_client.rs index d67c009b95..b66f2f2782 100644 --- a/runtime/src/bank_client.rs +++ b/runtime/src/bank_client.rs @@ -84,7 +84,7 @@ mod tests { SystemInstruction::new_move(&doe_client.pubkey(), &bob_pubkey, 42); move_instruction .accounts - .push(AccountMeta(jane_pubkey, true)); + .push(AccountMeta::new(jane_pubkey, true)); doe_client.process_instruction(move_instruction).unwrap(); assert_eq!(bank.get_balance(&bob_pubkey), 42); diff --git a/runtime/src/system_program.rs b/runtime/src/system_program.rs index ccaa593fa9..ed24ad1ac1 100644 --- a/runtime/src/system_program.rs +++ b/runtime/src/system_program.rs @@ -292,8 +292,8 @@ mod tests { // Erroneously sign transaction with recipient account key // No signature case is tested by bank `test_zero_signatures()` let account_metas = vec![ - AccountMeta(alice_pubkey, false), - AccountMeta(mallory_pubkey, true), + AccountMeta::new(alice_pubkey, false), + AccountMeta::new(mallory_pubkey, true), ]; let malicious_script = Script::new(vec![Instruction::new( system_program::id(), diff --git a/sdk/src/script.rs b/sdk/src/script.rs index e8ca5c0ccd..e2e01faccd 100644 --- a/sdk/src/script.rs +++ b/sdk/src/script.rs @@ -2,7 +2,7 @@ use crate::hash::Hash; use crate::pubkey::Pubkey; -use crate::transaction::{AccountMeta, CompiledInstruction, Instruction, Transaction}; +use crate::transaction::{CompiledInstruction, Instruction, Transaction}; use itertools::Itertools; fn position(keys: &[Pubkey], key: &Pubkey) -> u8 { @@ -17,7 +17,7 @@ fn compile_instruction( let accounts: Vec<_> = ix .accounts .iter() - .map(|AccountMeta(k, _)| position(keys, k)) + .map(|account_meta| position(keys, &account_meta.pubkey)) .collect(); CompiledInstruction { @@ -56,15 +56,15 @@ impl Script { .iter() .flat_map(|ix| ix.accounts.iter()) .collect(); - keys_and_signed.sort_by(|x, y| y.1.cmp(&x.1)); + keys_and_signed.sort_by(|x, y| y.is_signer.cmp(&x.is_signer)); let mut signed_keys = vec![]; let mut unsigned_keys = vec![]; - for AccountMeta(key, signed) in keys_and_signed.into_iter().unique_by(|x| x.0) { - if *signed { - signed_keys.push(*key); + for account_meta in keys_and_signed.into_iter().unique_by(|x| x.pubkey) { + if account_meta.is_signer { + signed_keys.push(account_meta.pubkey); } else { - unsigned_keys.push(*key); + unsigned_keys.push(account_meta.pubkey); } } (signed_keys, unsigned_keys) @@ -101,6 +101,7 @@ impl Script { mod tests { use super::*; use crate::signature::{Keypair, KeypairUtil}; + use crate::transaction::AccountMeta; #[test] fn test_transaction_builder_unique_program_ids() { @@ -144,8 +145,8 @@ mod tests { let program_id = Pubkey::default(); let id0 = Pubkey::default(); let keys = Script::new(vec![ - Instruction::new(program_id, &0, vec![AccountMeta(id0, true)]), - Instruction::new(program_id, &0, vec![AccountMeta(id0, true)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]), ]) .keys(); assert_eq!(keys, (vec![id0], vec![])); @@ -156,8 +157,8 @@ mod tests { let program_id = Pubkey::default(); let id0 = Pubkey::default(); let keys = Script::new(vec![ - Instruction::new(program_id, &0, vec![AccountMeta(id0, false)]), - Instruction::new(program_id, &0, vec![AccountMeta(id0, true)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id0, false)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]), ]) .keys(); assert_eq!(keys, (vec![id0], vec![])); @@ -169,8 +170,8 @@ mod tests { let id0 = Keypair::new().pubkey(); let id1 = Pubkey::default(); // Key less than id0 let keys = Script::new(vec![ - Instruction::new(program_id, &0, vec![AccountMeta(id0, false)]), - Instruction::new(program_id, &0, vec![AccountMeta(id1, false)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id0, false)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id1, false)]), ]) .keys(); assert_eq!(keys, (vec![], vec![id0, id1])); @@ -182,9 +183,9 @@ mod tests { let id0 = Pubkey::default(); let id1 = Keypair::new().pubkey(); let keys = Script::new(vec![ - Instruction::new(program_id, &0, vec![AccountMeta(id0, false)]), - Instruction::new(program_id, &0, vec![AccountMeta(id1, false)]), - Instruction::new(program_id, &0, vec![AccountMeta(id0, true)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id0, false)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id1, false)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]), ]) .keys(); assert_eq!(keys, (vec![id0], vec![id1])); @@ -196,8 +197,8 @@ mod tests { let id0 = Pubkey::default(); let id1 = Keypair::new().pubkey(); let keys = Script::new(vec![ - Instruction::new(program_id, &0, vec![AccountMeta(id0, false)]), - Instruction::new(program_id, &0, vec![AccountMeta(id1, true)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id0, false)]), + Instruction::new(program_id, &0, vec![AccountMeta::new(id1, true)]), ]) .keys(); assert_eq!(keys, (vec![id1], vec![id0])); @@ -208,11 +209,11 @@ mod tests { fn test_transaction_builder_signed_keys_len() { let program_id = Pubkey::default(); let id0 = Pubkey::default(); - let ix = Instruction::new(program_id, &0, vec![AccountMeta(id0, false)]); + let ix = Instruction::new(program_id, &0, vec![AccountMeta::new(id0, false)]); let tx = Script::new(vec![ix]).compile(); assert_eq!(tx.signatures.capacity(), 0); - let ix = Instruction::new(program_id, &0, vec![AccountMeta(id0, true)]); + let ix = Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]); let tx = Script::new(vec![ix]).compile(); assert_eq!(tx.signatures.capacity(), 1); } @@ -225,9 +226,9 @@ mod tests { let keypair1 = Keypair::new(); let id1 = keypair1.pubkey(); let tx = Script::new(vec![ - Instruction::new(program_id0, &0, vec![AccountMeta(id0, false)]), - Instruction::new(program_id1, &0, vec![AccountMeta(id1, true)]), - Instruction::new(program_id0, &0, vec![AccountMeta(id1, false)]), + Instruction::new(program_id0, &0, vec![AccountMeta::new(id0, false)]), + Instruction::new(program_id1, &0, vec![AccountMeta::new(id1, true)]), + Instruction::new(program_id0, &0, vec![AccountMeta::new(id1, false)]), ]) .compile(); assert_eq!(tx.instructions[0], CompiledInstruction::new(0, &0, vec![1])); diff --git a/sdk/src/system_instruction.rs b/sdk/src/system_instruction.rs index 0518db065a..52f7112adc 100644 --- a/sdk/src/system_instruction.rs +++ b/sdk/src/system_instruction.rs @@ -39,6 +39,10 @@ impl SystemInstruction { space: u64, program_id: &Pubkey, ) -> Instruction { + let account_metas = vec![ + AccountMeta::new(*from_id, true), + AccountMeta::new(*to_id, false), + ]; Instruction::new( system_program::id(), &SystemInstruction::CreateAccount { @@ -46,15 +50,19 @@ impl SystemInstruction { space, program_id: *program_id, }, - vec![AccountMeta(*from_id, true), AccountMeta(*to_id, false)], + account_metas, ) } pub fn new_move(from_id: &Pubkey, to_id: &Pubkey, lamports: u64) -> Instruction { + let account_metas = vec![ + AccountMeta::new(*from_id, true), + AccountMeta::new(*to_id, false), + ]; Instruction::new( system_program::id(), &SystemInstruction::Move { lamports }, - vec![AccountMeta(*from_id, true), AccountMeta(*to_id, false)], + account_metas, ) } } diff --git a/sdk/src/transaction.rs b/sdk/src/transaction.rs index 09000007dd..9e3c85256d 100644 --- a/sdk/src/transaction.rs +++ b/sdk/src/transaction.rs @@ -100,9 +100,19 @@ impl GenericInstruction { } } -/// An account's pubkey and a Boolean that is true if an Instruciton -/// requires a Transaction signature corresponding to this key. -pub struct AccountMeta(pub Pubkey, pub bool); +/// Account metadata used to define Instructions +pub struct AccountMeta { + /// An account's public key + pub pubkey: Pubkey, + /// True if an Instruciton requires a Transaction signature matching `pubkey`. + pub is_signer: bool, +} + +impl AccountMeta { + pub fn new(pubkey: Pubkey, is_signer: bool) -> Self { + Self { pubkey, is_signer } + } +} pub type Instruction = GenericInstruction; pub type CompiledInstruction = GenericInstruction; @@ -213,11 +223,11 @@ impl Transaction { recent_blockhash: Hash, fee: u64, ) -> Self { - let mut account_keys = vec![AccountMeta(*from_pubkey, true)]; + let mut account_metas = vec![AccountMeta::new(*from_pubkey, true)]; for pubkey in transaction_keys { - account_keys.push(AccountMeta(*pubkey, false)); + account_metas.push(AccountMeta::new(*pubkey, false)); } - let instruction = Instruction::new(*program_id, data, account_keys); + let instruction = Instruction::new(*program_id, data, account_metas); let mut transaction = Self::new(vec![instruction]); transaction.fee = fee; transaction.recent_blockhash = recent_blockhash; @@ -709,7 +719,7 @@ mod tests { let program_id = Pubkey::default(); let keypair0 = Keypair::new(); let id0 = keypair0.pubkey(); - let ix = Instruction::new(program_id, &0, vec![AccountMeta(id0, true)]); + let ix = Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]); Transaction::new(vec![ix]).sign(&Vec::<&Keypair>::new(), Hash::default()); } @@ -719,7 +729,7 @@ mod tests { let program_id = Pubkey::default(); let keypair0 = Keypair::new(); let wrong_id = Pubkey::default(); - let ix = Instruction::new(program_id, &0, vec![AccountMeta(wrong_id, true)]); + let ix = Instruction::new(program_id, &0, vec![AccountMeta::new(wrong_id, true)]); Transaction::new(vec![ix]).sign(&[&keypair0], Hash::default()); } @@ -728,7 +738,7 @@ mod tests { let program_id = Pubkey::default(); let keypair0 = Keypair::new(); let id0 = keypair0.pubkey(); - let ix = Instruction::new(program_id, &0, vec![AccountMeta(id0, true)]); + let ix = Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]); let mut tx = Transaction::new(vec![ix]); tx.sign(&[&keypair0], Hash::default()); assert_eq!(tx.instructions[0], CompiledInstruction::new(0, &0, vec![0]));