Use cluster confirmations in rpc and pubsub (#9138)
* Add runtime methods to simply get status and slot * Add helper function to get slot confirmation_count from BlockCommitmentCache * Return cluster confirmations in getSignatureStatus * Remove use of invalid get_signature_confirmation_status * Remove unused methods * Update pubsub to use cluster confirmations * Fix test_check_signature_subscribe failure * Refactor confirmations to read commitment cache only once * Review comments * Use bank, root from BlockCommitmentCache * Update docs * Add metric for block-commitment aggregations Co-authored-by: Justin Starry <justin@solana.com>
This commit is contained in:
@ -14,7 +14,7 @@ use crate::{
|
||||
deserialize_atomicbool, deserialize_atomicu64, serialize_atomicbool, serialize_atomicu64,
|
||||
},
|
||||
stakes::Stakes,
|
||||
status_cache::{SignatureConfirmationStatus, SlotDelta, StatusCache},
|
||||
status_cache::{SlotDelta, StatusCache},
|
||||
storage_utils,
|
||||
storage_utils::StorageAccounts,
|
||||
system_instruction_processor::{get_system_account_kind, SystemAccountKind},
|
||||
@ -1845,29 +1845,25 @@ impl Bank {
|
||||
&self,
|
||||
signature: &Signature,
|
||||
) -> Option<Result<()>> {
|
||||
if let Some(status) = self.get_signature_confirmation_status(signature) {
|
||||
if status.slot == self.slot() {
|
||||
return Some(status.status);
|
||||
if let Some((slot, status)) = self.get_signature_status_slot(signature) {
|
||||
if slot <= self.slot() {
|
||||
return Some(status);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_signature_confirmation_status(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
) -> Option<SignatureConfirmationStatus<Result<()>>> {
|
||||
pub fn get_signature_status_slot(&self, signature: &Signature) -> Option<(Slot, Result<()>)> {
|
||||
let rcache = self.src.status_cache.read().unwrap();
|
||||
rcache.get_signature_status_slow(signature, &self.ancestors)
|
||||
rcache.get_signature_slot(signature, &self.ancestors)
|
||||
}
|
||||
|
||||
pub fn get_signature_status(&self, signature: &Signature) -> Option<Result<()>> {
|
||||
self.get_signature_confirmation_status(signature)
|
||||
.map(|v| v.status)
|
||||
self.get_signature_status_slot(signature).map(|v| v.1)
|
||||
}
|
||||
|
||||
pub fn has_signature(&self, signature: &Signature) -> bool {
|
||||
self.get_signature_confirmation_status(signature).is_some()
|
||||
self.get_signature_status_slot(signature).is_some()
|
||||
}
|
||||
|
||||
/// Hash the `accounts` HashMap. This represents a validator's interpretation
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{bank::Bank, status_cache::SignatureConfirmationStatus};
|
||||
use crate::bank::Bank;
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
client::{AsyncClient, Client, SyncClient},
|
||||
@ -184,26 +184,15 @@ impl SyncClient for BankClient {
|
||||
signature: &Signature,
|
||||
min_confirmed_blocks: usize,
|
||||
) -> Result<usize> {
|
||||
let mut now = Instant::now();
|
||||
let mut confirmed_blocks = 0;
|
||||
// https://github.com/solana-labs/solana/issues/7199
|
||||
assert_eq!(min_confirmed_blocks, 1, "BankClient cannot observe the passage of multiple blocks, so min_confirmed_blocks must be 1");
|
||||
let now = Instant::now();
|
||||
let confirmed_blocks;
|
||||
loop {
|
||||
let response = self.bank.get_signature_confirmation_status(signature);
|
||||
if let Some(SignatureConfirmationStatus {
|
||||
confirmations,
|
||||
status,
|
||||
..
|
||||
}) = response
|
||||
{
|
||||
if status.is_ok() {
|
||||
if confirmed_blocks != confirmations {
|
||||
now = Instant::now();
|
||||
confirmed_blocks = confirmations;
|
||||
}
|
||||
if confirmations >= min_confirmed_blocks {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
if self.bank.get_signature_status(signature).is_some() {
|
||||
confirmed_blocks = 1;
|
||||
break;
|
||||
}
|
||||
if now.elapsed().as_secs() > 15 {
|
||||
return Err(TransportError::IoError(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
|
@ -103,29 +103,20 @@ impl<T: Serialize + Clone> StatusCache<T> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_signature_status_slow(
|
||||
pub fn get_signature_slot(
|
||||
&self,
|
||||
sig: &Signature,
|
||||
signature: &Signature,
|
||||
ancestors: &HashMap<Slot, usize>,
|
||||
) -> Option<SignatureConfirmationStatus<T>> {
|
||||
trace!("get_signature_status_slow");
|
||||
) -> Option<(Slot, T)> {
|
||||
let mut keys = vec![];
|
||||
let mut val: Vec<_> = self.cache.iter().map(|(k, _)| *k).collect();
|
||||
keys.append(&mut val);
|
||||
|
||||
for blockhash in keys.iter() {
|
||||
trace!("get_signature_status_slow: trying {}", blockhash);
|
||||
if let Some((forkid, res)) = self.get_signature_status(sig, blockhash, ancestors) {
|
||||
trace!("get_signature_status_slow: got {}", forkid);
|
||||
let confirmations = ancestors
|
||||
.get(&forkid)
|
||||
.copied()
|
||||
.unwrap_or_else(|| ancestors.len());
|
||||
return Some(SignatureConfirmationStatus {
|
||||
slot: forkid,
|
||||
confirmations,
|
||||
status: res,
|
||||
});
|
||||
trace!("get_signature_slot: trying {}", blockhash);
|
||||
let status = self.get_signature_status(signature, blockhash, ancestors);
|
||||
if status.is_some() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
None
|
||||
@ -265,10 +256,7 @@ mod tests {
|
||||
status_cache.get_signature_status(&sig, &blockhash, &HashMap::new()),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
status_cache.get_signature_status_slow(&sig, &HashMap::new()),
|
||||
None
|
||||
);
|
||||
assert_eq!(status_cache.get_signature_slot(&sig, &HashMap::new()), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -283,12 +271,8 @@ mod tests {
|
||||
Some((0, ()))
|
||||
);
|
||||
assert_eq!(
|
||||
status_cache.get_signature_status_slow(&sig, &ancestors),
|
||||
Some(SignatureConfirmationStatus {
|
||||
slot: 0,
|
||||
confirmations: 1,
|
||||
status: ()
|
||||
})
|
||||
status_cache.get_signature_slot(&sig, &ancestors),
|
||||
Some((0, ()))
|
||||
);
|
||||
}
|
||||
|
||||
@ -303,10 +287,7 @@ mod tests {
|
||||
status_cache.get_signature_status(&sig, &blockhash, &ancestors),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
status_cache.get_signature_status_slow(&sig, &ancestors),
|
||||
None
|
||||
);
|
||||
assert_eq!(status_cache.get_signature_slot(&sig, &ancestors), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -323,24 +304,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_sig_with_root_ancestor_fork_max_len() {
|
||||
let sig = Signature::default();
|
||||
let mut status_cache = BankStatusCache::default();
|
||||
let blockhash = hash(Hash::default().as_ref());
|
||||
let ancestors = vec![(2, 2)].into_iter().collect();
|
||||
status_cache.insert(&blockhash, &sig, 0, ());
|
||||
status_cache.add_root(0);
|
||||
assert_eq!(
|
||||
status_cache.get_signature_status_slow(&sig, &ancestors),
|
||||
Some(SignatureConfirmationStatus {
|
||||
slot: 0,
|
||||
confirmations: ancestors.len(),
|
||||
status: ()
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_picks_latest_blockhash_fork() {
|
||||
let sig = Signature::default();
|
||||
@ -371,10 +334,6 @@ mod tests {
|
||||
status_cache.get_signature_status(&sig, &blockhash, &ancestors),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
status_cache.get_signature_status_slow(&sig, &ancestors),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Reference in New Issue
Block a user