Fix mismatch between leader/validator bank votability (#3942)
* Fix mismatch between leader/validator bank votability
This commit is contained in:
parent
3ba93aa8fe
commit
ab11327e34
|
@ -20,7 +20,7 @@ use solana_runtime::bank::Bank;
|
||||||
use solana_runtime::locked_accounts_results::LockedAccountsResults;
|
use solana_runtime::locked_accounts_results::LockedAccountsResults;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::timing::{self, duration_as_us, DEFAULT_TICKS_PER_SLOT, MAX_RECENT_BLOCKHASHES};
|
use solana_sdk::timing::{self, duration_as_us, DEFAULT_TICKS_PER_SLOT, MAX_RECENT_BLOCKHASHES};
|
||||||
use solana_sdk::transaction::{self, Transaction, TransactionError};
|
use solana_sdk::transaction::{self, Transaction};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
@ -367,14 +367,10 @@ impl BankingStage {
|
||||||
let processed_transactions: Vec<_> = results
|
let processed_transactions: Vec<_> = results
|
||||||
.iter()
|
.iter()
|
||||||
.zip(txs.iter())
|
.zip(txs.iter())
|
||||||
.filter_map(|(r, x)| match r {
|
.filter_map(|(r, x)| {
|
||||||
Ok(_) => Some(x.clone()),
|
if Bank::can_commit(r) {
|
||||||
Err(TransactionError::InstructionError(index, err)) => {
|
|
||||||
debug!("instruction error {:?}, {:?}", index, err);
|
|
||||||
Some(x.clone())
|
Some(x.clone())
|
||||||
}
|
} else {
|
||||||
Err(ref e) => {
|
|
||||||
debug!("process transaction failed {:?}", e);
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -667,6 +663,7 @@ mod tests {
|
||||||
use solana_sdk::instruction::InstructionError;
|
use solana_sdk::instruction::InstructionError;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::system_transaction;
|
use solana_sdk::system_transaction;
|
||||||
|
use solana_sdk::transaction::TransactionError;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
|
|
||||||
|
|
|
@ -423,33 +423,26 @@ impl Bank {
|
||||||
self.status_cache.write().unwrap().clear_signatures();
|
self.status_cache.write().unwrap().clear_signatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn can_commit(result: &Result<()>) -> bool {
|
||||||
|
match result {
|
||||||
|
Ok(_) => true,
|
||||||
|
Err(TransactionError::InstructionError(_, _)) => true,
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn update_transaction_statuses(&self, txs: &[Transaction], res: &[Result<()>]) {
|
fn update_transaction_statuses(&self, txs: &[Transaction], res: &[Result<()>]) {
|
||||||
let mut status_cache = self.status_cache.write().unwrap();
|
let mut status_cache = self.status_cache.write().unwrap();
|
||||||
for (i, tx) in txs.iter().enumerate() {
|
for (i, tx) in txs.iter().enumerate() {
|
||||||
match &res[i] {
|
if Self::can_commit(&res[i]) && !tx.signatures.is_empty() {
|
||||||
Ok(_) => {
|
|
||||||
if !tx.signatures.is_empty() {
|
|
||||||
status_cache.insert(
|
status_cache.insert(
|
||||||
&tx.message().recent_blockhash,
|
&tx.message().recent_blockhash,
|
||||||
&tx.signatures[0],
|
&tx.signatures[0],
|
||||||
self.slot(),
|
self.slot(),
|
||||||
Ok(()),
|
res[i].clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(TransactionError::InstructionError(b, e)) => {
|
|
||||||
if !tx.signatures.is_empty() {
|
|
||||||
status_cache.insert(
|
|
||||||
&tx.message().recent_blockhash,
|
|
||||||
&tx.signatures[0],
|
|
||||||
self.slot(),
|
|
||||||
Err(TransactionError::InstructionError(*b, e.clone())),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Looks through a list of tick heights and stakes, and finds the latest
|
/// Looks through a list of tick heights and stakes, and finds the latest
|
||||||
|
@ -769,7 +762,9 @@ impl Bank {
|
||||||
warn!("=========== FIXME: commit_transactions() working on a frozen bank! ================");
|
warn!("=========== FIXME: commit_transactions() working on a frozen bank! ================");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if executed.iter().any(|res| Self::can_commit(res)) {
|
||||||
self.is_delta.store(true, Ordering::Relaxed);
|
self.is_delta.store(true, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: put this assert back in
|
// TODO: put this assert back in
|
||||||
// assert!(!self.is_frozen());
|
// assert!(!self.is_frozen());
|
||||||
|
@ -1952,4 +1947,44 @@ mod tests {
|
||||||
bank.tick_height.store(max_tick_height, Ordering::Relaxed);
|
bank.tick_height.store(max_tick_height, Ordering::Relaxed);
|
||||||
assert!(bank.is_votable());
|
assert!(bank.is_votable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_delta_with_no_committables() {
|
||||||
|
let (genesis_block, mint_keypair) = GenesisBlock::new(8000);
|
||||||
|
let bank = Bank::new(&genesis_block);
|
||||||
|
bank.is_delta.store(false, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let keypair1 = Keypair::new();
|
||||||
|
let keypair2 = Keypair::new();
|
||||||
|
let fail_tx = system_transaction::create_user_account(
|
||||||
|
&keypair1,
|
||||||
|
&keypair2.pubkey(),
|
||||||
|
1,
|
||||||
|
bank.last_blockhash(),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should fail with TransactionError::AccountNotFound, which means
|
||||||
|
// the account which this tx operated on will not be committed. Thus
|
||||||
|
// the bank is_delta should still be false
|
||||||
|
assert_eq!(
|
||||||
|
bank.process_transaction(&fail_tx),
|
||||||
|
Err(TransactionError::AccountNotFound)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check the bank is_delta is still false
|
||||||
|
assert!(!bank.is_delta.load(Ordering::Relaxed));
|
||||||
|
|
||||||
|
// Should fail with InstructionError, but InstructionErrors are committable,
|
||||||
|
// so is_delta should be true
|
||||||
|
assert_eq!(
|
||||||
|
bank.transfer(10_001, &mint_keypair, &Pubkey::new_rand()),
|
||||||
|
Err(TransactionError::InstructionError(
|
||||||
|
0,
|
||||||
|
InstructionError::new_result_with_negative_lamports(),
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(bank.is_delta.load(Ordering::Relaxed));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue