From c142a82ae0df5f33814b0cfccab94cabc96a68ac Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 20 Feb 2019 09:14:28 -0800 Subject: [PATCH] Charge transaction fee even in case of ProgramError --- runtime/src/bank.rs | 6 ++++++ src/blocktree_processor.rs | 30 +++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 9c96098179..fe58f0b26b 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -579,6 +579,12 @@ impl Bank { parents } + pub fn withdraw(&self, pubkey: &Pubkey, tokens: u64) { + let mut account = self.get_account(pubkey).unwrap_or_default(); + account.tokens -= tokens; + self.accounts.store_slow(true, pubkey, &account); + } + pub fn deposit(&self, pubkey: &Pubkey, tokens: u64) { let mut account = self.get_account(pubkey).unwrap_or_default(); account.tokens += tokens; diff --git a/src/blocktree_processor.rs b/src/blocktree_processor.rs index e3bcf9990b..16e5cbfac8 100644 --- a/src/blocktree_processor.rs +++ b/src/blocktree_processor.rs @@ -16,13 +16,21 @@ use std::time::Instant; pub fn process_entry(bank: &Bank, entry: &Entry) -> (Result<()>, u64) { if !entry.is_tick() { let old_results = bank.process_transactions(&entry.transactions); - let results = ignore_program_errors(old_results); let fee = entry .transactions .iter() - .zip(&results) - .map(|(tx, res)| if res.is_ok() { tx.fee } else { 0 }) + .zip(&old_results) + .map(|(tx, res)| match res { + Err(BankError::ProgramError(_, _)) => { + // Charge the transaction fee in case of ProgramError + bank.withdraw(&tx.account_keys[0], tx.fee); + tx.fee + } + Ok(()) => tx.fee, + _ => 0, + }) .sum(); + let results = ignore_program_errors(old_results); (first_err(&results), fee) } else { bank.register_tick(&entry.id); @@ -63,14 +71,22 @@ fn par_execute_entries(bank: &Bank, entries: &[(&Entry, Vec>)]) -> (R lock_results.to_vec(), MAX_ENTRY_IDS, ); - let results = ignore_program_errors(old_results); - bank.unlock_accounts(&e.transactions, &results); let fee = e .transactions .iter() - .zip(&results) - .map(|(tx, res)| if res.is_ok() { tx.fee } else { 0 }) + .zip(&old_results) + .map(|(tx, res)| match res { + Err(BankError::ProgramError(_, _)) => { + // Charge the transaction fee in case of ProgramError + bank.withdraw(&tx.account_keys[0], tx.fee); + tx.fee + } + Ok(()) => tx.fee, + _ => 0, + }) .sum(); + let results = ignore_program_errors(old_results); + bank.unlock_accounts(&e.transactions, &results); (first_err(&results), fee) }) .collect();