diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 3c1bf0334b..569631442b 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -902,8 +902,8 @@ impl JsonRpcRequestProcessor { ), ); match bigtable_results { - Ok(mut bigtable_results) => { - results.append(&mut bigtable_results); + Ok(bigtable_results) => { + results.extend(bigtable_results.into_iter().map(|x| x.0)); } Err(err) => { warn!("{:?}", err); diff --git a/ledger-tool/src/bigtable.rs b/ledger-tool/src/bigtable.rs index 5497cc98f8..a6b9cd16c7 100644 --- a/ledger-tool/src/bigtable.rs +++ b/ledger-tool/src/bigtable.rs @@ -138,6 +138,7 @@ pub async fn transaction_history( ) -> Result<(), Box> { let bigtable = solana_storage_bigtable::LedgerStorage::new(true).await?; + let mut loaded_block: Option<(Slot, solana_transaction_status::ConfirmedBlock)> = None; while limit > 0 { let results = bigtable .get_confirmed_signatures_for_address( @@ -151,11 +152,11 @@ pub async fn transaction_history( if results.is_empty() { break; } - before = Some(results.last().unwrap().signature); + before = Some(results.last().unwrap().0.signature); assert!(limit >= results.len()); limit = limit.saturating_sub(results.len()); - for result in results { + for (result, index) in results { if verbose { println!( "{}, slot={}, memo=\"{}\", status={}", @@ -172,23 +173,45 @@ pub async fn transaction_history( } if show_transactions { - match bigtable - .get_confirmed_transaction(&result.signature, UiTransactionEncoding::Base64) - .await - { - Ok(Some(confirmed_transaction)) => { - println_transaction( - &confirmed_transaction - .transaction - .transaction - .decode() - .expect("Successful decode"), - &confirmed_transaction.transaction.meta, - " ", - ); + // Instead of using `bigtable.get_confirmed_transaction()`, fetch the entire block + // and keep it around. This helps reduce BigTable query traffic and speeds up the + // results for high-volume addresses + loop { + if let Some((slot, block)) = &loaded_block { + if *slot == result.slot { + match block.transactions.get(index as usize) { + None => { + println!( + " Transaction info for {} is corrupt", + result.signature + ); + } + Some(transaction_with_meta) => { + println_transaction( + &transaction_with_meta + .transaction + .decode() + .expect("Successful decode"), + &transaction_with_meta.meta, + " ", + ); + } + } + break; + } + } + match bigtable + .get_confirmed_block(result.slot, UiTransactionEncoding::Base64) + .await + { + Err(err) => { + println!(" Unable to get confirmed transaction details: {}", err); + break; + } + Ok(block) => { + loaded_block = Some((result.slot, block)); + } } - Ok(None) => println!(" Confirmed transaction details not available"), - Err(err) => println!(" Unable to get confirmed transaction details: {}", err), } println!(); } diff --git a/storage-bigtable/src/lib.rs b/storage-bigtable/src/lib.rs index 5f90b1ec84..0d48b62597 100644 --- a/storage-bigtable/src/lib.rs +++ b/storage-bigtable/src/lib.rs @@ -367,7 +367,12 @@ impl LedgerStorage { before_signature: Option<&Signature>, until_signature: Option<&Signature>, limit: usize, - ) -> Result> { + ) -> Result< + Vec<( + ConfirmedTransactionStatusWithSignature, + u32, /*slot index*/ + )>, + > { let mut bigtable = self.connection.client(); let address_prefix = format!("{}/", address); @@ -436,12 +441,15 @@ impl LedgerStorage { if slot == last_slot && tx_by_addr_info.index <= until_transaction_index { continue; } - infos.push((ConfirmedTransactionStatusWithSignature { - signature: tx_by_addr_info.signature, - slot, - err: tx_by_addr_info.err, - memo: tx_by_addr_info.memo, - }, tx_by_addr_info.index)); + infos.push(( + ConfirmedTransactionStatusWithSignature { + signature: tx_by_addr_info.signature, + slot, + err: tx_by_addr_info.err, + memo: tx_by_addr_info.memo, + }, + tx_by_addr_info.index, + )); // Respect limit if infos.len() >= limit { break 'outer;