Pass payer key into get_keys() (#4203)

This commit is contained in:
Michael Vines 2019-05-07 18:48:31 -07:00 committed by GitHub
parent 401764ddb1
commit d10bde656a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 79 additions and 29 deletions

View File

@ -1,7 +1,7 @@
//! A library for generating a message from a sequence of instructions //! A library for generating a message from a sequence of instructions
use crate::hash::Hash; use crate::hash::Hash;
use crate::instruction::{CompiledInstruction, Instruction}; use crate::instruction::{AccountMeta, CompiledInstruction, Instruction};
use crate::pubkey::Pubkey; use crate::pubkey::Pubkey;
use crate::short_vec; use crate::short_vec;
use itertools::Itertools; use itertools::Itertools;
@ -39,14 +39,24 @@ fn compile_instructions(
} }
/// Return pubkeys referenced by all instructions, with the ones needing signatures first. /// Return pubkeys referenced by all instructions, with the ones needing signatures first.
/// If the payer key is provided, it is always placed first in the list of signed keys.
/// No duplicates and order is preserved. /// No duplicates and order is preserved.
fn get_keys(instructions: &[Instruction]) -> (Vec<Pubkey>, Vec<Pubkey>) { fn get_keys(instructions: &[Instruction], payer: Option<&Pubkey>) -> (Vec<Pubkey>, Vec<Pubkey>) {
let mut keys_and_signed: Vec<_> = instructions let mut keys_and_signed: Vec<_> = instructions
.iter() .iter()
.flat_map(|ix| ix.accounts.iter()) .flat_map(|ix| ix.accounts.iter())
.collect(); .collect();
keys_and_signed.sort_by(|x, y| y.is_signer.cmp(&x.is_signer)); keys_and_signed.sort_by(|x, y| y.is_signer.cmp(&x.is_signer));
let payer_account_meta;
if let Some(payer) = payer {
payer_account_meta = AccountMeta {
pubkey: *payer,
is_signer: true,
};
keys_and_signed.insert(0, &payer_account_meta);
}
let mut signed_keys = vec![]; let mut signed_keys = vec![];
let mut unsigned_keys = vec![]; let mut unsigned_keys = vec![];
for account_meta in keys_and_signed.into_iter().unique_by(|x| x.pubkey) { for account_meta in keys_and_signed.into_iter().unique_by(|x| x.pubkey) {
@ -114,12 +124,7 @@ impl Message {
pub fn new_with_payer(instructions: Vec<Instruction>, payer: Option<&Pubkey>) -> Self { pub fn new_with_payer(instructions: Vec<Instruction>, payer: Option<&Pubkey>) -> Self {
let program_ids = get_program_ids(&instructions); let program_ids = get_program_ids(&instructions);
let (mut signed_keys, unsigned_keys) = get_keys(&instructions); let (mut signed_keys, unsigned_keys) = get_keys(&instructions, payer);
if let Some(payer) = payer {
if signed_keys.is_empty() || signed_keys[0] != *payer {
signed_keys.insert(0, *payer);
}
}
let num_required_signatures = signed_keys.len() as u8; let num_required_signatures = signed_keys.len() as u8;
signed_keys.extend(&unsigned_keys); signed_keys.extend(&unsigned_keys);
let instructions = compile_instructions(instructions, &signed_keys, &program_ids); let instructions = compile_instructions(instructions, &signed_keys, &program_ids);
@ -181,10 +186,43 @@ mod tests {
fn test_message_unique_keys_both_signed() { fn test_message_unique_keys_both_signed() {
let program_id = Pubkey::default(); let program_id = Pubkey::default();
let id0 = Pubkey::default(); let id0 = Pubkey::default();
let keys = get_keys(&[ let keys = get_keys(
Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]), &[
Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]), Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]),
]); Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]),
],
None,
);
assert_eq!(keys, (vec![id0], vec![]));
}
#[test]
fn test_message_unique_keys_signed_and_payer() {
let program_id = Pubkey::default();
let id0 = Pubkey::default();
let keys = get_keys(
&[Instruction::new(
program_id,
&0,
vec![AccountMeta::new(id0, true)],
)],
Some(&id0),
);
assert_eq!(keys, (vec![id0], vec![]));
}
#[test]
fn test_message_unique_keys_unsigned_and_payer() {
let program_id = Pubkey::default();
let id0 = Pubkey::default();
let keys = get_keys(
&[Instruction::new(
program_id,
&0,
vec![AccountMeta::new(id0, false)],
)],
Some(&id0),
);
assert_eq!(keys, (vec![id0], vec![])); assert_eq!(keys, (vec![id0], vec![]));
} }
@ -192,10 +230,13 @@ mod tests {
fn test_message_unique_keys_one_signed() { fn test_message_unique_keys_one_signed() {
let program_id = Pubkey::default(); let program_id = Pubkey::default();
let id0 = Pubkey::default(); let id0 = Pubkey::default();
let keys = get_keys(&[ let keys = get_keys(
Instruction::new(program_id, &0, vec![AccountMeta::new(id0, false)]), &[
Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]), Instruction::new(program_id, &0, vec![AccountMeta::new(id0, false)]),
]); Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]),
],
None,
);
assert_eq!(keys, (vec![id0], vec![])); assert_eq!(keys, (vec![id0], vec![]));
} }
@ -204,10 +245,13 @@ mod tests {
let program_id = Pubkey::default(); let program_id = Pubkey::default();
let id0 = Pubkey::new_rand(); let id0 = Pubkey::new_rand();
let id1 = Pubkey::default(); // Key less than id0 let id1 = Pubkey::default(); // Key less than id0
let keys = get_keys(&[ let keys = get_keys(
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, false)]),
]); Instruction::new(program_id, &0, vec![AccountMeta::new(id1, false)]),
],
None,
);
assert_eq!(keys, (vec![], vec![id0, id1])); assert_eq!(keys, (vec![], vec![id0, id1]));
} }
@ -216,11 +260,14 @@ mod tests {
let program_id = Pubkey::default(); let program_id = Pubkey::default();
let id0 = Pubkey::default(); let id0 = Pubkey::default();
let id1 = Pubkey::new_rand(); let id1 = Pubkey::new_rand();
let keys = get_keys(&[ let keys = get_keys(
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, false)]),
Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]), Instruction::new(program_id, &0, vec![AccountMeta::new(id1, false)]),
]); Instruction::new(program_id, &0, vec![AccountMeta::new(id0, true)]),
],
None,
);
assert_eq!(keys, (vec![id0], vec![id1])); assert_eq!(keys, (vec![id0], vec![id1]));
} }
@ -229,10 +276,13 @@ mod tests {
let program_id = Pubkey::default(); let program_id = Pubkey::default();
let id0 = Pubkey::default(); let id0 = Pubkey::default();
let id1 = Pubkey::new_rand(); let id1 = Pubkey::new_rand();
let keys = get_keys(&[ let keys = get_keys(
Instruction::new(program_id, &0, vec![AccountMeta::new(id0, false)]), &[
Instruction::new(program_id, &0, vec![AccountMeta::new(id1, true)]), Instruction::new(program_id, &0, vec![AccountMeta::new(id0, false)]),
]); Instruction::new(program_id, &0, vec![AccountMeta::new(id1, true)]),
],
None,
);
assert_eq!(keys, (vec![id1], vec![id0])); assert_eq!(keys, (vec![id1], vec![id0]));
} }