Refactor instruction compilation and update message account key ordering (#23729)

* Refactor: Make instruction compilation usable for other message versions

* apply trents feedback

* Fix tests

* Fix bpf compatiblity
This commit is contained in:
Justin Starry
2022-03-21 20:53:32 +08:00
committed by GitHub
parent a1a29b0b86
commit 15357480ec
11 changed files with 1212 additions and 972 deletions

View File

@ -160,8 +160,10 @@ mod test {
super::*,
serde_json::Value,
solana_sdk::{
bpf_loader_upgradeable,
message::Message,
pubkey::{self, Pubkey},
system_program, sysvar,
},
};
@ -248,19 +250,16 @@ mod test {
}
#[test]
fn test_parse_bpf_upgradeable_loader_instructions() {
let mut keys: Vec<Pubkey> = vec![];
for _ in 0..8 {
keys.push(Pubkey::new_unique());
}
let offset = 4242;
let bytes = vec![8; 99];
fn test_parse_bpf_upgradeable_loader_create_buffer_ix() {
let max_data_len = 54321;
let instructions = solana_sdk::bpf_loader_upgradeable::create_buffer(
&keys[0],
&keys[1],
&keys[2],
let payer_address = Pubkey::new_unique();
let buffer_address = Pubkey::new_unique();
let authority_address = Pubkey::new_unique();
let instructions = bpf_loader_upgradeable::create_buffer(
&payer_address,
&buffer_address,
&authority_address,
55,
max_data_len,
)
@ -269,30 +268,42 @@ mod test {
assert_eq!(
parse_bpf_upgradeable_loader(
&message.instructions[1],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "initializeBuffer".to_string(),
info: json!({
"account": keys[1].to_string(),
"authority": keys[2].to_string(),
"account": buffer_address.to_string(),
"authority": authority_address.to_string(),
}),
}
);
assert!(parse_bpf_upgradeable_loader(
&message.instructions[1],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
let instruction =
solana_sdk::bpf_loader_upgradeable::write(&keys[1], &keys[0], offset, bytes.clone());
#[test]
fn test_parse_bpf_upgradeable_loader_write_ix() {
let offset = 4242;
let bytes = vec![8; 99];
let buffer_address = Pubkey::new_unique();
let authority_address = Pubkey::new_unique();
let instruction = bpf_loader_upgradeable::write(
&buffer_address,
&authority_address,
offset,
bytes.clone(),
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
@ -300,22 +311,36 @@ mod test {
info: json!({
"offset": offset,
"bytes": base64::encode(&bytes),
"account": keys[1].to_string(),
"authority": keys[0].to_string(),
"account": buffer_address.to_string(),
"authority": authority_address.to_string(),
}),
}
);
assert!(parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}
let instructions = solana_sdk::bpf_loader_upgradeable::deploy_with_max_program_len(
&keys[0],
&keys[1],
&keys[4],
&keys[2],
#[test]
fn test_parse_bpf_upgradeable_loader_deploy_ix() {
let max_data_len = 54321;
let payer_address = Pubkey::new_unique();
let program_address = Pubkey::new_unique();
let buffer_address = Pubkey::new_unique();
let upgrade_authority_address = Pubkey::new_unique();
let programdata_address = Pubkey::find_program_address(
&[program_address.as_ref()],
&bpf_loader_upgradeable::id(),
)
.0;
let instructions = bpf_loader_upgradeable::deploy_with_max_program_len(
&payer_address,
&program_address,
&buffer_address,
&upgrade_authority_address,
55,
max_data_len,
)
@ -324,153 +349,198 @@ mod test {
assert_eq!(
parse_bpf_upgradeable_loader(
&message.instructions[1],
&AccountKeys::new(&keys[0..8], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "deployWithMaxDataLen".to_string(),
info: json!({
"maxDataLen": max_data_len,
"payerAccount": keys[0].to_string(),
"programAccount": keys[1].to_string(),
"authority": keys[2].to_string(),
"programDataAccount": keys[3].to_string(),
"bufferAccount": keys[4].to_string(),
"rentSysvar": keys[5].to_string(),
"clockSysvar": keys[6].to_string(),
"systemProgram": keys[7].to_string(),
"payerAccount": payer_address.to_string(),
"programAccount": program_address.to_string(),
"authority": upgrade_authority_address.to_string(),
"programDataAccount": programdata_address.to_string(),
"bufferAccount": buffer_address.to_string(),
"rentSysvar": sysvar::rent::ID.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"systemProgram": system_program::ID.to_string(),
}),
}
);
assert!(parse_bpf_upgradeable_loader(
&message.instructions[1],
&AccountKeys::new(&keys[0..7], None)
&AccountKeys::new(&message.account_keys[0..7], None)
)
.is_err());
}
let instruction =
solana_sdk::bpf_loader_upgradeable::upgrade(&keys[2], &keys[3], &keys[0], &keys[4]);
#[test]
fn test_parse_bpf_upgradeable_loader_upgrade_ix() {
let program_address = Pubkey::new_unique();
let buffer_address = Pubkey::new_unique();
let authority_address = Pubkey::new_unique();
let spill_address = Pubkey::new_unique();
let programdata_address = Pubkey::find_program_address(
&[program_address.as_ref()],
&bpf_loader_upgradeable::id(),
)
.0;
let instruction = bpf_loader_upgradeable::upgrade(
&program_address,
&buffer_address,
&authority_address,
&spill_address,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..7], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "upgrade".to_string(),
info: json!({
"authority": keys[0].to_string(),
"programDataAccount": keys[1].to_string(),
"programAccount": keys[2].to_string(),
"bufferAccount": keys[3].to_string(),
"spillAccount": keys[4].to_string(),
"rentSysvar": keys[5].to_string(),
"clockSysvar": keys[6].to_string(),
"authority": authority_address.to_string(),
"programDataAccount": programdata_address.to_string(),
"programAccount": program_address.to_string(),
"bufferAccount": buffer_address.to_string(),
"spillAccount": spill_address.to_string(),
"rentSysvar": sysvar::rent::ID.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
}),
}
);
assert!(parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..6], None)
&AccountKeys::new(&message.account_keys[0..6], None)
)
.is_err());
}
let instruction =
solana_sdk::bpf_loader_upgradeable::set_buffer_authority(&keys[1], &keys[0], &keys[2]);
#[test]
fn test_parse_bpf_upgradeable_loader_set_buffer_authority_ix() {
let buffer_address = Pubkey::new_unique();
let current_authority_address = Pubkey::new_unique();
let new_authority_address = Pubkey::new_unique();
let instruction = bpf_loader_upgradeable::set_buffer_authority(
&buffer_address,
&current_authority_address,
&new_authority_address,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "setAuthority".to_string(),
info: json!({
"account": keys[1].to_string(),
"authority": keys[0].to_string(),
"newAuthority": keys[2].to_string(),
"account": buffer_address.to_string(),
"authority": current_authority_address.to_string(),
"newAuthority": new_authority_address.to_string(),
}),
}
);
assert!(parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}
let instruction = solana_sdk::bpf_loader_upgradeable::set_upgrade_authority(
&keys[1],
&keys[0],
Some(&keys[2]),
#[test]
fn test_parse_bpf_upgradeable_loader_set_upgrade_authority_ix() {
let program_address = Pubkey::new_unique();
let current_authority_address = Pubkey::new_unique();
let new_authority_address = Pubkey::new_unique();
let (programdata_address, _) = Pubkey::find_program_address(
&[program_address.as_ref()],
&bpf_loader_upgradeable::id(),
);
let instruction = bpf_loader_upgradeable::set_upgrade_authority(
&program_address,
&current_authority_address,
Some(&new_authority_address),
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "setAuthority".to_string(),
info: json!({
"account": keys[1].to_string(),
"authority": keys[0].to_string(),
"newAuthority": keys[2].to_string(),
"account": programdata_address.to_string(),
"authority": current_authority_address.to_string(),
"newAuthority": new_authority_address.to_string(),
}),
}
);
assert!(parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
let instruction =
solana_sdk::bpf_loader_upgradeable::set_upgrade_authority(&keys[1], &keys[0], None);
let instruction = bpf_loader_upgradeable::set_upgrade_authority(
&program_address,
&current_authority_address,
None,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "setAuthority".to_string(),
info: json!({
"account": keys[1].to_string(),
"authority": keys[0].to_string(),
"account": programdata_address.to_string(),
"authority": current_authority_address.to_string(),
"newAuthority": Value::Null,
}),
}
);
assert!(parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}
let instruction = solana_sdk::bpf_loader_upgradeable::close(&keys[0], &keys[1], &keys[2]);
#[test]
fn test_parse_bpf_upgradeable_loader_close_ix() {
let close_address = Pubkey::new_unique();
let recipient_address = Pubkey::new_unique();
let authority_address = Pubkey::new_unique();
let instruction =
bpf_loader_upgradeable::close(&close_address, &recipient_address, &authority_address);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "close".to_string(),
info: json!({
"account": keys[1].to_string(),
"recipient": keys[2].to_string(),
"authority": keys[0].to_string(),
"account": close_address.to_string(),
"recipient": recipient_address.to_string(),
"authority": authority_address.to_string(),
}),
}
);
assert!(parse_bpf_upgradeable_loader(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}

View File

@ -284,20 +284,18 @@ mod test {
message::Message,
pubkey::Pubkey,
stake::{
config,
instruction::{self, LockupArgs},
state::{Authorized, Lockup, StakeAuthorize},
},
sysvar,
},
};
#[test]
#[allow(clippy::same_item_push)]
fn test_parse_stake_instruction() {
let mut keys: Vec<Pubkey> = vec![];
for _ in 0..6 {
keys.push(Pubkey::new_unique());
}
fn test_parse_stake_initialize_ix() {
let from_pubkey = Pubkey::new_unique();
let stake_pubkey = Pubkey::new_unique();
let authorized = Authorized {
staker: Pubkey::new_unique(),
withdrawer: Pubkey::new_unique(),
@ -309,20 +307,25 @@ mod test {
};
let lamports = 55;
let instructions =
instruction::create_account(&keys[0], &keys[1], &authorized, &lockup, lamports);
let instructions = instruction::create_account(
&from_pubkey,
&stake_pubkey,
&authorized,
&lockup,
lamports,
);
let message = Message::new(&instructions, None);
assert_eq!(
parse_stake(
&message.instructions[1],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "initialize".to_string(),
info: json!({
"stakeAccount": keys[1].to_string(),
"rentSysvar": keys[2].to_string(),
"stakeAccount": stake_pubkey.to_string(),
"rentSysvar": sysvar::rent::ID.to_string(),
"authorized": {
"staker": authorized.staker.to_string(),
"withdrawer": authorized.withdrawer.to_string(),
@ -337,225 +340,21 @@ mod test {
);
assert!(parse_stake(
&message.instructions[1],
&AccountKeys::new(&keys[0..2], None)
)
.is_err());
let instruction =
instruction::authorize(&keys[1], &keys[0], &keys[3], StakeAuthorize::Staker, None);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorize".to_string(),
info: json!({
"stakeAccount": keys[1].to_string(),
"clockSysvar": keys[2].to_string(),
"authority": keys[0].to_string(),
"newAuthority": keys[3].to_string(),
"authorityType": StakeAuthorize::Staker,
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
#[test]
fn test_parse_stake_authorize_ix() {
let stake_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let new_authorized_pubkey = Pubkey::new_unique();
let custodian_pubkey = Pubkey::new_unique();
let instruction = instruction::authorize(
&keys[2],
&keys[0],
&keys[4],
StakeAuthorize::Withdrawer,
Some(&keys[1]),
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorize".to_string(),
info: json!({
"stakeAccount": keys[2].to_string(),
"clockSysvar": keys[3].to_string(),
"authority": keys[0].to_string(),
"newAuthority": keys[4].to_string(),
"authorityType": StakeAuthorize::Withdrawer,
"custodian": keys[1].to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
)
.is_err());
let instruction = instruction::delegate_stake(&keys[1], &keys[0], &keys[2]);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..6], None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "delegate".to_string(),
info: json!({
"stakeAccount": keys[1].to_string(),
"voteAccount": keys[2].to_string(),
"clockSysvar": keys[3].to_string(),
"stakeHistorySysvar": keys[4].to_string(),
"stakeConfigAccount": keys[5].to_string(),
"stakeAuthority": keys[0].to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..5], None)
)
.is_err());
// This looks wrong, but in an actual compiled instruction, the order is:
// * split account (signer, allocate + assign first)
// * stake authority (signer)
// * stake account
let instructions = instruction::split(&keys[2], &keys[1], lamports, &keys[0]);
let message = Message::new(&instructions, None);
assert_eq!(
parse_stake(
&message.instructions[2],
&AccountKeys::new(&keys[0..3], None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "split".to_string(),
info: json!({
"stakeAccount": keys[2].to_string(),
"newSplitAccount": keys[0].to_string(),
"stakeAuthority": keys[1].to_string(),
"lamports": lamports,
}),
}
);
assert!(parse_stake(
&message.instructions[2],
&AccountKeys::new(&keys[0..2], None)
)
.is_err());
let instruction = instruction::withdraw(&keys[1], &keys[0], &keys[2], lamports, None);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..5], None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "withdraw".to_string(),
info: json!({
"stakeAccount": keys[1].to_string(),
"destination": keys[2].to_string(),
"clockSysvar": keys[3].to_string(),
"stakeHistorySysvar": keys[4].to_string(),
"withdrawAuthority": keys[0].to_string(),
"lamports": lamports,
}),
}
);
let instruction =
instruction::withdraw(&keys[2], &keys[0], &keys[3], lamports, Some(&keys[1]));
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..6], None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "withdraw".to_string(),
info: json!({
"stakeAccount": keys[2].to_string(),
"destination": keys[3].to_string(),
"clockSysvar": keys[4].to_string(),
"stakeHistorySysvar": keys[5].to_string(),
"withdrawAuthority": keys[0].to_string(),
"custodian": keys[1].to_string(),
"lamports": lamports,
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
)
.is_err());
let instruction = instruction::deactivate_stake(&keys[1], &keys[0]);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "deactivate".to_string(),
info: json!({
"stakeAccount": keys[1].to_string(),
"clockSysvar": keys[2].to_string(),
"stakeAuthority": keys[0].to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
)
.is_err());
let instructions = instruction::merge(&keys[1], &keys[0], &keys[2]);
let message = Message::new(&instructions, None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..5], None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "merge".to_string(),
info: json!({
"destination": keys[1].to_string(),
"source": keys[2].to_string(),
"clockSysvar": keys[3].to_string(),
"stakeHistorySysvar": keys[4].to_string(),
"stakeAuthority": keys[0].to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
)
.is_err());
let seed = "test_seed";
let instruction = instruction::authorize_with_seed(
&keys[1],
&keys[0],
seed.to_string(),
&keys[0],
&keys[3],
&stake_pubkey,
&authorized_pubkey,
&new_authorized_pubkey,
StakeAuthorize::Staker,
None,
);
@ -563,61 +362,335 @@ mod test {
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeWithSeed".to_string(),
instruction_type: "authorize".to_string(),
info: json!({
"stakeAccount": keys[1].to_string(),
"authorityOwner": keys[0].to_string(),
"newAuthorized": keys[3].to_string(),
"authorityBase": keys[0].to_string(),
"authoritySeed": seed,
"stakeAccount": stake_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"authority": authorized_pubkey.to_string(),
"newAuthority": new_authorized_pubkey.to_string(),
"authorityType": StakeAuthorize::Staker,
"clockSysvar": keys[2].to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
let instruction = instruction::authorize_with_seed(
&keys[2],
&keys[0],
seed.to_string(),
&keys[0],
&keys[4],
let instruction = instruction::authorize(
&stake_pubkey,
&authorized_pubkey,
&new_authorized_pubkey,
StakeAuthorize::Withdrawer,
Some(&keys[1]),
Some(&custodian_pubkey),
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeWithSeed".to_string(),
instruction_type: "authorize".to_string(),
info: json!({
"stakeAccount": keys[2].to_string(),
"authorityOwner": keys[0].to_string(),
"newAuthorized": keys[4].to_string(),
"authorityBase": keys[0].to_string(),
"authoritySeed": seed,
"stakeAccount": stake_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"authority": authorized_pubkey.to_string(),
"newAuthority": new_authorized_pubkey.to_string(),
"authorityType": StakeAuthorize::Withdrawer,
"clockSysvar": keys[3].to_string(),
"custodian": keys[1].to_string(),
"custodian": custodian_pubkey.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
#[test]
fn test_parse_stake_delegate_ix() {
let stake_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let vote_pubkey = Pubkey::new_unique();
let instruction =
instruction::delegate_stake(&stake_pubkey, &authorized_pubkey, &vote_pubkey);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "delegate".to_string(),
info: json!({
"stakeAccount": stake_pubkey.to_string(),
"voteAccount": vote_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"stakeHistorySysvar": sysvar::stake_history::ID.to_string(),
"stakeConfigAccount": config::ID.to_string(),
"stakeAuthority": authorized_pubkey.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys[0..5], None)
)
.is_err());
}
#[test]
fn test_parse_stake_split_ix() {
let lamports = 55;
let stake_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let split_stake_pubkey = Pubkey::new_unique();
let instructions = instruction::split(
&stake_pubkey,
&authorized_pubkey,
lamports,
&split_stake_pubkey,
);
let message = Message::new(&instructions, None);
assert_eq!(
parse_stake(
&message.instructions[2],
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "split".to_string(),
info: json!({
"stakeAccount": stake_pubkey.to_string(),
"newSplitAccount": split_stake_pubkey.to_string(),
"stakeAuthority": authorized_pubkey.to_string(),
"lamports": lamports,
}),
}
);
assert!(parse_stake(
&message.instructions[2],
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
#[test]
fn test_parse_stake_withdraw_ix() {
let lamports = 55;
let stake_pubkey = Pubkey::new_unique();
let withdrawer_pubkey = Pubkey::new_unique();
let to_pubkey = Pubkey::new_unique();
let custodian_pubkey = Pubkey::new_unique();
let instruction = instruction::withdraw(
&stake_pubkey,
&withdrawer_pubkey,
&to_pubkey,
lamports,
None,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "withdraw".to_string(),
info: json!({
"stakeAccount": stake_pubkey.to_string(),
"destination": to_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"stakeHistorySysvar": sysvar::stake_history::ID.to_string(),
"withdrawAuthority": withdrawer_pubkey.to_string(),
"lamports": lamports,
}),
}
);
let instruction = instruction::withdraw(
&stake_pubkey,
&withdrawer_pubkey,
&to_pubkey,
lamports,
Some(&custodian_pubkey),
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "withdraw".to_string(),
info: json!({
"stakeAccount": stake_pubkey.to_string(),
"destination": to_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"stakeHistorySysvar": sysvar::stake_history::ID.to_string(),
"withdrawAuthority": withdrawer_pubkey.to_string(),
"custodian": custodian_pubkey.to_string(),
"lamports": lamports,
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys[0..4], None)
)
.is_err());
}
#[test]
fn test_parse_stake_deactivate_stake_ix() {
let stake_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let instruction = instruction::deactivate_stake(&stake_pubkey, &authorized_pubkey);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "deactivate".to_string(),
info: json!({
"stakeAccount": stake_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"stakeAuthority": authorized_pubkey.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
#[test]
fn test_parse_stake_merge_ix() {
let destination_stake_pubkey = Pubkey::new_unique();
let source_stake_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let instructions = instruction::merge(
&destination_stake_pubkey,
&source_stake_pubkey,
&authorized_pubkey,
);
let message = Message::new(&instructions, None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "merge".to_string(),
info: json!({
"destination": destination_stake_pubkey.to_string(),
"source": source_stake_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"stakeHistorySysvar": sysvar::stake_history::ID.to_string(),
"stakeAuthority": authorized_pubkey.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys[0..4], None)
)
.is_err());
}
#[test]
fn test_parse_stake_authorize_with_seed_ix() {
let stake_pubkey = Pubkey::new_unique();
let authority_base_pubkey = Pubkey::new_unique();
let authority_owner_pubkey = Pubkey::new_unique();
let new_authorized_pubkey = Pubkey::new_unique();
let custodian_pubkey = Pubkey::new_unique();
let seed = "test_seed";
let instruction = instruction::authorize_with_seed(
&stake_pubkey,
&authority_base_pubkey,
seed.to_string(),
&authority_owner_pubkey,
&new_authorized_pubkey,
StakeAuthorize::Staker,
None,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeWithSeed".to_string(),
info: json!({
"stakeAccount": stake_pubkey.to_string(),
"authorityOwner": authority_owner_pubkey.to_string(),
"newAuthorized": new_authorized_pubkey.to_string(),
"authorityBase": authority_base_pubkey.to_string(),
"authoritySeed": seed,
"authorityType": StakeAuthorize::Staker,
"clockSysvar": sysvar::clock::ID.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
let instruction = instruction::authorize_with_seed(
&stake_pubkey,
&authority_base_pubkey,
seed.to_string(),
&authority_owner_pubkey,
&new_authorized_pubkey,
StakeAuthorize::Withdrawer,
Some(&custodian_pubkey),
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeWithSeed".to_string(),
info: json!({
"stakeAccount": stake_pubkey.to_string(),
"authorityOwner": authority_owner_pubkey.to_string(),
"newAuthorized": new_authorized_pubkey.to_string(),
"authorityBase": authority_base_pubkey.to_string(),
"authoritySeed": seed,
"authorityType": StakeAuthorize::Withdrawer,
"clockSysvar": sysvar::clock::ID.to_string(),
"custodian": custodian_pubkey.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&message.account_keys[0..3], None)
)
.is_err());
}
@ -807,48 +880,53 @@ mod test {
}
#[test]
#[allow(clippy::same_item_push)]
fn test_parse_stake_checked_instructions() {
let mut keys: Vec<Pubkey> = vec![];
for _ in 0..6 {
keys.push(Pubkey::new_unique());
}
fn test_parse_stake_create_account_checked_ix() {
let from_pubkey = Pubkey::new_unique();
let stake_pubkey = Pubkey::new_unique();
let authorized = Authorized {
staker: keys[3],
withdrawer: keys[0],
staker: Pubkey::new_unique(),
withdrawer: Pubkey::new_unique(),
};
let lamports = 55;
let instructions =
instruction::create_account_checked(&keys[0], &keys[1], &authorized, lamports);
instruction::create_account_checked(&from_pubkey, &stake_pubkey, &authorized, lamports);
let message = Message::new(&instructions, None);
assert_eq!(
parse_stake(
&message.instructions[1],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "initializeChecked".to_string(),
info: json!({
"stakeAccount": keys[1].to_string(),
"rentSysvar": keys[2].to_string(),
"staker": keys[3].to_string(),
"withdrawer": keys[0].to_string(),
"stakeAccount": stake_pubkey.to_string(),
"rentSysvar": sysvar::rent::ID.to_string(),
"staker": authorized.staker.to_string(),
"withdrawer": authorized.withdrawer.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[1],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys[0..3], None)
)
.is_err());
}
#[test]
fn test_parse_stake_authorize_checked_ix() {
let stake_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let new_authorized_pubkey = Pubkey::new_unique();
let custodian_pubkey = Pubkey::new_unique();
let instruction = instruction::authorize_checked(
&keys[2],
&keys[0],
&keys[1],
&stake_pubkey,
&authorized_pubkey,
&new_authorized_pubkey,
StakeAuthorize::Staker,
None,
);
@ -856,65 +934,74 @@ mod test {
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeChecked".to_string(),
info: json!({
"stakeAccount": keys[2].to_string(),
"clockSysvar": keys[3].to_string(),
"authority": keys[0].to_string(),
"newAuthority": keys[1].to_string(),
"stakeAccount": stake_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"authority": authorized_pubkey.to_string(),
"newAuthority": new_authorized_pubkey.to_string(),
"authorityType": StakeAuthorize::Staker,
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys[0..3], None)
)
.is_err());
let instruction = instruction::authorize_checked(
&keys[3],
&keys[0],
&keys[1],
&stake_pubkey,
&authorized_pubkey,
&new_authorized_pubkey,
StakeAuthorize::Withdrawer,
Some(&keys[2]),
Some(&custodian_pubkey),
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..5], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeChecked".to_string(),
info: json!({
"stakeAccount": keys[3].to_string(),
"clockSysvar": keys[4].to_string(),
"authority": keys[0].to_string(),
"newAuthority": keys[1].to_string(),
"stakeAccount": stake_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"authority": authorized_pubkey.to_string(),
"newAuthority": new_authorized_pubkey.to_string(),
"authorityType": StakeAuthorize::Withdrawer,
"custodian": keys[2].to_string(),
"custodian": custodian_pubkey.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys[0..4], None)
)
.is_err());
}
#[test]
fn test_parse_stake_authorize_checked_with_seed_ix() {
let stake_pubkey = Pubkey::new_unique();
let authority_base_pubkey = Pubkey::new_unique();
let authority_owner_pubkey = Pubkey::new_unique();
let new_authorized_pubkey = Pubkey::new_unique();
let custodian_pubkey = Pubkey::new_unique();
let seed = "test_seed";
let instruction = instruction::authorize_checked_with_seed(
&keys[2],
&keys[0],
&stake_pubkey,
&authority_base_pubkey,
seed.to_string(),
&keys[0],
&keys[1],
&authority_owner_pubkey,
&new_authorized_pubkey,
StakeAuthorize::Staker,
None,
);
@ -922,61 +1009,61 @@ mod test {
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeCheckedWithSeed".to_string(),
info: json!({
"stakeAccount": keys[2].to_string(),
"authorityOwner": keys[0].to_string(),
"newAuthorized": keys[1].to_string(),
"authorityBase": keys[0].to_string(),
"stakeAccount": stake_pubkey.to_string(),
"authorityOwner": authority_owner_pubkey.to_string(),
"newAuthorized": new_authorized_pubkey.to_string(),
"authorityBase": authority_base_pubkey.to_string(),
"authoritySeed": seed,
"authorityType": StakeAuthorize::Staker,
"clockSysvar": keys[3].to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys[0..3], None)
)
.is_err());
let instruction = instruction::authorize_checked_with_seed(
&keys[3],
&keys[0],
&stake_pubkey,
&authority_base_pubkey,
seed.to_string(),
&keys[0],
&keys[1],
&authority_owner_pubkey,
&new_authorized_pubkey,
StakeAuthorize::Withdrawer,
Some(&keys[2]),
Some(&custodian_pubkey),
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..5], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeCheckedWithSeed".to_string(),
info: json!({
"stakeAccount": keys[3].to_string(),
"authorityOwner": keys[0].to_string(),
"newAuthorized": keys[1].to_string(),
"authorityBase": keys[0].to_string(),
"stakeAccount": stake_pubkey.to_string(),
"authorityOwner": authority_owner_pubkey.to_string(),
"newAuthorized": new_authorized_pubkey.to_string(),
"authorityBase": authority_base_pubkey.to_string(),
"authoritySeed": seed,
"authorityType": StakeAuthorize::Withdrawer,
"clockSysvar": keys[4].to_string(),
"custodian": keys[2].to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"custodian": custodian_pubkey.to_string(),
}),
}
);
assert!(parse_stake(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys[0..4], None)
)
.is_err());
}

View File

@ -202,348 +202,423 @@ fn check_num_system_accounts(accounts: &[u8], num: usize) -> Result<(), ParseIns
mod test {
use {
super::*,
solana_sdk::{message::Message, pubkey::Pubkey, system_instruction},
solana_sdk::{message::Message, pubkey::Pubkey, system_instruction, sysvar},
};
#[test]
#[allow(clippy::same_item_push)]
fn test_parse_system_instruction() {
let mut keys: Vec<Pubkey> = vec![];
for _ in 0..6 {
keys.push(solana_sdk::pubkey::new_rand());
}
fn test_parse_system_create_account_ix() {
let lamports = 55;
let space = 128;
let from_pubkey = Pubkey::new_unique();
let to_pubkey = Pubkey::new_unique();
let owner_pubkey = Pubkey::new_unique();
let instruction =
system_instruction::create_account(&keys[0], &keys[1], lamports, space, &keys[2]);
let instruction = system_instruction::create_account(
&from_pubkey,
&to_pubkey,
lamports,
space,
&owner_pubkey,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "createAccount".to_string(),
info: json!({
"source": keys[0].to_string(),
"newAccount": keys[1].to_string(),
"source": from_pubkey.to_string(),
"newAccount": to_pubkey.to_string(),
"lamports": lamports,
"owner": keys[2].to_string(),
"owner": owner_pubkey.to_string(),
"space": space,
}),
}
);
assert!(parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}
let instruction = system_instruction::assign(&keys[0], &keys[1]);
#[test]
fn test_parse_system_assign_ix() {
let account_pubkey = Pubkey::new_unique();
let owner_pubkey = Pubkey::new_unique();
let instruction = system_instruction::assign(&account_pubkey, &owner_pubkey);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "assign".to_string(),
info: json!({
"account": keys[0].to_string(),
"owner": keys[1].to_string(),
"account": account_pubkey.to_string(),
"owner": owner_pubkey.to_string(),
}),
}
);
assert!(parse_system(&message.instructions[0], &AccountKeys::new(&[], None)).is_err());
}
let instruction = system_instruction::transfer(&keys[0], &keys[1], lamports);
#[test]
fn test_parse_system_transfer_ix() {
let lamports = 55;
let from_pubkey = Pubkey::new_unique();
let to_pubkey = Pubkey::new_unique();
let instruction = system_instruction::transfer(&from_pubkey, &to_pubkey, lamports);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "transfer".to_string(),
info: json!({
"source": keys[0].to_string(),
"destination": keys[1].to_string(),
"source": from_pubkey.to_string(),
"destination": to_pubkey.to_string(),
"lamports": lamports,
}),
}
);
assert!(parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}
#[test]
fn test_parse_system_create_account_with_seed_ix() {
let lamports = 55;
let space = 128;
let seed = "test_seed";
let from_pubkey = Pubkey::new_unique();
let to_pubkey = Pubkey::new_unique();
let base_pubkey = Pubkey::new_unique();
let owner_pubkey = Pubkey::new_unique();
let instruction = system_instruction::create_account_with_seed(
&keys[0], &keys[2], &keys[1], seed, lamports, space, &keys[3],
&from_pubkey,
&to_pubkey,
&base_pubkey,
seed,
lamports,
space,
&owner_pubkey,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "createAccountWithSeed".to_string(),
info: json!({
"source": keys[0].to_string(),
"newAccount": keys[2].to_string(),
"source": from_pubkey.to_string(),
"newAccount": to_pubkey.to_string(),
"lamports": lamports,
"base": keys[1].to_string(),
"base": base_pubkey.to_string(),
"seed": seed,
"owner": keys[3].to_string(),
"owner": owner_pubkey.to_string(),
"space": space,
}),
}
);
let seed = "test_seed";
let instruction = system_instruction::create_account_with_seed(
&keys[0], &keys[1], &keys[0], seed, lamports, space, &keys[3],
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "createAccountWithSeed".to_string(),
info: json!({
"source": keys[0].to_string(),
"newAccount": keys[1].to_string(),
"lamports": lamports,
"base": keys[0].to_string(),
"seed": seed,
"owner": keys[3].to_string(),
"space": space,
}),
}
);
assert!(parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}
let instruction = system_instruction::allocate(&keys[0], space);
#[test]
fn test_parse_system_allocate_ix() {
let space = 128;
let account_pubkey = Pubkey::new_unique();
let instruction = system_instruction::allocate(&account_pubkey, space);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "allocate".to_string(),
info: json!({
"account": keys[0].to_string(),
"account": account_pubkey.to_string(),
"space": space,
}),
}
);
assert!(parse_system(&message.instructions[0], &AccountKeys::new(&[], None)).is_err());
}
let instruction =
system_instruction::allocate_with_seed(&keys[1], &keys[0], seed, space, &keys[2]);
#[test]
fn test_parse_system_allocate_with_seed_ix() {
let space = 128;
let seed = "test_seed";
let account_pubkey = Pubkey::new_unique();
let base_pubkey = Pubkey::new_unique();
let owner_pubkey = Pubkey::new_unique();
let instruction = system_instruction::allocate_with_seed(
&account_pubkey,
&base_pubkey,
seed,
space,
&owner_pubkey,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "allocateWithSeed".to_string(),
info: json!({
"account": keys[1].to_string(),
"base": keys[0].to_string(),
"account": account_pubkey.to_string(),
"base": base_pubkey.to_string(),
"seed": seed,
"owner": keys[2].to_string(),
"owner": owner_pubkey.to_string(),
"space": space,
}),
}
);
assert!(parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}
let instruction = system_instruction::assign_with_seed(&keys[1], &keys[0], seed, &keys[2]);
#[test]
fn test_parse_system_assign_with_seed_ix() {
let seed = "test_seed";
let account_pubkey = Pubkey::new_unique();
let base_pubkey = Pubkey::new_unique();
let owner_pubkey = Pubkey::new_unique();
let instruction = system_instruction::assign_with_seed(
&account_pubkey,
&base_pubkey,
seed,
&owner_pubkey,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "assignWithSeed".to_string(),
info: json!({
"account": keys[1].to_string(),
"base": keys[0].to_string(),
"account": account_pubkey.to_string(),
"base": base_pubkey.to_string(),
"seed": seed,
"owner": keys[2].to_string(),
"owner": owner_pubkey.to_string(),
}),
}
);
assert!(parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}
#[test]
fn test_parse_system_transfer_with_seed_ix() {
let lamports = 55;
let seed = "test_seed";
let from_pubkey = Pubkey::new_unique();
let from_base_pubkey = Pubkey::new_unique();
let from_owner_pubkey = Pubkey::new_unique();
let to_pubkey = Pubkey::new_unique();
let instruction = system_instruction::transfer_with_seed(
&keys[1],
&keys[0],
&from_pubkey,
&from_base_pubkey,
seed.to_string(),
&keys[3],
&keys[2],
&from_owner_pubkey,
&to_pubkey,
lamports,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "transferWithSeed".to_string(),
info: json!({
"source": keys[1].to_string(),
"sourceBase": keys[0].to_string(),
"source": from_pubkey.to_string(),
"sourceBase": from_base_pubkey.to_string(),
"sourceSeed": seed,
"sourceOwner": keys[3].to_string(),
"sourceOwner": from_owner_pubkey.to_string(),
"lamports": lamports,
"destination": keys[2].to_string()
"destination": to_pubkey.to_string()
}),
}
);
assert!(parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
#[test]
#[allow(clippy::same_item_push)]
fn test_parse_system_instruction_nonce() {
let mut keys: Vec<Pubkey> = vec![];
for _ in 0..5 {
keys.push(solana_sdk::pubkey::new_rand());
}
fn test_parse_system_advance_nonce_account_ix() {
let nonce_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let instruction = system_instruction::advance_nonce_account(&keys[1], &keys[0]);
let instruction =
system_instruction::advance_nonce_account(&nonce_pubkey, &authorized_pubkey);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "advanceNonce".to_string(),
info: json!({
"nonceAccount": keys[1].to_string(),
"recentBlockhashesSysvar": keys[2].to_string(),
"nonceAuthority": keys[0].to_string(),
"nonceAccount": nonce_pubkey.to_string(),
"recentBlockhashesSysvar": sysvar::recent_blockhashes::ID.to_string(),
"nonceAuthority": authorized_pubkey.to_string(),
}),
}
);
assert!(parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
#[test]
fn test_parse_system_withdraw_nonce_account_ix() {
let nonce_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let to_pubkey = Pubkey::new_unique();
let lamports = 55;
let instruction =
system_instruction::withdraw_nonce_account(&keys[1], &keys[0], &keys[2], lamports);
let instruction = system_instruction::withdraw_nonce_account(
&nonce_pubkey,
&authorized_pubkey,
&to_pubkey,
lamports,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..5], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "withdrawFromNonce".to_string(),
info: json!({
"nonceAccount": keys[1].to_string(),
"destination": keys[2].to_string(),
"recentBlockhashesSysvar": keys[3].to_string(),
"rentSysvar": keys[4].to_string(),
"nonceAuthority": keys[0].to_string(),
"nonceAccount": nonce_pubkey.to_string(),
"destination": to_pubkey.to_string(),
"recentBlockhashesSysvar": sysvar::recent_blockhashes::ID.to_string(),
"rentSysvar": sysvar::rent::ID.to_string(),
"nonceAuthority": authorized_pubkey.to_string(),
"lamports": lamports
}),
}
);
assert!(parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys[0..4], None)
)
.is_err());
}
let instructions =
system_instruction::create_nonce_account(&keys[0], &keys[1], &keys[4], lamports);
#[test]
fn test_parse_system_initialize_nonce_ix() {
let lamports = 55;
let from_pubkey = Pubkey::new_unique();
let nonce_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let instructions = system_instruction::create_nonce_account(
&from_pubkey,
&nonce_pubkey,
&authorized_pubkey,
lamports,
);
let message = Message::new(&instructions, None);
assert_eq!(
parse_system(
&message.instructions[1],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "initializeNonce".to_string(),
info: json!({
"nonceAccount": keys[1].to_string(),
"recentBlockhashesSysvar": keys[2].to_string(),
"rentSysvar": keys[3].to_string(),
"nonceAuthority": keys[4].to_string(),
"nonceAccount": nonce_pubkey.to_string(),
"recentBlockhashesSysvar": sysvar::recent_blockhashes::ID.to_string(),
"rentSysvar": sysvar::rent::ID.to_string(),
"nonceAuthority": authorized_pubkey.to_string(),
}),
}
);
assert!(parse_system(
&message.instructions[1],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys[0..3], None)
)
.is_err());
}
let instruction = system_instruction::authorize_nonce_account(&keys[1], &keys[0], &keys[2]);
#[test]
fn test_parse_system_authorize_nonce_account_ix() {
let nonce_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let new_authority_pubkey = Pubkey::new_unique();
let instruction = system_instruction::authorize_nonce_account(
&nonce_pubkey,
&authorized_pubkey,
&new_authority_pubkey,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeNonce".to_string(),
info: json!({
"nonceAccount": keys[1].to_string(),
"newAuthorized": keys[2].to_string(),
"nonceAuthority": keys[0].to_string(),
"nonceAccount": nonce_pubkey.to_string(),
"newAuthorized": new_authority_pubkey.to_string(),
"nonceAuthority": authorized_pubkey.to_string(),
}),
}
);
assert!(parse_system(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}

View File

@ -186,7 +186,7 @@ fn check_num_vote_accounts(accounts: &[u8], num: usize) -> Result<(), ParseInstr
mod test {
use {
super::*,
solana_sdk::{hash::Hash, message::Message, pubkey::Pubkey},
solana_sdk::{hash::Hash, message::Message, pubkey::Pubkey, sysvar},
solana_vote_program::{
vote_instruction,
vote_state::{Vote, VoteAuthorize, VoteInit},
@ -194,34 +194,24 @@ mod test {
};
#[test]
#[allow(clippy::same_item_push)]
fn test_parse_vote_instruction() {
let mut keys: Vec<Pubkey> = vec![];
for _ in 0..5 {
keys.push(solana_sdk::pubkey::new_rand());
}
fn test_parse_vote_initialize_ix() {
let lamports = 55;
let hash = Hash::new_from_array([1; 32]);
let vote = Vote {
slots: vec![1, 2, 4],
hash,
timestamp: Some(1_234_567_890),
};
let commission = 10;
let authorized_voter = solana_sdk::pubkey::new_rand();
let authorized_withdrawer = solana_sdk::pubkey::new_rand();
let node_pubkey = Pubkey::new_unique();
let vote_pubkey = Pubkey::new_unique();
let authorized_voter = Pubkey::new_unique();
let authorized_withdrawer = Pubkey::new_unique();
let vote_init = VoteInit {
node_pubkey: keys[2],
node_pubkey,
authorized_voter,
authorized_withdrawer,
commission,
};
let instructions = vote_instruction::create_account(
&solana_sdk::pubkey::new_rand(),
&keys[1],
&Pubkey::new_unique(),
&vote_pubkey,
&vote_init,
lamports,
);
@ -229,16 +219,16 @@ mod test {
assert_eq!(
parse_vote(
&message.instructions[1],
&AccountKeys::new(&keys[0..5], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "initialize".to_string(),
info: json!({
"voteAccount": keys[1].to_string(),
"rentSysvar": keys[3].to_string(),
"clockSysvar": keys[4].to_string(),
"node": keys[2].to_string(),
"voteAccount": vote_pubkey.to_string(),
"rentSysvar": sysvar::rent::ID.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"node": node_pubkey.to_string(),
"authorizedVoter": authorized_voter.to_string(),
"authorizedWithdrawer": authorized_withdrawer.to_string(),
"commission": commission,
@ -247,51 +237,74 @@ mod test {
);
assert!(parse_vote(
&message.instructions[1],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys[0..3], None)
)
.is_err());
}
#[test]
fn test_parse_vote_authorize_ix() {
let vote_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let new_authorized_pubkey = Pubkey::new_unique();
let authority_type = VoteAuthorize::Voter;
let instruction = vote_instruction::authorize(&keys[1], &keys[0], &keys[3], authority_type);
let instruction = vote_instruction::authorize(
&vote_pubkey,
&authorized_pubkey,
&new_authorized_pubkey,
authority_type,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorize".to_string(),
info: json!({
"voteAccount": keys[1].to_string(),
"clockSysvar": keys[2].to_string(),
"authority": keys[0].to_string(),
"newAuthority": keys[3].to_string(),
"voteAccount": vote_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"authority": authorized_pubkey.to_string(),
"newAuthority": new_authorized_pubkey.to_string(),
"authorityType": authority_type,
}),
}
);
assert!(parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
let instruction = vote_instruction::vote(&keys[1], &keys[0], vote.clone());
#[test]
fn test_parse_vote_ix() {
let hash = Hash::new_from_array([1; 32]);
let vote = Vote {
slots: vec![1, 2, 4],
hash,
timestamp: Some(1_234_567_890),
};
let vote_pubkey = Pubkey::new_unique();
let authorized_voter_pubkey = Pubkey::new_unique();
let instruction = vote_instruction::vote(&vote_pubkey, &authorized_voter_pubkey, vote);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "vote".to_string(),
info: json!({
"voteAccount": keys[1].to_string(),
"slotHashesSysvar": keys[2].to_string(),
"clockSysvar": keys[3].to_string(),
"voteAuthority": keys[0].to_string(),
"voteAccount": vote_pubkey.to_string(),
"slotHashesSysvar": sysvar::slot_hashes::ID.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"voteAuthority": authorized_voter_pubkey.to_string(),
"vote": {
"slots": [1, 2, 4],
"hash": hash.to_string(),
@ -302,96 +315,141 @@ mod test {
);
assert!(parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys[0..3], None)
)
.is_err());
}
let instruction = vote_instruction::withdraw(&keys[1], &keys[0], lamports, &keys[2]);
#[test]
fn test_parse_vote_withdraw_ix() {
let lamports = 55;
let vote_pubkey = Pubkey::new_unique();
let authorized_withdrawer_pubkey = Pubkey::new_unique();
let to_pubkey = Pubkey::new_unique();
let instruction = vote_instruction::withdraw(
&vote_pubkey,
&authorized_withdrawer_pubkey,
lamports,
&to_pubkey,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "withdraw".to_string(),
info: json!({
"voteAccount": keys[1].to_string(),
"destination": keys[2].to_string(),
"withdrawAuthority": keys[0].to_string(),
"voteAccount": vote_pubkey.to_string(),
"destination": to_pubkey.to_string(),
"withdrawAuthority": authorized_withdrawer_pubkey.to_string(),
"lamports": lamports,
}),
}
);
assert!(parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
let instruction = vote_instruction::update_validator_identity(&keys[2], &keys[1], &keys[0]);
#[test]
fn test_parse_vote_update_validator_identity_ix() {
let vote_pubkey = Pubkey::new_unique();
let authorized_withdrawer_pubkey = Pubkey::new_unique();
let node_pubkey = Pubkey::new_unique();
let instruction = vote_instruction::update_validator_identity(
&vote_pubkey,
&authorized_withdrawer_pubkey,
&node_pubkey,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "updateValidatorIdentity".to_string(),
info: json!({
"voteAccount": keys[2].to_string(),
"newValidatorIdentity": keys[0].to_string(),
"withdrawAuthority": keys[1].to_string(),
"voteAccount": vote_pubkey.to_string(),
"newValidatorIdentity": node_pubkey.to_string(),
"withdrawAuthority": authorized_withdrawer_pubkey.to_string(),
}),
}
);
assert!(parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys[0..2], None)
)
.is_err());
}
let instruction = vote_instruction::update_commission(&keys[1], &keys[0], commission);
#[test]
fn test_parse_vote_update_commission_ix() {
let commission = 10;
let vote_pubkey = Pubkey::new_unique();
let authorized_withdrawer_pubkey = Pubkey::new_unique();
let instruction = vote_instruction::update_commission(
&vote_pubkey,
&authorized_withdrawer_pubkey,
commission,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..2], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "updateCommission".to_string(),
info: json!({
"voteAccount": keys[1].to_string(),
"withdrawAuthority": keys[0].to_string(),
"voteAccount": vote_pubkey.to_string(),
"withdrawAuthority": authorized_withdrawer_pubkey.to_string(),
"commission": commission,
}),
}
);
assert!(parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..1], None)
&AccountKeys::new(&message.account_keys[0..1], None)
)
.is_err());
}
#[test]
fn test_parse_vote_switch_ix() {
let hash = Hash::new_from_array([1; 32]);
let vote = Vote {
slots: vec![1, 2, 4],
hash,
timestamp: Some(1_234_567_890),
};
let vote_pubkey = Pubkey::new_unique();
let authorized_voter_pubkey = Pubkey::new_unique();
let proof_hash = Hash::new_from_array([2; 32]);
let instruction = vote_instruction::vote_switch(&keys[1], &keys[0], vote, proof_hash);
let instruction =
vote_instruction::vote_switch(&vote_pubkey, &authorized_voter_pubkey, vote, proof_hash);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "voteSwitch".to_string(),
info: json!({
"voteAccount": keys[1].to_string(),
"slotHashesSysvar": keys[2].to_string(),
"clockSysvar": keys[3].to_string(),
"voteAuthority": keys[0].to_string(),
"voteAccount": vote_pubkey.to_string(),
"slotHashesSysvar": sysvar::slot_hashes::ID.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"voteAuthority": authorized_voter_pubkey.to_string(),
"vote": {
"slots": [1, 2, 4],
"hash": hash.to_string(),
@ -403,34 +461,44 @@ mod test {
);
assert!(parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys[0..3], None)
)
.is_err());
}
#[test]
fn test_parse_vote_authorized_checked_ix() {
let vote_pubkey = Pubkey::new_unique();
let authorized_pubkey = Pubkey::new_unique();
let new_authorized_pubkey = Pubkey::new_unique();
let authority_type = VoteAuthorize::Voter;
let instruction =
vote_instruction::authorize_checked(&keys[1], &keys[0], &keys[3], authority_type);
let instruction = vote_instruction::authorize_checked(
&vote_pubkey,
&authorized_pubkey,
&new_authorized_pubkey,
authority_type,
);
let message = Message::new(&[instruction], None);
assert_eq!(
parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..4], None)
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "authorizeChecked".to_string(),
info: json!({
"voteAccount": keys[2].to_string(),
"clockSysvar": keys[3].to_string(),
"authority": keys[0].to_string(),
"newAuthority": keys[1].to_string(),
"voteAccount": vote_pubkey.to_string(),
"clockSysvar": sysvar::clock::ID.to_string(),
"authority": authorized_pubkey.to_string(),
"newAuthority": new_authorized_pubkey.to_string(),
"authorityType": authority_type,
}),
}
);
assert!(parse_vote(
&message.instructions[0],
&AccountKeys::new(&keys[0..3], None)
&AccountKeys::new(&message.account_keys[0..3], None)
)
.is_err());
}