Avoid panicking invalid instructions

This commit is contained in:
Michael Vines
2018-09-20 13:54:42 -07:00
committed by Grimes
parent 5691bf557c
commit a6c15684c9
3 changed files with 65 additions and 38 deletions

View File

@@ -246,7 +246,7 @@ impl BudgetContract {
/// * accounts[1] - The contract context. Once the contract has been completed, the tokens can
/// be spent from this account .
pub fn process_transaction(tx: &Transaction, accounts: &mut [Account]) -> () {
let instruction = deserialize(&tx.userdata).unwrap();
if let Ok(instruction) = deserialize(&tx.userdata) {
trace!("process_transaction: {:?}", instruction);
let _ = Self::apply_debits_to_budget_state(tx, accounts, &instruction)
.and_then(|_| Self::apply_credits_to_budget_state(tx, accounts, &instruction))
@@ -254,6 +254,9 @@ impl BudgetContract {
trace!("saving error {:?}", e);
Self::save_error_to_budget_state(e, accounts);
});
} else {
info!("Invalid transaction userdata: {:?}", tx.userdata);
}
}
//TODO the contract needs to provide a "get_balance" introspection call of the userdata
@@ -299,6 +302,27 @@ mod test {
Err(BudgetError::UserdataTooSmall)
);
}
#[test]
fn test_invalid_instruction() {
let mut accounts = vec![
Account::new(1, 0, BudgetContract::id()),
Account::new(0, 512, BudgetContract::id()),
];
let from = Keypair::new();
let contract = Keypair::new();
let tx = Transaction::new_with_userdata(
&from,
&[contract.pubkey()],
BudgetContract::id(),
vec![1, 2, 3], // <== garbage instruction
Hash::default(),
0,
);
BudgetContract::process_transaction(&tx, &mut accounts);
// Success if there was no panic...
}
#[test]
fn test_transfer_on_date() {

View File

@@ -41,7 +41,7 @@ impl SystemContract {
account.tokens
}
pub fn process_transaction(tx: &Transaction, accounts: &mut [Account]) {
let syscall: SystemContract = deserialize(&tx.userdata).unwrap();
if let Ok(syscall) = deserialize(&tx.userdata) {
trace!("process_transaction: {:?}", syscall);
match syscall {
SystemContract::CreateAccount {
@@ -75,6 +75,9 @@ impl SystemContract {
accounts[1].tokens += tokens;
}
}
} else {
info!("Invalid transaction userdata: {:?}", tx.userdata);
}
}
}
#[cfg(test)]

View File

@@ -49,7 +49,7 @@ impl Transaction {
/// * `userdata` - The input data that the contract will execute with
/// * `last_id` - The PoH hash.
/// * `fee` - The transaction fee.
fn new_with_userdata(
pub fn new_with_userdata(
from_keypair: &Keypair,
transaction_keys: &[Pubkey],
contract_id: Pubkey,