Add StakeInstruction::AuthorizeWithSeed (#11700)

* Add StakeInstruction::AuthorizeWithSeed

* chore: add authorize-with-seed to web.js

* fix: add address_owner

* Add SystemInstruction::TransferWithSeed

* Update ABI hash

* chore: better variable names

* Add AuthorizeWithSeedArgs

* Reorder and rename arguments for clarity
This commit is contained in:
Greg Fitzgerald
2020-08-21 12:28:01 -06:00
committed by GitHub
parent 247f27af37
commit f02a78d8ff
9 changed files with 469 additions and 40 deletions

View File

@ -145,16 +145,11 @@ fn create_account(
transfer(from, to, lamports)
}
fn transfer(from: &KeyedAccount, to: &KeyedAccount, lamports: u64) -> Result<(), InstructionError> {
if lamports == 0 {
return Ok(());
}
if from.signer_key().is_none() {
debug!("Transfer: from must sign");
return Err(InstructionError::MissingRequiredSignature);
}
fn transfer_verified(
from: &KeyedAccount,
to: &KeyedAccount,
lamports: u64,
) -> Result<(), InstructionError> {
if !from.data_is_empty()? {
debug!("Transfer: `from` must not carry data");
return Err(InstructionError::InvalidArgument);
@ -173,6 +168,45 @@ fn transfer(from: &KeyedAccount, to: &KeyedAccount, lamports: u64) -> Result<(),
Ok(())
}
fn transfer(from: &KeyedAccount, to: &KeyedAccount, lamports: u64) -> Result<(), InstructionError> {
if lamports == 0 {
return Ok(());
}
if from.signer_key().is_none() {
debug!("Transfer: from must sign");
return Err(InstructionError::MissingRequiredSignature);
}
transfer_verified(from, to, lamports)
}
fn transfer_with_seed(
from: &KeyedAccount,
from_base: &KeyedAccount,
from_seed: &str,
from_owner: &Pubkey,
to: &KeyedAccount,
lamports: u64,
) -> Result<(), InstructionError> {
if lamports == 0 {
return Ok(());
}
if from_base.signer_key().is_none() {
debug!("Transfer: from must sign");
return Err(InstructionError::MissingRequiredSignature);
}
if *from.unsigned_key()
!= Pubkey::create_with_seed(from_base.unsigned_key(), from_seed, from_owner)?
{
return Err(SystemError::AddressWithSeedMismatch.into());
}
transfer_verified(from, to, lamports)
}
pub fn process_instruction(
_owner: &Pubkey,
keyed_accounts: &[KeyedAccount],
@ -220,6 +254,16 @@ pub fn process_instruction(
let to = next_keyed_account(keyed_accounts_iter)?;
transfer(from, to, lamports)
}
SystemInstruction::TransferWithSeed {
lamports,
from_seed,
from_owner,
} => {
let from = next_keyed_account(keyed_accounts_iter)?;
let base = next_keyed_account(keyed_accounts_iter)?;
let to = next_keyed_account(keyed_accounts_iter)?;
transfer_with_seed(from, base, &from_seed, &from_owner, to, lamports)
}
SystemInstruction::AdvanceNonceAccount => {
let me = &mut next_keyed_account(keyed_accounts_iter)?;
me.advance_nonce_account(
@ -864,6 +908,62 @@ mod tests {
assert_eq!(to_keyed_account.account.borrow().lamports, 51);
}
#[test]
fn test_transfer_with_seed() {
let base = Pubkey::new_rand();
let base_account = Account::new_ref(100, 0, &Pubkey::new(&[2; 32])); // account owner should not matter
let from_base_keyed_account = KeyedAccount::new(&base, true, &base_account);
let from_seed = "42";
let from_owner = system_program::id();
let from = Pubkey::create_with_seed(&base, from_seed, &from_owner).unwrap();
let from_account = Account::new_ref(100, 0, &Pubkey::new(&[2; 32])); // account owner should not matter
let to = Pubkey::new(&[3; 32]);
let to_account = Account::new_ref(1, 0, &to); // account owner should not matter
let from_keyed_account = KeyedAccount::new(&from, true, &from_account);
let to_keyed_account = KeyedAccount::new(&to, false, &to_account);
transfer_with_seed(
&from_keyed_account,
&from_base_keyed_account,
&from_seed,
&from_owner,
&to_keyed_account,
50,
)
.unwrap();
let from_lamports = from_keyed_account.account.borrow().lamports;
let to_lamports = to_keyed_account.account.borrow().lamports;
assert_eq!(from_lamports, 50);
assert_eq!(to_lamports, 51);
// Attempt to move more lamports than remaining in from_account
let from_keyed_account = KeyedAccount::new(&from, true, &from_account);
let result = transfer_with_seed(
&from_keyed_account,
&from_base_keyed_account,
&from_seed,
&from_owner,
&to_keyed_account,
100,
);
assert_eq!(result, Err(SystemError::ResultWithNegativeLamports.into()));
assert_eq!(from_keyed_account.account.borrow().lamports, 50);
assert_eq!(to_keyed_account.account.borrow().lamports, 51);
// test unsigned transfer of zero
let from_keyed_account = KeyedAccount::new(&from, false, &from_account);
assert!(transfer_with_seed(
&from_keyed_account,
&from_base_keyed_account,
&from_seed,
&from_owner,
&to_keyed_account,
0,
)
.is_ok(),);
assert_eq!(from_keyed_account.account.borrow().lamports, 50);
assert_eq!(to_keyed_account.account.borrow().lamports, 51);
}
#[test]
fn test_transfer_lamports_from_nonce_account_fail() {
let from = Pubkey::new_rand();