Store address table lookups in blockstore and bigtable (#22402)

This commit is contained in:
Justin Starry
2022-01-14 15:24:41 +08:00
committed by GitHub
parent 4c577d7f8c
commit f804ccdece
28 changed files with 836 additions and 199 deletions

View File

@ -77,9 +77,10 @@ use {
solana_storage_bigtable::Error as StorageError,
solana_streamer::socket::SocketAddrSpace,
solana_transaction_status::{
ConfirmedBlock, ConfirmedTransactionStatusWithSignature, Encodable,
ConfirmedTransactionStatusWithSignature, Encodable,
EncodedConfirmedTransactionWithStatusMeta, Reward, RewardType,
TransactionConfirmationStatus, TransactionStatus, UiConfirmedBlock, UiTransactionEncoding,
VersionedConfirmedBlock,
},
solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY},
spl_token::{
@ -1002,48 +1003,62 @@ impl JsonRpcRequestProcessor {
self.check_status_is_complete(slot)?;
let result = self.blockstore.get_rooted_block(slot, true);
self.check_blockstore_root(&result, slot)?;
let configure_block = |confirmed_block: ConfirmedBlock| {
let configure_block = |versioned_block: VersionedConfirmedBlock| {
let confirmed_block = versioned_block
.into_legacy_block()
.ok_or(RpcCustomError::UnsupportedTransactionVersion)?;
let mut confirmed_block =
confirmed_block.configure(encoding, transaction_details, show_rewards);
if slot == 0 {
confirmed_block.block_time = Some(self.genesis_creation_time());
confirmed_block.block_height = Some(0);
}
confirmed_block
Ok(confirmed_block)
};
if result.is_err() {
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
let bigtable_result =
bigtable_ledger_storage.get_confirmed_block(slot).await;
self.check_bigtable_result(&bigtable_result)?;
return Ok(bigtable_result.ok().map(configure_block));
return bigtable_result.ok().map(configure_block).transpose();
}
}
self.check_slot_cleaned_up(&result, slot)?;
return Ok(result.ok().map(configure_block));
return result.ok().map(configure_block).transpose();
} else if commitment.is_confirmed() {
// Check if block is confirmed
let confirmed_bank = self.bank(Some(CommitmentConfig::confirmed()));
if confirmed_bank.status_cache_ancestors().contains(&slot) {
self.check_status_is_complete(slot)?;
let result = self.blockstore.get_complete_block(slot, true);
return Ok(result.ok().map(|mut confirmed_block| {
if confirmed_block.block_time.is_none()
|| confirmed_block.block_height.is_none()
{
let r_bank_forks = self.bank_forks.read().unwrap();
let bank = r_bank_forks.get(slot).cloned();
if let Some(bank) = bank {
if confirmed_block.block_time.is_none() {
confirmed_block.block_time = Some(bank.clock().unix_timestamp);
}
if confirmed_block.block_height.is_none() {
confirmed_block.block_height = Some(bank.block_height());
return result
.ok()
.map(|versioned_block| {
let mut confirmed_block = versioned_block
.into_legacy_block()
.ok_or(RpcCustomError::UnsupportedTransactionVersion)?;
if confirmed_block.block_time.is_none()
|| confirmed_block.block_height.is_none()
{
let r_bank_forks = self.bank_forks.read().unwrap();
let bank = r_bank_forks.get(slot).cloned();
if let Some(bank) = bank {
if confirmed_block.block_time.is_none() {
confirmed_block.block_time =
Some(bank.clock().unix_timestamp);
}
if confirmed_block.block_height.is_none() {
confirmed_block.block_height = Some(bank.block_height());
}
}
}
}
confirmed_block.configure(encoding, transaction_details, show_rewards)
}));
Ok(confirmed_block.configure(
encoding,
transaction_details,
show_rewards,
))
})
.transpose();
}
}
} else {
@ -1368,15 +1383,20 @@ impl JsonRpcRequestProcessor {
if self.config.enable_rpc_transaction_history {
let confirmed_bank = self.bank(Some(CommitmentConfig::confirmed()));
let transaction = if commitment.is_confirmed() {
let versioned_confirmed_tx = if commitment.is_confirmed() {
let highest_confirmed_slot = confirmed_bank.slot();
self.blockstore
.get_complete_transaction(signature, highest_confirmed_slot)
} else {
self.blockstore.get_rooted_transaction(signature)
};
match transaction.unwrap_or(None) {
Some(mut confirmed_transaction) => {
match versioned_confirmed_tx.unwrap_or(None) {
Some(versioned_confirmed_tx) => {
let mut confirmed_transaction = versioned_confirmed_tx
.into_legacy_confirmed_transaction()
.ok_or(RpcCustomError::UnsupportedTransactionVersion)?;
if commitment.is_confirmed()
&& confirmed_bank // should be redundant
.status_cache_ancestors()
@ -1402,11 +1422,18 @@ impl JsonRpcRequestProcessor {
}
None => {
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
return Ok(bigtable_ledger_storage
return bigtable_ledger_storage
.get_confirmed_transaction(&signature)
.await
.unwrap_or(None)
.map(|confirmed| confirmed.encode(encoding)));
.map(|versioned_confirmed_tx| {
let confirmed_tx = versioned_confirmed_tx
.into_legacy_confirmed_transaction()
.ok_or(RpcCustomError::UnsupportedTransactionVersion)?;
Ok(confirmed_tx.encode(encoding))
})
.transpose();
}
}
}

View File

@ -957,7 +957,20 @@ impl RpcSubscriptions {
if s > max_complete_transaction_status_slot.load(Ordering::SeqCst) {
break;
}
match blockstore.get_complete_block(s, false) {
let block_result = blockstore
.get_complete_block(s, false)
.map_err(|e| {
error!("get_complete_block error: {}", e);
RpcBlockUpdateError::BlockStoreError
})
.and_then(|versioned_block| {
versioned_block.into_legacy_block().ok_or(
RpcBlockUpdateError::UnsupportedTransactionVersion,
)
});
match block_result {
Ok(block) => {
if let Some(res) = filter_block_result_txs(block, s, params)
{
@ -975,17 +988,16 @@ impl RpcSubscriptions {
*w_last_unnotified_slot = s + 1;
}
}
Err(e) => {
Err(err) => {
// we don't advance `w_last_unnotified_slot` so that
// it'll retry on the next notification trigger
error!("get_complete_block error: {}", e);
notifier.notify(
Response {
context: RpcResponseContext { slot: s },
value: RpcBlockUpdate {
slot,
block: None,
err: Some(RpcBlockUpdateError::BlockStoreError),
err: Some(err),
},
},
subscription,
@ -1398,8 +1410,9 @@ pub(crate) mod tests {
let actual_resp = receiver.recv();
let actual_resp = serde_json::from_str::<serde_json::Value>(&actual_resp).unwrap();
let block = blockstore.get_complete_block(slot, false).unwrap();
let block = block.configure(params.encoding, params.transaction_details, false);
let versioned_block = blockstore.get_complete_block(slot, false).unwrap();
let legacy_block = versioned_block.into_legacy_block().unwrap();
let block = legacy_block.configure(params.encoding, params.transaction_details, false);
let expected_resp = RpcBlockUpdate {
slot,
block: Some(block),
@ -1497,14 +1510,16 @@ pub(crate) mod tests {
let actual_resp = serde_json::from_str::<serde_json::Value>(&actual_resp).unwrap();
// make sure it filtered out the other keypairs
let mut block = blockstore.get_complete_block(slot, false).unwrap();
block.transactions.retain(|tx| {
tx.transaction
let versioned_block = blockstore.get_complete_block(slot, false).unwrap();
let mut legacy_block = versioned_block.into_legacy_block().unwrap();
legacy_block.transactions.retain(|tx_with_meta| {
tx_with_meta
.transaction
.message
.account_keys
.contains(&keypair1.pubkey())
});
let block = block.configure(params.encoding, params.transaction_details, false);
let block = legacy_block.configure(params.encoding, params.transaction_details, false);
let expected_resp = RpcBlockUpdate {
slot,
block: Some(block),
@ -1594,8 +1609,9 @@ pub(crate) mod tests {
let actual_resp = receiver.recv();
let actual_resp = serde_json::from_str::<serde_json::Value>(&actual_resp).unwrap();
let block = blockstore.get_complete_block(slot, false).unwrap();
let block = block.configure(params.encoding, params.transaction_details, false);
let versioned_block = blockstore.get_complete_block(slot, false).unwrap();
let legacy_block = versioned_block.into_legacy_block().unwrap();
let block = legacy_block.configure(params.encoding, params.transaction_details, false);
let expected_resp = RpcBlockUpdate {
slot,
block: Some(block),

View File

@ -141,7 +141,7 @@ impl TransactionStatusService {
})
.collect(),
);
let loaded_addresses = transaction.get_loaded_addresses();
let transaction_status_meta = TransactionStatusMeta {
status,
fee,
@ -152,6 +152,7 @@ impl TransactionStatusService {
pre_token_balances,
post_token_balances,
rewards,
loaded_addresses,
};
if let Some(transaction_notifier) = transaction_notifier.as_ref() {