diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index f483adabd5..36e89cf787 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -130,7 +130,7 @@ fn main() { last_id = entry.id; num_entries += 1; - if let Err(e) = blocktree_processor::process_entry(&bank, &entry) { + if let Err(e) = blocktree_processor::process_entry(&bank, &entry).0 { eprintln!("verify failed at entry[{}], err: {:?}", i + 2, e); if !matches.is_present("continue") { exit(1); diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index b471399966..c77f7b31b3 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -112,21 +112,18 @@ impl AccountsDB { txs: &[Transaction], res: &[Result<()>], loaded: &[Result<(InstructionAccounts, InstructionLoaders)>], - ) -> u64 { - let mut fee = 0; + ) { for (i, raccs) in loaded.iter().enumerate() { if res[i].is_err() || raccs.is_err() { continue; } let tx = &txs[i]; - fee += tx.fee; let acc = raccs.as_ref().unwrap(); for (key, account) in tx.account_keys.iter().zip(acc.0.iter()) { self.store(purge, key, account); } } - fee } fn load_tx_accounts( checkpoints: &[U], @@ -375,7 +372,7 @@ impl Accounts { txs: &[Transaction], res: &[Result<()>], loaded: &[Result<(InstructionAccounts, InstructionLoaders)>], - ) -> u64 { + ) { self.accounts_db .write() .unwrap() diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 863f9c71fc..c784c38549 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -446,10 +446,9 @@ impl Bank { txs: &[Transaction], loaded_accounts: &[Result<(InstructionAccounts, InstructionLoaders)>], executed: &[Result<()>], - ) -> u64 { + ) { let now = Instant::now(); - let fee = self - .accounts + self.accounts .store_accounts(true, txs, executed, loaded_accounts); // once committed there is no way to unroll @@ -460,7 +459,6 @@ impl Bank { txs.len(), ); self.update_transaction_statuses(txs, &executed); - fee } /// Process a batch of transactions. @@ -470,19 +468,18 @@ impl Bank { txs: &[Transaction], lock_results: Vec>, max_age: usize, - ) -> (Vec>, u64) { + ) -> Vec> { let (loaded_accounts, executed) = self.load_and_execute_transactions(txs, lock_results, max_age); - let fee = self.commit_transactions(txs, &loaded_accounts, &executed); - (executed, fee) + self.commit_transactions(txs, &loaded_accounts, &executed); + executed } #[must_use] pub fn process_transactions(&self, txs: &[Transaction]) -> Vec> { let lock_results = self.lock_accounts(txs); - let (results, _fee) = - self.load_execute_and_commit_transactions(txs, lock_results, MAX_ENTRY_IDS); + let results = self.load_execute_and_commit_transactions(txs, lock_results, MAX_ENTRY_IDS); self.unlock_accounts(txs, &results); results } @@ -529,7 +526,7 @@ impl Bank { parents } - pub fn collect_tx_fee(&self, pubkey: &Pubkey, fee: u64) { + pub fn deposit(&self, pubkey: &Pubkey, fee: u64) { if let Some(mut account) = self.get_account(pubkey) { account.tokens += fee; self.accounts.store_slow(false, pubkey, &account); @@ -898,7 +895,7 @@ mod tests { let pay_alice = vec![tx1]; let lock_result = bank.lock_accounts(&pay_alice); - let (results_alice, _fee) = + let results_alice = bank.load_execute_and_commit_transactions(&pay_alice, lock_result, MAX_ENTRY_IDS); assert_eq!(results_alice[0], Ok(())); diff --git a/src/blocktree_processor.rs b/src/blocktree_processor.rs index e022b5d21d..1739f5ca51 100644 --- a/src/blocktree_processor.rs +++ b/src/blocktree_processor.rs @@ -16,21 +16,21 @@ use std::time::Instant; pub const VERIFY_BLOCK_SIZE: usize = 16; -pub fn process_entry(bank: &Bank, entry: &Entry) -> Result<()> { +pub fn process_entry(bank: &Bank, entry: &Entry) -> (Result<()>, u64) { if !entry.is_tick() { - for result in bank.process_transactions(&entry.transactions) { - match result { - // Entries that result in a ProgramError are still valid and are written in the - // ledger so map them to an ok return value - Err(BankError::ProgramError(_, _)) => Ok(()), - _ => result, - }?; - } + 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 }) + .sum(); + (first_err(&results), fee) } else { bank.register_tick(&entry.id); + (Ok(()), 0) } - - Ok(()) } fn first_err(results: &[Result<()>]) -> Result<()> { @@ -61,21 +61,25 @@ fn par_execute_entries(bank: &Bank, entries: &[(&Entry, Vec>)]) -> (R let results_fees: Vec<(Result<()>, u64)> = entries .into_par_iter() .map(|(e, lock_results)| { - let (old_results, fee) = bank.load_execute_and_commit_transactions( + let old_results = bank.load_execute_and_commit_transactions( &e.transactions, 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 }) + .sum(); (first_err(&results), fee) }) .collect(); let fee = results_fees.iter().map(|(_, fee)| fee).sum(); - let mut results = Vec::new(); - results.reserve_exact(results_fees.len()); - results = results_fees.into_iter().map(|(res, _)| res).collect(); + let results: Vec> = results_fees.into_iter().map(|(res, _)| res).collect(); (first_err(&results[..]), fee) } @@ -150,11 +154,26 @@ fn process_block( leader_scheduler: &Arc>, ) -> Result<()> { for entry in entries { - process_entry(bank, entry)?; + let (res, fee) = process_entry(bank, entry); + let num_ticks = bank.tick_height(); + let slot_num = leader_scheduler + .read() + .unwrap() + .tick_height_to_slot(num_ticks); + if let Some(leader) = leader_scheduler + .read() + .unwrap() + .get_leader_for_slot(slot_num) + { + // Credit the accumulated fees to the current leader and reset the fee to 0 + bank.deposit(&leader, fee); + } + if entry.is_tick() { let mut leader_scheduler = leader_scheduler.write().unwrap(); leader_scheduler.update_tick_height(bank.tick_height(), bank); } + res?; } Ok(()) diff --git a/src/replay_stage.rs b/src/replay_stage.rs index 2d2ce82866..6736c1b603 100644 --- a/src/replay_stage.rs +++ b/src/replay_stage.rs @@ -137,7 +137,7 @@ impl ReplayStage { .get_leader_for_slot(slot_num) { // Credit the accumulated fees to the current leader and reset the fee to 0 - bank.collect_tx_fee(&leader, *fees); + bank.deposit(&leader, *fees); *fees = 0; } if let Some(voting_keypair) = voting_keypair {