Add `getSnapshotSlot` RPC method

This commit is contained in:
Michael Vines 2021-01-14 21:45:11 -08:00 committed by mergify[bot]
parent dacb95083d
commit 4003f86f04
7 changed files with 89 additions and 12 deletions

View File

@ -274,6 +274,10 @@ impl RpcClient {
) )
} }
pub fn get_snapshot_slot(&self) -> ClientResult<Slot> {
self.send(RpcRequest::GetSnapshotSlot, Value::Null)
}
pub fn get_signature_status( pub fn get_signature_status(
&self, &self,
signature: &Signature, signature: &Signature,

View File

@ -11,6 +11,7 @@ pub const JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE: i64 = -32004;
pub const JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY: i64 = -32005; pub const JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY: i64 = -32005;
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64 = -32006; pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64 = -32006;
pub const JSON_RPC_SERVER_ERROR_SLOT_SKIPPED: i64 = -32007; pub const JSON_RPC_SERVER_ERROR_SLOT_SKIPPED: i64 = -32007;
pub const JSON_RPC_SERVER_ERROR_NO_SNAPSHOT: i64 = -32008;
pub enum RpcCustomError { pub enum RpcCustomError {
BlockCleanedUp { BlockCleanedUp {
@ -32,6 +33,7 @@ pub enum RpcCustomError {
SlotSkipped { SlotSkipped {
slot: Slot, slot: Slot,
}, },
NoSnapshot,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -95,6 +97,11 @@ impl From<RpcCustomError> for Error {
), ),
data: None, data: None,
}, },
RpcCustomError::NoSnapshot => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_NO_SNAPSHOT),
message: "No snapshot".to_string(),
data: None,
},
} }
} }
} }

View File

