From 1061b5066561b84e47ae28b915b70ca5d567f9cb Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Thu, 6 Aug 2020 16:21:46 -0600 Subject: [PATCH] Fix blockstore empty panic (#11423) * Add panicking test * Add failing test: fresh transaction-status column shouldn't point at valid root 0 * Prevent transaction status match outside of primary-index bounds * Initialize transaction-status and address-signature primer entries with Slot::MAX * Revert "Add failing test: fresh transaction-status column shouldn't point at valid root 0" This reverts commit cbad2a9fae22e5531e3b4ff1b0a9d6a223826c71. * Revert "Initialize transaction-status and address-signature primer entries with Slot::MAX" This reverts commit ffaeac0669d0cbe18dd68b5ce177e15a92360b72. --- ledger/src/blockstore.rs | 22 ++++++++++++++++++---- ledger/src/blockstore_db.rs | 1 + 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ledger/src/blockstore.rs b/ledger/src/blockstore.rs index a81b28272e..986964655a 100644 --- a/ledger/src/blockstore.rs +++ b/ledger/src/blockstore.rs @@ -1804,9 +1804,9 @@ impl Blockstore { (transaction_status_cf_primary_index, signature, 0), IteratorDirection::Forward, ))?; - for ((_, sig, slot), data) in index_iterator { + for ((i, sig, slot), data) in index_iterator { counter += 1; - if sig != signature { + if i != transaction_status_cf_primary_index || sig != signature { break; } if self.is_root(slot) { @@ -1842,8 +1842,9 @@ impl Blockstore { ("method", "get_confirmed_transaction".to_string(), String) ); if let Some((slot, status)) = self.get_transaction_status(signature)? { - let transaction = self.find_transaction_in_slot(slot, signature)? - .expect("Transaction to exist in slot entries if it exists in statuses and hasn't been cleaned up"); + let transaction = self + .find_transaction_in_slot(slot, signature)? + .ok_or(BlockstoreError::TransactionStatusSlotMismatch)?; // Should not happen let encoding = encoding.unwrap_or(UiTransactionEncoding::Json); let encoded_transaction = EncodedTransaction::encode(transaction, encoding); Ok(Some(ConfirmedTransaction { @@ -6059,6 +6060,19 @@ pub mod tests { } } + #[test] + fn test_empty_transaction_status() { + let blockstore_path = get_tmp_ledger_path!(); + let blockstore = Blockstore::open(&blockstore_path).unwrap(); + blockstore.set_roots(&[0]).unwrap(); + assert_eq!( + blockstore + .get_confirmed_transaction(Signature::default(), None) + .unwrap(), + None + ); + } + #[test] fn test_get_confirmed_signatures_for_address() { let blockstore_path = get_tmp_ledger_path!(); diff --git a/ledger/src/blockstore_db.rs b/ledger/src/blockstore_db.rs index edfcd985a4..93409f23d9 100644 --- a/ledger/src/blockstore_db.rs +++ b/ledger/src/blockstore_db.rs @@ -58,6 +58,7 @@ pub enum BlockstoreError { SlotCleanedUp, UnpackError(#[from] UnpackError), UnableToSetOpenFileDescriptorLimit, + TransactionStatusSlotMismatch, } pub type Result = std::result::Result;