Rpc: Use cluster largest_confirmed_root as commitment max (#9750)

automerge
This commit is contained in:
Tyera Eulberg
2020-04-28 11:20:43 -06:00
committed by GitHub
parent 659e87703b
commit 655e3bc418
2 changed files with 72 additions and 35 deletions

View File

@ -161,6 +161,11 @@ impl BlockCommitmentCache {
root: Slot::default(), root: Slot::default(),
} }
} }
#[cfg(test)]
pub(crate) fn set_get_largest_confirmed_root(&mut self, root: Slot) {
self.largest_confirmed_root = root;
}
} }
pub struct CommitmentAggregationData { pub struct CommitmentAggregationData {

View File

@ -8,7 +8,7 @@ use crate::{
validator::ValidatorExit, validator::ValidatorExit,
}; };
use bincode::serialize; use bincode::serialize;
use jsonrpc_core::{Error, Metadata, Result}; use jsonrpc_core::{Error, ErrorCode, Metadata, Result};
use jsonrpc_derive::rpc; use jsonrpc_derive::rpc;
use solana_client::{ use solana_client::{
rpc_request::{ rpc_request::{
@ -45,6 +45,8 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
const JSON_RPC_SERVER_ERROR_0: i64 = -32000;
type RpcResponse<T> = Result<Response<T>>; type RpcResponse<T> = Result<Response<T>>;
fn new_response<T>(bank: &Bank, value: T) -> RpcResponse<T> { fn new_response<T>(bank: &Bank, value: T) -> RpcResponse<T> {
@ -78,17 +80,32 @@ pub struct JsonRpcRequestProcessor {
} }
impl JsonRpcRequestProcessor { impl JsonRpcRequestProcessor {
fn bank(&self, commitment: Option<CommitmentConfig>) -> Arc<Bank> { fn bank(&self, commitment: Option<CommitmentConfig>) -> Result<Arc<Bank>> {
debug!("RPC commitment_config: {:?}", commitment); debug!("RPC commitment_config: {:?}", commitment);
let r_bank_forks = self.bank_forks.read().unwrap(); let r_bank_forks = self.bank_forks.read().unwrap();
if commitment.is_some() && commitment.unwrap().commitment == CommitmentLevel::Recent { if commitment.is_some() && commitment.unwrap().commitment == CommitmentLevel::Recent {
let bank = r_bank_forks.working_bank(); let bank = r_bank_forks.working_bank();
debug!("RPC using working_bank: {:?}", bank.slot()); debug!("RPC using working_bank: {:?}", bank.slot());
bank Ok(bank)
} else { } else {
let slot = r_bank_forks.root(); let cluster_root = self
debug!("RPC using block: {:?}", slot); .block_commitment_cache
r_bank_forks.get(slot).cloned().unwrap() .read()
.unwrap()
.largest_confirmed_root();
debug!("RPC using block: {:?}", cluster_root);
r_bank_forks
.get(cluster_root)
.cloned()
.ok_or_else(|| Error {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_0),
message: format!(
"Cluster largest_confirmed_root {} does not exist on node. Node root: {}",
cluster_root,
r_bank_forks.root(),
),
data: None,
})
} }
} }
@ -115,7 +132,7 @@ impl JsonRpcRequestProcessor {
pubkey: Result<Pubkey>, pubkey: Result<Pubkey>,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<Option<RpcAccount>> { ) -> RpcResponse<Option<RpcAccount>> {
let bank = &*self.bank(commitment); let bank = &*self.bank(commitment)?;
pubkey.and_then(|key| new_response(bank, bank.get_account(&key).map(RpcAccount::encode))) pubkey.and_then(|key| new_response(bank, bank.get_account(&key).map(RpcAccount::encode)))
} }
@ -125,7 +142,7 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<u64> { ) -> Result<u64> {
Ok(self Ok(self
.bank(commitment) .bank(commitment)?
.get_minimum_balance_for_rent_exemption(data_len)) .get_minimum_balance_for_rent_exemption(data_len))
} }
@ -135,7 +152,7 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<Vec<RpcKeyedAccount>> { ) -> Result<Vec<RpcKeyedAccount>> {
Ok(self Ok(self
.bank(commitment) .bank(commitment)?
.get_program_accounts(Some(&program_id)) .get_program_accounts(Some(&program_id))
.into_iter() .into_iter()
.map(|(pubkey, account)| RpcKeyedAccount { .map(|(pubkey, account)| RpcKeyedAccount {
@ -146,13 +163,13 @@ impl JsonRpcRequestProcessor {
} }
pub fn get_inflation(&self, commitment: Option<CommitmentConfig>) -> Result<Inflation> { pub fn get_inflation(&self, commitment: Option<CommitmentConfig>) -> Result<Inflation> {
Ok(self.bank(commitment).inflation()) Ok(self.bank(commitment)?.inflation())
} }
pub fn get_epoch_schedule(&self) -> Result<EpochSchedule> { pub fn get_epoch_schedule(&self) -> Result<EpochSchedule> {
// Since epoch schedule data comes from the genesis config, any commitment level should be // Since epoch schedule data comes from the genesis config, any commitment level should be
// fine // fine
Ok(*self.bank(None).epoch_schedule()) Ok(*self.bank(None)?.epoch_schedule())
} }
pub fn get_balance( pub fn get_balance(
@ -160,7 +177,7 @@ impl JsonRpcRequestProcessor {
pubkey: Result<Pubkey>, pubkey: Result<Pubkey>,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<u64> { ) -> RpcResponse<u64> {
let bank = &*self.bank(commitment); let bank = &*self.bank(commitment)?;
pubkey.and_then(|key| new_response(bank, bank.get_balance(&key))) pubkey.and_then(|key| new_response(bank, bank.get_balance(&key)))
} }
@ -168,7 +185,7 @@ impl JsonRpcRequestProcessor {
&self, &self,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<RpcBlockhashFeeCalculator> { ) -> RpcResponse<RpcBlockhashFeeCalculator> {
let bank = &*self.bank(commitment); let bank = &*self.bank(commitment)?;
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash(); let (blockhash, fee_calculator) = bank.confirmed_last_blockhash();
new_response( new_response(
bank, bank,
@ -183,7 +200,7 @@ impl JsonRpcRequestProcessor {
&self, &self,
blockhash: &Hash, blockhash: &Hash,
) -> RpcResponse<Option<RpcFeeCalculator>> { ) -> RpcResponse<Option<RpcFeeCalculator>> {
let bank = &*self.bank(None); let bank = &*self.bank(None)?;
let fee_calculator = bank.get_fee_calculator(blockhash); let fee_calculator = bank.get_fee_calculator(blockhash);
new_response( new_response(
bank, bank,
@ -192,7 +209,7 @@ impl JsonRpcRequestProcessor {
} }
fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> { fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> {
let bank = &*self.bank(None); let bank = &*self.bank(None)?;
let fee_rate_governor = bank.get_fee_rate_governor(); let fee_rate_governor = bank.get_fee_rate_governor();
new_response( new_response(
bank, bank,
@ -207,7 +224,7 @@ impl JsonRpcRequestProcessor {
signature: Result<Signature>, signature: Result<Signature>,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> RpcResponse<bool> { ) -> RpcResponse<bool> {
let bank = &*self.bank(commitment); let bank = &*self.bank(commitment)?;
match signature { match signature {
Err(e) => Err(e), Err(e) => Err(e),
Ok(sig) => { Ok(sig) => {
@ -231,11 +248,11 @@ impl JsonRpcRequestProcessor {
} }
fn get_slot(&self, commitment: Option<CommitmentConfig>) -> Result<u64> { fn get_slot(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
Ok(self.bank(commitment).slot()) Ok(self.bank(commitment)?.slot())
} }
fn get_slot_leader(&self, commitment: Option<CommitmentConfig>) -> Result<String> { fn get_slot_leader(&self, commitment: Option<CommitmentConfig>) -> Result<String> {
Ok(self.bank(commitment).collector_id().to_string()) Ok(self.bank(commitment)?.collector_id().to_string())
} }
fn minimum_ledger_slot(&self) -> Result<Slot> { fn minimum_ledger_slot(&self) -> Result<Slot> {
@ -252,18 +269,18 @@ impl JsonRpcRequestProcessor {
} }
fn get_transaction_count(&self, commitment: Option<CommitmentConfig>) -> Result<u64> { fn get_transaction_count(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
Ok(self.bank(commitment).transaction_count() as u64) Ok(self.bank(commitment)?.transaction_count() as u64)
} }
fn get_total_supply(&self, commitment: Option<CommitmentConfig>) -> Result<u64> { fn get_total_supply(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
Ok(self.bank(commitment).capitalization()) Ok(self.bank(commitment)?.capitalization())
} }
fn get_vote_accounts( fn get_vote_accounts(
&self, &self,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<RpcVoteAccountStatus> { ) -> Result<RpcVoteAccountStatus> {
let bank = self.bank(commitment); let bank = self.bank(commitment)?;
let vote_accounts = bank.vote_accounts(); let vote_accounts = bank.vote_accounts();
let epoch_vote_accounts = bank let epoch_vote_accounts = bank
.epoch_vote_accounts(bank.get_epoch_and_slot_index(bank.slot()).0) .epoch_vote_accounts(bank.get_epoch_and_slot_index(bank.slot()).0)
@ -325,7 +342,7 @@ impl JsonRpcRequestProcessor {
} }
fn get_slots_per_segment(&self, commitment: Option<CommitmentConfig>) -> Result<u64> { fn get_slots_per_segment(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
Ok(self.bank(commitment).slots_per_segment()) Ok(self.bank(commitment)?.slots_per_segment())
} }
fn get_storage_pubkeys_for_slot(&self, slot: Slot) -> Result<Vec<String>> { fn get_storage_pubkeys_for_slot(&self, slot: Slot) -> Result<Vec<String>> {
@ -375,7 +392,11 @@ impl JsonRpcRequestProcessor {
start_slot: Slot, start_slot: Slot,
end_slot: Option<Slot>, end_slot: Option<Slot>,
) -> Result<Vec<Slot>> { ) -> Result<Vec<Slot>> {
let end_slot = end_slot.unwrap_or_else(|| self.bank(None).slot()); let end_slot = if let Some(end_slot) = end_slot {
end_slot
} else {
self.bank(None)?.slot()
};
if end_slot < start_slot { if end_slot < start_slot {
return Ok(vec![]); return Ok(vec![]);
} }
@ -393,7 +414,7 @@ impl JsonRpcRequestProcessor {
// queried). If these values will be variable in the future, those timing parameters will // queried). If these values will be variable in the future, those timing parameters will
// need to be stored persistently, and the slot_duration calculation will likely need to be // need to be stored persistently, and the slot_duration calculation will likely need to be
// moved upstream into blockstore. Also, an explicit commitment level will need to be set. // moved upstream into blockstore. Also, an explicit commitment level will need to be set.
let bank = self.bank(None); let bank = self.bank(None)?;
let slot_duration = slot_duration_from_slots_per_year(bank.slots_per_year()); let slot_duration = slot_duration_from_slots_per_year(bank.slots_per_year());
let epoch = bank.epoch_schedule().get_epoch(slot); let epoch = bank.epoch_schedule().get_epoch(slot);
let stakes = HashMap::new(); let stakes = HashMap::new();
@ -411,7 +432,7 @@ impl JsonRpcRequestProcessor {
signature: Signature, signature: Signature,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Option<RpcSignatureConfirmation> { ) -> Option<RpcSignatureConfirmation> {
self.get_transaction_status(signature, &self.bank(commitment)) self.get_transaction_status(signature, &self.bank(commitment).ok()?)
.map( .map(
|TransactionStatus { |TransactionStatus {
status, status,
@ -430,6 +451,7 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Option<transaction::Result<()>> { ) -> Option<transaction::Result<()>> {
self.bank(commitment) self.bank(commitment)
.ok()?
.get_signature_status_slot(&signature) .get_signature_status_slot(&signature)
.map(|(_, status)| status) .map(|(_, status)| status)
} }
@ -444,7 +466,7 @@ impl JsonRpcRequestProcessor {
let search_transaction_history = config let search_transaction_history = config
.map(|x| x.search_transaction_history) .map(|x| x.search_transaction_history)
.unwrap_or(false); .unwrap_or(false);
let bank = self.bank(Some(CommitmentConfig::recent())); let bank = self.bank(Some(CommitmentConfig::recent()))?;
for signature in signatures { for signature in signatures {
let status = if let Some(status) = self.get_transaction_status(signature, &bank) { let status = if let Some(status) = self.get_transaction_status(signature, &bank) {
@ -939,7 +961,7 @@ impl RpcSol for RpcSolImpl {
meta: Self::Metadata, meta: Self::Metadata,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<RpcEpochInfo> { ) -> Result<RpcEpochInfo> {
let bank = meta.request_processor.read().unwrap().bank(commitment); let bank = meta.request_processor.read().unwrap().bank(commitment)?;
let epoch_schedule = bank.epoch_schedule(); let epoch_schedule = bank.epoch_schedule();
let slot = bank.slot(); let slot = bank.slot();
@ -975,7 +997,7 @@ impl RpcSol for RpcSolImpl {
slot: Option<Slot>, slot: Option<Slot>,
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<Option<RpcLeaderSchedule>> { ) -> Result<Option<RpcLeaderSchedule>> {
let bank = meta.request_processor.read().unwrap().bank(commitment); let bank = meta.request_processor.read().unwrap().bank(commitment)?;
let slot = slot.unwrap_or_else(|| bank.slot()); let slot = slot.unwrap_or_else(|| bank.slot());
let epoch = bank.epoch_schedule().get_epoch(slot); let epoch = bank.epoch_schedule().get_epoch(slot);
@ -1139,7 +1161,7 @@ impl RpcSol for RpcSolImpl {
.request_processor .request_processor
.read() .read()
.unwrap() .unwrap()
.bank(commitment.clone()) .bank(commitment.clone())?
.confirmed_last_blockhash() .confirmed_last_blockhash()
.0; .0;
let transaction = request_airdrop_transaction(&faucet_addr, &pubkey, lamports, blockhash) let transaction = request_airdrop_transaction(&faucet_addr, &pubkey, lamports, blockhash)
@ -1522,15 +1544,13 @@ pub mod tests {
let mut roots = blockstore_roots.clone(); let mut roots = blockstore_roots.clone();
if !roots.is_empty() { if !roots.is_empty() {
roots.retain(|&x| x > 1); roots.retain(|&x| x > 0);
let mut parent_bank = bank; let mut parent_bank = bank;
for (i, root) in roots.iter().enumerate() { for (i, root) in roots.iter().enumerate() {
let new_bank = let new_bank =
Bank::new_from_parent(&parent_bank, parent_bank.collector_id(), *root); Bank::new_from_parent(&parent_bank, parent_bank.collector_id(), *root);
parent_bank = bank_forks.write().unwrap().insert(new_bank); parent_bank = bank_forks.write().unwrap().insert(new_bank);
parent_bank.squash(); let parent = if i > 0 { roots[i - 1] } else { 0 };
bank_forks.write().unwrap().set_root(*root, &None, None);
let parent = if i > 0 { roots[i - 1] } else { 1 };
fill_blockstore_slot_with_ticks(&blockstore, 5, *root, parent, Hash::default()); fill_blockstore_slot_with_ticks(&blockstore, 5, *root, parent, Hash::default());
} }
blockstore.set_roots(&roots).unwrap(); blockstore.set_roots(&roots).unwrap();
@ -1540,6 +1560,10 @@ pub mod tests {
roots.iter().max().unwrap() + 1, roots.iter().max().unwrap() + 1,
); );
bank_forks.write().unwrap().insert(new_bank); bank_forks.write().unwrap().insert(new_bank);
for root in roots.iter() {
bank_forks.write().unwrap().set_root(*root, &None, Some(0));
}
} }
let bank = bank_forks.read().unwrap().working_bank(); let bank = bank_forks.read().unwrap().working_bank();
@ -2649,8 +2673,16 @@ pub mod tests {
fn test_get_confirmed_blocks() { fn test_get_confirmed_blocks() {
let bob_pubkey = Pubkey::new_rand(); let bob_pubkey = Pubkey::new_rand();
let roots = vec![0, 1, 3, 4, 8]; let roots = vec![0, 1, 3, 4, 8];
let RpcHandler { io, meta, .. } = let RpcHandler {
start_rpc_handler_with_tx_and_blockstore(&bob_pubkey, roots.clone(), 0); io,
meta,
block_commitment_cache,
..
} = start_rpc_handler_with_tx_and_blockstore(&bob_pubkey, roots.clone(), 0);
block_commitment_cache
.write()
.unwrap()
.set_get_largest_confirmed_root(8);
let req = let req =
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0]}}"#); format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0]}}"#);