@ -35,6 +35,7 @@ pub enum RpcRequest {
GetMultipleAccounts, GetMultipleAccounts,
GetProgramAccounts, GetProgramAccounts,
GetRecentBlockhash, GetRecentBlockhash,
GetSnapshotSlot,
GetSignatureStatuses, GetSignatureStatuses,
GetSlot, GetSlot,
GetSlotLeader, GetSlotLeader,
@ -91,6 +92,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetMultipleAccounts => "getMultipleAccounts", RpcRequest::GetMultipleAccounts => "getMultipleAccounts",
RpcRequest::GetProgramAccounts => "getProgramAccounts", RpcRequest::GetProgramAccounts => "getProgramAccounts",
RpcRequest::GetRecentBlockhash => "getRecentBlockhash", RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
RpcRequest::GetSnapshotSlot => "getSnapshotSlot",
RpcRequest::GetSignatureStatuses => "getSignatureStatuses", RpcRequest::GetSignatureStatuses => "getSignatureStatuses",
RpcRequest::GetSlot => "getSlot", RpcRequest::GetSlot => "getSlot",
RpcRequest::GetSlotLeader => "getSlotLeader", RpcRequest::GetSlotLeader => "getSlotLeader",

View File

@ -41,9 +41,10 @@ use solana_runtime::{
accounts::AccountAddressFilter, accounts::AccountAddressFilter,
accounts_index::{AccountIndex, IndexKey}, accounts_index::{AccountIndex, IndexKey},
bank::Bank, bank::Bank,
bank_forks::BankForks, bank_forks::{BankForks, SnapshotConfig},
commitment::{BlockCommitmentArray, BlockCommitmentCache, CommitmentSlots}, commitment::{BlockCommitmentArray, BlockCommitmentCache, CommitmentSlots},
inline_spl_token_v2_0::{SPL_TOKEN_ACCOUNT_MINT_OFFSET, SPL_TOKEN_ACCOUNT_OWNER_OFFSET}, inline_spl_token_v2_0::{SPL_TOKEN_ACCOUNT_MINT_OFFSET, SPL_TOKEN_ACCOUNT_OWNER_OFFSET},
snapshot_utils::get_highest_snapshot_archive_path,
}; };
use solana_sdk::{ use solana_sdk::{
account::Account, account::Account,
@ -122,6 +123,7 @@ pub struct JsonRpcRequestProcessor {
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>, block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
blockstore: Arc<Blockstore>, blockstore: Arc<Blockstore>,
config: JsonRpcConfig, config: JsonRpcConfig,
snapshot_config: Option<SnapshotConfig>,
validator_exit: Arc<RwLock<Option<ValidatorExit>>>, validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
health: Arc<RpcHealth>, health: Arc<RpcHealth>,
cluster_info: Arc<ClusterInfo>, cluster_info: Arc<ClusterInfo>,
@ -199,6 +201,7 @@ impl JsonRpcRequestProcessor {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
config: JsonRpcConfig, config: JsonRpcConfig,
snapshot_config: Option<SnapshotConfig>,
bank_forks: Arc<RwLock<BankForks>>, bank_forks: Arc<RwLock<BankForks>>,
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>, block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
blockstore: Arc<Blockstore>, blockstore: Arc<Blockstore>,
@ -214,6 +217,7 @@ impl JsonRpcRequestProcessor {
( (
Self { Self {
config, config,
snapshot_config,
bank_forks, bank_forks,
block_commitment_cache, block_commitment_cache,
blockstore, blockstore,
@ -246,6 +250,7 @@ impl JsonRpcRequestProcessor {
Self { Self {
config: JsonRpcConfig::default(), config: JsonRpcConfig::default(),
snapshot_config: None,
bank_forks, bank_forks,
block_commitment_cache: Arc::new(RwLock::new(BlockCommitmentCache::new( block_commitment_cache: Arc::new(RwLock::new(BlockCommitmentCache::new(
HashMap::new(), HashMap::new(),
@ -463,7 +468,7 @@ impl JsonRpcRequestProcessor {
} }
} }
fn get_slot(&self, commitment: Option<CommitmentConfig>) -> u64 { fn get_slot(&self, commitment: Option<CommitmentConfig>) -> Slot {
self.bank(commitment).slot() self.bank(commitment).slot()
} }
@ -1799,6 +1804,9 @@ pub trait RpcSol {
meta: Self::Metadata, meta: Self::Metadata,
) -> Result<RpcResponse<RpcFeeRateGovernor>>; ) -> Result<RpcResponse<RpcFeeRateGovernor>>;
#[rpc(meta, name = "getSnapshotSlot")]
fn get_snapshot_slot(&self, meta: Self::Metadata) -> Result<Slot>;
#[rpc(meta, name = "getSignatureStatuses")] #[rpc(meta, name = "getSignatureStatuses")]
fn get_signature_statuses( fn get_signature_statuses(
&self, &self,
@ -1808,7 +1816,7 @@ pub trait RpcSol {
) -> Result<RpcResponse<Vec<Option<TransactionStatus>>>>; ) -> Result<RpcResponse<Vec<Option<TransactionStatus>>>>;
#[rpc(meta, name = "getSlot")] #[rpc(meta, name = "getSlot")]
fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<u64>; fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<Slot>;
#[rpc(meta, name = "getTransactionCount")] #[rpc(meta, name = "getTransactionCount")]
fn get_transaction_count( fn get_transaction_count(
@ -2354,6 +2362,17 @@ impl RpcSol for RpcSolImpl {
Ok(meta.get_signature_status(signature, commitment)) Ok(meta.get_signature_status(signature, commitment))
} }
fn get_snapshot_slot(&self, meta: Self::Metadata) -> Result<Slot> {
debug!("get_snapshot_slot rpc request received");
meta.snapshot_config
.and_then(|snapshot_config| {
get_highest_snapshot_archive_path(&snapshot_config.snapshot_package_output_path)
.map(|(_, (slot, _, _))| slot)
})
.ok_or_else(|| RpcCustomError::NoSnapshot.into())
}
fn get_signature_statuses( fn get_signature_statuses(
&self, &self,
meta: Self::Metadata, meta: Self::Metadata,
@ -2377,7 +2396,7 @@ impl RpcSol for RpcSolImpl {
meta.get_signature_statuses(signatures, config) meta.get_signature_statuses(signatures, config)
} }
fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<u64> { fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<Slot> {
debug!("get_slot rpc request received"); debug!("get_slot rpc request received");
Ok(meta.get_slot(commitment)) Ok(meta.get_slot(commitment))
} }
@ -3080,6 +3099,7 @@ pub mod tests {
identity_pubkey: *pubkey, identity_pubkey: *pubkey,
..JsonRpcConfig::default() ..JsonRpcConfig::default()
}, },
None,
bank_forks.clone(), bank_forks.clone(),
block_commitment_cache.clone(), block_commitment_cache.clone(),
blockstore, blockstore,
@ -4480,6 +4500,7 @@ pub mod tests {
let tpu_address = cluster_info.my_contact_info().tpu; let tpu_address = cluster_info.my_contact_info().tpu;
let (meta, receiver) = JsonRpcRequestProcessor::new( let (meta, receiver) = JsonRpcRequestProcessor::new(
JsonRpcConfig::default(), JsonRpcConfig::default(),
None,
bank_forks.clone(), bank_forks.clone(),
block_commitment_cache, block_commitment_cache,
blockstore, blockstore,
@ -4676,6 +4697,7 @@ pub mod tests {
let bank_forks = new_bank_forks().0; let bank_forks = new_bank_forks().0;
let (request_processor, receiver) = JsonRpcRequestProcessor::new( let (request_processor, receiver) = JsonRpcRequestProcessor::new(
JsonRpcConfig::default(), JsonRpcConfig::default(),
None,
bank_forks.clone(), bank_forks.clone(),
block_commitment_cache, block_commitment_cache,
blockstore, blockstore,
@ -4708,6 +4730,7 @@ pub mod tests {
let tpu_address = cluster_info.my_contact_info().tpu; let tpu_address = cluster_info.my_contact_info().tpu;
let (request_processor, receiver) = JsonRpcRequestProcessor::new( let (request_processor, receiver) = JsonRpcRequestProcessor::new(
config, config,
None,
bank_forks.clone(), bank_forks.clone(),
block_commitment_cache, block_commitment_cache,
blockstore, blockstore,
@ -4799,6 +4822,7 @@ pub mod tests {
let tpu_address = cluster_info.my_contact_info().tpu; let tpu_address = cluster_info.my_contact_info().tpu;
let (request_processor, receiver) = JsonRpcRequestProcessor::new( let (request_processor, receiver) = JsonRpcRequestProcessor::new(
config, config,
None,
bank_forks.clone(), bank_forks.clone(),
block_commitment_cache, block_commitment_cache,
blockstore, blockstore,
@ -6027,6 +6051,7 @@ pub mod tests {
let (meta, _receiver) = JsonRpcRequestProcessor::new( let (meta, _receiver) = JsonRpcRequestProcessor::new(
JsonRpcConfig::default(), JsonRpcConfig::default(),
None,
bank_forks.clone(), bank_forks.clone(),
block_commitment_cache, block_commitment_cache,
blockstore, blockstore,

View File

@ -329,6 +329,7 @@ impl JsonRpcService {
let (request_processor, receiver) = JsonRpcRequestProcessor::new( let (request_processor, receiver) = JsonRpcRequestProcessor::new(
config, config,
snapshot_config.clone(),
bank_forks.clone(), bank_forks.clone(),
block_commitment_cache, block_commitment_cache,
blockstore, blockstore,

View File

@ -1968,6 +1968,38 @@ Result:
} }
``` ```
### getSnapshotSlot
Returns the highest slot that the node has a snapshot for
#### Parameters:
None
#### Results:
- `<u64>` - Snapshot slot
#### Example:
Request:
```bash
curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d '
{"jsonrpc":"2.0","id":1, "method":"getSnapshotSlot"}
'
```
Result:
```json
{"jsonrpc":"2.0","result":100,"id":1}
```
Result when the node has no snapshot:
```json
{"jsonrpc":"2.0","error":{"code":-32008,"message":"No snapshot"},"id":1}
```
### getSignatureStatuses ### getSignatureStatuses
Returns the statuses of a list of signatures. Unless the Returns the statuses of a list of signatures. Unless the

View File

@ -380,10 +380,7 @@ fn main() {
} }
loop { loop {
let snapshot_slot = let snapshot_slot = rpc_client.get_snapshot_slot().ok();
solana_runtime::snapshot_utils::get_highest_snapshot_archive_path(&ledger_path)
.map(|(_, (slot, _, _))| slot)
.unwrap_or(0);
for _i in 0..10 { for _i in 0..10 {
match get_validator_stats(&rpc_client, &identity) { match get_validator_stats(&rpc_client, &identity) {
@ -400,16 +397,25 @@ fn main() {
progress_bar.set_message(&format!( progress_bar.set_message(&format!(
"{:02}:{:02}:{:02} \ "{:02}:{:02}:{:02} \
{}| \ {}| \
Processed Slot: {} | Confirmed Slot: {} | Finalized Slot: {} | Snapshot Slot: {} | \ Processed Slot: {} | Confirmed Slot: {} | Finalized Slot: {} | \
Snapshot Slot: {} | \
Transactions: {} | {}", Transactions: {} | {}",
uptime.num_hours(), uptime.num_minutes() % 60, uptime.num_seconds() % 60, uptime.num_hours(),
uptime.num_minutes() % 60,
uptime.num_seconds() % 60,
if health == "ok" { if health == "ok" {
"".to_string() "".to_string()
} else { } else {
format!("| {} ", style(health).bold().red()) format!("| {} ", style(health).bold().red())
}, },
processed_slot, confirmed_slot, finalized_slot, snapshot_slot, processed_slot,
transaction_count, identity_balance confirmed_slot,
finalized_slot,
snapshot_slot
.map(|s| s.to_string())
.unwrap_or_else(|| "-".to_string()),
transaction_count,
identity_balance
)); ));
} }
Err(err) => { Err(err) => {