SystemProgram transactions now fail on invalid arguments
This commit is contained in:
		@@ -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));
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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]
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user