SystemProgram transactions now fail on invalid arguments
This commit is contained in:
parent
785c619198
commit
262f26cf76
|
@ -536,12 +536,15 @@ impl Bank {
|
||||||
// Call the contract method
|
// Call the contract method
|
||||||
// It's up to the contract to implement its own rules on moving funds
|
// It's up to the contract to implement its own rules on moving funds
|
||||||
if SystemProgram::check_id(&tx_program_id) {
|
if SystemProgram::check_id(&tx_program_id) {
|
||||||
SystemProgram::process_transaction(
|
if SystemProgram::process_transaction(
|
||||||
&tx,
|
&tx,
|
||||||
instruction_index,
|
instruction_index,
|
||||||
program_accounts,
|
program_accounts,
|
||||||
&self.loaded_contracts,
|
&self.loaded_contracts,
|
||||||
)
|
).is_err()
|
||||||
|
{
|
||||||
|
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
|
||||||
|
}
|
||||||
} else if BudgetState::check_id(&tx_program_id) {
|
} else if BudgetState::check_id(&tx_program_id) {
|
||||||
if BudgetState::process_transaction(&tx, instruction_index, program_accounts).is_err() {
|
if BudgetState::process_transaction(&tx, instruction_index, program_accounts).is_err() {
|
||||||
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
|
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
|
||||||
|
|
|
@ -4,10 +4,24 @@ use bincode::deserialize;
|
||||||
use dynamic_program::DynamicProgram;
|
use dynamic_program::DynamicProgram;
|
||||||
use solana_program_interface::account::Account;
|
use solana_program_interface::account::Account;
|
||||||
use solana_program_interface::pubkey::Pubkey;
|
use solana_program_interface::pubkey::Pubkey;
|
||||||
|
use std;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use transaction::Transaction;
|
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)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum SystemProgram {
|
pub enum SystemProgram {
|
||||||
/// Create a new account
|
/// Create a new account
|
||||||
|
@ -52,7 +66,7 @@ impl SystemProgram {
|
||||||
pix: usize,
|
pix: usize,
|
||||||
accounts: &mut [&mut Account],
|
accounts: &mut [&mut Account],
|
||||||
loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
|
loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
|
||||||
) {
|
) -> Result<()> {
|
||||||
if let Ok(syscall) = deserialize(tx.userdata(pix)) {
|
if let Ok(syscall) = deserialize(tx.userdata(pix)) {
|
||||||
trace!("process_transaction: {:?}", syscall);
|
trace!("process_transaction: {:?}", syscall);
|
||||||
match syscall {
|
match syscall {
|
||||||
|
@ -62,13 +76,13 @@ impl SystemProgram {
|
||||||
program_id,
|
program_id,
|
||||||
} => {
|
} => {
|
||||||
if !Self::check_id(&accounts[0].program_id) {
|
if !Self::check_id(&accounts[0].program_id) {
|
||||||
return;
|
Err(Error::InvalidArgument)?;
|
||||||
}
|
}
|
||||||
if space > 0
|
if space > 0
|
||||||
&& (!accounts[1].userdata.is_empty()
|
&& (!accounts[1].userdata.is_empty()
|
||||||
|| !Self::check_id(&accounts[1].program_id))
|
|| !Self::check_id(&accounts[1].program_id))
|
||||||
{
|
{
|
||||||
return;
|
Err(Error::InvalidArgument)?;
|
||||||
}
|
}
|
||||||
accounts[0].tokens -= tokens;
|
accounts[0].tokens -= tokens;
|
||||||
accounts[1].tokens += tokens;
|
accounts[1].tokens += tokens;
|
||||||
|
@ -77,7 +91,7 @@ impl SystemProgram {
|
||||||
}
|
}
|
||||||
SystemProgram::Assign { program_id } => {
|
SystemProgram::Assign { program_id } => {
|
||||||
if !Self::check_id(&accounts[0].program_id) {
|
if !Self::check_id(&accounts[0].program_id) {
|
||||||
return;
|
Err(Error::InvalidArgument)?;
|
||||||
}
|
}
|
||||||
accounts[0].program_id = program_id;
|
accounts[0].program_id = program_id;
|
||||||
}
|
}
|
||||||
|
@ -91,8 +105,10 @@ impl SystemProgram {
|
||||||
hashmap.insert(program_id, DynamicProgram::new_native(name));
|
hashmap.insert(program_id, DynamicProgram::new_native(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
info!("Invalid transaction userdata: {:?}", tx.userdata(pix));
|
info!("Invalid transaction userdata: {:?}", tx.userdata(pix));
|
||||||
|
Err(Error::InvalidArgument)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,10 +129,11 @@ mod test {
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
accounts: &mut [Account],
|
accounts: &mut [Account],
|
||||||
loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
|
loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
|
||||||
) {
|
) -> Result<()> {
|
||||||
let mut refs: Vec<&mut Account> = accounts.iter_mut().collect();
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_noop() {
|
fn test_create_noop() {
|
||||||
let from = Keypair::new();
|
let from = Keypair::new();
|
||||||
|
@ -124,7 +141,7 @@ mod test {
|
||||||
let mut accounts = vec![Account::default(), Account::default()];
|
let mut accounts = vec![Account::default(), Account::default()];
|
||||||
let tx = Transaction::system_new(&from, to.pubkey(), 0, Hash::default());
|
let tx = Transaction::system_new(&from, to.pubkey(), 0, Hash::default());
|
||||||
let hash = RwLock::new(HashMap::new());
|
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[0].tokens, 0);
|
||||||
assert_eq!(accounts[1].tokens, 0);
|
assert_eq!(accounts[1].tokens, 0);
|
||||||
}
|
}
|
||||||
|
@ -136,7 +153,7 @@ mod test {
|
||||||
accounts[0].tokens = 1;
|
accounts[0].tokens = 1;
|
||||||
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
|
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
|
||||||
let hash = RwLock::new(HashMap::new());
|
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[0].tokens, 0);
|
||||||
assert_eq!(accounts[1].tokens, 1);
|
assert_eq!(accounts[1].tokens, 1);
|
||||||
}
|
}
|
||||||
|
@ -149,7 +166,7 @@ mod test {
|
||||||
accounts[0].program_id = from.pubkey();
|
accounts[0].program_id = from.pubkey();
|
||||||
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
|
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
|
||||||
let hash = RwLock::new(HashMap::new());
|
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[0].tokens, 1);
|
||||||
assert_eq!(accounts[1].tokens, 0);
|
assert_eq!(accounts[1].tokens, 0);
|
||||||
}
|
}
|
||||||
|
@ -161,7 +178,7 @@ mod test {
|
||||||
let tx =
|
let tx =
|
||||||
Transaction::system_create(&from, to.pubkey(), Hash::default(), 0, 1, to.pubkey(), 0);
|
Transaction::system_create(&from, to.pubkey(), Hash::default(), 0, 1, to.pubkey(), 0);
|
||||||
let hash = RwLock::new(HashMap::new());
|
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!(accounts[0].userdata.is_empty());
|
||||||
assert_eq!(accounts[1].userdata.len(), 1);
|
assert_eq!(accounts[1].userdata.len(), 1);
|
||||||
assert_eq!(accounts[1].program_id, to.pubkey());
|
assert_eq!(accounts[1].program_id, to.pubkey());
|
||||||
|
@ -182,7 +199,7 @@ mod test {
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let hash = RwLock::new(HashMap::new());
|
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());
|
assert!(accounts[1].userdata.is_empty());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -201,7 +218,7 @@ mod test {
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let hash = RwLock::new(HashMap::new());
|
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());
|
assert!(accounts[1].userdata.is_empty());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -220,7 +237,7 @@ mod test {
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let hash = RwLock::new(HashMap::new());
|
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);
|
assert_eq!(accounts[1].userdata.len(), 3);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -230,7 +247,7 @@ mod test {
|
||||||
let mut accounts = vec![Account::default()];
|
let mut accounts = vec![Account::default()];
|
||||||
let tx = Transaction::system_assign(&from, Hash::default(), program.pubkey(), 0);
|
let tx = Transaction::system_assign(&from, Hash::default(), program.pubkey(), 0);
|
||||||
let hash = RwLock::new(HashMap::new());
|
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());
|
assert_eq!(accounts[0].program_id, program.pubkey());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -241,7 +258,7 @@ mod test {
|
||||||
accounts[0].tokens = 1;
|
accounts[0].tokens = 1;
|
||||||
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
|
let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default());
|
||||||
let hash = RwLock::new(HashMap::new());
|
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[0].tokens, 0);
|
||||||
assert_eq!(accounts[1].tokens, 1);
|
assert_eq!(accounts[1].tokens, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,7 @@ fn process_transaction(
|
||||||
loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
|
loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
|
||||||
) {
|
) {
|
||||||
let mut refs: Vec<&mut Account> = accounts.iter_mut().collect();
|
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]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue