SystemProgram transactions now fail on invalid arguments

This commit is contained in:
Michael Vines 2018-10-10 14:55:45 -07:00
parent 785c619198
commit 262f26cf76
3 changed files with 37 additions and 17 deletions

View File

@ -536,12 +536,15 @@ impl Bank {
// Call the contract method
// It's up to the contract to implement its own rules on moving funds
if SystemProgram::check_id(&tx_program_id) {
SystemProgram::process_transaction(
if SystemProgram::process_transaction(
&tx,
instruction_index,
program_accounts,
&self.loaded_contracts,
)
).is_err()
{
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
}
} else if BudgetState::check_id(&tx_program_id) {
if BudgetState::process_transaction(&tx, instruction_index, program_accounts).is_err() {
return Err(BankError::ProgramRuntimeError(instruction_index as u8));

View File

@ -4,10 +4,24 @@ use bincode::deserialize;
use dynamic_program::DynamicProgram;
use solana_program_interface::account::Account;
use solana_program_interface::pubkey::Pubkey;
use std;
use std::collections::HashMap;
use std::sync::RwLock;
use transaction::Transaction;
#[derive(Debug)]
pub enum Error {
InvalidArgument,
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "error")
}
}
impl std::error::Error for Error {}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum SystemProgram {
/// Create a new account
@ -52,7 +66,7 @@ impl SystemProgram {
pix: usize,
accounts: &mut [&mut Account],
loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
) {
) -> Result<()> {
if let Ok(syscall) = deserialize(tx.userdata(pix)) {
trace!("process_transaction: {:?}", syscall);
match syscall {
@ -62,13 +76,13 @@ impl SystemProgram {
program_id,
} => {
if !Self::check_id(&accounts[0].program_id) {
return;
Err(Error::InvalidArgument)?;
}
if space > 0
&& (!accounts[1].userdata.is_empty()
|| !Self::check_id(&accounts[1].program_id))
{
return;
Err(Error::InvalidArgument)?;
}
accounts[0].tokens -= tokens;
accounts[1].tokens += tokens;
@ -77,7 +91,7 @@ impl SystemProgram {
}
SystemProgram::Assign { program_id } => {
if !Self::check_id(&accounts[0].program_id) {
return;
Err(Error::InvalidArgument)?;
}
accounts[0].program_id = program_id;
}
@ -91,8 +105,10 @@ impl SystemProgram {
hashmap.insert(program_id, DynamicProgram::new_native(name));
}
}
Ok(())
} else {
info!("Invalid transaction userdata: {:?}", tx.userdata(pix));
Err(Error::InvalidArgument)
}
}
}
@ -113,10 +129,11 @@ mod test {
tx: &Transaction,
accounts: &mut [Account],
loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
) {
) -> Result<()> {
let mut refs: Vec<&mut Account> = accounts.iter_mut().collect();
SystemProgram::process_transaction(&tx, 0, &mut refs[..], loaded_programs)
}
#[test]
fn test_create_noop() {
let from = Keypair::new();
@ -124,7 +141,7 @@ mod test {
let mut accounts = vec![Account::default(), Account::default()];
let tx = Transaction::system_new(&from, to.pubkey(), 0, Hash::default());
let hash = RwLock::new(HashMap::new());
process_transaction(&tx, &mut accounts, &hash);
process_transaction(&tx, &mut accounts, &hash).unwrap();
assert_eq!(accounts[0].tokens, 0);
assert_eq!(accounts[1].tokens, 0);
}
@ -136,7 +153,7 @@ mod test {
accounts[0].tokens = 1;
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
let hash = RwLock::new(HashMap::new());
process_transaction(&tx, &mut accounts, &hash);
process_transaction(&tx, &mut accounts, &hash).unwrap();
assert_eq!(accounts[0].tokens, 0);
assert_eq!(accounts[1].tokens, 1);
}
@ -149,7 +166,7 @@ mod test {
accounts[0].program_id = from.pubkey();
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
let hash = RwLock::new(HashMap::new());
process_transaction(&tx, &mut accounts, &hash);
assert!(process_transaction(&tx, &mut accounts, &hash).is_err());
assert_eq!(accounts[0].tokens, 1);
assert_eq!(accounts[1].tokens, 0);
}
@ -161,7 +178,7 @@ mod test {
let tx =
Transaction::system_create(&from, to.pubkey(), Hash::default(), 0, 1, to.pubkey(), 0);
let hash = RwLock::new(HashMap::new());
process_transaction(&tx, &mut accounts, &hash);
process_transaction(&tx, &mut accounts, &hash).unwrap();
assert!(accounts[0].userdata.is_empty());
assert_eq!(accounts[1].userdata.len(), 1);
assert_eq!(accounts[1].program_id, to.pubkey());
@ -182,7 +199,7 @@ mod test {
0,
);
let hash = RwLock::new(HashMap::new());
process_transaction(&tx, &mut accounts, &hash);
assert!(process_transaction(&tx, &mut accounts, &hash).is_err());
assert!(accounts[1].userdata.is_empty());
}
#[test]
@ -201,7 +218,7 @@ mod test {
0,
);
let hash = RwLock::new(HashMap::new());
process_transaction(&tx, &mut accounts, &hash);
assert!(process_transaction(&tx, &mut accounts, &hash).is_err());
assert!(accounts[1].userdata.is_empty());
}
#[test]
@ -220,7 +237,7 @@ mod test {
0,
);
let hash = RwLock::new(HashMap::new());
process_transaction(&tx, &mut accounts, &hash);
assert!(process_transaction(&tx, &mut accounts, &hash).is_err());
assert_eq!(accounts[1].userdata.len(), 3);
}
#[test]
@ -230,7 +247,7 @@ mod test {
let mut accounts = vec![Account::default()];
let tx = Transaction::system_assign(&from, Hash::default(), program.pubkey(), 0);
let hash = RwLock::new(HashMap::new());
process_transaction(&tx, &mut accounts, &hash);
process_transaction(&tx, &mut accounts, &hash).unwrap();
assert_eq!(accounts[0].program_id, program.pubkey());
}
#[test]
@ -241,7 +258,7 @@ mod test {
accounts[0].tokens = 1;
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
let hash = RwLock::new(HashMap::new());
process_transaction(&tx, &mut accounts, &hash);
process_transaction(&tx, &mut accounts, &hash).unwrap();
assert_eq!(accounts[0].tokens, 0);
assert_eq!(accounts[1].tokens, 1);
}

View File

@ -236,7 +236,7 @@ fn process_transaction(
loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
) {
let mut refs: Vec<&mut Account> = accounts.iter_mut().collect();
SystemProgram::process_transaction(&tx, 0, &mut refs[..], loaded_programs)
SystemProgram::process_transaction(&tx, 0, &mut refs[..], loaded_programs).unwrap();
}
#[test]