From 186a1c743dc1f42ac28b7c57b1cd72b8d3b5e86b Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Wed, 21 Jul 2021 14:40:33 -0600 Subject: [PATCH] Add new rpc modules and split apis (#18782) --- rpc/src/rpc.rs | 1077 +++++++++++++++++++++------------------- rpc/src/rpc_service.rs | 7 +- 2 files changed, 561 insertions(+), 523 deletions(-) diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index f0034178cd..9e20e752c9 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -2345,38 +2345,14 @@ pub mod rpc_minimal { } } -// Full RPC interface that an API node is expected to provide -// (rpc_minimal should also be provided by an API node) -pub mod rpc_full { +// RPC interface that only depends on immediate Bank data +// Expected to be provided by both API nodes and (future) accounts replica nodes +pub mod rpc_bank { use super::*; #[rpc] - pub trait Full { + pub trait BankData { type Metadata; - #[rpc(meta, name = "getAccountInfo")] - fn get_account_info( - &self, - meta: Self::Metadata, - pubkey_str: String, - config: Option, - ) -> Result>>; - - #[rpc(meta, name = "getMultipleAccounts")] - fn get_multiple_accounts( - &self, - meta: Self::Metadata, - pubkey_strs: Vec, - config: Option, - ) -> Result>>>; - - #[rpc(meta, name = "getProgramAccounts")] - fn get_program_accounts( - &self, - meta: Self::Metadata, - program_id_str: String, - config: Option, - ) -> Result>>; - #[rpc(meta, name = "getMinimumBalanceForRentExemption")] fn get_minimum_balance_for_rent_exemption( &self, @@ -2385,14 +2361,6 @@ pub mod rpc_full { commitment: Option, ) -> Result; - #[rpc(meta, name = "getInflationReward")] - fn get_inflation_reward( - &self, - meta: Self::Metadata, - address_strs: Vec, - config: Option, - ) -> Result>>; - #[rpc(meta, name = "getInflationGovernor")] fn get_inflation_governor( &self, @@ -2406,26 +2374,6 @@ pub mod rpc_full { #[rpc(meta, name = "getEpochSchedule")] fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result; - #[rpc(meta, name = "getClusterNodes")] - fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result>; - - #[rpc(meta, name = "getRecentPerformanceSamples")] - fn get_recent_performance_samples( - &self, - meta: Self::Metadata, - limit: Option, - ) -> Result>; - - #[rpc(meta, name = "getBlockCommitment")] - fn get_block_commitment( - &self, - meta: Self::Metadata, - block: Slot, - ) -> Result>; - - #[rpc(meta, name = "getGenesisHash")] - fn get_genesis_hash(&self, meta: Self::Metadata) -> Result; - #[rpc(meta, name = "getRecentBlockhash")] fn get_recent_blockhash( &self, @@ -2454,19 +2402,271 @@ pub mod rpc_full { meta: Self::Metadata, ) -> Result>; - #[rpc(meta, name = "getSignatureStatuses")] - fn get_signature_statuses( + #[rpc(meta, name = "getSlotLeader")] + fn get_slot_leader( &self, meta: Self::Metadata, - signature_strs: Vec, - config: Option, - ) -> Result>>>; + commitment: Option, + ) -> Result; - #[rpc(meta, name = "getMaxRetransmitSlot")] - fn get_max_retransmit_slot(&self, meta: Self::Metadata) -> Result; + #[rpc(meta, name = "getSlotLeaders")] + fn get_slot_leaders( + &self, + meta: Self::Metadata, + start_slot: Slot, + limit: u64, + ) -> Result>; - #[rpc(meta, name = "getMaxShredInsertSlot")] - fn get_max_shred_insert_slot(&self, meta: Self::Metadata) -> Result; + #[rpc(meta, name = "getBlockProduction")] + fn get_block_production( + &self, + meta: Self::Metadata, + config: Option, + ) -> Result>; + } + + pub struct BankDataImpl; + impl BankData for BankDataImpl { + type Metadata = JsonRpcRequestProcessor; + + fn get_minimum_balance_for_rent_exemption( + &self, + meta: Self::Metadata, + data_len: usize, + commitment: Option, + ) -> Result { + debug!( + "get_minimum_balance_for_rent_exemption rpc request received: {:?}", + data_len + ); + if data_len as u64 > system_instruction::MAX_PERMITTED_DATA_LENGTH { + return Err(Error::invalid_request()); + } + Ok(meta.get_minimum_balance_for_rent_exemption(data_len, commitment)) + } + + fn get_inflation_governor( + &self, + meta: Self::Metadata, + commitment: Option, + ) -> Result { + debug!("get_inflation_governor rpc request received"); + Ok(meta.get_inflation_governor(commitment)) + } + + fn get_inflation_rate(&self, meta: Self::Metadata) -> Result { + debug!("get_inflation_rate rpc request received"); + Ok(meta.get_inflation_rate()) + } + + fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result { + debug!("get_epoch_schedule rpc request received"); + Ok(meta.get_epoch_schedule()) + } + + fn get_recent_blockhash( + &self, + meta: Self::Metadata, + commitment: Option, + ) -> Result> { + debug!("get_recent_blockhash rpc request received"); + Ok(meta.get_recent_blockhash(commitment)) + } + + fn get_fees( + &self, + meta: Self::Metadata, + commitment: Option, + ) -> Result> { + debug!("get_fees rpc request received"); + Ok(meta.get_fees(commitment)) + } + + fn get_fee_calculator_for_blockhash( + &self, + meta: Self::Metadata, + blockhash: String, + commitment: Option, + ) -> Result>> { + debug!("get_fee_calculator_for_blockhash rpc request received"); + let blockhash = Hash::from_str(&blockhash) + .map_err(|e| Error::invalid_params(format!("{:?}", e)))?; + Ok(meta.get_fee_calculator_for_blockhash(&blockhash, commitment)) + } + + fn get_fee_rate_governor( + &self, + meta: Self::Metadata, + ) -> Result> { + debug!("get_fee_rate_governor rpc request received"); + Ok(meta.get_fee_rate_governor()) + } + + fn get_slot_leader( + &self, + meta: Self::Metadata, + commitment: Option, + ) -> Result { + debug!("get_slot_leader rpc request received"); + Ok(meta.get_slot_leader(commitment)) + } + + fn get_slot_leaders( + &self, + meta: Self::Metadata, + start_slot: Slot, + limit: u64, + ) -> Result> { + debug!( + "get_slot_leaders rpc request received (start: {} limit: {})", + start_slot, limit + ); + + let limit = limit as usize; + if limit > MAX_GET_SLOT_LEADERS { + return Err(Error::invalid_params(format!( + "Invalid limit; max {}", + MAX_GET_SLOT_LEADERS + ))); + } + + Ok(meta + .get_slot_leaders(None, start_slot, limit)? + .into_iter() + .map(|identity| identity.to_string()) + .collect()) + } + + fn get_block_production( + &self, + meta: Self::Metadata, + config: Option, + ) -> Result> { + debug!("get_block_production rpc request received"); + + let config = config.unwrap_or_default(); + let filter_by_identity = if let Some(ref identity) = config.identity { + Some(verify_pubkey(identity)?) + } else { + None + }; + + let bank = meta.bank(config.commitment); + let (first_slot, last_slot) = match config.range { + None => ( + bank.epoch_schedule().get_first_slot_in_epoch(bank.epoch()), + bank.slot(), + ), + Some(range) => { + let first_slot = range.first_slot; + let last_slot = range.last_slot.unwrap_or_else(|| bank.slot()); + if last_slot < first_slot { + return Err(Error::invalid_params(format!( + "lastSlot, {}, cannot be less than firstSlot, {}", + last_slot, first_slot + ))); + } + (first_slot, last_slot) + } + }; + + let slot_history = bank.get_slot_history(); + if first_slot < slot_history.oldest() { + return Err(Error::invalid_params(format!( + "firstSlot, {}, is too small; min {}", + first_slot, + slot_history.oldest() + ))); + } + if last_slot > slot_history.newest() { + return Err(Error::invalid_params(format!( + "lastSlot, {}, is too large; max {}", + last_slot, + slot_history.newest() + ))); + } + + let slot_leaders = meta.get_slot_leaders( + config.commitment, + first_slot, + last_slot.saturating_sub(first_slot) as usize + 1, // +1 because last_slot is inclusive + )?; + + let mut block_production: HashMap<_, (usize, usize)> = HashMap::new(); + + let mut slot = first_slot; + for identity in slot_leaders { + if let Some(ref filter_by_identity) = filter_by_identity { + if identity != *filter_by_identity { + slot += 1; + continue; + } + } + + let mut entry = block_production.entry(identity).or_default(); + if slot_history.check(slot) == solana_sdk::slot_history::Check::Found { + entry.1 += 1; // Increment blocks_produced + } + entry.0 += 1; // Increment leader_slots + slot += 1; + } + + Ok(new_response( + &bank, + RpcBlockProduction { + by_identity: block_production + .into_iter() + .map(|(k, v)| (k.to_string(), v)) + .collect(), + range: RpcBlockProductionRange { + first_slot, + last_slot, + }, + }, + )) + } + } +} + +// RPC interface that depends on AccountsDB +// Expected to be provided by API nodes, but collected for easy separation and offloading to +// accounts replica nodes in the future. +pub mod rpc_accounts { + use super::*; + #[rpc] + pub trait AccountsData { + type Metadata; + + #[rpc(meta, name = "getAccountInfo")] + fn get_account_info( + &self, + meta: Self::Metadata, + pubkey_str: String, + config: Option, + ) -> Result>>; + + #[rpc(meta, name = "getMultipleAccounts")] + fn get_multiple_accounts( + &self, + meta: Self::Metadata, + pubkey_strs: Vec, + config: Option, + ) -> Result>>>; + + #[rpc(meta, name = "getProgramAccounts")] + fn get_program_accounts( + &self, + meta: Self::Metadata, + program_id_str: String, + config: Option, + ) -> Result>>; + + #[rpc(meta, name = "getBlockCommitment")] + fn get_block_commitment( + &self, + meta: Self::Metadata, + block: Slot, + ) -> Result>; #[rpc(meta, name = "getLargestAccounts")] fn get_largest_accounts( @@ -2482,6 +2682,293 @@ pub mod rpc_full { commitment: Option, ) -> Result>; + #[rpc(meta, name = "getStakeActivation")] + fn get_stake_activation( + &self, + meta: Self::Metadata, + pubkey_str: String, + config: Option, + ) -> Result; + + // SPL Token-specific RPC endpoints + // See https://github.com/solana-labs/solana-program-library/releases/tag/token-v2.0.0 for + // program details + + #[rpc(meta, name = "getTokenAccountBalance")] + fn get_token_account_balance( + &self, + meta: Self::Metadata, + pubkey_str: String, + commitment: Option, + ) -> Result>; + + #[rpc(meta, name = "getTokenSupply")] + fn get_token_supply( + &self, + meta: Self::Metadata, + mint_str: String, + commitment: Option, + ) -> Result>; + + #[rpc(meta, name = "getTokenLargestAccounts")] + fn get_token_largest_accounts( + &self, + meta: Self::Metadata, + mint_str: String, + commitment: Option, + ) -> Result>>; + + #[rpc(meta, name = "getTokenAccountsByOwner")] + fn get_token_accounts_by_owner( + &self, + meta: Self::Metadata, + owner_str: String, + token_account_filter: RpcTokenAccountsFilter, + config: Option, + ) -> Result>>; + + #[rpc(meta, name = "getTokenAccountsByDelegate")] + fn get_token_accounts_by_delegate( + &self, + meta: Self::Metadata, + delegate_str: String, + token_account_filter: RpcTokenAccountsFilter, + config: Option, + ) -> Result>>; + } + + pub struct AccountsDataImpl; + impl AccountsData for AccountsDataImpl { + type Metadata = JsonRpcRequestProcessor; + + fn get_account_info( + &self, + meta: Self::Metadata, + pubkey_str: String, + config: Option, + ) -> Result>> { + debug!("get_account_info rpc request received: {:?}", pubkey_str); + let pubkey = verify_pubkey(&pubkey_str)?; + meta.get_account_info(&pubkey, config) + } + + fn get_multiple_accounts( + &self, + meta: Self::Metadata, + pubkey_strs: Vec, + config: Option, + ) -> Result>>> { + debug!( + "get_multiple_accounts rpc request received: {:?}", + pubkey_strs.len() + ); + + let max_multiple_accounts = meta + .config + .max_multiple_accounts + .unwrap_or(MAX_MULTIPLE_ACCOUNTS); + if pubkey_strs.len() > max_multiple_accounts { + return Err(Error::invalid_params(format!( + "Too many inputs provided; max {}", + max_multiple_accounts + ))); + } + let mut pubkeys: Vec = vec![]; + for pubkey_str in pubkey_strs { + pubkeys.push(verify_pubkey(&pubkey_str)?); + } + meta.get_multiple_accounts(pubkeys, config) + } + + fn get_program_accounts( + &self, + meta: Self::Metadata, + program_id_str: String, + config: Option, + ) -> Result>> { + debug!( + "get_program_accounts rpc request received: {:?}", + program_id_str + ); + let program_id = verify_pubkey(&program_id_str)?; + let (config, filters, with_context) = if let Some(config) = config { + ( + Some(config.account_config), + config.filters.unwrap_or_default(), + config.with_context.unwrap_or_default(), + ) + } else { + (None, vec![], false) + }; + if filters.len() > MAX_GET_PROGRAM_ACCOUNT_FILTERS { + return Err(Error::invalid_params(format!( + "Too many filters provided; max {}", + MAX_GET_PROGRAM_ACCOUNT_FILTERS + ))); + } + for filter in &filters { + verify_filter(filter)?; + } + meta.get_program_accounts(&program_id, config, filters, with_context) + } + + fn get_block_commitment( + &self, + meta: Self::Metadata, + block: Slot, + ) -> Result> { + debug!("get_block_commitment rpc request received"); + Ok(meta.get_block_commitment(block)) + } + + fn get_largest_accounts( + &self, + meta: Self::Metadata, + config: Option, + ) -> Result>> { + debug!("get_largest_accounts rpc request received"); + Ok(meta.get_largest_accounts(config)?) + } + + fn get_supply( + &self, + meta: Self::Metadata, + commitment: Option, + ) -> Result> { + debug!("get_supply rpc request received"); + Ok(meta.get_supply(commitment)?) + } + + fn get_stake_activation( + &self, + meta: Self::Metadata, + pubkey_str: String, + config: Option, + ) -> Result { + debug!( + "get_stake_activation rpc request received: {:?}", + pubkey_str + ); + let pubkey = verify_pubkey(&pubkey_str)?; + meta.get_stake_activation(&pubkey, config) + } + + fn get_token_account_balance( + &self, + meta: Self::Metadata, + pubkey_str: String, + commitment: Option, + ) -> Result> { + debug!( + "get_token_account_balance rpc request received: {:?}", + pubkey_str + ); + let pubkey = verify_pubkey(&pubkey_str)?; + meta.get_token_account_balance(&pubkey, commitment) + } + + fn get_token_supply( + &self, + meta: Self::Metadata, + mint_str: String, + commitment: Option, + ) -> Result> { + debug!("get_token_supply rpc request received: {:?}", mint_str); + let mint = verify_pubkey(&mint_str)?; + meta.get_token_supply(&mint, commitment) + } + + fn get_token_largest_accounts( + &self, + meta: Self::Metadata, + mint_str: String, + commitment: Option, + ) -> Result>> { + debug!( + "get_token_largest_accounts rpc request received: {:?}", + mint_str + ); + let mint = verify_pubkey(&mint_str)?; + meta.get_token_largest_accounts(&mint, commitment) + } + + fn get_token_accounts_by_owner( + &self, + meta: Self::Metadata, + owner_str: String, + token_account_filter: RpcTokenAccountsFilter, + config: Option, + ) -> Result>> { + debug!( + "get_token_accounts_by_owner rpc request received: {:?}", + owner_str + ); + let owner = verify_pubkey(&owner_str)?; + let token_account_filter = verify_token_account_filter(token_account_filter)?; + meta.get_token_accounts_by_owner(&owner, token_account_filter, config) + } + + fn get_token_accounts_by_delegate( + &self, + meta: Self::Metadata, + delegate_str: String, + token_account_filter: RpcTokenAccountsFilter, + config: Option, + ) -> Result>> { + debug!( + "get_token_accounts_by_delegate rpc request received: {:?}", + delegate_str + ); + let delegate = verify_pubkey(&delegate_str)?; + let token_account_filter = verify_token_account_filter(token_account_filter)?; + meta.get_token_accounts_by_delegate(&delegate, token_account_filter, config) + } + } +} + +// Full RPC interface that an API node is expected to provide +// (rpc_minimal should also be provided by an API node) +pub mod rpc_full { + use super::*; + #[rpc] + pub trait Full { + type Metadata; + + #[rpc(meta, name = "getInflationReward")] + fn get_inflation_reward( + &self, + meta: Self::Metadata, + address_strs: Vec, + config: Option, + ) -> Result>>; + + #[rpc(meta, name = "getClusterNodes")] + fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result>; + + #[rpc(meta, name = "getRecentPerformanceSamples")] + fn get_recent_performance_samples( + &self, + meta: Self::Metadata, + limit: Option, + ) -> Result>; + + #[rpc(meta, name = "getGenesisHash")] + fn get_genesis_hash(&self, meta: Self::Metadata) -> Result; + + #[rpc(meta, name = "getSignatureStatuses")] + fn get_signature_statuses( + &self, + meta: Self::Metadata, + signature_strs: Vec, + config: Option, + ) -> Result>>>; + + #[rpc(meta, name = "getMaxRetransmitSlot")] + fn get_max_retransmit_slot(&self, meta: Self::Metadata) -> Result; + + #[rpc(meta, name = "getMaxShredInsertSlot")] + fn get_max_shred_insert_slot(&self, meta: Self::Metadata) -> Result; + #[rpc(meta, name = "requestAirdrop")] fn request_airdrop( &self, @@ -2507,21 +2994,6 @@ pub mod rpc_full { config: Option, ) -> Result>; - #[rpc(meta, name = "getSlotLeader")] - fn get_slot_leader( - &self, - meta: Self::Metadata, - commitment: Option, - ) -> Result; - - #[rpc(meta, name = "getSlotLeaders")] - fn get_slot_leaders( - &self, - meta: Self::Metadata, - start_slot: Slot, - limit: u64, - ) -> Result>; - #[rpc(meta, name = "minimumLedgerSlot")] fn minimum_ledger_slot(&self, meta: Self::Metadata) -> Result; @@ -2573,179 +3045,12 @@ pub mod rpc_full { #[rpc(meta, name = "getFirstAvailableBlock")] fn get_first_available_block(&self, meta: Self::Metadata) -> Result; - - #[rpc(meta, name = "getStakeActivation")] - fn get_stake_activation( - &self, - meta: Self::Metadata, - pubkey_str: String, - config: Option, - ) -> Result; - - #[rpc(meta, name = "getBlockProduction")] - fn get_block_production( - &self, - meta: Self::Metadata, - config: Option, - ) -> Result>; - - // SPL Token-specific RPC endpoints - // See https://github.com/solana-labs/solana-program-library/releases/tag/token-v2.0.0 for - // program details - - #[rpc(meta, name = "getTokenAccountBalance")] - fn get_token_account_balance( - &self, - meta: Self::Metadata, - pubkey_str: String, - commitment: Option, - ) -> Result>; - - #[rpc(meta, name = "getTokenSupply")] - fn get_token_supply( - &self, - meta: Self::Metadata, - mint_str: String, - commitment: Option, - ) -> Result>; - - #[rpc(meta, name = "getTokenLargestAccounts")] - fn get_token_largest_accounts( - &self, - meta: Self::Metadata, - mint_str: String, - commitment: Option, - ) -> Result>>; - - #[rpc(meta, name = "getTokenAccountsByOwner")] - fn get_token_accounts_by_owner( - &self, - meta: Self::Metadata, - owner_str: String, - token_account_filter: RpcTokenAccountsFilter, - config: Option, - ) -> Result>>; - - #[rpc(meta, name = "getTokenAccountsByDelegate")] - fn get_token_accounts_by_delegate( - &self, - meta: Self::Metadata, - delegate_str: String, - token_account_filter: RpcTokenAccountsFilter, - config: Option, - ) -> Result>>; } pub struct FullImpl; impl Full for FullImpl { type Metadata = JsonRpcRequestProcessor; - fn get_account_info( - &self, - meta: Self::Metadata, - pubkey_str: String, - config: Option, - ) -> Result>> { - debug!("get_account_info rpc request received: {:?}", pubkey_str); - let pubkey = verify_pubkey(&pubkey_str)?; - meta.get_account_info(&pubkey, config) - } - - fn get_multiple_accounts( - &self, - meta: Self::Metadata, - pubkey_strs: Vec, - config: Option, - ) -> Result>>> { - debug!( - "get_multiple_accounts rpc request received: {:?}", - pubkey_strs.len() - ); - - let max_multiple_accounts = meta - .config - .max_multiple_accounts - .unwrap_or(MAX_MULTIPLE_ACCOUNTS); - if pubkey_strs.len() > max_multiple_accounts { - return Err(Error::invalid_params(format!( - "Too many inputs provided; max {}", - max_multiple_accounts - ))); - } - let mut pubkeys: Vec = vec![]; - for pubkey_str in pubkey_strs { - pubkeys.push(verify_pubkey(&pubkey_str)?); - } - meta.get_multiple_accounts(pubkeys, config) - } - - fn get_minimum_balance_for_rent_exemption( - &self, - meta: Self::Metadata, - data_len: usize, - commitment: Option, - ) -> Result { - debug!( - "get_minimum_balance_for_rent_exemption rpc request received: {:?}", - data_len - ); - if data_len as u64 > system_instruction::MAX_PERMITTED_DATA_LENGTH { - return Err(Error::invalid_request()); - } - Ok(meta.get_minimum_balance_for_rent_exemption(data_len, commitment)) - } - - fn get_program_accounts( - &self, - meta: Self::Metadata, - program_id_str: String, - config: Option, - ) -> Result>> { - debug!( - "get_program_accounts rpc request received: {:?}", - program_id_str - ); - let program_id = verify_pubkey(&program_id_str)?; - let (config, filters, with_context) = if let Some(config) = config { - ( - Some(config.account_config), - config.filters.unwrap_or_default(), - config.with_context.unwrap_or_default(), - ) - } else { - (None, vec![], false) - }; - if filters.len() > MAX_GET_PROGRAM_ACCOUNT_FILTERS { - return Err(Error::invalid_params(format!( - "Too many filters provided; max {}", - MAX_GET_PROGRAM_ACCOUNT_FILTERS - ))); - } - for filter in &filters { - verify_filter(filter)?; - } - meta.get_program_accounts(&program_id, config, filters, with_context) - } - - fn get_inflation_governor( - &self, - meta: Self::Metadata, - commitment: Option, - ) -> Result { - debug!("get_inflation_governor rpc request received"); - Ok(meta.get_inflation_governor(commitment)) - } - - fn get_inflation_rate(&self, meta: Self::Metadata) -> Result { - debug!("get_inflation_rate rpc request received"); - Ok(meta.get_inflation_rate()) - } - - fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result { - debug!("get_epoch_schedule rpc request received"); - Ok(meta.get_epoch_schedule()) - } - fn get_recent_performance_samples( &self, meta: Self::Metadata, @@ -2820,58 +3125,11 @@ pub mod rpc_full { .collect()) } - fn get_block_commitment( - &self, - meta: Self::Metadata, - block: Slot, - ) -> Result> { - debug!("get_block_commitment rpc request received"); - Ok(meta.get_block_commitment(block)) - } - fn get_genesis_hash(&self, meta: Self::Metadata) -> Result { debug!("get_genesis_hash rpc request received"); Ok(meta.genesis_hash.to_string()) } - fn get_recent_blockhash( - &self, - meta: Self::Metadata, - commitment: Option, - ) -> Result> { - debug!("get_recent_blockhash rpc request received"); - Ok(meta.get_recent_blockhash(commitment)) - } - - fn get_fees( - &self, - meta: Self::Metadata, - commitment: Option, - ) -> Result> { - debug!("get_fees rpc request received"); - Ok(meta.get_fees(commitment)) - } - - fn get_fee_calculator_for_blockhash( - &self, - meta: Self::Metadata, - blockhash: String, - commitment: Option, - ) -> Result>> { - debug!("get_fee_calculator_for_blockhash rpc request received"); - let blockhash = Hash::from_str(&blockhash) - .map_err(|e| Error::invalid_params(format!("{:?}", e)))?; - Ok(meta.get_fee_calculator_for_blockhash(&blockhash, commitment)) - } - - fn get_fee_rate_governor( - &self, - meta: Self::Metadata, - ) -> Result> { - debug!("get_fee_rate_governor rpc request received"); - Ok(meta.get_fee_rate_governor()) - } - fn get_signature_statuses( &self, meta: Self::Metadata, @@ -2905,24 +3163,6 @@ pub mod rpc_full { Ok(meta.get_max_shred_insert_slot()) } - fn get_largest_accounts( - &self, - meta: Self::Metadata, - config: Option, - ) -> Result>> { - debug!("get_largest_accounts rpc request received"); - Ok(meta.get_largest_accounts(config)?) - } - - fn get_supply( - &self, - meta: Self::Metadata, - commitment: Option, - ) -> Result> { - debug!("get_supply rpc request received"); - Ok(meta.get_supply(commitment)?) - } - fn request_airdrop( &self, meta: Self::Metadata, @@ -3159,41 +3399,6 @@ pub mod rpc_full { )) } - fn get_slot_leader( - &self, - meta: Self::Metadata, - commitment: Option, - ) -> Result { - debug!("get_slot_leader rpc request received"); - Ok(meta.get_slot_leader(commitment)) - } - - fn get_slot_leaders( - &self, - meta: Self::Metadata, - start_slot: Slot, - limit: u64, - ) -> Result> { - debug!( - "get_slot_leaders rpc request received (start: {} limit: {})", - start_slot, limit - ); - - let limit = limit as usize; - if limit > MAX_GET_SLOT_LEADERS { - return Err(Error::invalid_params(format!( - "Invalid limit; max {}", - MAX_GET_SLOT_LEADERS - ))); - } - - Ok(meta - .get_slot_leaders(None, start_slot, limit)? - .into_iter() - .map(|identity| identity.to_string()) - .collect()) - } - fn minimum_ledger_slot(&self, meta: Self::Metadata) -> Result { debug!("minimum_ledger_slot rpc request received"); meta.minimum_ledger_slot() @@ -3294,109 +3499,6 @@ pub mod rpc_full { Ok(meta.get_first_available_block()) } - fn get_stake_activation( - &self, - meta: Self::Metadata, - pubkey_str: String, - config: Option, - ) -> Result { - debug!( - "get_stake_activation rpc request received: {:?}", - pubkey_str - ); - let pubkey = verify_pubkey(&pubkey_str)?; - meta.get_stake_activation(&pubkey, config) - } - - fn get_block_production( - &self, - meta: Self::Metadata, - config: Option, - ) -> Result> { - debug!("get_block_production rpc request received"); - - let config = config.unwrap_or_default(); - let filter_by_identity = if let Some(ref identity) = config.identity { - Some(verify_pubkey(identity)?) - } else { - None - }; - - let bank = meta.bank(config.commitment); - let (first_slot, last_slot) = match config.range { - None => ( - bank.epoch_schedule().get_first_slot_in_epoch(bank.epoch()), - bank.slot(), - ), - Some(range) => { - let first_slot = range.first_slot; - let last_slot = range.last_slot.unwrap_or_else(|| bank.slot()); - if last_slot < first_slot { - return Err(Error::invalid_params(format!( - "lastSlot, {}, cannot be less than firstSlot, {}", - last_slot, first_slot - ))); - } - (first_slot, last_slot) - } - }; - - let slot_history = bank.get_slot_history(); - if first_slot < slot_history.oldest() { - return Err(Error::invalid_params(format!( - "firstSlot, {}, is too small; min {}", - first_slot, - slot_history.oldest() - ))); - } - if last_slot > slot_history.newest() { - return Err(Error::invalid_params(format!( - "lastSlot, {}, is too large; max {}", - last_slot, - slot_history.newest() - ))); - } - - let slot_leaders = meta.get_slot_leaders( - config.commitment, - first_slot, - last_slot.saturating_sub(first_slot) as usize + 1, // +1 because last_slot is inclusive - )?; - - let mut block_production: HashMap<_, (usize, usize)> = HashMap::new(); - - let mut slot = first_slot; - for identity in slot_leaders { - if let Some(ref filter_by_identity) = filter_by_identity { - if identity != *filter_by_identity { - slot += 1; - continue; - } - } - - let mut entry = block_production.entry(identity).or_default(); - if slot_history.check(slot) == solana_sdk::slot_history::Check::Found { - entry.1 += 1; // Increment blocks_produced - } - entry.0 += 1; // Increment leader_slots - slot += 1; - } - - Ok(new_response( - &bank, - RpcBlockProduction { - by_identity: block_production - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect(), - range: RpcBlockProductionRange { - first_slot, - last_slot, - }, - }, - )) - } - fn get_inflation_reward( &self, meta: Self::Metadata, @@ -3415,77 +3517,6 @@ pub mod rpc_full { meta.get_inflation_reward(addresses, config) } - - fn get_token_account_balance( - &self, - meta: Self::Metadata, - pubkey_str: String, - commitment: Option, - ) -> Result> { - debug!( - "get_token_account_balance rpc request received: {:?}", - pubkey_str - ); - let pubkey = verify_pubkey(&pubkey_str)?; - meta.get_token_account_balance(&pubkey, commitment) - } - - fn get_token_supply( - &self, - meta: Self::Metadata, - mint_str: String, - commitment: Option, - ) -> Result> { - debug!("get_token_supply rpc request received: {:?}", mint_str); - let mint = verify_pubkey(&mint_str)?; - meta.get_token_supply(&mint, commitment) - } - - fn get_token_largest_accounts( - &self, - meta: Self::Metadata, - mint_str: String, - commitment: Option, - ) -> Result>> { - debug!( - "get_token_largest_accounts rpc request received: {:?}", - mint_str - ); - let mint = verify_pubkey(&mint_str)?; - meta.get_token_largest_accounts(&mint, commitment) - } - - fn get_token_accounts_by_owner( - &self, - meta: Self::Metadata, - owner_str: String, - token_account_filter: RpcTokenAccountsFilter, - config: Option, - ) -> Result>> { - debug!( - "get_token_accounts_by_owner rpc request received: {:?}", - owner_str - ); - let owner = verify_pubkey(&owner_str)?; - let token_account_filter = verify_token_account_filter(token_account_filter)?; - meta.get_token_accounts_by_owner(&owner, token_account_filter, config) - } - - fn get_token_accounts_by_delegate( - &self, - meta: Self::Metadata, - delegate_str: String, - token_account_filter: RpcTokenAccountsFilter, - config: Option, - ) -> Result>> { - debug!( - "get_token_accounts_by_delegate rpc request received: {:?}", - delegate_str - ); - let delegate = verify_pubkey(&delegate_str)?; - let token_account_filter = verify_token_account_filter(token_account_filter)?; - meta.get_token_accounts_by_delegate(&delegate, token_account_filter, config) - } } } @@ -3932,7 +3963,7 @@ pub fn create_test_transactions_and_populate_blockstore( #[cfg(test)] pub mod tests { use { - super::{rpc_full::*, rpc_minimal::*, *}, + super::{rpc_accounts::*, rpc_bank::*, rpc_full::*, rpc_minimal::*, *}, crate::{ optimistically_confirmed_bank_tracker::{ BankNotification, OptimisticallyConfirmedBankTracker, @@ -4161,6 +4192,8 @@ pub mod tests { let mut io = MetaIoHandler::default(); io.extend_with(rpc_minimal::MinimalImpl.to_delegate()); + io.extend_with(rpc_bank::BankDataImpl.to_delegate()); + io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate()); io.extend_with(rpc_full::FullImpl.to_delegate()); RpcHandler { io, diff --git a/rpc/src/rpc_service.rs b/rpc/src/rpc_service.rs index e1935a8c35..4a357c4360 100644 --- a/rpc/src/rpc_service.rs +++ b/rpc/src/rpc_service.rs @@ -4,7 +4,10 @@ use { crate::{ max_slots::MaxSlots, optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank, - rpc::{rpc_deprecated_v1_7::*, rpc_full::*, rpc_minimal::*, rpc_obsolete_v1_7::*, *}, + rpc::{ + rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_7::*, rpc_full::*, rpc_minimal::*, + rpc_obsolete_v1_7::*, *, + }, rpc_health::*, send_transaction_service::{LeaderInfo, SendTransactionService}, }, @@ -414,6 +417,8 @@ impl JsonRpcService { io.extend_with(rpc_minimal::MinimalImpl.to_delegate()); if !minimal_api { + io.extend_with(rpc_bank::BankDataImpl.to_delegate()); + io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate()); io.extend_with(rpc_full::FullImpl.to_delegate()); io.extend_with(rpc_deprecated_v1_7::DeprecatedV1_7Impl.to_delegate()); }