solana_rpc/
rpc.rs

1//! The `rpc` module implements the Solana RPC interface.
2#[cfg(feature = "dev-context-only-utils")]
3use solana_runtime::installed_scheduler_pool::BankWithScheduler;
4use {
5    crate::{
6        filter::filter_allows, max_slots::MaxSlots,
7        optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
8        parsed_token_accounts::*, rpc_cache::LargestAccountsCache, rpc_health::*,
9    },
10    agave_snapshots::{paths as snapshot_paths, snapshot_config::SnapshotConfig},
11    base64::{prelude::BASE64_STANDARD, Engine},
12    bincode::{config::Options, serialize},
13    crossbeam_channel::{unbounded, Receiver, Sender},
14    jsonrpc_core::{
15        futures::future::{self, FutureExt, OptionFuture},
16        types::error,
17        BoxFuture, Error, Metadata, Result,
18    },
19    jsonrpc_derive::rpc,
20    solana_account::{AccountSharedData, ReadableAccount},
21    solana_account_decoder::{
22        encode_ui_account,
23        parse_account_data::SplTokenAdditionalDataV2,
24        parse_token::{is_known_spl_token_id, token_amount_to_ui_amount_v3, UiTokenAmount},
25        UiAccount, UiAccountEncoding, UiDataSliceConfig, MAX_BASE58_BYTES,
26    },
27    solana_accounts_db::{
28        accounts::AccountAddressFilter,
29        accounts_index::{
30            AccountIndex, AccountSecondaryIndexes, IndexKey, ScanConfig, ScanOrder, ScanResult,
31        },
32    },
33    solana_client::connection_cache::Protocol,
34    solana_clock::{Slot, UnixTimestamp, MAX_PROCESSING_AGE},
35    solana_commitment_config::{CommitmentConfig, CommitmentLevel},
36    solana_entry::entry::Entry,
37    solana_epoch_info::EpochInfo,
38    solana_epoch_rewards_hasher::EpochRewardsHasher,
39    solana_epoch_schedule::EpochSchedule,
40    solana_faucet::faucet::request_airdrop_transaction,
41    solana_gossip::cluster_info::ClusterInfo,
42    solana_hash::Hash,
43    solana_keypair::Keypair,
44    solana_ledger::{
45        blockstore::{Blockstore, BlockstoreError, SignatureInfosForAddress},
46        blockstore_meta::{PerfSample, PerfSampleV1, PerfSampleV2},
47        leader_schedule_cache::LeaderScheduleCache,
48    },
49    solana_message::{AddressLoader, SanitizedMessage},
50    solana_metrics::inc_new_counter_info,
51    solana_perf::packet::PACKET_DATA_SIZE,
52    solana_program_pack::Pack,
53    solana_pubkey::{Pubkey, PUBKEY_BYTES},
54    solana_rpc_client_api::{
55        config::*,
56        custom_error::RpcCustomError,
57        filter::{Memcmp, RpcFilterType},
58        request::{
59            TokenAccountsFilter, DELINQUENT_VALIDATOR_SLOT_DISTANCE,
60            MAX_GET_CONFIRMED_BLOCKS_RANGE, MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT,
61            MAX_GET_PROGRAM_ACCOUNT_FILTERS, MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
62            MAX_GET_SLOT_LEADERS, MAX_MULTIPLE_ACCOUNTS,
63            MAX_RPC_VOTE_ACCOUNT_INFO_EPOCH_CREDITS_HISTORY, NUM_LARGEST_ACCOUNTS,
64        },
65        response::{Response as RpcResponse, *},
66    },
67    solana_runtime::{
68        bank::{Bank, TransactionSimulationResult},
69        bank_forks::BankForks,
70        commitment::{BlockCommitmentArray, BlockCommitmentCache},
71        non_circulating_supply::{calculate_non_circulating_supply, NonCirculatingSupply},
72        prioritization_fee_cache::PrioritizationFeeCache,
73        stake_utils,
74    },
75    solana_runtime_transaction::runtime_transaction::RuntimeTransaction,
76    solana_send_transaction_service::send_transaction_service::TransactionInfo,
77    solana_signature::Signature,
78    solana_signer::Signer,
79    solana_storage_bigtable::Error as StorageError,
80    solana_transaction::{
81        sanitized::{MessageHash, SanitizedTransaction, MAX_TX_ACCOUNT_LOCKS},
82        versioned::VersionedTransaction,
83    },
84    solana_transaction_context::transaction_accounts::KeyedAccountSharedData,
85    solana_transaction_error::TransactionError,
86    solana_transaction_status::{
87        map_inner_instructions, BlockEncodingOptions, ConfirmedBlock,
88        ConfirmedTransactionStatusWithSignature, ConfirmedTransactionWithStatusMeta,
89        EncodedConfirmedTransactionWithStatusMeta, Reward, RewardType, Rewards,
90        TransactionBinaryEncoding, TransactionConfirmationStatus, TransactionStatus,
91        UiConfirmedBlock, UiTransactionEncoding,
92    },
93    solana_validator_exit::Exit,
94    solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY,
95    spl_generic_token::{
96        token::{SPL_TOKEN_ACCOUNT_MINT_OFFSET, SPL_TOKEN_ACCOUNT_OWNER_OFFSET},
97        token_2022::{self, ACCOUNTTYPE_ACCOUNT},
98    },
99    spl_token_2022_interface::{
100        extension::{
101            interest_bearing_mint::InterestBearingConfig, scaled_ui_amount::ScaledUiAmountConfig,
102            BaseStateWithExtensions, StateWithExtensions,
103        },
104        state::{Account as TokenAccount, Mint},
105    },
106    std::{
107        any::type_name,
108        cmp::{max, min, Reverse},
109        collections::{BinaryHeap, HashMap, HashSet},
110        convert::TryFrom,
111        net::SocketAddr,
112        str::FromStr,
113        sync::{
114            atomic::{AtomicBool, AtomicU64, Ordering},
115            Arc, RwLock,
116        },
117        time::Duration,
118    },
119    tokio::runtime::Runtime,
120};
121#[cfg(test)]
122use {
123    solana_gossip::contact_info::ContactInfo,
124    solana_ledger::get_tmp_ledger_path,
125    solana_runtime::commitment::CommitmentSlots,
126    solana_send_transaction_service::{
127        send_transaction_service::Config as SendTransactionServiceConfig,
128        send_transaction_service::SendTransactionService, test_utils::ClientWithCreator,
129    },
130    solana_streamer::socket::SocketAddrSpace,
131};
132
133mod transaction {
134    pub use solana_transaction_error::TransactionResult as Result;
135}
136
137pub mod account_resolver;
138
139type RpcCustomResult<T> = std::result::Result<T, RpcCustomError>;
140
141pub const MAX_REQUEST_BODY_SIZE: usize = 50 * (1 << 10); // 50kB
142pub const PERFORMANCE_SAMPLES_LIMIT: usize = 720;
143
144fn new_response<T>(bank: &Bank, value: T) -> RpcResponse<T> {
145    RpcResponse {
146        context: RpcResponseContext::new(bank.slot()),
147        value,
148    }
149}
150
151fn is_finalized(
152    block_commitment_cache: &BlockCommitmentCache,
153    bank: &Bank,
154    blockstore: &Blockstore,
155    slot: Slot,
156) -> bool {
157    slot <= block_commitment_cache.highest_super_majority_root()
158        && (blockstore.is_root(slot) || bank.status_cache_ancestors().contains(&slot))
159}
160
161#[derive(Debug, Clone, PartialEq)]
162pub struct JsonRpcConfig {
163    pub enable_rpc_transaction_history: bool,
164    pub enable_extended_tx_metadata_storage: bool,
165    pub faucet_addr: Option<SocketAddr>,
166    pub health_check_slot_distance: u64,
167    pub skip_preflight_health_check: bool,
168    pub rpc_bigtable_config: Option<RpcBigtableConfig>,
169    pub max_multiple_accounts: Option<usize>,
170    pub account_indexes: AccountSecondaryIndexes,
171    pub rpc_threads: usize,
172    pub rpc_blocking_threads: usize,
173    pub rpc_niceness_adj: i8,
174    pub full_api: bool,
175    pub rpc_scan_and_fix_roots: bool,
176    pub max_request_body_size: Option<usize>,
177    /// Disable the health check, used for tests and TestValidator
178    pub disable_health_check: bool,
179}
180
181impl Default for JsonRpcConfig {
182    fn default() -> Self {
183        Self {
184            enable_rpc_transaction_history: Default::default(),
185            enable_extended_tx_metadata_storage: Default::default(),
186            faucet_addr: Option::default(),
187            health_check_slot_distance: Default::default(),
188            skip_preflight_health_check: bool::default(),
189            rpc_bigtable_config: Option::default(),
190            max_multiple_accounts: Option::default(),
191            account_indexes: AccountSecondaryIndexes::default(),
192            rpc_threads: 1,
193            rpc_blocking_threads: 1,
194            rpc_niceness_adj: Default::default(),
195            full_api: Default::default(),
196            rpc_scan_and_fix_roots: Default::default(),
197            max_request_body_size: Option::default(),
198            disable_health_check: Default::default(),
199        }
200    }
201}
202
203impl JsonRpcConfig {
204    pub fn default_for_test() -> Self {
205        Self {
206            full_api: true,
207            disable_health_check: true,
208            ..Self::default()
209        }
210    }
211}
212
213#[derive(Debug, Clone, PartialEq)]
214pub struct RpcBigtableConfig {
215    pub enable_bigtable_ledger_upload: bool,
216    pub bigtable_instance_name: String,
217    pub bigtable_app_profile_id: String,
218    pub timeout: Option<Duration>,
219    pub max_message_size: usize,
220}
221
222impl Default for RpcBigtableConfig {
223    fn default() -> Self {
224        let bigtable_instance_name = solana_storage_bigtable::DEFAULT_INSTANCE_NAME.to_string();
225        let bigtable_app_profile_id = solana_storage_bigtable::DEFAULT_APP_PROFILE_ID.to_string();
226        Self {
227            enable_bigtable_ledger_upload: false,
228            bigtable_instance_name,
229            bigtable_app_profile_id,
230            timeout: None,
231            max_message_size: solana_storage_bigtable::DEFAULT_MAX_MESSAGE_SIZE,
232        }
233    }
234}
235
236#[derive(Clone)]
237pub struct JsonRpcRequestProcessor {
238    bank_forks: Arc<RwLock<BankForks>>,
239    block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
240    blockstore: Arc<Blockstore>,
241    config: JsonRpcConfig,
242    snapshot_config: Option<SnapshotConfig>,
243    #[allow(dead_code)]
244    validator_exit: Arc<RwLock<Exit>>,
245    health: Arc<RpcHealth>,
246    cluster_info: Arc<ClusterInfo>,
247    genesis_hash: Hash,
248    transaction_sender: Sender<TransactionInfo>,
249    bigtable_ledger_storage: Option<solana_storage_bigtable::LedgerStorage>,
250    optimistically_confirmed_bank: Arc<RwLock<OptimisticallyConfirmedBank>>,
251    largest_accounts_cache: Arc<RwLock<LargestAccountsCache>>,
252    max_slots: Arc<MaxSlots>,
253    leader_schedule_cache: Arc<LeaderScheduleCache>,
254    max_complete_transaction_status_slot: Arc<AtomicU64>,
255    prioritization_fee_cache: Arc<PrioritizationFeeCache>,
256    runtime: Arc<Runtime>,
257}
258impl Metadata for JsonRpcRequestProcessor {}
259
260impl JsonRpcRequestProcessor {
261    pub fn clone_without_bigtable(&self) -> JsonRpcRequestProcessor {
262        Self {
263            bigtable_ledger_storage: None, // Disable BigTable
264            ..self.clone()
265        }
266    }
267}
268
269impl JsonRpcRequestProcessor {
270    fn get_bank_with_config(&self, config: RpcContextConfig) -> Result<Arc<Bank>> {
271        let RpcContextConfig {
272            commitment,
273            min_context_slot,
274        } = config;
275        let bank = self.bank(commitment);
276        if let Some(min_context_slot) = min_context_slot {
277            if bank.slot() < min_context_slot {
278                return Err(RpcCustomError::MinContextSlotNotReached {
279                    context_slot: bank.slot(),
280                }
281                .into());
282            }
283        }
284        Ok(bank)
285    }
286
287    fn check_if_transaction_history_enabled(&self) -> Result<()> {
288        if !self.config.enable_rpc_transaction_history {
289            return Err(RpcCustomError::TransactionHistoryNotAvailable.into());
290        }
291        Ok(())
292    }
293
294    async fn calculate_non_circulating_supply(
295        &self,
296        bank: &Arc<Bank>,
297    ) -> ScanResult<NonCirculatingSupply> {
298        let bank = Arc::clone(bank);
299        self.runtime
300            .spawn_blocking(move || calculate_non_circulating_supply(&bank))
301            .await
302            .expect("Failed to spawn blocking task")
303    }
304
305    pub async fn get_filtered_indexed_accounts(
306        &self,
307        bank: &Arc<Bank>,
308        index_key: &IndexKey,
309        program_id: &Pubkey,
310        filters: Vec<RpcFilterType>,
311        sort_results: bool,
312    ) -> ScanResult<Vec<KeyedAccountSharedData>> {
313        let scan_order = if sort_results {
314            ScanOrder::Sorted
315        } else {
316            ScanOrder::Unsorted
317        };
318        let bank = Arc::clone(bank);
319        let index_key = index_key.to_owned();
320        let program_id = program_id.to_owned();
321        self.runtime
322            .spawn_blocking(move || {
323                bank.get_filtered_indexed_accounts(
324                    &index_key,
325                    |account| {
326                        // The program-id account index checks for Account owner on inclusion.
327                        // However, due to the current AccountsDb implementation, an account may
328                        // remain in storage as a zero-lamport AccountSharedData::Default() after
329                        // being wiped and reinitialized in later updates. We include the redundant
330                        // filters here to avoid returning these accounts.
331                        account.owner().eq(&program_id)
332                            && filters
333                                .iter()
334                                .all(|filter_type| filter_allows(filter_type, account))
335                    },
336                    &ScanConfig::new(scan_order),
337                    bank.byte_limit_for_scans(),
338                )
339            })
340            .await
341            .expect("Failed to spawn blocking task")
342    }
343
344    #[allow(deprecated)]
345    fn bank(&self, commitment: Option<CommitmentConfig>) -> Arc<Bank> {
346        debug!("RPC commitment_config: {commitment:?}");
347
348        let commitment = commitment.unwrap_or_default();
349        if commitment.is_confirmed() {
350            let bank = self
351                .optimistically_confirmed_bank
352                .read()
353                .unwrap()
354                .bank
355                .clone();
356            debug!("RPC using optimistically confirmed slot: {:?}", bank.slot());
357            return bank;
358        }
359
360        let slot = self
361            .block_commitment_cache
362            .read()
363            .unwrap()
364            .slot_with_commitment(commitment.commitment);
365
366        match commitment.commitment {
367            CommitmentLevel::Processed => {
368                debug!("RPC using the heaviest slot: {slot:?}");
369            }
370            CommitmentLevel::Finalized => {
371                debug!("RPC using block: {slot:?}");
372            }
373            CommitmentLevel::Confirmed => unreachable!(), // SingleGossip variant is deprecated
374        };
375
376        let r_bank_forks = self.bank_forks.read().unwrap();
377        r_bank_forks.get(slot).unwrap_or_else(|| {
378            // We log a warning instead of returning an error, because all known error cases
379            // are due to known bugs that should be fixed instead.
380            //
381            // The slot may not be found as a result of a known bug in snapshot creation, where
382            // the bank at the given slot was not included in the snapshot.
383            // Also, it may occur after an old bank has been purged from BankForks and a new
384            // BlockCommitmentCache has not yet arrived. To make this case impossible,
385            // BlockCommitmentCache should hold an `Arc<Bank>` everywhere it currently holds
386            // a slot.
387            //
388            // For more information, see https://github.com/solana-labs/solana/issues/11078
389            warn!(
390                "Bank with {:?} not found at slot: {:?}",
391                commitment.commitment, slot
392            );
393            r_bank_forks.root_bank()
394        })
395    }
396
397    fn genesis_creation_time(&self) -> UnixTimestamp {
398        self.bank(None).genesis_creation_time()
399    }
400
401    #[allow(clippy::too_many_arguments)]
402    pub fn new(
403        config: JsonRpcConfig,
404        snapshot_config: Option<SnapshotConfig>,
405        bank_forks: Arc<RwLock<BankForks>>,
406        block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
407        blockstore: Arc<Blockstore>,
408        validator_exit: Arc<RwLock<Exit>>,
409        health: Arc<RpcHealth>,
410        cluster_info: Arc<ClusterInfo>,
411        genesis_hash: Hash,
412        bigtable_ledger_storage: Option<solana_storage_bigtable::LedgerStorage>,
413        optimistically_confirmed_bank: Arc<RwLock<OptimisticallyConfirmedBank>>,
414        largest_accounts_cache: Arc<RwLock<LargestAccountsCache>>,
415        max_slots: Arc<MaxSlots>,
416        leader_schedule_cache: Arc<LeaderScheduleCache>,
417        max_complete_transaction_status_slot: Arc<AtomicU64>,
418        prioritization_fee_cache: Arc<PrioritizationFeeCache>,
419        runtime: Arc<Runtime>,
420    ) -> (Self, Receiver<TransactionInfo>) {
421        let (transaction_sender, transaction_receiver) = unbounded();
422        (
423            Self {
424                config,
425                snapshot_config,
426                bank_forks,
427                block_commitment_cache,
428                blockstore,
429                validator_exit,
430                health,
431                cluster_info,
432                genesis_hash,
433                transaction_sender,
434                bigtable_ledger_storage,
435                optimistically_confirmed_bank,
436                largest_accounts_cache,
437                max_slots,
438                leader_schedule_cache,
439                max_complete_transaction_status_slot,
440                prioritization_fee_cache,
441                runtime,
442            },
443            transaction_receiver,
444        )
445    }
446
447    #[cfg(test)]
448    pub fn new_from_bank<Client: ClientWithCreator>(
449        bank: Bank,
450        socket_addr_space: SocketAddrSpace,
451    ) -> Self {
452        use crate::rpc_service::service_runtime;
453
454        let genesis_hash = bank.hash();
455        let bank_forks = BankForks::new_rw_arc(bank);
456        let bank = bank_forks.read().unwrap().root_bank();
457        let blockstore = Arc::new(Blockstore::open(&get_tmp_ledger_path!()).unwrap());
458        let exit = Arc::new(AtomicBool::new(false));
459        let cluster_info = Arc::new({
460            let keypair = Arc::new(Keypair::new());
461            let contact_info = ContactInfo::new_localhost(
462                &keypair.pubkey(),
463                solana_time_utils::timestamp(), // wallclock
464            );
465            ClusterInfo::new(contact_info, keypair, socket_addr_space)
466        });
467        // QUIC is the default TPU protocol and is used by ConnectionCache
468        // by default (see `DEFAULT_CONNECTION_CACHE_USE_QUIC`).
469        // Therefore, explicitly specifying QUIC here does not change the test behavior.
470        let my_tpu_address = cluster_info.my_contact_info().tpu(Protocol::QUIC).unwrap();
471        let (transaction_sender, transaction_receiver) = unbounded();
472
473        let config = JsonRpcConfig::default();
474        let JsonRpcConfig {
475            rpc_threads,
476            rpc_blocking_threads,
477            rpc_niceness_adj,
478            ..
479        } = config;
480        let runtime = service_runtime(rpc_threads, rpc_blocking_threads, rpc_niceness_adj);
481        let client = Client::create_client(Some(runtime.handle().clone()), my_tpu_address, None, 1);
482
483        SendTransactionService::new_with_client(
484            &bank_forks,
485            transaction_receiver,
486            client,
487            SendTransactionServiceConfig {
488                retry_rate_ms: 1_000,
489                leader_forward_count: 1,
490                ..SendTransactionServiceConfig::default()
491            },
492            exit.clone(),
493        );
494
495        let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
496        let slot = bank.slot();
497        let optimistically_confirmed_bank =
498            Arc::new(RwLock::new(OptimisticallyConfirmedBank { bank }));
499        Self {
500            config,
501            snapshot_config: None,
502            bank_forks,
503            block_commitment_cache: Arc::new(RwLock::new(BlockCommitmentCache::new(
504                HashMap::new(),
505                0,
506                CommitmentSlots::new_from_slot(slot),
507            ))),
508            blockstore: Arc::clone(&blockstore),
509            validator_exit: create_validator_exit(exit.clone()),
510            health: Arc::new(RpcHealth::new(
511                Arc::clone(&optimistically_confirmed_bank),
512                blockstore,
513                0,
514                exit,
515            )),
516            cluster_info,
517            genesis_hash,
518            transaction_sender,
519            bigtable_ledger_storage: None,
520            optimistically_confirmed_bank,
521            largest_accounts_cache: Arc::new(RwLock::new(LargestAccountsCache::new(30))),
522            max_slots: Arc::new(MaxSlots::default()),
523            leader_schedule_cache,
524            max_complete_transaction_status_slot: Arc::new(AtomicU64::default()),
525            prioritization_fee_cache: Arc::new(PrioritizationFeeCache::default()),
526            runtime,
527        }
528    }
529
530    pub async fn get_account_info(
531        &self,
532        pubkey: Pubkey,
533        config: Option<RpcAccountInfoConfig>,
534    ) -> Result<RpcResponse<Option<UiAccount>>> {
535        let RpcAccountInfoConfig {
536            encoding,
537            data_slice,
538            commitment,
539            min_context_slot,
540        } = config.unwrap_or_default();
541        let bank = self.get_bank_with_config(RpcContextConfig {
542            commitment,
543            min_context_slot,
544        })?;
545        let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
546
547        let response = self
548            .runtime
549            .spawn_blocking({
550                let bank = Arc::clone(&bank);
551                move || get_encoded_account(&bank, &pubkey, encoding, data_slice, None)
552            })
553            .await
554            .expect("rpc: get_encoded_account panicked")?;
555        Ok(new_response(&bank, response))
556    }
557
558    pub async fn get_multiple_accounts(
559        &self,
560        pubkeys: Vec<Pubkey>,
561        config: Option<RpcAccountInfoConfig>,
562    ) -> Result<RpcResponse<Vec<Option<UiAccount>>>> {
563        let RpcAccountInfoConfig {
564            encoding,
565            data_slice,
566            commitment,
567            min_context_slot,
568        } = config.unwrap_or_default();
569        let bank = self.get_bank_with_config(RpcContextConfig {
570            commitment,
571            min_context_slot,
572        })?;
573        let encoding = encoding.unwrap_or(UiAccountEncoding::Base64);
574
575        let mut accounts = Vec::with_capacity(pubkeys.len());
576        for pubkey in pubkeys {
577            let bank = Arc::clone(&bank);
578            accounts.push(
579                self.runtime
580                    .spawn_blocking(move || {
581                        get_encoded_account(&bank, &pubkey, encoding, data_slice, None)
582                    })
583                    .await
584                    .expect("rpc: get_encoded_account panicked")?,
585            );
586        }
587        Ok(new_response(&bank, accounts))
588    }
589
590    pub fn get_minimum_balance_for_rent_exemption(
591        &self,
592        data_len: usize,
593        commitment: Option<CommitmentConfig>,
594    ) -> u64 {
595        self.bank(commitment)
596            .get_minimum_balance_for_rent_exemption(data_len)
597    }
598
599    pub async fn get_program_accounts(
600        &self,
601        program_id: Pubkey,
602        config: Option<RpcAccountInfoConfig>,
603        mut filters: Vec<RpcFilterType>,
604        with_context: bool,
605        sort_results: bool,
606    ) -> Result<OptionalContext<Vec<RpcKeyedAccount>>> {
607        let RpcAccountInfoConfig {
608            encoding,
609            data_slice: data_slice_config,
610            commitment,
611            min_context_slot,
612        } = config.unwrap_or_default();
613        let bank = self.get_bank_with_config(RpcContextConfig {
614            commitment,
615            min_context_slot,
616        })?;
617        let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
618        optimize_filters(&mut filters);
619        let keyed_accounts = {
620            if let Some(owner) = get_spl_token_owner_filter(&program_id, &filters)? {
621                self.get_filtered_spl_token_accounts_by_owner(
622                    Arc::clone(&bank),
623                    program_id,
624                    owner,
625                    filters,
626                    sort_results,
627                )
628                .await?
629            } else if let Some(mint) = get_spl_token_mint_filter(&program_id, &filters)? {
630                self.get_filtered_spl_token_accounts_by_mint(
631                    Arc::clone(&bank),
632                    program_id,
633                    mint,
634                    filters,
635                    sort_results,
636                )
637                .await?
638            } else {
639                self.get_filtered_program_accounts(
640                    Arc::clone(&bank),
641                    program_id,
642                    filters,
643                    sort_results,
644                )
645                .await?
646            }
647        };
648        let accounts = if is_known_spl_token_id(&program_id)
649            && encoding == UiAccountEncoding::JsonParsed
650        {
651            get_parsed_token_accounts(Arc::clone(&bank), keyed_accounts.into_iter()).collect()
652        } else {
653            keyed_accounts
654                .into_iter()
655                .map(|(pubkey, account)| {
656                    Ok(RpcKeyedAccount {
657                        pubkey: pubkey.to_string(),
658                        account: encode_account(&account, &pubkey, encoding, data_slice_config)?,
659                    })
660                })
661                .collect::<Result<Vec<_>>>()?
662        };
663        Ok(match with_context {
664            true => OptionalContext::Context(new_response(&bank, accounts)),
665            false => OptionalContext::NoContext(accounts),
666        })
667    }
668
669    fn filter_map_rewards<'a, F>(
670        rewards: Option<Rewards>,
671        slot: Slot,
672        addresses: &'a [String],
673        reward_type_filter: &'a F,
674    ) -> impl Iterator<Item = (String, (Reward, Slot))> + use<'a, F>
675    where
676        F: Fn(RewardType) -> bool,
677    {
678        Self::filter_rewards(rewards, reward_type_filter)
679            .filter(|reward| addresses.contains(&reward.pubkey))
680            .map(move |reward| (reward.pubkey.clone(), (reward, slot)))
681    }
682
683    fn filter_rewards<F>(
684        rewards: Option<Rewards>,
685        reward_type_filter: &F,
686    ) -> impl Iterator<Item = Reward> + use<'_, F>
687    where
688        F: Fn(RewardType) -> bool,
689    {
690        rewards
691            .into_iter()
692            .flatten()
693            .filter(move |reward| reward.reward_type.is_some_and(reward_type_filter))
694    }
695
696    pub async fn get_inflation_reward(
697        &self,
698        addresses: Vec<Pubkey>,
699        config: Option<RpcEpochConfig>,
700    ) -> Result<Vec<Option<RpcInflationReward>>> {
701        let config = config.unwrap_or_default();
702        let epoch_schedule = self.get_epoch_schedule();
703        let first_available_block = self.get_first_available_block().await;
704        let context_config = RpcContextConfig {
705            commitment: config.commitment,
706            min_context_slot: config.min_context_slot,
707        };
708        let epoch = match config.epoch {
709            Some(epoch) => epoch,
710            None => epoch_schedule
711                .get_epoch(self.get_slot(context_config)?)
712                .saturating_sub(1),
713        };
714
715        // Rewards for this epoch are found in the first confirmed block of the next epoch
716        let first_slot_in_epoch = epoch_schedule.get_first_slot_in_epoch(epoch.saturating_add(1));
717        if first_slot_in_epoch < first_available_block {
718            if self.bigtable_ledger_storage.is_some() {
719                return Err(RpcCustomError::LongTermStorageSlotSkipped {
720                    slot: first_slot_in_epoch,
721                }
722                .into());
723            } else {
724                return Err(RpcCustomError::BlockCleanedUp {
725                    slot: first_slot_in_epoch,
726                    first_available_block,
727                }
728                .into());
729            }
730        }
731
732        let first_confirmed_block_in_epoch = *self
733            .get_blocks_with_limit(first_slot_in_epoch, 1, Some(context_config))
734            .await?
735            .first()
736            .ok_or(RpcCustomError::BlockNotAvailable {
737                slot: first_slot_in_epoch,
738            })?;
739
740        // Determine if partitioned epoch rewards were enabled for the desired
741        // epoch
742        let bank = self.get_bank_with_config(context_config)?;
743
744        // Get first block in the epoch
745        let Ok(Some(epoch_boundary_block)) = self
746            .get_block(
747                first_confirmed_block_in_epoch,
748                Some(RpcBlockConfig::rewards_with_commitment(config.commitment).into()),
749            )
750            .await
751        else {
752            return Err(RpcCustomError::BlockNotAvailable {
753                slot: first_confirmed_block_in_epoch,
754            }
755            .into());
756        };
757
758        // If there is a gap in blockstore or long-term historical storage that
759        // includes the epoch boundary, the `get_blocks_with_limit()` call above
760        // will return the slot of the block at the end of that gap, not a
761        // legitimate epoch-boundary block. Therefore, verify that the parent of
762        // `epoch_boundary_block` occurred before the `first_slot_in_epoch`. If
763        // it didn't, return an error; it will be impossible to locate
764        // rewards properly.
765        if epoch_boundary_block.parent_slot >= first_slot_in_epoch {
766            return Err(RpcCustomError::SlotNotEpochBoundary {
767                slot: first_confirmed_block_in_epoch,
768            }
769            .into());
770        }
771
772        let epoch_has_partitioned_rewards = epoch_boundary_block.num_reward_partitions.is_some();
773
774        // Collect rewards from first block in the epoch if partitioned epoch
775        // rewards not enabled, or address is a vote account
776        let mut reward_map: HashMap<String, (Reward, Slot)> = {
777            let addresses: Vec<String> =
778                addresses.iter().map(|pubkey| pubkey.to_string()).collect();
779            Self::filter_map_rewards(
780                epoch_boundary_block.rewards,
781                first_confirmed_block_in_epoch,
782                &addresses,
783                &|reward_type| -> bool {
784                    reward_type == RewardType::Voting
785                        || (!epoch_has_partitioned_rewards && reward_type == RewardType::Staking)
786                },
787            )
788            .collect()
789        };
790
791        // Append stake account rewards from partitions if partitions epoch
792        // rewards is enabled
793        if epoch_has_partitioned_rewards {
794            let num_partitions = epoch_boundary_block.num_reward_partitions.expect(
795                "epoch-boundary block should have num_reward_partitions for epochs with \
796                 partitioned rewards enabled",
797            );
798
799            let num_partitions = usize::try_from(num_partitions)
800                .expect("num_partitions should never exceed usize::MAX");
801            let hasher = EpochRewardsHasher::new(
802                num_partitions,
803                &Hash::from_str(&epoch_boundary_block.previous_blockhash)
804                    .expect("UiConfirmedBlock::previous_blockhash should be properly formed"),
805            );
806            let mut partition_index_addresses: HashMap<usize, Vec<String>> = HashMap::new();
807            for address in addresses.iter() {
808                let address_string = address.to_string();
809                // Skip this address if (Voting) rewards were already found in
810                // the first block of the epoch
811                if !reward_map.contains_key(&address_string) {
812                    let partition_index = hasher.clone().hash_address_to_partition(address);
813                    partition_index_addresses
814                        .entry(partition_index)
815                        .and_modify(|list| list.push(address_string.clone()))
816                        .or_insert(vec![address_string]);
817                }
818            }
819
820            let block_list = self
821                .get_blocks_with_limit(
822                    first_confirmed_block_in_epoch + 1,
823                    num_partitions,
824                    Some(context_config),
825                )
826                .await?;
827
828            for (partition_index, addresses) in partition_index_addresses.iter() {
829                let slot = *block_list.get(*partition_index).ok_or_else(|| {
830                    // If block_list.len() too short to contain
831                    // partition_index, the epoch rewards period must be
832                    // currently active.
833                    let rewards_complete_block_height = epoch_boundary_block
834                        .block_height
835                        .map(|block_height| {
836                            block_height
837                                .saturating_add(num_partitions as u64)
838                                .saturating_add(1)
839                        })
840                        .expect(
841                            "every block after partitioned_epoch_reward_enabled should have a \
842                             populated block_height",
843                        );
844                    RpcCustomError::EpochRewardsPeriodActive {
845                        slot: bank.slot(),
846                        current_block_height: bank.block_height(),
847                        rewards_complete_block_height,
848                    }
849                })?;
850
851                let Ok(Some(block)) = self
852                    .get_block(
853                        slot,
854                        Some(RpcBlockConfig::rewards_with_commitment(config.commitment).into()),
855                    )
856                    .await
857                else {
858                    return Err(RpcCustomError::BlockNotAvailable { slot }.into());
859                };
860
861                let index_reward_map = Self::filter_map_rewards(
862                    block.rewards,
863                    slot,
864                    addresses,
865                    &|reward_type| -> bool { reward_type == RewardType::Staking },
866                );
867                reward_map.extend(index_reward_map);
868            }
869        }
870
871        let rewards = addresses
872            .iter()
873            .map(|address| {
874                if let Some((reward, slot)) = reward_map.get(&address.to_string()) {
875                    return Some(RpcInflationReward {
876                        epoch,
877                        effective_slot: *slot,
878                        amount: reward.lamports.unsigned_abs(),
879                        post_balance: reward.post_balance,
880                        commission: reward.commission,
881                    });
882                }
883                None
884            })
885            .collect();
886
887        Ok(rewards)
888    }
889
890    pub fn get_inflation_governor(
891        &self,
892        commitment: Option<CommitmentConfig>,
893    ) -> RpcInflationGovernor {
894        self.bank(commitment).inflation().into()
895    }
896
897    pub fn get_inflation_rate(&self) -> RpcInflationRate {
898        let bank = self.bank(None);
899        let epoch = bank.epoch();
900        let inflation = bank.inflation();
901        let slot_in_year = bank.slot_in_year_for_inflation();
902
903        RpcInflationRate {
904            total: inflation.total(slot_in_year),
905            validator: inflation.validator(slot_in_year),
906            foundation: inflation.foundation(slot_in_year),
907            epoch,
908        }
909    }
910
911    pub fn get_epoch_schedule(&self) -> EpochSchedule {
912        // Since epoch schedule data comes from the genesis config, any commitment level should be
913        // fine
914        let bank = self.bank(Some(CommitmentConfig::finalized()));
915        bank.epoch_schedule().clone()
916    }
917
918    pub fn get_balance(
919        &self,
920        pubkey: &Pubkey,
921        config: RpcContextConfig,
922    ) -> Result<RpcResponse<u64>> {
923        let bank = self.get_bank_with_config(config)?;
924        Ok(new_response(&bank, bank.get_balance(pubkey)))
925    }
926
927    pub fn confirm_transaction(
928        &self,
929        signature: &Signature,
930        commitment: Option<CommitmentConfig>,
931    ) -> Result<RpcResponse<bool>> {
932        let bank = self.bank(commitment);
933        let status = bank.get_signature_status(signature);
934        match status {
935            Some(status) => Ok(new_response(&bank, status.is_ok())),
936            None => Ok(new_response(&bank, false)),
937        }
938    }
939
940    fn get_block_commitment(&self, block: Slot) -> RpcBlockCommitment<BlockCommitmentArray> {
941        let r_block_commitment = self.block_commitment_cache.read().unwrap();
942        RpcBlockCommitment {
943            commitment: r_block_commitment
944                .get_block_commitment(block)
945                .map(|block_commitment| block_commitment.commitment),
946            total_stake: r_block_commitment.total_stake(),
947        }
948    }
949
950    fn get_slot(&self, config: RpcContextConfig) -> Result<Slot> {
951        let bank = self.get_bank_with_config(config)?;
952        Ok(bank.slot())
953    }
954
955    fn get_block_height(&self, config: RpcContextConfig) -> Result<u64> {
956        let bank = self.get_bank_with_config(config)?;
957        Ok(bank.block_height())
958    }
959
960    fn get_max_retransmit_slot(&self) -> Slot {
961        self.max_slots.retransmit.load(Ordering::Relaxed)
962    }
963
964    fn get_max_shred_insert_slot(&self) -> Slot {
965        self.max_slots.shred_insert.load(Ordering::Relaxed)
966    }
967
968    fn get_slot_leader(&self, config: RpcContextConfig) -> Result<String> {
969        let bank = self.get_bank_with_config(config)?;
970        Ok(bank.collector_id().to_string())
971    }
972
973    fn get_slot_leaders(
974        &self,
975        commitment: Option<CommitmentConfig>,
976        start_slot: Slot,
977        limit: usize,
978    ) -> Result<Vec<Pubkey>> {
979        let bank = self.bank(commitment);
980
981        let (mut epoch, mut slot_index) =
982            bank.epoch_schedule().get_epoch_and_slot_index(start_slot);
983
984        let mut slot_leaders = Vec::with_capacity(limit);
985        while slot_leaders.len() < limit {
986            if let Some(leader_schedule) =
987                self.leader_schedule_cache.get_epoch_leader_schedule(epoch)
988            {
989                slot_leaders.extend(
990                    leader_schedule
991                        .get_slot_leaders()
992                        .iter()
993                        .skip(slot_index as usize)
994                        .take(limit.saturating_sub(slot_leaders.len())),
995                );
996            } else {
997                return Err(Error::invalid_params(format!(
998                    "Invalid slot range: leader schedule for epoch {epoch} is unavailable"
999                )));
1000            }
1001
1002            epoch += 1;
1003            slot_index = 0;
1004        }
1005
1006        Ok(slot_leaders)
1007    }
1008
1009    fn minimum_ledger_slot(&self) -> Result<Slot> {
1010        match self.blockstore.slot_meta_iterator(0) {
1011            Ok(mut metas) => match metas.next() {
1012                Some((slot, _meta)) => Ok(slot),
1013                None => Err(Error::invalid_request()),
1014            },
1015            Err(err) => {
1016                warn!("slot_meta_iterator failed: {err:?}");
1017                Err(Error::invalid_request())
1018            }
1019        }
1020    }
1021
1022    fn get_transaction_count(&self, config: RpcContextConfig) -> Result<u64> {
1023        let bank = self.get_bank_with_config(config)?;
1024        Ok(bank.transaction_count())
1025    }
1026
1027    fn get_cached_largest_accounts(
1028        &self,
1029        filter: &Option<RpcLargestAccountsFilter>,
1030    ) -> Option<(u64, Vec<RpcAccountBalance>)> {
1031        let largest_accounts_cache = self.largest_accounts_cache.read().unwrap();
1032        largest_accounts_cache.get_largest_accounts(filter)
1033    }
1034
1035    fn set_cached_largest_accounts(
1036        &self,
1037        filter: &Option<RpcLargestAccountsFilter>,
1038        slot: u64,
1039        accounts: &[RpcAccountBalance],
1040    ) {
1041        let mut largest_accounts_cache = self.largest_accounts_cache.write().unwrap();
1042        largest_accounts_cache.set_largest_accounts(filter, slot, accounts)
1043    }
1044
1045    async fn get_largest_accounts(
1046        &self,
1047        config: Option<RpcLargestAccountsConfig>,
1048    ) -> RpcCustomResult<RpcResponse<Vec<RpcAccountBalance>>> {
1049        let config = config.unwrap_or_default();
1050        let bank = self.bank(config.commitment);
1051        let sort_results = config.sort_results.unwrap_or(true);
1052
1053        if let Some((slot, accounts)) = self.get_cached_largest_accounts(&config.filter) {
1054            Ok(RpcResponse {
1055                context: RpcResponseContext::new(slot),
1056                value: accounts,
1057            })
1058        } else {
1059            let (addresses, address_filter) = if let Some(filter) = config.clone().filter {
1060                let non_circulating_supply = self
1061                    .calculate_non_circulating_supply(&bank)
1062                    .await
1063                    .map_err(|e| RpcCustomError::ScanError {
1064                        message: e.to_string(),
1065                    })?;
1066                let addresses = non_circulating_supply.accounts.into_iter().collect();
1067                let address_filter = match filter {
1068                    RpcLargestAccountsFilter::Circulating => AccountAddressFilter::Exclude,
1069                    RpcLargestAccountsFilter::NonCirculating => AccountAddressFilter::Include,
1070                };
1071                (addresses, address_filter)
1072            } else {
1073                (HashSet::new(), AccountAddressFilter::Exclude)
1074            };
1075            let accounts = self
1076                .runtime
1077                .spawn_blocking({
1078                    let bank = Arc::clone(&bank);
1079                    move || {
1080                        bank.get_largest_accounts(
1081                            NUM_LARGEST_ACCOUNTS,
1082                            &addresses,
1083                            address_filter,
1084                            sort_results,
1085                        )
1086                    }
1087                })
1088                .await
1089                .expect("Failed to spawn blocking task")
1090                .map_err(|e| RpcCustomError::ScanError {
1091                    message: e.to_string(),
1092                })?
1093                .into_iter()
1094                .map(|(address, lamports)| RpcAccountBalance {
1095                    address: address.to_string(),
1096                    lamports,
1097                })
1098                .collect::<Vec<RpcAccountBalance>>();
1099
1100            self.set_cached_largest_accounts(&config.filter, bank.slot(), &accounts);
1101            Ok(new_response(&bank, accounts))
1102        }
1103    }
1104
1105    async fn get_supply(
1106        &self,
1107        config: Option<RpcSupplyConfig>,
1108    ) -> RpcCustomResult<RpcResponse<RpcSupply>> {
1109        let config = config.unwrap_or_default();
1110        let bank = self.bank(config.commitment);
1111        let non_circulating_supply =
1112            self.calculate_non_circulating_supply(&bank)
1113                .await
1114                .map_err(|e| RpcCustomError::ScanError {
1115                    message: e.to_string(),
1116                })?;
1117        let total_supply = bank.capitalization();
1118        let non_circulating_accounts = if config.exclude_non_circulating_accounts_list {
1119            vec![]
1120        } else {
1121            non_circulating_supply
1122                .accounts
1123                .iter()
1124                .map(|pubkey| pubkey.to_string())
1125                .collect()
1126        };
1127
1128        Ok(new_response(
1129            &bank,
1130            RpcSupply {
1131                total: total_supply,
1132                circulating: total_supply - non_circulating_supply.lamports,
1133                non_circulating: non_circulating_supply.lamports,
1134                non_circulating_accounts,
1135            },
1136        ))
1137    }
1138
1139    fn get_vote_accounts(
1140        &self,
1141        config: Option<RpcGetVoteAccountsConfig>,
1142    ) -> Result<RpcVoteAccountStatus> {
1143        let config = config.unwrap_or_default();
1144
1145        let filter_by_vote_pubkey = if let Some(ref vote_pubkey) = config.vote_pubkey {
1146            Some(verify_pubkey(vote_pubkey)?)
1147        } else {
1148            None
1149        };
1150
1151        let bank = self.bank(config.commitment);
1152        let vote_accounts = bank.vote_accounts();
1153        let epoch_vote_accounts = bank
1154            .epoch_vote_accounts(bank.get_epoch_and_slot_index(bank.slot()).0)
1155            .ok_or_else(Error::invalid_request)?;
1156        let delinquent_validator_slot_distance = config
1157            .delinquent_slot_distance
1158            .unwrap_or(DELINQUENT_VALIDATOR_SLOT_DISTANCE);
1159        let (current_vote_accounts, delinquent_vote_accounts): (
1160            Vec<RpcVoteAccountInfo>,
1161            Vec<RpcVoteAccountInfo>,
1162        ) = vote_accounts
1163            .iter()
1164            .filter_map(|(vote_pubkey, (activated_stake, account))| {
1165                if let Some(filter_by_vote_pubkey) = filter_by_vote_pubkey {
1166                    if *vote_pubkey != filter_by_vote_pubkey {
1167                        return None;
1168                    }
1169                }
1170
1171                let vote_state_view = account.vote_state_view();
1172                let last_vote = vote_state_view.last_voted_slot().unwrap_or(0);
1173                let num_epoch_credits = vote_state_view.num_epoch_credits();
1174                let epoch_credits = vote_state_view
1175                    .epoch_credits_iter()
1176                    .skip(
1177                        num_epoch_credits
1178                            .saturating_sub(MAX_RPC_VOTE_ACCOUNT_INFO_EPOCH_CREDITS_HISTORY),
1179                    )
1180                    .map(Into::into)
1181                    .collect();
1182
1183                Some(RpcVoteAccountInfo {
1184                    vote_pubkey: vote_pubkey.to_string(),
1185                    node_pubkey: vote_state_view.node_pubkey().to_string(),
1186                    activated_stake: *activated_stake,
1187                    commission: vote_state_view.commission(),
1188                    root_slot: vote_state_view.root_slot().unwrap_or(0),
1189                    epoch_credits,
1190                    epoch_vote_account: epoch_vote_accounts.contains_key(vote_pubkey),
1191                    last_vote,
1192                })
1193            })
1194            .partition(|vote_account_info| {
1195                if bank.slot() >= delinquent_validator_slot_distance {
1196                    vote_account_info.last_vote > bank.slot() - delinquent_validator_slot_distance
1197                } else {
1198                    vote_account_info.last_vote > 0
1199                }
1200            });
1201
1202        let keep_unstaked_delinquents = config.keep_unstaked_delinquents.unwrap_or_default();
1203        let delinquent_vote_accounts = if !keep_unstaked_delinquents {
1204            delinquent_vote_accounts
1205                .into_iter()
1206                .filter(|vote_account_info| vote_account_info.activated_stake > 0)
1207                .collect::<Vec<_>>()
1208        } else {
1209            delinquent_vote_accounts
1210        };
1211
1212        Ok(RpcVoteAccountStatus {
1213            current: current_vote_accounts,
1214            delinquent: delinquent_vote_accounts,
1215        })
1216    }
1217
1218    fn check_blockstore_root<T>(
1219        &self,
1220        result: &std::result::Result<T, BlockstoreError>,
1221        slot: Slot,
1222    ) -> Result<()> {
1223        if let Err(err) = result {
1224            debug!(
1225                "check_blockstore_root, slot: {:?}, max root: {:?}, err: {:?}",
1226                slot,
1227                self.blockstore.max_root(),
1228                err
1229            );
1230            if slot >= self.blockstore.max_root() {
1231                return Err(RpcCustomError::BlockNotAvailable { slot }.into());
1232            }
1233            if self.blockstore.is_skipped(slot) {
1234                return Err(RpcCustomError::SlotSkipped { slot }.into());
1235            }
1236        }
1237        Ok(())
1238    }
1239
1240    fn check_slot_cleaned_up<T>(
1241        &self,
1242        result: &std::result::Result<T, BlockstoreError>,
1243        slot: Slot,
1244    ) -> Result<()> {
1245        let first_available_block = self
1246            .blockstore
1247            .get_first_available_block()
1248            .unwrap_or_default();
1249        let err: Error = RpcCustomError::BlockCleanedUp {
1250            slot,
1251            first_available_block,
1252        }
1253        .into();
1254        if let Err(BlockstoreError::SlotCleanedUp) = result {
1255            return Err(err);
1256        }
1257        if slot < first_available_block {
1258            return Err(err);
1259        }
1260        Ok(())
1261    }
1262
1263    fn check_bigtable_result<T>(
1264        &self,
1265        result: &std::result::Result<T, solana_storage_bigtable::Error>,
1266    ) -> Result<()> {
1267        if let Err(solana_storage_bigtable::Error::BlockNotFound(slot)) = result {
1268            return Err(RpcCustomError::LongTermStorageSlotSkipped { slot: *slot }.into());
1269        }
1270        Ok(())
1271    }
1272
1273    fn check_blockstore_writes_complete(&self, slot: Slot) -> Result<()> {
1274        if slot
1275            > self
1276                .max_complete_transaction_status_slot
1277                .load(Ordering::SeqCst)
1278        {
1279            Err(RpcCustomError::BlockStatusNotAvailableYet { slot }.into())
1280        } else {
1281            Ok(())
1282        }
1283    }
1284
1285    pub async fn get_block(
1286        &self,
1287        slot: Slot,
1288        config: Option<RpcEncodingConfigWrapper<RpcBlockConfig>>,
1289    ) -> Result<Option<UiConfirmedBlock>> {
1290        self.check_if_transaction_history_enabled()?;
1291
1292        let config = config
1293            .map(|config| config.convert_to_current())
1294            .unwrap_or_default();
1295        let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Json);
1296        let encoding_options = BlockEncodingOptions {
1297            transaction_details: config.transaction_details.unwrap_or_default(),
1298            show_rewards: config.rewards.unwrap_or(true),
1299            max_supported_transaction_version: config.max_supported_transaction_version,
1300        };
1301        let commitment = config.commitment.unwrap_or_default();
1302        check_is_at_least_confirmed(commitment)?;
1303
1304        // Block is old enough to be finalized
1305        if slot
1306            <= self
1307                .block_commitment_cache
1308                .read()
1309                .unwrap()
1310                .highest_super_majority_root()
1311        {
1312            self.check_blockstore_writes_complete(slot)?;
1313            let result = self
1314                .runtime
1315                .spawn_blocking({
1316                    let blockstore = Arc::clone(&self.blockstore);
1317                    move || blockstore.get_rooted_block(slot, true)
1318                })
1319                .await
1320                .expect("Failed to spawn blocking task");
1321            self.check_blockstore_root(&result, slot)?;
1322            let encode_block = |confirmed_block: ConfirmedBlock| async move {
1323                let mut encoded_block = self
1324                    .runtime
1325                    .spawn_blocking(move || {
1326                        confirmed_block
1327                            .encode_with_options(encoding, encoding_options)
1328                            .map_err(RpcCustomError::from)
1329                    })
1330                    .await
1331                    .expect("Failed to spawn blocking task")?;
1332                if slot == 0 {
1333                    encoded_block.block_time = Some(self.genesis_creation_time());
1334                    encoded_block.block_height = Some(0);
1335                }
1336                Ok::<UiConfirmedBlock, Error>(encoded_block)
1337            };
1338            if result.is_err() {
1339                if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
1340                    let bigtable_result = bigtable_ledger_storage.get_confirmed_block(slot).await;
1341                    self.check_bigtable_result(&bigtable_result)?;
1342                    let encoded_block_future: OptionFuture<_> =
1343                        bigtable_result.ok().map(encode_block).into();
1344                    return encoded_block_future.await.transpose();
1345                }
1346            }
1347            self.check_slot_cleaned_up(&result, slot)?;
1348            let encoded_block_future: OptionFuture<_> = result
1349                .ok()
1350                .map(ConfirmedBlock::from)
1351                .map(encode_block)
1352                .into();
1353            return encoded_block_future.await.transpose();
1354        } else if commitment.is_confirmed() {
1355            // Check if block is confirmed
1356            let confirmed_bank = self.bank(Some(CommitmentConfig::confirmed()));
1357            if confirmed_bank.status_cache_ancestors().contains(&slot) {
1358                self.check_blockstore_writes_complete(slot)?;
1359                let result = self
1360                    .runtime
1361                    .spawn_blocking({
1362                        let blockstore = Arc::clone(&self.blockstore);
1363                        move || blockstore.get_complete_block(slot, true)
1364                    })
1365                    .await
1366                    .expect("Failed to spawn blocking task");
1367                let encoded_block_future: OptionFuture<_> = result
1368                    .ok()
1369                    .map(ConfirmedBlock::from)
1370                    .map(|mut confirmed_block| async move {
1371                        if confirmed_block.block_time.is_none()
1372                            || confirmed_block.block_height.is_none()
1373                        {
1374                            let r_bank_forks = self.bank_forks.read().unwrap();
1375                            if let Some(bank) = r_bank_forks.get(slot) {
1376                                if confirmed_block.block_time.is_none() {
1377                                    confirmed_block.block_time = Some(bank.clock().unix_timestamp);
1378                                }
1379                                if confirmed_block.block_height.is_none() {
1380                                    confirmed_block.block_height = Some(bank.block_height());
1381                                }
1382                            }
1383                        }
1384                        let encoded_block = self
1385                            .runtime
1386                            .spawn_blocking(move || {
1387                                confirmed_block
1388                                    .encode_with_options(encoding, encoding_options)
1389                                    .map_err(RpcCustomError::from)
1390                            })
1391                            .await
1392                            .expect("Failed to spawn blocking task")?;
1393
1394                        Ok(encoded_block)
1395                    })
1396                    .into();
1397                return encoded_block_future.await.transpose();
1398            }
1399        }
1400
1401        Err(RpcCustomError::BlockNotAvailable { slot }.into())
1402    }
1403
1404    pub async fn get_blocks(
1405        &self,
1406        start_slot: Slot,
1407        end_slot: Option<Slot>,
1408        config: Option<RpcContextConfig>,
1409    ) -> Result<Vec<Slot>> {
1410        let config = config.unwrap_or_default();
1411        let commitment = config.commitment.unwrap_or_default();
1412        check_is_at_least_confirmed(commitment)?;
1413
1414        let highest_super_majority_root = self
1415            .block_commitment_cache
1416            .read()
1417            .unwrap()
1418            .highest_super_majority_root();
1419
1420        let min_context_slot = config.min_context_slot.unwrap_or_default();
1421        if commitment.is_finalized() && highest_super_majority_root < min_context_slot {
1422            return Err(RpcCustomError::MinContextSlotNotReached {
1423                context_slot: highest_super_majority_root,
1424            }
1425            .into());
1426        }
1427
1428        let end_slot = min(
1429            end_slot.unwrap_or_else(|| start_slot.saturating_add(MAX_GET_CONFIRMED_BLOCKS_RANGE)),
1430            if commitment.is_finalized() {
1431                highest_super_majority_root
1432            } else {
1433                self.get_bank_with_config(config)?.slot()
1434            },
1435        );
1436        if end_slot < start_slot {
1437            return Ok(vec![]);
1438        }
1439        if end_slot - start_slot > MAX_GET_CONFIRMED_BLOCKS_RANGE {
1440            return Err(Error::invalid_params(format!(
1441                "Slot range too large; max {MAX_GET_CONFIRMED_BLOCKS_RANGE}"
1442            )));
1443        }
1444
1445        let lowest_blockstore_slot = self
1446            .blockstore
1447            .get_first_available_block()
1448            .unwrap_or_default();
1449        if start_slot < lowest_blockstore_slot {
1450            // If the starting slot is lower than what's available in blockstore assume the entire
1451            // [start_slot..end_slot] can be fetched from BigTable. This range should not ever run
1452            // into unfinalized confirmed blocks due to MAX_GET_CONFIRMED_BLOCKS_RANGE
1453            if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
1454                return bigtable_ledger_storage
1455                    .get_confirmed_blocks(start_slot, (end_slot - start_slot) as usize + 1) // increment limit by 1 to ensure returned range is inclusive of both start_slot and end_slot
1456                    .await
1457                    .map(|mut bigtable_blocks| {
1458                        bigtable_blocks.retain(|&slot| slot <= end_slot);
1459                        bigtable_blocks
1460                    })
1461                    .map_err(|_| {
1462                        Error::invalid_params(
1463                            "BigTable query failed (maybe timeout due to too large range?)"
1464                                .to_string(),
1465                        )
1466                    });
1467            }
1468        }
1469
1470        // Finalized blocks
1471        let mut blocks: Vec<_> = self
1472            .blockstore
1473            .rooted_slot_iterator(max(start_slot, lowest_blockstore_slot))
1474            .map_err(|_| Error::internal_error())?
1475            .filter(|&slot| slot <= end_slot && slot <= highest_super_majority_root)
1476            .collect();
1477        let last_element = blocks
1478            .last()
1479            .cloned()
1480            .unwrap_or_else(|| start_slot.saturating_sub(1));
1481
1482        // Maybe add confirmed blocks
1483        if commitment.is_confirmed() {
1484            let confirmed_bank = self.get_bank_with_config(config)?;
1485            if last_element < end_slot {
1486                let mut confirmed_blocks = confirmed_bank
1487                    .status_cache_ancestors()
1488                    .into_iter()
1489                    .filter(|&slot| slot <= end_slot && slot > last_element)
1490                    .collect();
1491                blocks.append(&mut confirmed_blocks);
1492            }
1493        }
1494
1495        Ok(blocks)
1496    }
1497
1498    pub async fn get_blocks_with_limit(
1499        &self,
1500        start_slot: Slot,
1501        limit: usize,
1502        config: Option<RpcContextConfig>,
1503    ) -> Result<Vec<Slot>> {
1504        let config = config.unwrap_or_default();
1505        let commitment = config.commitment.unwrap_or_default();
1506        check_is_at_least_confirmed(commitment)?;
1507
1508        if limit > MAX_GET_CONFIRMED_BLOCKS_RANGE as usize {
1509            return Err(Error::invalid_params(format!(
1510                "Limit too large; max {MAX_GET_CONFIRMED_BLOCKS_RANGE}"
1511            )));
1512        }
1513
1514        let lowest_blockstore_slot = self
1515            .blockstore
1516            .get_first_available_block()
1517            .unwrap_or_default();
1518
1519        if start_slot < lowest_blockstore_slot {
1520            // If the starting slot is lower than what's available in blockstore assume the entire
1521            // range can be fetched from BigTable. This range should not ever run into unfinalized
1522            // confirmed blocks due to MAX_GET_CONFIRMED_BLOCKS_RANGE
1523            if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
1524                return Ok(bigtable_ledger_storage
1525                    .get_confirmed_blocks(start_slot, limit)
1526                    .await
1527                    .unwrap_or_default());
1528            }
1529        }
1530
1531        let highest_super_majority_root = self
1532            .block_commitment_cache
1533            .read()
1534            .unwrap()
1535            .highest_super_majority_root();
1536
1537        if commitment.is_finalized() {
1538            let min_context_slot = config.min_context_slot.unwrap_or_default();
1539            if highest_super_majority_root < min_context_slot {
1540                return Err(RpcCustomError::MinContextSlotNotReached {
1541                    context_slot: highest_super_majority_root,
1542                }
1543                .into());
1544            }
1545        }
1546
1547        // Finalized blocks
1548        let mut blocks: Vec<_> = self
1549            .blockstore
1550            .rooted_slot_iterator(max(start_slot, lowest_blockstore_slot))
1551            .map_err(|_| Error::internal_error())?
1552            .take(limit)
1553            .filter(|&slot| slot <= highest_super_majority_root)
1554            .collect();
1555
1556        // Maybe add confirmed blocks
1557        if commitment.is_confirmed() {
1558            let confirmed_bank = self.get_bank_with_config(config)?;
1559            if blocks.len() < limit {
1560                let last_element = blocks
1561                    .last()
1562                    .cloned()
1563                    .unwrap_or_else(|| start_slot.saturating_sub(1));
1564                let mut confirmed_blocks = confirmed_bank
1565                    .status_cache_ancestors()
1566                    .into_iter()
1567                    .filter(|&slot| slot > last_element)
1568                    .collect();
1569                blocks.append(&mut confirmed_blocks);
1570                blocks.truncate(limit);
1571            }
1572        }
1573
1574        Ok(blocks)
1575    }
1576
1577    pub async fn get_block_time(&self, slot: Slot) -> Result<Option<UnixTimestamp>> {
1578        if slot == 0 {
1579            return Ok(Some(self.genesis_creation_time()));
1580        }
1581        if slot
1582            <= self
1583                .block_commitment_cache
1584                .read()
1585                .unwrap()
1586                .highest_super_majority_root()
1587        {
1588            let result = self.blockstore.get_rooted_block_time(slot);
1589            self.check_blockstore_root(&result, slot)?;
1590            if result.is_err() {
1591                if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
1592                    let bigtable_result = bigtable_ledger_storage.get_confirmed_block(slot).await;
1593                    self.check_bigtable_result(&bigtable_result)?;
1594                    return Ok(bigtable_result
1595                        .ok()
1596                        .and_then(|confirmed_block| confirmed_block.block_time));
1597                }
1598            }
1599            self.check_slot_cleaned_up(&result, slot)?;
1600            Ok(result.ok())
1601        } else {
1602            let r_bank_forks = self.bank_forks.read().unwrap();
1603            if let Some(bank) = r_bank_forks.get(slot) {
1604                Ok(Some(bank.clock().unix_timestamp))
1605            } else {
1606                Err(RpcCustomError::BlockNotAvailable { slot }.into())
1607            }
1608        }
1609    }
1610
1611    pub fn get_signature_confirmation_status(
1612        &self,
1613        signature: Signature,
1614        commitment: Option<CommitmentConfig>,
1615    ) -> Result<Option<RpcSignatureConfirmation>> {
1616        let bank = self.bank(commitment);
1617        Ok(self
1618            .get_transaction_status(signature, &bank)
1619            .map(|transaction_status| {
1620                let confirmations = transaction_status
1621                    .confirmations
1622                    .unwrap_or(MAX_LOCKOUT_HISTORY + 1);
1623                RpcSignatureConfirmation {
1624                    confirmations,
1625                    status: transaction_status.status,
1626                }
1627            }))
1628    }
1629
1630    pub fn get_signature_status(
1631        &self,
1632        signature: Signature,
1633        commitment: Option<CommitmentConfig>,
1634    ) -> Result<Option<transaction::Result<()>>> {
1635        let bank = self.bank(commitment);
1636        Ok(bank
1637            .get_signature_status_slot(&signature)
1638            .map(|(_, status)| status))
1639    }
1640
1641    pub async fn get_signature_statuses(
1642        &self,
1643        signatures: Vec<Signature>,
1644        config: Option<RpcSignatureStatusConfig>,
1645    ) -> Result<RpcResponse<Vec<Option<TransactionStatus>>>> {
1646        let search_transaction_history = config
1647            .map(|x| x.search_transaction_history)
1648            .unwrap_or(false);
1649        if search_transaction_history {
1650            self.check_if_transaction_history_enabled()?;
1651        }
1652
1653        let bank = self.bank(Some(CommitmentConfig::processed()));
1654        let mut statuses: Vec<Option<TransactionStatus>> = vec![];
1655
1656        for signature in signatures {
1657            let status = if let Some(status) = self.get_transaction_status(signature, &bank) {
1658                Some(status)
1659            } else if search_transaction_history {
1660                if let Some(status) = self
1661                    .blockstore
1662                    .get_rooted_transaction_status(signature)
1663                    .map_err(|_| Error::internal_error())?
1664                    .filter(|(slot, _status_meta)| {
1665                        slot <= &self
1666                            .block_commitment_cache
1667                            .read()
1668                            .unwrap()
1669                            .highest_super_majority_root()
1670                    })
1671                    .map(|(slot, status_meta)| {
1672                        let err = status_meta.status.clone().err();
1673                        TransactionStatus {
1674                            slot,
1675                            status: status_meta.status,
1676                            confirmations: None,
1677                            err,
1678                            confirmation_status: Some(TransactionConfirmationStatus::Finalized),
1679                        }
1680                    })
1681                {
1682                    Some(status)
1683                } else if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
1684                    bigtable_ledger_storage
1685                        .get_signature_status(&signature)
1686                        .await
1687                        .map(Some)
1688                        .unwrap_or(None)
1689                } else {
1690                    None
1691                }
1692            } else {
1693                None
1694            };
1695            statuses.push(status);
1696        }
1697        Ok(new_response(&bank, statuses))
1698    }
1699
1700    fn get_transaction_status(
1701        &self,
1702        signature: Signature,
1703        bank: &Bank,
1704    ) -> Option<TransactionStatus> {
1705        let (slot, status) = bank.get_signature_status_slot(&signature)?;
1706
1707        let optimistically_confirmed_bank = self.bank(Some(CommitmentConfig::confirmed()));
1708        let optimistically_confirmed =
1709            optimistically_confirmed_bank.get_signature_status_slot(&signature);
1710
1711        let r_block_commitment_cache = self.block_commitment_cache.read().unwrap();
1712        let confirmations = if r_block_commitment_cache.root() >= slot
1713            && is_finalized(&r_block_commitment_cache, bank, &self.blockstore, slot)
1714        {
1715            None
1716        } else {
1717            r_block_commitment_cache
1718                .get_confirmation_count(slot)
1719                .or(Some(0))
1720        };
1721        let err = status.clone().err();
1722        Some(TransactionStatus {
1723            slot,
1724            status,
1725            confirmations,
1726            err,
1727            confirmation_status: if confirmations.is_none() {
1728                Some(TransactionConfirmationStatus::Finalized)
1729            } else if optimistically_confirmed.is_some() {
1730                Some(TransactionConfirmationStatus::Confirmed)
1731            } else {
1732                Some(TransactionConfirmationStatus::Processed)
1733            },
1734        })
1735    }
1736
1737    pub async fn get_transaction(
1738        &self,
1739        signature: Signature,
1740        config: Option<RpcEncodingConfigWrapper<RpcTransactionConfig>>,
1741    ) -> Result<Option<EncodedConfirmedTransactionWithStatusMeta>> {
1742        self.check_if_transaction_history_enabled()?;
1743
1744        let config = config
1745            .map(|config| config.convert_to_current())
1746            .unwrap_or_default();
1747        let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Json);
1748        let max_supported_transaction_version = config.max_supported_transaction_version;
1749        let commitment = config.commitment.unwrap_or_default();
1750        check_is_at_least_confirmed(commitment)?;
1751
1752        let confirmed_bank = self.bank(Some(CommitmentConfig::confirmed()));
1753        let confirmed_transaction = self
1754            .runtime
1755            .spawn_blocking({
1756                let blockstore = Arc::clone(&self.blockstore);
1757                let confirmed_bank = Arc::clone(&confirmed_bank);
1758                move || {
1759                    if commitment.is_confirmed() {
1760                        let highest_confirmed_slot = confirmed_bank.slot();
1761                        blockstore.get_complete_transaction(signature, highest_confirmed_slot)
1762                    } else {
1763                        blockstore.get_rooted_transaction(signature)
1764                    }
1765                }
1766            })
1767            .await
1768            .expect("Failed to spawn blocking task");
1769
1770        let encode_transaction =
1771                |confirmed_tx_with_meta: ConfirmedTransactionWithStatusMeta| -> Result<EncodedConfirmedTransactionWithStatusMeta> {
1772                    Ok(confirmed_tx_with_meta.encode(encoding, max_supported_transaction_version).map_err(RpcCustomError::from)?)
1773                };
1774
1775        match confirmed_transaction.unwrap_or(None) {
1776            Some(mut confirmed_transaction) => {
1777                if commitment.is_confirmed()
1778                    && confirmed_bank // should be redundant
1779                        .status_cache_ancestors()
1780                        .contains(&confirmed_transaction.slot)
1781                {
1782                    if confirmed_transaction.block_time.is_none() {
1783                        let r_bank_forks = self.bank_forks.read().unwrap();
1784                        confirmed_transaction.block_time = r_bank_forks
1785                            .get(confirmed_transaction.slot)
1786                            .map(|bank| bank.clock().unix_timestamp);
1787                    }
1788                    return Ok(Some(encode_transaction(confirmed_transaction)?));
1789                }
1790
1791                if confirmed_transaction.slot
1792                    <= self
1793                        .block_commitment_cache
1794                        .read()
1795                        .unwrap()
1796                        .highest_super_majority_root()
1797                {
1798                    return Ok(Some(encode_transaction(confirmed_transaction)?));
1799                }
1800            }
1801            None => {
1802                if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
1803                    return bigtable_ledger_storage
1804                        .get_confirmed_transaction(&signature)
1805                        .await
1806                        .unwrap_or(None)
1807                        .map(encode_transaction)
1808                        .transpose();
1809                }
1810            }
1811        }
1812
1813        Ok(None)
1814    }
1815
1816    pub async fn get_signatures_for_address(
1817        &self,
1818        address: Pubkey,
1819        before: Option<Signature>,
1820        until: Option<Signature>,
1821        mut limit: usize,
1822        config: RpcContextConfig,
1823    ) -> Result<Vec<RpcConfirmedTransactionStatusWithSignature>> {
1824        self.check_if_transaction_history_enabled()?;
1825
1826        let commitment = config.commitment.unwrap_or_default();
1827        check_is_at_least_confirmed(commitment)?;
1828
1829        let highest_super_majority_root = self
1830            .block_commitment_cache
1831            .read()
1832            .unwrap()
1833            .highest_super_majority_root();
1834        let highest_slot = if commitment.is_confirmed() {
1835            let confirmed_bank = self.get_bank_with_config(config)?;
1836            confirmed_bank.slot()
1837        } else {
1838            let min_context_slot = config.min_context_slot.unwrap_or_default();
1839            if highest_super_majority_root < min_context_slot {
1840                return Err(RpcCustomError::MinContextSlotNotReached {
1841                    context_slot: highest_super_majority_root,
1842                }
1843                .into());
1844            }
1845            highest_super_majority_root
1846        };
1847
1848        let SignatureInfosForAddress {
1849            infos: mut results,
1850            found_before,
1851        } = self
1852            .blockstore
1853            .get_confirmed_signatures_for_address2(address, highest_slot, before, until, limit)
1854            .map_err(|err| Error::invalid_params(format!("{err}")))?;
1855
1856        let map_results = |results: Vec<ConfirmedTransactionStatusWithSignature>| {
1857            results
1858                .into_iter()
1859                .map(|x| {
1860                    let mut item: RpcConfirmedTransactionStatusWithSignature = x.into();
1861                    if item.slot <= highest_super_majority_root {
1862                        item.confirmation_status = Some(TransactionConfirmationStatus::Finalized);
1863                    } else {
1864                        item.confirmation_status = Some(TransactionConfirmationStatus::Confirmed);
1865                        if item.block_time.is_none() {
1866                            let r_bank_forks = self.bank_forks.read().unwrap();
1867                            item.block_time = r_bank_forks
1868                                .get(item.slot)
1869                                .map(|bank| bank.clock().unix_timestamp);
1870                        }
1871                    }
1872                    item
1873                })
1874                .collect()
1875        };
1876
1877        if results.len() < limit {
1878            if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
1879                let mut bigtable_before = before;
1880                if !results.is_empty() {
1881                    limit -= results.len();
1882                    bigtable_before = results.last().map(|x| x.signature);
1883                }
1884
1885                // If the oldest address-signature found in Blockstore has not yet been
1886                // uploaded to long-term storage, modify the storage query to return all latest
1887                // signatures to prevent erroring on RowNotFound. This can race with upload.
1888                if found_before && bigtable_before.is_some() {
1889                    match bigtable_ledger_storage
1890                        .get_signature_status(&bigtable_before.unwrap())
1891                        .await
1892                    {
1893                        Err(StorageError::SignatureNotFound) => {
1894                            bigtable_before = None;
1895                        }
1896                        Err(err) => {
1897                            warn!("Failed to query Bigtable: {err:?}");
1898                            return Err(RpcCustomError::LongTermStorageUnreachable.into());
1899                        }
1900                        Ok(_) => {}
1901                    }
1902                }
1903
1904                let bigtable_results = bigtable_ledger_storage
1905                    .get_confirmed_signatures_for_address(
1906                        &address,
1907                        bigtable_before.as_ref(),
1908                        until.as_ref(),
1909                        limit,
1910                    )
1911                    .await;
1912                match bigtable_results {
1913                    Ok(bigtable_results) => {
1914                        let results_set: HashSet<_> =
1915                            results.iter().map(|result| result.signature).collect();
1916                        for (bigtable_result, _) in bigtable_results {
1917                            // In the upload race condition, latest address-signatures in
1918                            // long-term storage may include original `before` signature...
1919                            if before != Some(bigtable_result.signature)
1920                                    // ...or earlier Blockstore signatures
1921                                    && !results_set.contains(&bigtable_result.signature)
1922                            {
1923                                results.push(bigtable_result);
1924                            }
1925                        }
1926                    }
1927                    Err(StorageError::SignatureNotFound) => {}
1928                    Err(err) => {
1929                        warn!("Failed to query Bigtable: {err:?}");
1930                        return Err(RpcCustomError::LongTermStorageUnreachable.into());
1931                    }
1932                }
1933            }
1934        }
1935
1936        Ok(map_results(results))
1937    }
1938
1939    pub async fn get_first_available_block(&self) -> Slot {
1940        let slot = self
1941            .blockstore
1942            .get_first_available_block()
1943            .unwrap_or_default();
1944
1945        if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
1946            let bigtable_slot = bigtable_ledger_storage
1947                .get_first_available_block()
1948                .await
1949                .unwrap_or(None)
1950                .unwrap_or(slot);
1951
1952            if bigtable_slot < slot {
1953                return bigtable_slot;
1954            }
1955        }
1956        slot
1957    }
1958
1959    pub fn get_token_account_balance(
1960        &self,
1961        pubkey: &Pubkey,
1962        commitment: Option<CommitmentConfig>,
1963    ) -> Result<RpcResponse<UiTokenAmount>> {
1964        let bank = self.bank(commitment);
1965        let account = bank.get_account(pubkey).ok_or_else(|| {
1966            Error::invalid_params("Invalid param: could not find account".to_string())
1967        })?;
1968
1969        if !is_known_spl_token_id(account.owner()) {
1970            return Err(Error::invalid_params(
1971                "Invalid param: not a Token account".to_string(),
1972            ));
1973        }
1974        let token_account = StateWithExtensions::<TokenAccount>::unpack(account.data())
1975            .map_err(|_| Error::invalid_params("Invalid param: not a Token account".to_string()))?;
1976        let mint = &Pubkey::from_str(&token_account.base.mint.to_string())
1977            .expect("Token account mint should be convertible to Pubkey");
1978        let (_, data) = get_mint_owner_and_additional_data(&bank, mint)?;
1979        let balance = token_amount_to_ui_amount_v3(token_account.base.amount, &data);
1980        Ok(new_response(&bank, balance))
1981    }
1982
1983    pub fn get_token_supply(
1984        &self,
1985        mint: &Pubkey,
1986        commitment: Option<CommitmentConfig>,
1987    ) -> Result<RpcResponse<UiTokenAmount>> {
1988        let bank = self.bank(commitment);
1989        let mint_account = bank.get_account(mint).ok_or_else(|| {
1990            Error::invalid_params("Invalid param: could not find account".to_string())
1991        })?;
1992        if !is_known_spl_token_id(mint_account.owner()) {
1993            return Err(Error::invalid_params(
1994                "Invalid param: not a Token mint".to_string(),
1995            ));
1996        }
1997        let mint = StateWithExtensions::<Mint>::unpack(mint_account.data()).map_err(|_| {
1998            Error::invalid_params("Invalid param: mint could not be unpacked".to_string())
1999        })?;
2000
2001        let interest_bearing_config = mint
2002            .get_extension::<InterestBearingConfig>()
2003            .map(|x| (*x, bank.clock().unix_timestamp))
2004            .ok();
2005
2006        let scaled_ui_amount_config = mint
2007            .get_extension::<ScaledUiAmountConfig>()
2008            .map(|x| (*x, bank.clock().unix_timestamp))
2009            .ok();
2010
2011        let supply = token_amount_to_ui_amount_v3(
2012            mint.base.supply,
2013            &SplTokenAdditionalDataV2 {
2014                decimals: mint.base.decimals,
2015                interest_bearing_config,
2016                scaled_ui_amount_config,
2017            },
2018        );
2019        Ok(new_response(&bank, supply))
2020    }
2021
2022    pub async fn get_token_largest_accounts(
2023        &self,
2024        mint: Pubkey,
2025        commitment: Option<CommitmentConfig>,
2026    ) -> Result<RpcResponse<Vec<RpcTokenAccountBalance>>> {
2027        let bank = self.bank(commitment);
2028        let (mint_owner, data) = get_mint_owner_and_additional_data(&bank, &mint)?;
2029        if !is_known_spl_token_id(&mint_owner) {
2030            return Err(Error::invalid_params(
2031                "Invalid param: not a Token mint".to_string(),
2032            ));
2033        }
2034
2035        let mut token_balances =
2036            BinaryHeap::<Reverse<(u64, Pubkey)>>::with_capacity(NUM_LARGEST_ACCOUNTS);
2037        for (address, account) in self
2038            .get_filtered_spl_token_accounts_by_mint(
2039                Arc::clone(&bank),
2040                mint_owner,
2041                mint,
2042                vec![],
2043                true,
2044            )
2045            .await?
2046        {
2047            let amount = StateWithExtensions::<TokenAccount>::unpack(account.data())
2048                .map(|account| account.base.amount)
2049                .unwrap_or(0);
2050
2051            let new_entry = (amount, address);
2052            if token_balances.len() >= NUM_LARGEST_ACCOUNTS {
2053                let Reverse(entry) = token_balances
2054                    .peek()
2055                    .expect("BinaryHeap::peek should succeed when len > 0");
2056                if *entry >= new_entry {
2057                    continue;
2058                }
2059                token_balances.pop();
2060            }
2061            token_balances.push(Reverse(new_entry));
2062        }
2063
2064        let token_balances = token_balances
2065            .into_sorted_vec()
2066            .into_iter()
2067            .map(|Reverse((amount, address))| {
2068                Ok(RpcTokenAccountBalance {
2069                    address: address.to_string(),
2070                    amount: token_amount_to_ui_amount_v3(amount, &data),
2071                })
2072            })
2073            .collect::<Result<Vec<_>>>()?;
2074
2075        Ok(new_response(&bank, token_balances))
2076    }
2077
2078    pub async fn get_token_accounts_by_owner(
2079        &self,
2080        owner: Pubkey,
2081        token_account_filter: TokenAccountsFilter,
2082        config: Option<RpcAccountInfoConfig>,
2083        sort_results: bool,
2084    ) -> Result<RpcResponse<Vec<RpcKeyedAccount>>> {
2085        let RpcAccountInfoConfig {
2086            encoding,
2087            data_slice: data_slice_config,
2088            commitment,
2089            min_context_slot,
2090        } = config.unwrap_or_default();
2091        let bank = self.get_bank_with_config(RpcContextConfig {
2092            commitment,
2093            min_context_slot,
2094        })?;
2095        let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
2096        let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
2097
2098        let mut filters = vec![];
2099        if let Some(mint) = mint {
2100            // Optional filter on Mint address
2101            filters.push(RpcFilterType::Memcmp(Memcmp::new_raw_bytes(
2102                0,
2103                mint.to_bytes().into(),
2104            )));
2105        }
2106
2107        let keyed_accounts = self
2108            .get_filtered_spl_token_accounts_by_owner(
2109                Arc::clone(&bank),
2110                token_program_id,
2111                owner,
2112                filters,
2113                sort_results,
2114            )
2115            .await?;
2116        let accounts = if encoding == UiAccountEncoding::JsonParsed {
2117            get_parsed_token_accounts(bank.clone(), keyed_accounts.into_iter()).collect()
2118        } else {
2119            keyed_accounts
2120                .into_iter()
2121                .map(|(pubkey, account)| {
2122                    Ok(RpcKeyedAccount {
2123                        pubkey: pubkey.to_string(),
2124                        account: encode_account(&account, &pubkey, encoding, data_slice_config)?,
2125                    })
2126                })
2127                .collect::<Result<Vec<_>>>()?
2128        };
2129        Ok(new_response(&bank, accounts))
2130    }
2131
2132    pub async fn get_token_accounts_by_delegate(
2133        &self,
2134        delegate: Pubkey,
2135        token_account_filter: TokenAccountsFilter,
2136        config: Option<RpcAccountInfoConfig>,
2137        sort_results: bool,
2138    ) -> Result<RpcResponse<Vec<RpcKeyedAccount>>> {
2139        let RpcAccountInfoConfig {
2140            encoding,
2141            data_slice: data_slice_config,
2142            commitment,
2143            min_context_slot,
2144        } = config.unwrap_or_default();
2145        let bank = self.get_bank_with_config(RpcContextConfig {
2146            commitment,
2147            min_context_slot,
2148        })?;
2149        let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
2150        let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
2151
2152        let mut filters = vec![
2153            // Filter on Delegate is_some()
2154            RpcFilterType::Memcmp(Memcmp::new_raw_bytes(
2155                72,
2156                bincode::serialize(&1u32).unwrap(),
2157            )),
2158            // Filter on Delegate address
2159            RpcFilterType::Memcmp(Memcmp::new_raw_bytes(76, delegate.to_bytes().into())),
2160        ];
2161        // Optional filter on Mint address, uses mint account index for scan
2162        let keyed_accounts = if let Some(mint) = mint {
2163            self.get_filtered_spl_token_accounts_by_mint(
2164                Arc::clone(&bank),
2165                token_program_id,
2166                mint,
2167                filters,
2168                sort_results,
2169            )
2170            .await?
2171        } else {
2172            // Filter on Token Account state
2173            filters.push(RpcFilterType::TokenAccountState);
2174            self.get_filtered_program_accounts(
2175                Arc::clone(&bank),
2176                token_program_id,
2177                filters,
2178                sort_results,
2179            )
2180            .await?
2181        };
2182        let accounts = if encoding == UiAccountEncoding::JsonParsed {
2183            get_parsed_token_accounts(bank.clone(), keyed_accounts.into_iter()).collect()
2184        } else {
2185            keyed_accounts
2186                .into_iter()
2187                .map(|(pubkey, account)| {
2188                    Ok(RpcKeyedAccount {
2189                        pubkey: pubkey.to_string(),
2190                        account: encode_account(&account, &pubkey, encoding, data_slice_config)?,
2191                    })
2192                })
2193                .collect::<Result<Vec<_>>>()?
2194        };
2195        Ok(new_response(&bank, accounts))
2196    }
2197
2198    /// Use a set of filters to get an iterator of keyed program accounts from a bank
2199    async fn get_filtered_program_accounts(
2200        &self,
2201        bank: Arc<Bank>,
2202        program_id: Pubkey,
2203        mut filters: Vec<RpcFilterType>,
2204        sort_results: bool,
2205    ) -> RpcCustomResult<Vec<(Pubkey, AccountSharedData)>> {
2206        optimize_filters(&mut filters);
2207        if self
2208            .config
2209            .account_indexes
2210            .contains(&AccountIndex::ProgramId)
2211        {
2212            if !self.config.account_indexes.include_key(&program_id) {
2213                return Err(RpcCustomError::KeyExcludedFromSecondaryIndex {
2214                    index_key: program_id.to_string(),
2215                });
2216            }
2217            self.get_filtered_indexed_accounts(
2218                &bank,
2219                &IndexKey::ProgramId(program_id),
2220                &program_id,
2221                filters,
2222                sort_results,
2223            )
2224            .await
2225            .map_err(|e| RpcCustomError::ScanError {
2226                message: e.to_string(),
2227            })
2228        } else {
2229            // this path does not need to provide a mb limit because we only want to support secondary indexes
2230            let scan_order = if sort_results {
2231                ScanOrder::Sorted
2232            } else {
2233                ScanOrder::Unsorted
2234            };
2235            self.runtime
2236                .spawn_blocking(move || {
2237                    bank.get_filtered_program_accounts(
2238                        &program_id,
2239                        |account: &AccountSharedData| {
2240                            filters
2241                                .iter()
2242                                .all(|filter_type| filter_allows(filter_type, account))
2243                        },
2244                        &ScanConfig::new(scan_order),
2245                    )
2246                    .map_err(|e| RpcCustomError::ScanError {
2247                        message: e.to_string(),
2248                    })
2249                })
2250                .await
2251                .expect("Failed to spawn blocking task")
2252        }
2253    }
2254
2255    /// Get an iterator of spl-token accounts by owner address
2256    async fn get_filtered_spl_token_accounts_by_owner(
2257        &self,
2258        bank: Arc<Bank>,
2259        program_id: Pubkey,
2260        owner_key: Pubkey,
2261        mut filters: Vec<RpcFilterType>,
2262        sort_results: bool,
2263    ) -> RpcCustomResult<Vec<(Pubkey, AccountSharedData)>> {
2264        // The by-owner accounts index checks for Token Account state and Owner address on
2265        // inclusion. However, due to the current AccountsDb implementation, an account may remain
2266        // in storage as a zero-lamport AccountSharedData::Default() after being wiped and reinitialized in
2267        // later updates. We include the redundant filters here to avoid returning these accounts.
2268        //
2269        // Filter on Token Account state
2270        filters.push(RpcFilterType::TokenAccountState);
2271        // Filter on Owner address
2272        filters.push(RpcFilterType::Memcmp(Memcmp::new_raw_bytes(
2273            SPL_TOKEN_ACCOUNT_OWNER_OFFSET,
2274            owner_key.to_bytes().into(),
2275        )));
2276
2277        if self
2278            .config
2279            .account_indexes
2280            .contains(&AccountIndex::SplTokenOwner)
2281        {
2282            if !self.config.account_indexes.include_key(&owner_key) {
2283                return Err(RpcCustomError::KeyExcludedFromSecondaryIndex {
2284                    index_key: owner_key.to_string(),
2285                });
2286            }
2287            self.get_filtered_indexed_accounts(
2288                &bank,
2289                &IndexKey::SplTokenOwner(owner_key),
2290                &program_id,
2291                filters,
2292                sort_results,
2293            )
2294            .await
2295            .map_err(|e| RpcCustomError::ScanError {
2296                message: e.to_string(),
2297            })
2298        } else {
2299            self.get_filtered_program_accounts(bank, program_id, filters, sort_results)
2300                .await
2301        }
2302    }
2303
2304    /// Get an iterator of spl-token accounts by mint address
2305    async fn get_filtered_spl_token_accounts_by_mint(
2306        &self,
2307        bank: Arc<Bank>,
2308        program_id: Pubkey,
2309        mint_key: Pubkey,
2310        mut filters: Vec<RpcFilterType>,
2311        sort_results: bool,
2312    ) -> RpcCustomResult<Vec<(Pubkey, AccountSharedData)>> {
2313        // The by-mint accounts index checks for Token Account state and Mint address on inclusion.
2314        // However, due to the current AccountsDb implementation, an account may remain in storage
2315        // as be zero-lamport AccountSharedData::Default() after being wiped and reinitialized in later
2316        // updates. We include the redundant filters here to avoid returning these accounts.
2317        //
2318        // Filter on Token Account state
2319        filters.push(RpcFilterType::TokenAccountState);
2320        // Filter on Mint address
2321        filters.push(RpcFilterType::Memcmp(Memcmp::new_raw_bytes(
2322            SPL_TOKEN_ACCOUNT_MINT_OFFSET,
2323            mint_key.to_bytes().into(),
2324        )));
2325        if self
2326            .config
2327            .account_indexes
2328            .contains(&AccountIndex::SplTokenMint)
2329        {
2330            if !self.config.account_indexes.include_key(&mint_key) {
2331                return Err(RpcCustomError::KeyExcludedFromSecondaryIndex {
2332                    index_key: mint_key.to_string(),
2333                });
2334            }
2335            self.get_filtered_indexed_accounts(
2336                &bank,
2337                &IndexKey::SplTokenMint(mint_key),
2338                &program_id,
2339                filters,
2340                sort_results,
2341            )
2342            .await
2343            .map_err(|e| RpcCustomError::ScanError {
2344                message: e.to_string(),
2345            })
2346        } else {
2347            self.get_filtered_program_accounts(bank, program_id, filters, sort_results)
2348                .await
2349        }
2350    }
2351
2352    fn get_latest_blockhash(&self, config: RpcContextConfig) -> Result<RpcResponse<RpcBlockhash>> {
2353        let bank = self.get_bank_with_config(config)?;
2354        let blockhash = bank.last_blockhash();
2355        let last_valid_block_height = bank
2356            .get_blockhash_last_valid_block_height(&blockhash)
2357            .expect("bank blockhash queue should contain blockhash");
2358        Ok(new_response(
2359            &bank,
2360            RpcBlockhash {
2361                blockhash: blockhash.to_string(),
2362                last_valid_block_height,
2363            },
2364        ))
2365    }
2366
2367    fn is_blockhash_valid(
2368        &self,
2369        blockhash: &Hash,
2370        config: RpcContextConfig,
2371    ) -> Result<RpcResponse<bool>> {
2372        let bank = self.get_bank_with_config(config)?;
2373        let is_valid = bank.is_blockhash_valid(blockhash);
2374        Ok(new_response(&bank, is_valid))
2375    }
2376
2377    fn get_stake_minimum_delegation(&self, config: RpcContextConfig) -> Result<RpcResponse<u64>> {
2378        let bank = self.get_bank_with_config(config)?;
2379        let stake_minimum_delegation = stake_utils::get_minimum_delegation(
2380            bank.feature_set
2381                .is_active(&agave_feature_set::stake_raise_minimum_delegation_to_1_sol::id()),
2382        );
2383        Ok(new_response(&bank, stake_minimum_delegation))
2384    }
2385
2386    fn get_recent_prioritization_fees(
2387        &self,
2388        pubkeys: Vec<Pubkey>,
2389    ) -> Result<Vec<RpcPrioritizationFee>> {
2390        Ok(self
2391            .prioritization_fee_cache
2392            .get_prioritization_fees(&pubkeys)
2393            .into_iter()
2394            .map(|(slot, prioritization_fee)| RpcPrioritizationFee {
2395                slot,
2396                prioritization_fee,
2397            })
2398            .collect())
2399    }
2400}
2401
2402pub(crate) fn optimize_filters(filters: &mut [RpcFilterType]) {
2403    filters.iter_mut().for_each(|filter_type| {
2404        if let RpcFilterType::Memcmp(compare) = filter_type {
2405            if let Err(err) = compare.convert_to_raw_bytes() {
2406                // All filters should have been previously verified
2407                warn!("Invalid filter: bytes could not be decoded, {err}");
2408            }
2409        }
2410    })
2411}
2412
2413pub(crate) fn verify_filters(filters: &[RpcFilterType]) -> Result<()> {
2414    if filters.len() > MAX_GET_PROGRAM_ACCOUNT_FILTERS {
2415        return Err(Error::invalid_params(format!(
2416            "Too many filters provided; max {MAX_GET_PROGRAM_ACCOUNT_FILTERS}"
2417        )));
2418    }
2419    for filter in filters {
2420        verify_filter(filter)?;
2421    }
2422    Ok(())
2423}
2424
2425fn verify_filter(input: &RpcFilterType) -> Result<()> {
2426    input
2427        .verify()
2428        .map_err(|e| Error::invalid_params(format!("Invalid param: {e:?}")))
2429}
2430
2431pub fn verify_pubkey(input: &str) -> Result<Pubkey> {
2432    input
2433        .parse()
2434        .map_err(|e| Error::invalid_params(format!("Invalid param: {e:?}")))
2435}
2436
2437fn verify_hash(input: &str) -> Result<Hash> {
2438    input
2439        .parse()
2440        .map_err(|e| Error::invalid_params(format!("Invalid param: {e:?}")))
2441}
2442
2443fn verify_signature(input: &str) -> Result<Signature> {
2444    input
2445        .parse()
2446        .map_err(|e| Error::invalid_params(format!("Invalid param: {e:?}")))
2447}
2448
2449fn verify_token_account_filter(
2450    token_account_filter: RpcTokenAccountsFilter,
2451) -> Result<TokenAccountsFilter> {
2452    match token_account_filter {
2453        RpcTokenAccountsFilter::Mint(mint_str) => {
2454            let mint = verify_pubkey(&mint_str)?;
2455            Ok(TokenAccountsFilter::Mint(mint))
2456        }
2457        RpcTokenAccountsFilter::ProgramId(program_id_str) => {
2458            let program_id = verify_pubkey(&program_id_str)?;
2459            Ok(TokenAccountsFilter::ProgramId(program_id))
2460        }
2461    }
2462}
2463
2464fn verify_and_parse_signatures_for_address_params(
2465    address: String,
2466    before: Option<String>,
2467    until: Option<String>,
2468    limit: Option<usize>,
2469) -> Result<(Pubkey, Option<Signature>, Option<Signature>, usize)> {
2470    let address = verify_pubkey(&address)?;
2471    let before = before
2472        .map(|ref before| verify_signature(before))
2473        .transpose()?;
2474    let until = until.map(|ref until| verify_signature(until)).transpose()?;
2475    let limit = limit.unwrap_or(MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT);
2476
2477    if limit == 0 || limit > MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT {
2478        return Err(Error::invalid_params(format!(
2479            "Invalid limit; max {MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT}"
2480        )));
2481    }
2482    Ok((address, before, until, limit))
2483}
2484
2485pub(crate) fn check_is_at_least_confirmed(commitment: CommitmentConfig) -> Result<()> {
2486    if !commitment.is_at_least_confirmed() {
2487        return Err(Error::invalid_params(
2488            "Method does not support commitment below `confirmed`",
2489        ));
2490    }
2491    Ok(())
2492}
2493
2494fn get_encoded_account(
2495    bank: &Bank,
2496    pubkey: &Pubkey,
2497    encoding: UiAccountEncoding,
2498    data_slice: Option<UiDataSliceConfig>,
2499    // only used for simulation results
2500    overwrite_accounts: Option<&HashMap<Pubkey, AccountSharedData>>,
2501) -> Result<Option<UiAccount>> {
2502    match account_resolver::get_account_from_overwrites_or_bank(pubkey, bank, overwrite_accounts) {
2503        Some(account) => {
2504            let response = if is_known_spl_token_id(account.owner())
2505                && encoding == UiAccountEncoding::JsonParsed
2506            {
2507                get_parsed_token_account(bank, pubkey, account, overwrite_accounts)
2508            } else {
2509                encode_account(&account, pubkey, encoding, data_slice)?
2510            };
2511            Ok(Some(response))
2512        }
2513        None => Ok(None),
2514    }
2515}
2516
2517fn encode_account<T: ReadableAccount>(
2518    account: &T,
2519    pubkey: &Pubkey,
2520    encoding: UiAccountEncoding,
2521    data_slice: Option<UiDataSliceConfig>,
2522) -> Result<UiAccount> {
2523    if (encoding == UiAccountEncoding::Binary || encoding == UiAccountEncoding::Base58)
2524        && data_slice
2525            .map(|s| min(s.length, account.data().len().saturating_sub(s.offset)))
2526            .unwrap_or(account.data().len())
2527            > MAX_BASE58_BYTES
2528    {
2529        let message = format!(
2530            "Encoded binary (base 58) data should be less than {MAX_BASE58_BYTES} bytes, please \
2531             use Base64 encoding."
2532        );
2533        Err(error::Error {
2534            code: error::ErrorCode::InvalidRequest,
2535            message,
2536            data: None,
2537        })
2538    } else {
2539        Ok(encode_ui_account(
2540            pubkey, account, encoding, None, data_slice,
2541        ))
2542    }
2543}
2544
2545/// Analyze custom filters to determine if the result will be a subset of spl-token accounts by
2546/// owner.
2547/// NOTE: `optimize_filters()` should almost always be called before using this method because of
2548/// the requirement that `Memcmp::raw_bytes_as_ref().is_some()`.
2549fn get_spl_token_owner_filter(
2550    program_id: &Pubkey,
2551    filters: &[RpcFilterType],
2552) -> Result<Option<Pubkey>> {
2553    if !is_known_spl_token_id(program_id) {
2554        return Ok(None);
2555    }
2556    let mut data_size_filter: Option<u64> = None;
2557    let mut memcmp_filter: Option<&[u8]> = None;
2558    let mut owner_key: Option<Pubkey> = None;
2559    let mut token_account_state_filter = false;
2560    let account_packed_len = TokenAccount::get_packed_len();
2561    for filter in filters {
2562        match filter {
2563            RpcFilterType::DataSize(size) => data_size_filter = Some(*size),
2564            RpcFilterType::Memcmp(memcmp) => {
2565                let offset = memcmp.offset();
2566                if let Some(bytes) = memcmp.raw_bytes_as_ref() {
2567                    if offset == account_packed_len && *program_id == token_2022::id() {
2568                        memcmp_filter = Some(bytes);
2569                    } else if offset == SPL_TOKEN_ACCOUNT_OWNER_OFFSET {
2570                        if bytes.len() == PUBKEY_BYTES {
2571                            owner_key = Pubkey::try_from(bytes).ok();
2572                        } else {
2573                            return Err(Error::invalid_params(format!(
2574                                "Incorrect byte length {} for SPL token owner filter, expected {}",
2575                                bytes.len(),
2576                                PUBKEY_BYTES
2577                            )));
2578                        }
2579                    }
2580                }
2581            }
2582            RpcFilterType::TokenAccountState => token_account_state_filter = true,
2583        }
2584    }
2585    if data_size_filter == Some(account_packed_len as u64)
2586        || memcmp_filter == Some(&[ACCOUNTTYPE_ACCOUNT])
2587        || token_account_state_filter
2588    {
2589        Ok(owner_key)
2590    } else {
2591        debug!("spl_token program filters do not match by-owner index requisites");
2592        Ok(None)
2593    }
2594}
2595
2596/// Analyze custom filters to determine if the result will be a subset of spl-token accounts by
2597/// mint.
2598/// NOTE: `optimize_filters()` should almost always be called before using this method because of
2599/// the requirement that `Memcmp::raw_bytes_as_ref().is_some()`.
2600fn get_spl_token_mint_filter(
2601    program_id: &Pubkey,
2602    filters: &[RpcFilterType],
2603) -> Result<Option<Pubkey>> {
2604    if !is_known_spl_token_id(program_id) {
2605        return Ok(None);
2606    }
2607    let mut data_size_filter: Option<u64> = None;
2608    let mut memcmp_filter: Option<&[u8]> = None;
2609    let mut mint: Option<Pubkey> = None;
2610    let mut token_account_state_filter = false;
2611    let account_packed_len = TokenAccount::get_packed_len();
2612    for filter in filters {
2613        match filter {
2614            RpcFilterType::DataSize(size) => data_size_filter = Some(*size),
2615            RpcFilterType::Memcmp(memcmp) => {
2616                let offset = memcmp.offset();
2617                if let Some(bytes) = memcmp.raw_bytes_as_ref() {
2618                    if offset == account_packed_len && *program_id == token_2022::id() {
2619                        memcmp_filter = Some(bytes);
2620                    } else if offset == SPL_TOKEN_ACCOUNT_MINT_OFFSET {
2621                        if bytes.len() == PUBKEY_BYTES {
2622                            mint = Pubkey::try_from(bytes).ok();
2623                        } else {
2624                            return Err(Error::invalid_params(format!(
2625                                "Incorrect byte length {} for SPL token mint filter, expected {}",
2626                                bytes.len(),
2627                                PUBKEY_BYTES
2628                            )));
2629                        }
2630                    }
2631                }
2632            }
2633            RpcFilterType::TokenAccountState => token_account_state_filter = true,
2634        }
2635    }
2636    if data_size_filter == Some(account_packed_len as u64)
2637        || memcmp_filter == Some(&[ACCOUNTTYPE_ACCOUNT])
2638        || token_account_state_filter
2639    {
2640        Ok(mint)
2641    } else {
2642        debug!("spl_token program filters do not match by-mint index requisites");
2643        Ok(None)
2644    }
2645}
2646
2647/// Analyze a passed Pubkey that may be a Token program id or Mint address to determine the program
2648/// id and optional Mint
2649fn get_token_program_id_and_mint(
2650    bank: &Bank,
2651    token_account_filter: TokenAccountsFilter,
2652) -> Result<(Pubkey, Option<Pubkey>)> {
2653    match token_account_filter {
2654        TokenAccountsFilter::Mint(mint) => {
2655            let (mint_owner, _) = get_mint_owner_and_additional_data(bank, &mint)?;
2656            if !is_known_spl_token_id(&mint_owner) {
2657                return Err(Error::invalid_params(
2658                    "Invalid param: not a Token mint".to_string(),
2659                ));
2660            }
2661            Ok((mint_owner, Some(mint)))
2662        }
2663        TokenAccountsFilter::ProgramId(program_id) => {
2664            if is_known_spl_token_id(&program_id) {
2665                Ok((program_id, None))
2666            } else {
2667                Err(Error::invalid_params(
2668                    "Invalid param: unrecognized Token program id".to_string(),
2669                ))
2670            }
2671        }
2672    }
2673}
2674
2675fn _send_transaction(
2676    meta: JsonRpcRequestProcessor,
2677    message_hash: Hash,
2678    signature: Signature,
2679    blockhash: Hash,
2680    wire_transaction: Vec<u8>,
2681    last_valid_block_height: u64,
2682    durable_nonce_info: Option<(Pubkey, Hash)>,
2683    max_retries: Option<usize>,
2684) -> Result<String> {
2685    let transaction_info = TransactionInfo::new(
2686        message_hash,
2687        signature,
2688        blockhash,
2689        wire_transaction,
2690        last_valid_block_height,
2691        durable_nonce_info,
2692        max_retries,
2693        None,
2694    );
2695    meta.transaction_sender
2696        .send(transaction_info)
2697        .unwrap_or_else(|err| warn!("Failed to enqueue transaction: {err}"));
2698
2699    Ok(signature.to_string())
2700}
2701
2702// Minimal RPC interface that known validators are expected to provide
2703pub mod rpc_minimal {
2704    use super::*;
2705    #[rpc]
2706    pub trait Minimal {
2707        type Metadata;
2708
2709        #[rpc(meta, name = "getBalance")]
2710        fn get_balance(
2711            &self,
2712            meta: Self::Metadata,
2713            pubkey_str: String,
2714            config: Option<RpcContextConfig>,
2715        ) -> Result<RpcResponse<u64>>;
2716
2717        #[rpc(meta, name = "getEpochInfo")]
2718        fn get_epoch_info(
2719            &self,
2720            meta: Self::Metadata,
2721            config: Option<RpcContextConfig>,
2722        ) -> Result<EpochInfo>;
2723
2724        #[rpc(meta, name = "getGenesisHash")]
2725        fn get_genesis_hash(&self, meta: Self::Metadata) -> Result<String>;
2726
2727        #[rpc(meta, name = "getHealth")]
2728        fn get_health(&self, meta: Self::Metadata) -> Result<String>;
2729
2730        #[rpc(meta, name = "getIdentity")]
2731        fn get_identity(&self, meta: Self::Metadata) -> Result<RpcIdentity>;
2732
2733        #[rpc(meta, name = "getSlot")]
2734        fn get_slot(&self, meta: Self::Metadata, config: Option<RpcContextConfig>) -> Result<Slot>;
2735
2736        #[rpc(meta, name = "getBlockHeight")]
2737        fn get_block_height(
2738            &self,
2739            meta: Self::Metadata,
2740            config: Option<RpcContextConfig>,
2741        ) -> Result<u64>;
2742
2743        #[rpc(meta, name = "getHighestSnapshotSlot")]
2744        fn get_highest_snapshot_slot(&self, meta: Self::Metadata) -> Result<RpcSnapshotSlotInfo>;
2745
2746        #[rpc(meta, name = "getTransactionCount")]
2747        fn get_transaction_count(
2748            &self,
2749            meta: Self::Metadata,
2750            config: Option<RpcContextConfig>,
2751        ) -> Result<u64>;
2752
2753        #[rpc(meta, name = "getVersion")]
2754        fn get_version(&self, meta: Self::Metadata) -> Result<RpcVersionInfo>;
2755
2756        // TODO: Refactor `agave-validator wait-for-restart-window` to not require this method, so
2757        //       it can be removed from rpc_minimal
2758        #[rpc(meta, name = "getVoteAccounts")]
2759        fn get_vote_accounts(
2760            &self,
2761            meta: Self::Metadata,
2762            config: Option<RpcGetVoteAccountsConfig>,
2763        ) -> Result<RpcVoteAccountStatus>;
2764
2765        // TODO: Refactor `agave-validator wait-for-restart-window` to not require this method, so
2766        //       it can be removed from rpc_minimal
2767        #[rpc(meta, name = "getLeaderSchedule")]
2768        fn get_leader_schedule(
2769            &self,
2770            meta: Self::Metadata,
2771            options: Option<RpcLeaderScheduleConfigWrapper>,
2772            config: Option<RpcLeaderScheduleConfig>,
2773        ) -> Result<Option<RpcLeaderSchedule>>;
2774    }
2775
2776    pub struct MinimalImpl;
2777    impl Minimal for MinimalImpl {
2778        type Metadata = JsonRpcRequestProcessor;
2779
2780        fn get_balance(
2781            &self,
2782            meta: Self::Metadata,
2783            pubkey_str: String,
2784            config: Option<RpcContextConfig>,
2785        ) -> Result<RpcResponse<u64>> {
2786            debug!("get_balance rpc request received: {pubkey_str:?}");
2787            let pubkey = verify_pubkey(&pubkey_str)?;
2788            meta.get_balance(&pubkey, config.unwrap_or_default())
2789        }
2790
2791        fn get_epoch_info(
2792            &self,
2793            meta: Self::Metadata,
2794            config: Option<RpcContextConfig>,
2795        ) -> Result<EpochInfo> {
2796            debug!("get_epoch_info rpc request received");
2797            let bank = meta.get_bank_with_config(config.unwrap_or_default())?;
2798            Ok(bank.get_epoch_info())
2799        }
2800
2801        fn get_genesis_hash(&self, meta: Self::Metadata) -> Result<String> {
2802            debug!("get_genesis_hash rpc request received");
2803            Ok(meta.genesis_hash.to_string())
2804        }
2805
2806        fn get_health(&self, meta: Self::Metadata) -> Result<String> {
2807            match meta.health.check() {
2808                RpcHealthStatus::Ok => Ok("ok".to_string()),
2809                RpcHealthStatus::Unknown => Err(RpcCustomError::NodeUnhealthy {
2810                    num_slots_behind: None,
2811                }
2812                .into()),
2813                RpcHealthStatus::Behind { num_slots } => Err(RpcCustomError::NodeUnhealthy {
2814                    num_slots_behind: Some(num_slots),
2815                }
2816                .into()),
2817            }
2818        }
2819
2820        fn get_identity(&self, meta: Self::Metadata) -> Result<RpcIdentity> {
2821            debug!("get_identity rpc request received");
2822            Ok(RpcIdentity {
2823                identity: meta.cluster_info.id().to_string(),
2824            })
2825        }
2826
2827        fn get_slot(&self, meta: Self::Metadata, config: Option<RpcContextConfig>) -> Result<Slot> {
2828            debug!("get_slot rpc request received");
2829            meta.get_slot(config.unwrap_or_default())
2830        }
2831
2832        fn get_block_height(
2833            &self,
2834            meta: Self::Metadata,
2835            config: Option<RpcContextConfig>,
2836        ) -> Result<u64> {
2837            debug!("get_block_height rpc request received");
2838            meta.get_block_height(config.unwrap_or_default())
2839        }
2840
2841        fn get_highest_snapshot_slot(&self, meta: Self::Metadata) -> Result<RpcSnapshotSlotInfo> {
2842            debug!("get_highest_snapshot_slot rpc request received");
2843
2844            if meta.snapshot_config.is_none() {
2845                return Err(RpcCustomError::NoSnapshot.into());
2846            }
2847
2848            let (full_snapshot_archives_dir, incremental_snapshot_archives_dir) = meta
2849                .snapshot_config
2850                .map(|snapshot_config| {
2851                    (
2852                        snapshot_config.full_snapshot_archives_dir,
2853                        snapshot_config.incremental_snapshot_archives_dir,
2854                    )
2855                })
2856                .unwrap();
2857
2858            let full_snapshot_slot =
2859                snapshot_paths::get_highest_full_snapshot_archive_slot(full_snapshot_archives_dir)
2860                    .ok_or(RpcCustomError::NoSnapshot)?;
2861            let incremental_snapshot_slot =
2862                snapshot_paths::get_highest_incremental_snapshot_archive_slot(
2863                    incremental_snapshot_archives_dir,
2864                    full_snapshot_slot,
2865                );
2866
2867            Ok(RpcSnapshotSlotInfo {
2868                full: full_snapshot_slot,
2869                incremental: incremental_snapshot_slot,
2870            })
2871        }
2872
2873        fn get_transaction_count(
2874            &self,
2875            meta: Self::Metadata,
2876            config: Option<RpcContextConfig>,
2877        ) -> Result<u64> {
2878            debug!("get_transaction_count rpc request received");
2879            meta.get_transaction_count(config.unwrap_or_default())
2880        }
2881
2882        fn get_version(&self, _: Self::Metadata) -> Result<RpcVersionInfo> {
2883            debug!("get_version rpc request received");
2884            let version = solana_version::Version::default();
2885            Ok(RpcVersionInfo {
2886                solana_core: version.to_string(),
2887                feature_set: Some(version.feature_set),
2888            })
2889        }
2890
2891        // TODO: Refactor `agave-validator wait-for-restart-window` to not require this method, so
2892        //       it can be removed from rpc_minimal
2893        fn get_vote_accounts(
2894            &self,
2895            meta: Self::Metadata,
2896            config: Option<RpcGetVoteAccountsConfig>,
2897        ) -> Result<RpcVoteAccountStatus> {
2898            debug!("get_vote_accounts rpc request received");
2899            meta.get_vote_accounts(config)
2900        }
2901
2902        // TODO: Refactor `agave-validator wait-for-restart-window` to not require this method, so
2903        //       it can be removed from rpc_minimal
2904        fn get_leader_schedule(
2905            &self,
2906            meta: Self::Metadata,
2907            options: Option<RpcLeaderScheduleConfigWrapper>,
2908            config: Option<RpcLeaderScheduleConfig>,
2909        ) -> Result<Option<RpcLeaderSchedule>> {
2910            let (slot, maybe_config) = options.map(|options| options.unzip()).unwrap_or_default();
2911            let config = maybe_config.or(config).unwrap_or_default();
2912
2913            if let Some(ref identity) = config.identity {
2914                let _ = verify_pubkey(identity)?;
2915            }
2916
2917            let bank = meta.bank(config.commitment);
2918            let slot = slot.unwrap_or_else(|| bank.slot());
2919            let epoch = bank.epoch_schedule().get_epoch(slot);
2920
2921            debug!("get_leader_schedule rpc request received: {slot:?}");
2922
2923            Ok(meta
2924                .leader_schedule_cache
2925                .get_epoch_leader_schedule(epoch)
2926                .map(|leader_schedule| {
2927                    let mut schedule_by_identity =
2928                        solana_ledger::leader_schedule_utils::leader_schedule_by_identity(
2929                            leader_schedule.get_slot_leaders().iter().enumerate(),
2930                        );
2931                    if let Some(identity) = config.identity {
2932                        schedule_by_identity.retain(|k, _| *k == identity);
2933                    }
2934                    schedule_by_identity
2935                }))
2936        }
2937    }
2938}
2939
2940// RPC interface that only depends on immediate Bank data
2941// Expected to be provided by API nodes
2942pub mod rpc_bank {
2943    use super::*;
2944    #[rpc]
2945    pub trait BankData {
2946        type Metadata;
2947
2948        #[rpc(meta, name = "getMinimumBalanceForRentExemption")]
2949        fn get_minimum_balance_for_rent_exemption(
2950            &self,
2951            meta: Self::Metadata,
2952            data_len: usize,
2953            commitment: Option<CommitmentConfig>,
2954        ) -> Result<u64>;
2955
2956        #[rpc(meta, name = "getInflationGovernor")]
2957        fn get_inflation_governor(
2958            &self,
2959            meta: Self::Metadata,
2960            commitment: Option<CommitmentConfig>,
2961        ) -> Result<RpcInflationGovernor>;
2962
2963        #[rpc(meta, name = "getInflationRate")]
2964        fn get_inflation_rate(&self, meta: Self::Metadata) -> Result<RpcInflationRate>;
2965
2966        #[rpc(meta, name = "getEpochSchedule")]
2967        fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result<EpochSchedule>;
2968
2969        #[rpc(meta, name = "getSlotLeader")]
2970        fn get_slot_leader(
2971            &self,
2972            meta: Self::Metadata,
2973            config: Option<RpcContextConfig>,
2974        ) -> Result<String>;
2975
2976        #[rpc(meta, name = "getSlotLeaders")]
2977        fn get_slot_leaders(
2978            &self,
2979            meta: Self::Metadata,
2980            start_slot: Slot,
2981            limit: u64,
2982        ) -> Result<Vec<String>>;
2983
2984        #[rpc(meta, name = "getBlockProduction")]
2985        fn get_block_production(
2986            &self,
2987            meta: Self::Metadata,
2988            config: Option<RpcBlockProductionConfig>,
2989        ) -> Result<RpcResponse<RpcBlockProduction>>;
2990    }
2991
2992    pub struct BankDataImpl;
2993    impl BankData for BankDataImpl {
2994        type Metadata = JsonRpcRequestProcessor;
2995
2996        fn get_minimum_balance_for_rent_exemption(
2997            &self,
2998            meta: Self::Metadata,
2999            data_len: usize,
3000            commitment: Option<CommitmentConfig>,
3001        ) -> Result<u64> {
3002            debug!("get_minimum_balance_for_rent_exemption rpc request received: {data_len:?}");
3003            if data_len as u64 > solana_system_interface::MAX_PERMITTED_DATA_LENGTH {
3004                return Err(Error::invalid_request());
3005            }
3006            Ok(meta.get_minimum_balance_for_rent_exemption(data_len, commitment))
3007        }
3008
3009        fn get_inflation_governor(
3010            &self,
3011            meta: Self::Metadata,
3012            commitment: Option<CommitmentConfig>,
3013        ) -> Result<RpcInflationGovernor> {
3014            debug!("get_inflation_governor rpc request received");
3015            Ok(meta.get_inflation_governor(commitment))
3016        }
3017
3018        fn get_inflation_rate(&self, meta: Self::Metadata) -> Result<RpcInflationRate> {
3019            debug!("get_inflation_rate rpc request received");
3020            Ok(meta.get_inflation_rate())
3021        }
3022
3023        fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result<EpochSchedule> {
3024            debug!("get_epoch_schedule rpc request received");
3025            Ok(meta.get_epoch_schedule())
3026        }
3027
3028        fn get_slot_leader(
3029            &self,
3030            meta: Self::Metadata,
3031            config: Option<RpcContextConfig>,
3032        ) -> Result<String> {
3033            debug!("get_slot_leader rpc request received");
3034            meta.get_slot_leader(config.unwrap_or_default())
3035        }
3036
3037        fn get_slot_leaders(
3038            &self,
3039            meta: Self::Metadata,
3040            start_slot: Slot,
3041            limit: u64,
3042        ) -> Result<Vec<String>> {
3043            debug!("get_slot_leaders rpc request received (start: {start_slot} limit: {limit})");
3044
3045            let limit = limit as usize;
3046            if limit > MAX_GET_SLOT_LEADERS {
3047                return Err(Error::invalid_params(format!(
3048                    "Invalid limit; max {MAX_GET_SLOT_LEADERS}"
3049                )));
3050            }
3051
3052            Ok(meta
3053                .get_slot_leaders(None, start_slot, limit)?
3054                .into_iter()
3055                .map(|identity| identity.to_string())
3056                .collect())
3057        }
3058
3059        fn get_block_production(
3060            &self,
3061            meta: Self::Metadata,
3062            config: Option<RpcBlockProductionConfig>,
3063        ) -> Result<RpcResponse<RpcBlockProduction>> {
3064            debug!("get_block_production rpc request received");
3065
3066            let config = config.unwrap_or_default();
3067            let filter_by_identity = if let Some(ref identity) = config.identity {
3068                Some(verify_pubkey(identity)?)
3069            } else {
3070                None
3071            };
3072
3073            let bank = meta.bank(config.commitment);
3074            let (first_slot, last_slot) = match config.range {
3075                None => (
3076                    bank.epoch_schedule().get_first_slot_in_epoch(bank.epoch()),
3077                    bank.slot(),
3078                ),
3079                Some(range) => {
3080                    let first_slot = range.first_slot;
3081                    let last_slot = range.last_slot.unwrap_or_else(|| bank.slot());
3082                    if last_slot < first_slot {
3083                        return Err(Error::invalid_params(format!(
3084                            "lastSlot, {last_slot}, cannot be less than firstSlot, {first_slot}"
3085                        )));
3086                    }
3087                    (first_slot, last_slot)
3088                }
3089            };
3090
3091            let slot_history = bank.get_slot_history();
3092            if first_slot < slot_history.oldest() {
3093                return Err(Error::invalid_params(format!(
3094                    "firstSlot, {}, is too small; min {}",
3095                    first_slot,
3096                    slot_history.oldest()
3097                )));
3098            }
3099            if last_slot > slot_history.newest() {
3100                return Err(Error::invalid_params(format!(
3101                    "lastSlot, {}, is too large; max {}",
3102                    last_slot,
3103                    slot_history.newest()
3104                )));
3105            }
3106
3107            let slot_leaders = meta.get_slot_leaders(
3108                config.commitment,
3109                first_slot,
3110                last_slot.saturating_sub(first_slot) as usize + 1, // +1 because last_slot is inclusive
3111            )?;
3112
3113            let mut block_production: HashMap<_, (usize, usize)> = HashMap::new();
3114
3115            let mut slot = first_slot;
3116            for identity in slot_leaders {
3117                if let Some(ref filter_by_identity) = filter_by_identity {
3118                    if identity != *filter_by_identity {
3119                        slot += 1;
3120                        continue;
3121                    }
3122                }
3123
3124                let entry = block_production.entry(identity).or_default();
3125                if slot_history.check(slot) == solana_slot_history::Check::Found {
3126                    entry.1 += 1; // Increment blocks_produced
3127                }
3128                entry.0 += 1; // Increment leader_slots
3129                slot += 1;
3130            }
3131
3132            Ok(new_response(
3133                &bank,
3134                RpcBlockProduction {
3135                    by_identity: block_production
3136                        .into_iter()
3137                        .map(|(k, v)| (k.to_string(), v))
3138                        .collect(),
3139                    range: RpcBlockProductionRange {
3140                        first_slot,
3141                        last_slot,
3142                    },
3143                },
3144            ))
3145        }
3146    }
3147}
3148
3149// RPC interface that depends on AccountsDB
3150// Expected to be provided by API nodes
3151pub mod rpc_accounts {
3152    use super::*;
3153    #[rpc]
3154    pub trait AccountsData {
3155        type Metadata;
3156
3157        #[rpc(meta, name = "getAccountInfo")]
3158        fn get_account_info(
3159            &self,
3160            meta: Self::Metadata,
3161            pubkey_str: String,
3162            config: Option<RpcAccountInfoConfig>,
3163        ) -> BoxFuture<Result<RpcResponse<Option<UiAccount>>>>;
3164
3165        #[rpc(meta, name = "getMultipleAccounts")]
3166        fn get_multiple_accounts(
3167            &self,
3168            meta: Self::Metadata,
3169            pubkey_strs: Vec<String>,
3170            config: Option<RpcAccountInfoConfig>,
3171        ) -> BoxFuture<Result<RpcResponse<Vec<Option<UiAccount>>>>>;
3172
3173        #[rpc(meta, name = "getBlockCommitment")]
3174        fn get_block_commitment(
3175            &self,
3176            meta: Self::Metadata,
3177            block: Slot,
3178        ) -> Result<RpcBlockCommitment<BlockCommitmentArray>>;
3179
3180        // SPL Token-specific RPC endpoints
3181        // See https://github.com/solana-labs/solana-program-library/releases/tag/token-v2.0.0 for
3182        // program details
3183
3184        #[rpc(meta, name = "getTokenAccountBalance")]
3185        fn get_token_account_balance(
3186            &self,
3187            meta: Self::Metadata,
3188            pubkey_str: String,
3189            commitment: Option<CommitmentConfig>,
3190        ) -> Result<RpcResponse<UiTokenAmount>>;
3191
3192        #[rpc(meta, name = "getTokenSupply")]
3193        fn get_token_supply(
3194            &self,
3195            meta: Self::Metadata,
3196            mint_str: String,
3197            commitment: Option<CommitmentConfig>,
3198        ) -> Result<RpcResponse<UiTokenAmount>>;
3199    }
3200
3201    pub struct AccountsDataImpl;
3202    impl AccountsData for AccountsDataImpl {
3203        type Metadata = JsonRpcRequestProcessor;
3204
3205        fn get_account_info(
3206            &self,
3207            meta: Self::Metadata,
3208            pubkey_str: String,
3209            config: Option<RpcAccountInfoConfig>,
3210        ) -> BoxFuture<Result<RpcResponse<Option<UiAccount>>>> {
3211            debug!("get_account_info rpc request received: {pubkey_str:?}");
3212            async move {
3213                let pubkey = verify_pubkey(&pubkey_str)?;
3214                meta.get_account_info(pubkey, config).await
3215            }
3216            .boxed()
3217        }
3218
3219        fn get_multiple_accounts(
3220            &self,
3221            meta: Self::Metadata,
3222            pubkey_strs: Vec<String>,
3223            config: Option<RpcAccountInfoConfig>,
3224        ) -> BoxFuture<Result<RpcResponse<Vec<Option<UiAccount>>>>> {
3225            debug!(
3226                "get_multiple_accounts rpc request received: {:?}",
3227                pubkey_strs.len()
3228            );
3229            async move {
3230                let max_multiple_accounts = meta
3231                    .config
3232                    .max_multiple_accounts
3233                    .unwrap_or(MAX_MULTIPLE_ACCOUNTS);
3234                if pubkey_strs.len() > max_multiple_accounts {
3235                    return Err(Error::invalid_params(format!(
3236                        "Too many inputs provided; max {max_multiple_accounts}"
3237                    )));
3238                }
3239                let pubkeys = pubkey_strs
3240                    .into_iter()
3241                    .map(|pubkey_str| verify_pubkey(&pubkey_str))
3242                    .collect::<Result<Vec<_>>>()?;
3243                meta.get_multiple_accounts(pubkeys, config).await
3244            }
3245            .boxed()
3246        }
3247
3248        fn get_block_commitment(
3249            &self,
3250            meta: Self::Metadata,
3251            block: Slot,
3252        ) -> Result<RpcBlockCommitment<BlockCommitmentArray>> {
3253            debug!("get_block_commitment rpc request received");
3254            Ok(meta.get_block_commitment(block))
3255        }
3256
3257        fn get_token_account_balance(
3258            &self,
3259            meta: Self::Metadata,
3260            pubkey_str: String,
3261            commitment: Option<CommitmentConfig>,
3262        ) -> Result<RpcResponse<UiTokenAmount>> {
3263            debug!("get_token_account_balance rpc request received: {pubkey_str:?}");
3264            let pubkey = verify_pubkey(&pubkey_str)?;
3265            meta.get_token_account_balance(&pubkey, commitment)
3266        }
3267
3268        fn get_token_supply(
3269            &self,
3270            meta: Self::Metadata,
3271            mint_str: String,
3272            commitment: Option<CommitmentConfig>,
3273        ) -> Result<RpcResponse<UiTokenAmount>> {
3274            debug!("get_token_supply rpc request received: {mint_str:?}");
3275            let mint = verify_pubkey(&mint_str)?;
3276            meta.get_token_supply(&mint, commitment)
3277        }
3278    }
3279}
3280
3281// RPC interface that depends on AccountsDB and requires accounts scan
3282// Expected to be provided by API nodes for now, but collected for easy separation and removal in
3283// the future.
3284pub mod rpc_accounts_scan {
3285    use super::*;
3286    #[rpc]
3287    pub trait AccountsScan {
3288        type Metadata;
3289
3290        #[rpc(meta, name = "getProgramAccounts")]
3291        fn get_program_accounts(
3292            &self,
3293            meta: Self::Metadata,
3294            program_id_str: String,
3295            config: Option<RpcProgramAccountsConfig>,
3296        ) -> BoxFuture<Result<OptionalContext<Vec<RpcKeyedAccount>>>>;
3297
3298        #[rpc(meta, name = "getLargestAccounts")]
3299        fn get_largest_accounts(
3300            &self,
3301            meta: Self::Metadata,
3302            config: Option<RpcLargestAccountsConfig>,
3303        ) -> BoxFuture<Result<RpcResponse<Vec<RpcAccountBalance>>>>;
3304
3305        #[rpc(meta, name = "getSupply")]
3306        fn get_supply(
3307            &self,
3308            meta: Self::Metadata,
3309            config: Option<RpcSupplyConfig>,
3310        ) -> BoxFuture<Result<RpcResponse<RpcSupply>>>;
3311
3312        // SPL Token-specific RPC endpoints
3313        // See https://github.com/solana-labs/solana-program-library/releases/tag/token-v2.0.0 for
3314        // program details
3315
3316        #[rpc(meta, name = "getTokenLargestAccounts")]
3317        fn get_token_largest_accounts(
3318            &self,
3319            meta: Self::Metadata,
3320            mint_str: String,
3321            commitment: Option<CommitmentConfig>,
3322        ) -> BoxFuture<Result<RpcResponse<Vec<RpcTokenAccountBalance>>>>;
3323
3324        #[rpc(meta, name = "getTokenAccountsByOwner")]
3325        fn get_token_accounts_by_owner(
3326            &self,
3327            meta: Self::Metadata,
3328            owner_str: String,
3329            token_account_filter: RpcTokenAccountsFilter,
3330            config: Option<RpcAccountInfoConfig>,
3331        ) -> BoxFuture<Result<RpcResponse<Vec<RpcKeyedAccount>>>>;
3332
3333        #[rpc(meta, name = "getTokenAccountsByDelegate")]
3334        fn get_token_accounts_by_delegate(
3335            &self,
3336            meta: Self::Metadata,
3337            delegate_str: String,
3338            token_account_filter: RpcTokenAccountsFilter,
3339            config: Option<RpcAccountInfoConfig>,
3340        ) -> BoxFuture<Result<RpcResponse<Vec<RpcKeyedAccount>>>>;
3341    }
3342
3343    pub struct AccountsScanImpl;
3344    impl AccountsScan for AccountsScanImpl {
3345        type Metadata = JsonRpcRequestProcessor;
3346
3347        fn get_program_accounts(
3348            &self,
3349            meta: Self::Metadata,
3350            program_id_str: String,
3351            config: Option<RpcProgramAccountsConfig>,
3352        ) -> BoxFuture<Result<OptionalContext<Vec<RpcKeyedAccount>>>> {
3353            debug!("get_program_accounts rpc request received: {program_id_str:?}");
3354            async move {
3355                let program_id = verify_pubkey(&program_id_str)?;
3356                let (config, filters, with_context, sort_results) = if let Some(config) = config {
3357                    (
3358                        Some(config.account_config),
3359                        config.filters.unwrap_or_default(),
3360                        config.with_context.unwrap_or_default(),
3361                        config.sort_results.unwrap_or(true),
3362                    )
3363                } else {
3364                    (None, vec![], false, true)
3365                };
3366                verify_filters(&filters)?;
3367                meta.get_program_accounts(program_id, config, filters, with_context, sort_results)
3368                    .await
3369            }
3370            .boxed()
3371        }
3372
3373        fn get_largest_accounts(
3374            &self,
3375            meta: Self::Metadata,
3376            config: Option<RpcLargestAccountsConfig>,
3377        ) -> BoxFuture<Result<RpcResponse<Vec<RpcAccountBalance>>>> {
3378            debug!("get_largest_accounts rpc request received");
3379            async move { Ok(meta.get_largest_accounts(config).await?) }.boxed()
3380        }
3381
3382        fn get_supply(
3383            &self,
3384            meta: Self::Metadata,
3385            config: Option<RpcSupplyConfig>,
3386        ) -> BoxFuture<Result<RpcResponse<RpcSupply>>> {
3387            debug!("get_supply rpc request received");
3388            async move { Ok(meta.get_supply(config).await?) }.boxed()
3389        }
3390
3391        fn get_token_largest_accounts(
3392            &self,
3393            meta: Self::Metadata,
3394            mint_str: String,
3395            commitment: Option<CommitmentConfig>,
3396        ) -> BoxFuture<Result<RpcResponse<Vec<RpcTokenAccountBalance>>>> {
3397            debug!("get_token_largest_accounts rpc request received: {mint_str:?}");
3398            async move {
3399                let mint = verify_pubkey(&mint_str)?;
3400                meta.get_token_largest_accounts(mint, commitment).await
3401            }
3402            .boxed()
3403        }
3404
3405        fn get_token_accounts_by_owner(
3406            &self,
3407            meta: Self::Metadata,
3408            owner_str: String,
3409            token_account_filter: RpcTokenAccountsFilter,
3410            config: Option<RpcAccountInfoConfig>,
3411        ) -> BoxFuture<Result<RpcResponse<Vec<RpcKeyedAccount>>>> {
3412            debug!("get_token_accounts_by_owner rpc request received: {owner_str:?}");
3413            async move {
3414                let owner = verify_pubkey(&owner_str)?;
3415                let token_account_filter = verify_token_account_filter(token_account_filter)?;
3416                meta.get_token_accounts_by_owner(owner, token_account_filter, config, true)
3417                    .await
3418            }
3419            .boxed()
3420        }
3421
3422        fn get_token_accounts_by_delegate(
3423            &self,
3424            meta: Self::Metadata,
3425            delegate_str: String,
3426            token_account_filter: RpcTokenAccountsFilter,
3427            config: Option<RpcAccountInfoConfig>,
3428        ) -> BoxFuture<Result<RpcResponse<Vec<RpcKeyedAccount>>>> {
3429            debug!("get_token_accounts_by_delegate rpc request received: {delegate_str:?}");
3430            async move {
3431                let delegate = verify_pubkey(&delegate_str)?;
3432                let token_account_filter = verify_token_account_filter(token_account_filter)?;
3433                meta.get_token_accounts_by_delegate(delegate, token_account_filter, config, true)
3434                    .await
3435            }
3436            .boxed()
3437        }
3438    }
3439}
3440
3441// Full RPC interface that an API node is expected to provide
3442// (rpc_minimal should also be provided by an API node)
3443pub mod rpc_full {
3444    use {
3445        super::*,
3446        solana_message::{SanitizedVersionedMessage, VersionedMessage},
3447        solana_transaction_status::{parse_ui_inner_instructions, UiLoadedAddresses},
3448    };
3449    #[rpc]
3450    pub trait Full {
3451        type Metadata;
3452
3453        #[rpc(meta, name = "getInflationReward")]
3454        fn get_inflation_reward(
3455            &self,
3456            meta: Self::Metadata,
3457            address_strs: Vec<String>,
3458            config: Option<RpcEpochConfig>,
3459        ) -> BoxFuture<Result<Vec<Option<RpcInflationReward>>>>;
3460
3461        #[rpc(meta, name = "getClusterNodes")]
3462        fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>>;
3463
3464        #[rpc(meta, name = "getRecentPerformanceSamples")]
3465        fn get_recent_performance_samples(
3466            &self,
3467            meta: Self::Metadata,
3468            limit: Option<usize>,
3469        ) -> Result<Vec<RpcPerfSample>>;
3470
3471        #[rpc(meta, name = "getSignatureStatuses")]
3472        fn get_signature_statuses(
3473            &self,
3474            meta: Self::Metadata,
3475            signature_strs: Vec<String>,
3476            config: Option<RpcSignatureStatusConfig>,
3477        ) -> BoxFuture<Result<RpcResponse<Vec<Option<TransactionStatus>>>>>;
3478
3479        #[rpc(meta, name = "getMaxRetransmitSlot")]
3480        fn get_max_retransmit_slot(&self, meta: Self::Metadata) -> Result<Slot>;
3481
3482        #[rpc(meta, name = "getMaxShredInsertSlot")]
3483        fn get_max_shred_insert_slot(&self, meta: Self::Metadata) -> Result<Slot>;
3484
3485        #[rpc(meta, name = "requestAirdrop")]
3486        fn request_airdrop(
3487            &self,
3488            meta: Self::Metadata,
3489            pubkey_str: String,
3490            lamports: u64,
3491            config: Option<RpcRequestAirdropConfig>,
3492        ) -> Result<String>;
3493
3494        #[rpc(meta, name = "sendTransaction")]
3495        fn send_transaction(
3496            &self,
3497            meta: Self::Metadata,
3498            data: String,
3499            config: Option<RpcSendTransactionConfig>,
3500        ) -> Result<String>;
3501
3502        #[rpc(meta, name = "simulateTransaction")]
3503        fn simulate_transaction(
3504            &self,
3505            meta: Self::Metadata,
3506            data: String,
3507            config: Option<RpcSimulateTransactionConfig>,
3508        ) -> Result<RpcResponse<RpcSimulateTransactionResult>>;
3509
3510        #[rpc(meta, name = "minimumLedgerSlot")]
3511        fn minimum_ledger_slot(&self, meta: Self::Metadata) -> Result<Slot>;
3512
3513        #[rpc(meta, name = "getBlock")]
3514        fn get_block(
3515            &self,
3516            meta: Self::Metadata,
3517            slot: Slot,
3518            config: Option<RpcEncodingConfigWrapper<RpcBlockConfig>>,
3519        ) -> BoxFuture<Result<Option<UiConfirmedBlock>>>;
3520
3521        #[rpc(meta, name = "getBlockTime")]
3522        fn get_block_time(
3523            &self,
3524            meta: Self::Metadata,
3525            slot: Slot,
3526        ) -> BoxFuture<Result<Option<UnixTimestamp>>>;
3527
3528        #[rpc(meta, name = "getBlocks")]
3529        fn get_blocks(
3530            &self,
3531            meta: Self::Metadata,
3532            start_slot: Slot,
3533            wrapper: Option<RpcBlocksConfigWrapper>,
3534            config: Option<RpcContextConfig>,
3535        ) -> BoxFuture<Result<Vec<Slot>>>;
3536
3537        #[rpc(meta, name = "getBlocksWithLimit")]
3538        fn get_blocks_with_limit(
3539            &self,
3540            meta: Self::Metadata,
3541            start_slot: Slot,
3542            limit: usize,
3543            config: Option<RpcContextConfig>,
3544        ) -> BoxFuture<Result<Vec<Slot>>>;
3545
3546        #[rpc(meta, name = "getTransaction")]
3547        fn get_transaction(
3548            &self,
3549            meta: Self::Metadata,
3550            signature_str: String,
3551            config: Option<RpcEncodingConfigWrapper<RpcTransactionConfig>>,
3552        ) -> BoxFuture<Result<Option<EncodedConfirmedTransactionWithStatusMeta>>>;
3553
3554        #[rpc(meta, name = "getSignaturesForAddress")]
3555        fn get_signatures_for_address(
3556            &self,
3557            meta: Self::Metadata,
3558            address: String,
3559            config: Option<RpcSignaturesForAddressConfig>,
3560        ) -> BoxFuture<Result<Vec<RpcConfirmedTransactionStatusWithSignature>>>;
3561
3562        #[rpc(meta, name = "getFirstAvailableBlock")]
3563        fn get_first_available_block(&self, meta: Self::Metadata) -> BoxFuture<Result<Slot>>;
3564
3565        #[rpc(meta, name = "getLatestBlockhash")]
3566        fn get_latest_blockhash(
3567            &self,
3568            meta: Self::Metadata,
3569            config: Option<RpcContextConfig>,
3570        ) -> Result<RpcResponse<RpcBlockhash>>;
3571
3572        #[rpc(meta, name = "isBlockhashValid")]
3573        fn is_blockhash_valid(
3574            &self,
3575            meta: Self::Metadata,
3576            blockhash: String,
3577            config: Option<RpcContextConfig>,
3578        ) -> Result<RpcResponse<bool>>;
3579
3580        #[rpc(meta, name = "getFeeForMessage")]
3581        fn get_fee_for_message(
3582            &self,
3583            meta: Self::Metadata,
3584            data: String,
3585            config: Option<RpcContextConfig>,
3586        ) -> Result<RpcResponse<Option<u64>>>;
3587
3588        #[rpc(meta, name = "getStakeMinimumDelegation")]
3589        fn get_stake_minimum_delegation(
3590            &self,
3591            meta: Self::Metadata,
3592            config: Option<RpcContextConfig>,
3593        ) -> Result<RpcResponse<u64>>;
3594
3595        #[rpc(meta, name = "getRecentPrioritizationFees")]
3596        fn get_recent_prioritization_fees(
3597            &self,
3598            meta: Self::Metadata,
3599            pubkey_strs: Option<Vec<String>>,
3600        ) -> Result<Vec<RpcPrioritizationFee>>;
3601    }
3602
3603    pub struct FullImpl;
3604    impl Full for FullImpl {
3605        type Metadata = JsonRpcRequestProcessor;
3606
3607        fn get_recent_performance_samples(
3608            &self,
3609            meta: Self::Metadata,
3610            limit: Option<usize>,
3611        ) -> Result<Vec<RpcPerfSample>> {
3612            debug!("get_recent_performance_samples request received");
3613
3614            let limit = limit.unwrap_or(PERFORMANCE_SAMPLES_LIMIT);
3615
3616            if limit > PERFORMANCE_SAMPLES_LIMIT {
3617                return Err(Error::invalid_params(format!(
3618                    "Invalid limit; max {PERFORMANCE_SAMPLES_LIMIT}"
3619                )));
3620            }
3621
3622            Ok(meta
3623                .blockstore
3624                .get_recent_perf_samples(limit)
3625                .map_err(|err| {
3626                    warn!("get_recent_performance_samples failed: {err:?}");
3627                    Error::invalid_request()
3628                })?
3629                .into_iter()
3630                .map(|(slot, sample)| rpc_perf_sample_from_perf_sample(slot, sample))
3631                .collect())
3632        }
3633
3634        fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>> {
3635            debug!("get_cluster_nodes rpc request received");
3636            let cluster_info = &meta.cluster_info;
3637            let socket_addr_space = cluster_info.socket_addr_space();
3638            let my_shred_version = cluster_info.my_shred_version();
3639            Ok(cluster_info
3640                .all_peers()
3641                .iter()
3642                .filter_map(|(contact_info, _)| {
3643                    if my_shred_version == contact_info.shred_version()
3644                        && contact_info
3645                            .gossip()
3646                            .map(|addr| socket_addr_space.check(&addr))
3647                            .unwrap_or_default()
3648                    {
3649                        let (version, feature_set) = if let Some(version) =
3650                            cluster_info.get_node_version(contact_info.pubkey())
3651                        {
3652                            (Some(version.to_string()), Some(version.feature_set))
3653                        } else {
3654                            (None, None)
3655                        };
3656                        Some(RpcContactInfo {
3657                            pubkey: contact_info.pubkey().to_string(),
3658                            gossip: contact_info.gossip(),
3659                            tvu: contact_info
3660                                .tvu(Protocol::UDP)
3661                                .filter(|addr| socket_addr_space.check(addr)),
3662                            tpu: contact_info
3663                                .tpu(Protocol::UDP)
3664                                .filter(|addr| socket_addr_space.check(addr)),
3665                            tpu_quic: contact_info
3666                                .tpu(Protocol::QUIC)
3667                                .filter(|addr| socket_addr_space.check(addr)),
3668                            tpu_forwards: contact_info
3669                                .tpu_forwards(Protocol::UDP)
3670                                .filter(|addr| socket_addr_space.check(addr)),
3671                            tpu_forwards_quic: contact_info
3672                                .tpu_forwards(Protocol::QUIC)
3673                                .filter(|addr| socket_addr_space.check(addr)),
3674                            tpu_vote: contact_info
3675                                .tpu_vote(Protocol::UDP)
3676                                .filter(|addr| socket_addr_space.check(addr)),
3677                            serve_repair: contact_info
3678                                .serve_repair(Protocol::UDP)
3679                                .filter(|addr| socket_addr_space.check(addr)),
3680                            rpc: contact_info
3681                                .rpc()
3682                                .filter(|addr| socket_addr_space.check(addr)),
3683                            pubsub: contact_info
3684                                .rpc_pubsub()
3685                                .filter(|addr| socket_addr_space.check(addr)),
3686                            version,
3687                            feature_set,
3688                            shred_version: Some(my_shred_version),
3689                        })
3690                    } else {
3691                        None // Exclude spy nodes
3692                    }
3693                })
3694                .collect())
3695        }
3696
3697        fn get_signature_statuses(
3698            &self,
3699            meta: Self::Metadata,
3700            signature_strs: Vec<String>,
3701            config: Option<RpcSignatureStatusConfig>,
3702        ) -> BoxFuture<Result<RpcResponse<Vec<Option<TransactionStatus>>>>> {
3703            debug!(
3704                "get_signature_statuses rpc request received: {:?}",
3705                signature_strs.len()
3706            );
3707            if signature_strs.len() > MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS {
3708                return Box::pin(future::err(Error::invalid_params(format!(
3709                    "Too many inputs provided; max {MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS}"
3710                ))));
3711            }
3712            let mut signatures: Vec<Signature> = vec![];
3713            for signature_str in signature_strs {
3714                match verify_signature(&signature_str) {
3715                    Ok(signature) => {
3716                        signatures.push(signature);
3717                    }
3718                    Err(err) => return Box::pin(future::err(err)),
3719                }
3720            }
3721            Box::pin(async move { meta.get_signature_statuses(signatures, config).await })
3722        }
3723
3724        fn get_max_retransmit_slot(&self, meta: Self::Metadata) -> Result<Slot> {
3725            debug!("get_max_retransmit_slot rpc request received");
3726            Ok(meta.get_max_retransmit_slot())
3727        }
3728
3729        fn get_max_shred_insert_slot(&self, meta: Self::Metadata) -> Result<Slot> {
3730            debug!("get_max_shred_insert_slot rpc request received");
3731            Ok(meta.get_max_shred_insert_slot())
3732        }
3733
3734        fn request_airdrop(
3735            &self,
3736            meta: Self::Metadata,
3737            pubkey_str: String,
3738            lamports: u64,
3739            config: Option<RpcRequestAirdropConfig>,
3740        ) -> Result<String> {
3741            debug!("request_airdrop rpc request received");
3742            trace!(
3743                "request_airdrop id={} lamports={} config: {:?}",
3744                pubkey_str,
3745                lamports,
3746                &config
3747            );
3748
3749            let faucet_addr = meta.config.faucet_addr.ok_or_else(Error::invalid_request)?;
3750            let pubkey = verify_pubkey(&pubkey_str)?;
3751
3752            let config = config.unwrap_or_default();
3753            let bank = meta.bank(config.commitment);
3754
3755            let blockhash = if let Some(blockhash) = config.recent_blockhash {
3756                verify_hash(&blockhash)?
3757            } else {
3758                bank.confirmed_last_blockhash()
3759            };
3760            let last_valid_block_height = bank
3761                .get_blockhash_last_valid_block_height(&blockhash)
3762                .unwrap_or(0);
3763
3764            let transaction =
3765                request_airdrop_transaction(&faucet_addr, &pubkey, lamports, blockhash).map_err(
3766                    |err| {
3767                        info!("request_airdrop_transaction failed: {err:?}");
3768                        Error::internal_error()
3769                    },
3770                )?;
3771
3772            let wire_transaction = serialize(&transaction).map_err(|err| {
3773                info!("request_airdrop: serialize error: {err:?}");
3774                Error::internal_error()
3775            })?;
3776
3777            let message_hash = transaction.message().hash();
3778            let signature = if !transaction.signatures.is_empty() {
3779                transaction.signatures[0]
3780            } else {
3781                return Err(RpcCustomError::TransactionSignatureVerificationFailure.into());
3782            };
3783
3784            _send_transaction(
3785                meta,
3786                message_hash,
3787                signature,
3788                blockhash,
3789                wire_transaction,
3790                last_valid_block_height,
3791                None,
3792                None,
3793            )
3794        }
3795
3796        fn send_transaction(
3797            &self,
3798            meta: Self::Metadata,
3799            data: String,
3800            config: Option<RpcSendTransactionConfig>,
3801        ) -> Result<String> {
3802            debug!("send_transaction rpc request received");
3803            let RpcSendTransactionConfig {
3804                skip_preflight,
3805                preflight_commitment,
3806                encoding,
3807                max_retries,
3808                min_context_slot,
3809            } = config.unwrap_or_default();
3810            let tx_encoding = encoding.unwrap_or(UiTransactionEncoding::Base58);
3811            let binary_encoding = tx_encoding.into_binary_encoding().ok_or_else(|| {
3812                Error::invalid_params(format!(
3813                    "unsupported encoding: {tx_encoding}. Supported encodings: base58, base64"
3814                ))
3815            })?;
3816            let (wire_transaction, unsanitized_tx) =
3817                decode_and_deserialize::<VersionedTransaction>(data, binary_encoding)?;
3818
3819            let preflight_commitment = if skip_preflight {
3820                Some(CommitmentConfig::processed())
3821            } else {
3822                preflight_commitment.map(|commitment| CommitmentConfig { commitment })
3823            };
3824            let preflight_bank = &*meta.get_bank_with_config(RpcContextConfig {
3825                commitment: preflight_commitment,
3826                min_context_slot,
3827            })?;
3828
3829            let transaction = sanitize_transaction(
3830                unsanitized_tx,
3831                preflight_bank,
3832                preflight_bank.get_reserved_account_keys(),
3833                preflight_bank
3834                    .feature_set
3835                    .is_active(&agave_feature_set::static_instruction_limit::id()),
3836            )?;
3837            let blockhash = *transaction.message().recent_blockhash();
3838            let message_hash = *transaction.message_hash();
3839            let signature = *transaction.signature();
3840
3841            let mut last_valid_block_height = preflight_bank
3842                .get_blockhash_last_valid_block_height(&blockhash)
3843                .unwrap_or(0);
3844
3845            let durable_nonce_info = transaction
3846                .get_durable_nonce()
3847                .map(|&pubkey| (pubkey, blockhash));
3848            if durable_nonce_info.is_some() || (skip_preflight && last_valid_block_height == 0) {
3849                // While it uses a defined constant, this last_valid_block_height value is chosen arbitrarily.
3850                // It provides a fallback timeout for durable-nonce transaction retries in case of
3851                // malicious packing of the retry queue. Durable-nonce transactions are otherwise
3852                // retried until the nonce is advanced.
3853                last_valid_block_height = preflight_bank.block_height() + MAX_PROCESSING_AGE as u64;
3854            }
3855
3856            if !skip_preflight {
3857                let verification_error = transaction.verify().err();
3858
3859                if verification_error.is_none() && !meta.config.skip_preflight_health_check {
3860                    match meta.health.check() {
3861                        RpcHealthStatus::Ok => (),
3862                        RpcHealthStatus::Unknown => {
3863                            inc_new_counter_info!("rpc-send-tx_health-unknown", 1);
3864                            return Err(RpcCustomError::NodeUnhealthy {
3865                                num_slots_behind: None,
3866                            }
3867                            .into());
3868                        }
3869                        RpcHealthStatus::Behind { num_slots } => {
3870                            inc_new_counter_info!("rpc-send-tx_health-behind", 1);
3871                            return Err(RpcCustomError::NodeUnhealthy {
3872                                num_slots_behind: Some(num_slots),
3873                            }
3874                            .into());
3875                        }
3876                    }
3877                }
3878
3879                let simulation_result = if let Some(err) = verification_error {
3880                    TransactionSimulationResult::new_error(err)
3881                } else {
3882                    preflight_bank.simulate_transaction(&transaction, false)
3883                };
3884
3885                if let TransactionSimulationResult {
3886                    result: Err(err),
3887                    logs,
3888                    post_simulation_accounts: _,
3889                    units_consumed,
3890                    loaded_accounts_data_size,
3891                    return_data,
3892                    inner_instructions: _, // Always `None` due to `enable_cpi_recording = false`
3893                    fee,
3894                    pre_balances: _,
3895                    post_balances: _,
3896                    pre_token_balances: _,
3897                    post_token_balances: _,
3898                } = simulation_result
3899                {
3900                    match err {
3901                        TransactionError::BlockhashNotFound => {
3902                            inc_new_counter_info!("rpc-send-tx_err-blockhash-not-found", 1);
3903                        }
3904                        _ => {
3905                            inc_new_counter_info!("rpc-send-tx_err-other", 1);
3906                        }
3907                    }
3908                    return Err(RpcCustomError::SendTransactionPreflightFailure {
3909                        message: format!("Transaction simulation failed: {err}"),
3910                        result: RpcSimulateTransactionResult {
3911                            err: Some(err.into()),
3912                            logs: Some(logs),
3913                            accounts: None,
3914                            units_consumed: Some(units_consumed),
3915                            loaded_accounts_data_size: Some(loaded_accounts_data_size),
3916                            return_data: return_data.map(|return_data| return_data.into()),
3917                            inner_instructions: None,
3918                            replacement_blockhash: None,
3919                            fee,
3920                            pre_balances: None,
3921                            post_balances: None,
3922                            pre_token_balances: None,
3923                            post_token_balances: None,
3924                            loaded_addresses: None,
3925                        },
3926                    }
3927                    .into());
3928                }
3929            }
3930
3931            _send_transaction(
3932                meta,
3933                message_hash,
3934                signature,
3935                blockhash,
3936                wire_transaction,
3937                last_valid_block_height,
3938                durable_nonce_info,
3939                max_retries,
3940            )
3941        }
3942
3943        fn simulate_transaction(
3944            &self,
3945            meta: Self::Metadata,
3946            data: String,
3947            config: Option<RpcSimulateTransactionConfig>,
3948        ) -> Result<RpcResponse<RpcSimulateTransactionResult>> {
3949            debug!("simulate_transaction rpc request received");
3950            let RpcSimulateTransactionConfig {
3951                sig_verify,
3952                replace_recent_blockhash,
3953                commitment,
3954                encoding,
3955                accounts: config_accounts,
3956                min_context_slot,
3957                inner_instructions: enable_cpi_recording,
3958            } = config.unwrap_or_default();
3959            let tx_encoding = encoding.unwrap_or(UiTransactionEncoding::Base58);
3960            let binary_encoding = tx_encoding.into_binary_encoding().ok_or_else(|| {
3961                Error::invalid_params(format!(
3962                    "unsupported encoding: {tx_encoding}. Supported encodings: base58, base64"
3963                ))
3964            })?;
3965            let (_, mut unsanitized_tx) =
3966                decode_and_deserialize::<VersionedTransaction>(data, binary_encoding)?;
3967
3968            let bank = &*meta.get_bank_with_config(RpcContextConfig {
3969                commitment,
3970                min_context_slot,
3971            })?;
3972            let mut blockhash: Option<RpcBlockhash> = None;
3973            if replace_recent_blockhash {
3974                if sig_verify {
3975                    return Err(Error::invalid_params(
3976                        "sigVerify may not be used with replaceRecentBlockhash",
3977                    ));
3978                }
3979                let recent_blockhash = bank.last_blockhash();
3980                unsanitized_tx
3981                    .message
3982                    .set_recent_blockhash(recent_blockhash);
3983                let last_valid_block_height = bank
3984                    .get_blockhash_last_valid_block_height(&recent_blockhash)
3985                    .expect("bank blockhash queue should contain blockhash");
3986                blockhash.replace(RpcBlockhash {
3987                    blockhash: recent_blockhash.to_string(),
3988                    last_valid_block_height,
3989                });
3990            }
3991
3992            let transaction = sanitize_transaction(
3993                unsanitized_tx,
3994                bank,
3995                bank.get_reserved_account_keys(),
3996                bank.feature_set
3997                    .is_active(&agave_feature_set::static_instruction_limit::id()),
3998            )?;
3999
4000            let verification_error = if sig_verify {
4001                transaction.verify().err()
4002            } else {
4003                None
4004            };
4005
4006            let simulation_result = if let Some(err) = verification_error {
4007                TransactionSimulationResult::new_error(err)
4008            } else {
4009                bank.simulate_transaction(&transaction, enable_cpi_recording)
4010            };
4011
4012            let TransactionSimulationResult {
4013                result,
4014                logs,
4015                post_simulation_accounts,
4016                units_consumed,
4017                loaded_accounts_data_size,
4018                return_data,
4019                inner_instructions,
4020                fee,
4021                pre_balances,
4022                post_balances,
4023                pre_token_balances,
4024                post_token_balances,
4025            } = simulation_result;
4026
4027            let account_keys = transaction.message().account_keys();
4028            let number_of_accounts = account_keys.len();
4029
4030            let accounts = if let Some(config_accounts) = config_accounts {
4031                let accounts_encoding = config_accounts
4032                    .encoding
4033                    .unwrap_or(UiAccountEncoding::Base64);
4034
4035                if accounts_encoding == UiAccountEncoding::Binary
4036                    || accounts_encoding == UiAccountEncoding::Base58
4037                {
4038                    return Err(Error::invalid_params("base58 encoding not supported"));
4039                }
4040
4041                if config_accounts.addresses.len() > number_of_accounts {
4042                    return Err(Error::invalid_params(format!(
4043                        "Too many accounts provided; max {number_of_accounts}"
4044                    )));
4045                }
4046
4047                if result.is_err() {
4048                    Some(vec![None; config_accounts.addresses.len()])
4049                } else {
4050                    let mut post_simulation_accounts_map = HashMap::new();
4051                    for (pubkey, data) in post_simulation_accounts {
4052                        post_simulation_accounts_map.insert(pubkey, data);
4053                    }
4054
4055                    Some(
4056                        config_accounts
4057                            .addresses
4058                            .iter()
4059                            .map(|address_str| {
4060                                let pubkey = verify_pubkey(address_str)?;
4061                                get_encoded_account(
4062                                    bank,
4063                                    &pubkey,
4064                                    accounts_encoding,
4065                                    None,
4066                                    Some(&post_simulation_accounts_map),
4067                                )
4068                            })
4069                            .collect::<Result<Vec<_>>>()?,
4070                    )
4071                }
4072            } else {
4073                None
4074            };
4075
4076            let inner_instructions = inner_instructions.map(|info| {
4077                map_inner_instructions(info)
4078                    .map(|converted| parse_ui_inner_instructions(converted, &account_keys))
4079                    .collect()
4080            });
4081
4082            Ok(new_response(
4083                bank,
4084                RpcSimulateTransactionResult {
4085                    err: result.err().map(Into::into),
4086                    logs: Some(logs),
4087                    accounts,
4088                    units_consumed: Some(units_consumed),
4089                    loaded_accounts_data_size: Some(loaded_accounts_data_size),
4090                    return_data: return_data.map(|return_data| return_data.into()),
4091                    inner_instructions,
4092                    replacement_blockhash: blockhash,
4093                    fee,
4094                    pre_balances,
4095                    post_balances,
4096                    pre_token_balances: pre_token_balances.map(|balances| {
4097                        balances.into_iter().map(|balance| solana_ledger::transaction_balances::svm_token_info_to_token_balance(balance).into()).collect()
4098                    }),
4099                    post_token_balances: post_token_balances.map(|balances| {
4100                        balances.into_iter().map(|balance| solana_ledger::transaction_balances::svm_token_info_to_token_balance(balance).into()).collect()
4101                    }),
4102                    loaded_addresses: Some(UiLoadedAddresses::from(&transaction.get_loaded_addresses())),
4103                },
4104            ))
4105        }
4106
4107        fn minimum_ledger_slot(&self, meta: Self::Metadata) -> Result<Slot> {
4108            debug!("minimum_ledger_slot rpc request received");
4109            meta.minimum_ledger_slot()
4110        }
4111
4112        fn get_block(
4113            &self,
4114            meta: Self::Metadata,
4115            slot: Slot,
4116            config: Option<RpcEncodingConfigWrapper<RpcBlockConfig>>,
4117        ) -> BoxFuture<Result<Option<UiConfirmedBlock>>> {
4118            debug!("get_block rpc request received: {slot:?}");
4119            Box::pin(async move { meta.get_block(slot, config).await })
4120        }
4121
4122        fn get_blocks(
4123            &self,
4124            meta: Self::Metadata,
4125            start_slot: Slot,
4126            wrapper: Option<RpcBlocksConfigWrapper>,
4127            config: Option<RpcContextConfig>,
4128        ) -> BoxFuture<Result<Vec<Slot>>> {
4129            let (end_slot, maybe_config) =
4130                wrapper.map(|wrapper| wrapper.unzip()).unwrap_or_default();
4131            debug!("get_blocks rpc request received: {start_slot}-{end_slot:?}");
4132            Box::pin(async move {
4133                meta.get_blocks(start_slot, end_slot, config.or(maybe_config))
4134                    .await
4135            })
4136        }
4137
4138        fn get_blocks_with_limit(
4139            &self,
4140            meta: Self::Metadata,
4141            start_slot: Slot,
4142            limit: usize,
4143            config: Option<RpcContextConfig>,
4144        ) -> BoxFuture<Result<Vec<Slot>>> {
4145            debug!("get_blocks_with_limit rpc request received: {start_slot}-{limit}",);
4146            Box::pin(async move { meta.get_blocks_with_limit(start_slot, limit, config).await })
4147        }
4148
4149        fn get_block_time(
4150            &self,
4151            meta: Self::Metadata,
4152            slot: Slot,
4153        ) -> BoxFuture<Result<Option<UnixTimestamp>>> {
4154            Box::pin(async move { meta.get_block_time(slot).await })
4155        }
4156
4157        fn get_transaction(
4158            &self,
4159            meta: Self::Metadata,
4160            signature_str: String,
4161            config: Option<RpcEncodingConfigWrapper<RpcTransactionConfig>>,
4162        ) -> BoxFuture<Result<Option<EncodedConfirmedTransactionWithStatusMeta>>> {
4163            debug!("get_transaction rpc request received: {signature_str:?}");
4164            let signature = verify_signature(&signature_str);
4165            if let Err(err) = signature {
4166                return Box::pin(future::err(err));
4167            }
4168            Box::pin(async move { meta.get_transaction(signature.unwrap(), config).await })
4169        }
4170
4171        fn get_signatures_for_address(
4172            &self,
4173            meta: Self::Metadata,
4174            address: String,
4175            config: Option<RpcSignaturesForAddressConfig>,
4176        ) -> BoxFuture<Result<Vec<RpcConfirmedTransactionStatusWithSignature>>> {
4177            let RpcSignaturesForAddressConfig {
4178                before,
4179                until,
4180                limit,
4181                commitment,
4182                min_context_slot,
4183            } = config.unwrap_or_default();
4184            let verification =
4185                verify_and_parse_signatures_for_address_params(address, before, until, limit);
4186
4187            match verification {
4188                Err(err) => Box::pin(future::err(err)),
4189                Ok((address, before, until, limit)) => Box::pin(async move {
4190                    meta.get_signatures_for_address(
4191                        address,
4192                        before,
4193                        until,
4194                        limit,
4195                        RpcContextConfig {
4196                            commitment,
4197                            min_context_slot,
4198                        },
4199                    )
4200                    .await
4201                }),
4202            }
4203        }
4204
4205        fn get_first_available_block(&self, meta: Self::Metadata) -> BoxFuture<Result<Slot>> {
4206            debug!("get_first_available_block rpc request received");
4207            Box::pin(async move { Ok(meta.get_first_available_block().await) })
4208        }
4209
4210        fn get_inflation_reward(
4211            &self,
4212            meta: Self::Metadata,
4213            address_strs: Vec<String>,
4214            config: Option<RpcEpochConfig>,
4215        ) -> BoxFuture<Result<Vec<Option<RpcInflationReward>>>> {
4216            debug!(
4217                "get_inflation_reward rpc request received: {:?}",
4218                address_strs.len()
4219            );
4220
4221            let mut addresses: Vec<Pubkey> = vec![];
4222            for address_str in address_strs {
4223                match verify_pubkey(&address_str) {
4224                    Ok(pubkey) => {
4225                        addresses.push(pubkey);
4226                    }
4227                    Err(err) => return Box::pin(future::err(err)),
4228                }
4229            }
4230
4231            Box::pin(async move { meta.get_inflation_reward(addresses, config).await })
4232        }
4233
4234        fn get_latest_blockhash(
4235            &self,
4236            meta: Self::Metadata,
4237            config: Option<RpcContextConfig>,
4238        ) -> Result<RpcResponse<RpcBlockhash>> {
4239            debug!("get_latest_blockhash rpc request received");
4240            meta.get_latest_blockhash(config.unwrap_or_default())
4241        }
4242
4243        fn is_blockhash_valid(
4244            &self,
4245            meta: Self::Metadata,
4246            blockhash: String,
4247            config: Option<RpcContextConfig>,
4248        ) -> Result<RpcResponse<bool>> {
4249            let blockhash =
4250                Hash::from_str(&blockhash).map_err(|e| Error::invalid_params(format!("{e:?}")))?;
4251            meta.is_blockhash_valid(&blockhash, config.unwrap_or_default())
4252        }
4253
4254        fn get_fee_for_message(
4255            &self,
4256            meta: Self::Metadata,
4257            data: String,
4258            config: Option<RpcContextConfig>,
4259        ) -> Result<RpcResponse<Option<u64>>> {
4260            debug!("get_fee_for_message rpc request received");
4261            let (_, message) = decode_and_deserialize::<VersionedMessage>(
4262                data,
4263                TransactionBinaryEncoding::Base64,
4264            )?;
4265            let bank = &*meta.get_bank_with_config(config.unwrap_or_default())?;
4266            let sanitized_versioned_message = SanitizedVersionedMessage::try_from(message)
4267                .map_err(|err| {
4268                    Error::invalid_params(format!("invalid transaction message: {err}"))
4269                })?;
4270            let sanitized_message = SanitizedMessage::try_new(
4271                sanitized_versioned_message,
4272                bank,
4273                bank.get_reserved_account_keys(),
4274            )
4275            .map_err(|err| Error::invalid_params(format!("invalid transaction message: {err}")))?;
4276            let fee = bank.get_fee_for_message(&sanitized_message);
4277            Ok(new_response(bank, fee))
4278        }
4279
4280        fn get_stake_minimum_delegation(
4281            &self,
4282            meta: Self::Metadata,
4283            config: Option<RpcContextConfig>,
4284        ) -> Result<RpcResponse<u64>> {
4285            debug!("get_stake_minimum_delegation rpc request received");
4286            meta.get_stake_minimum_delegation(config.unwrap_or_default())
4287        }
4288
4289        fn get_recent_prioritization_fees(
4290            &self,
4291            meta: Self::Metadata,
4292            pubkey_strs: Option<Vec<String>>,
4293        ) -> Result<Vec<RpcPrioritizationFee>> {
4294            let pubkey_strs = pubkey_strs.unwrap_or_default();
4295            debug!(
4296                "get_recent_prioritization_fees rpc request received: {:?} pubkeys",
4297                pubkey_strs.len()
4298            );
4299            if pubkey_strs.len() > MAX_TX_ACCOUNT_LOCKS {
4300                return Err(Error::invalid_params(format!(
4301                    "Too many inputs provided; max {MAX_TX_ACCOUNT_LOCKS}"
4302                )));
4303            }
4304            let pubkeys = pubkey_strs
4305                .into_iter()
4306                .map(|pubkey_str| verify_pubkey(&pubkey_str))
4307                .collect::<Result<Vec<_>>>()?;
4308            meta.get_recent_prioritization_fees(pubkeys)
4309        }
4310    }
4311}
4312
4313fn rpc_perf_sample_from_perf_sample(slot: u64, sample: PerfSample) -> RpcPerfSample {
4314    match sample {
4315        PerfSample::V1(PerfSampleV1 {
4316            num_transactions,
4317            num_slots,
4318            sample_period_secs,
4319        }) => RpcPerfSample {
4320            slot,
4321            num_transactions,
4322            num_non_vote_transactions: None,
4323            num_slots,
4324            sample_period_secs,
4325        },
4326        PerfSample::V2(PerfSampleV2 {
4327            num_transactions,
4328            num_non_vote_transactions,
4329            num_slots,
4330            sample_period_secs,
4331        }) => RpcPerfSample {
4332            slot,
4333            num_transactions,
4334            num_non_vote_transactions: Some(num_non_vote_transactions),
4335            num_slots,
4336            sample_period_secs,
4337        },
4338    }
4339}
4340
4341const MAX_BASE58_SIZE: usize = 1683; // Golden, bump if PACKET_DATA_SIZE changes
4342const MAX_BASE64_SIZE: usize = 1644; // Golden, bump if PACKET_DATA_SIZE changes
4343fn decode_and_deserialize<T>(
4344    encoded: String,
4345    encoding: TransactionBinaryEncoding,
4346) -> Result<(Vec<u8>, T)>
4347where
4348    T: serde::de::DeserializeOwned,
4349{
4350    let wire_output = match encoding {
4351        TransactionBinaryEncoding::Base58 => {
4352            inc_new_counter_info!("rpc-base58_encoded_tx", 1);
4353            if encoded.len() > MAX_BASE58_SIZE {
4354                return Err(Error::invalid_params(format!(
4355                    "base58 encoded {} too large: {} bytes (max: encoded/raw {}/{})",
4356                    type_name::<T>(),
4357                    encoded.len(),
4358                    MAX_BASE58_SIZE,
4359                    PACKET_DATA_SIZE,
4360                )));
4361            }
4362            bs58::decode(encoded)
4363                .into_vec()
4364                .map_err(|e| Error::invalid_params(format!("invalid base58 encoding: {e:?}")))?
4365        }
4366        TransactionBinaryEncoding::Base64 => {
4367            inc_new_counter_info!("rpc-base64_encoded_tx", 1);
4368            if encoded.len() > MAX_BASE64_SIZE {
4369                return Err(Error::invalid_params(format!(
4370                    "base64 encoded {} too large: {} bytes (max: encoded/raw {}/{})",
4371                    type_name::<T>(),
4372                    encoded.len(),
4373                    MAX_BASE64_SIZE,
4374                    PACKET_DATA_SIZE,
4375                )));
4376            }
4377            BASE64_STANDARD
4378                .decode(encoded)
4379                .map_err(|e| Error::invalid_params(format!("invalid base64 encoding: {e:?}")))?
4380        }
4381    };
4382    if wire_output.len() > PACKET_DATA_SIZE {
4383        return Err(Error::invalid_params(format!(
4384            "decoded {} too large: {} bytes (max: {} bytes)",
4385            type_name::<T>(),
4386            wire_output.len(),
4387            PACKET_DATA_SIZE
4388        )));
4389    }
4390    bincode::options()
4391        .with_limit(PACKET_DATA_SIZE as u64)
4392        .with_fixint_encoding()
4393        .allow_trailing_bytes()
4394        .deserialize_from(&wire_output[..])
4395        .map_err(|err| {
4396            Error::invalid_params(format!(
4397                "failed to deserialize {}: {}",
4398                type_name::<T>(),
4399                &err.to_string()
4400            ))
4401        })
4402        .map(|output| (wire_output, output))
4403}
4404
4405fn sanitize_transaction(
4406    transaction: VersionedTransaction,
4407    address_loader: impl AddressLoader,
4408    reserved_account_keys: &HashSet<Pubkey>,
4409    enable_static_instruction_limit: bool,
4410) -> Result<RuntimeTransaction<SanitizedTransaction>> {
4411    RuntimeTransaction::try_create(
4412        transaction,
4413        MessageHash::Compute,
4414        None,
4415        address_loader,
4416        reserved_account_keys,
4417        enable_static_instruction_limit,
4418    )
4419    .map_err(|err| Error::invalid_params(format!("invalid transaction: {err}")))
4420}
4421
4422pub fn create_validator_exit(exit: Arc<AtomicBool>) -> Arc<RwLock<Exit>> {
4423    let mut validator_exit = Exit::default();
4424    validator_exit.register_exit(Box::new(move || exit.store(true, Ordering::Relaxed)));
4425    Arc::new(RwLock::new(validator_exit))
4426}
4427
4428pub fn create_test_transaction_entries(
4429    keypairs: Vec<&Keypair>,
4430    bank: Arc<Bank>,
4431) -> (Vec<Entry>, Vec<Signature>) {
4432    let mint_keypair = keypairs[0];
4433    let keypair1 = keypairs[1];
4434    let keypair2 = keypairs[2];
4435    let keypair3 = keypairs[3];
4436    let blockhash = bank.confirmed_last_blockhash();
4437    let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
4438
4439    let mut signatures = Vec::new();
4440    // Generate transactions for processing
4441    // Successful transaction
4442    let success_tx = solana_system_transaction::transfer(
4443        mint_keypair,
4444        &keypair1.pubkey(),
4445        rent_exempt_amount,
4446        blockhash,
4447    );
4448    signatures.push(success_tx.signatures[0]);
4449    let entry_1 = solana_entry::entry::next_entry(&blockhash, 1, vec![success_tx]);
4450    // Failed transaction, InstructionError
4451    let ix_error_tx = solana_system_transaction::transfer(
4452        keypair2,
4453        &keypair3.pubkey(),
4454        2 * rent_exempt_amount,
4455        blockhash,
4456    );
4457    signatures.push(ix_error_tx.signatures[0]);
4458    let entry_2 = solana_entry::entry::next_entry(&entry_1.hash, 1, vec![ix_error_tx]);
4459    (vec![entry_1, entry_2], signatures)
4460}
4461
4462#[cfg(feature = "dev-context-only-utils")]
4463pub fn populate_blockstore_for_tests(
4464    entries: Vec<Entry>,
4465    bank: Arc<Bank>,
4466    blockstore: Arc<Blockstore>,
4467    max_complete_transaction_status_slot: Arc<AtomicU64>,
4468) {
4469    let slot = bank.slot();
4470    let parent_slot = bank.parent_slot();
4471    let shreds =
4472        solana_ledger::blockstore::entries_to_test_shreds(&entries, slot, parent_slot, true, 0);
4473    blockstore.insert_shreds(shreds, None, false).unwrap();
4474    blockstore.set_roots(std::iter::once(&slot)).unwrap();
4475
4476    let (transaction_status_sender, transaction_status_receiver) = unbounded();
4477    let (replay_vote_sender, _replay_vote_receiver) = unbounded();
4478    let tss_exit = Arc::new(AtomicBool::new(false));
4479    let transaction_status_service =
4480        crate::transaction_status_service::TransactionStatusService::new(
4481            transaction_status_receiver,
4482            max_complete_transaction_status_slot,
4483            true,
4484            None,
4485            blockstore,
4486            false,
4487            None,
4488            tss_exit.clone(),
4489        );
4490
4491    // Check that process_entries successfully writes can_commit transactions statuses, and
4492    // that they are matched properly by get_rooted_block
4493    assert_eq!(
4494        solana_ledger::blockstore_processor::process_entries_for_tests(
4495            &BankWithScheduler::new_without_scheduler(bank),
4496            entries,
4497            Some(
4498                &solana_ledger::blockstore_processor::TransactionStatusSender {
4499                    sender: transaction_status_sender,
4500                    dependency_tracker: None,
4501                },
4502            ),
4503            Some(&replay_vote_sender),
4504        ),
4505        Ok(())
4506    );
4507
4508    transaction_status_service.quiesce_and_join_for_tests(tss_exit);
4509}
4510
4511#[cfg(test)]
4512pub mod tests {
4513    use {
4514        super::{
4515            rpc_accounts::*, rpc_accounts_scan::*, rpc_bank::*, rpc_full::*, rpc_minimal::*, *,
4516        },
4517        crate::{
4518            optimistically_confirmed_bank_tracker::{
4519                BankNotification, OptimisticallyConfirmedBankTracker,
4520            },
4521            rpc_service::service_runtime,
4522            rpc_subscriptions::RpcSubscriptions,
4523        },
4524        agave_reserved_account_keys::ReservedAccountKeys,
4525        bincode::deserialize,
4526        jsonrpc_core::{futures, ErrorCode, MetaIoHandler, Output, Response, Value},
4527        jsonrpc_core_client::transports::local,
4528        serde::de::DeserializeOwned,
4529        solana_account::{state_traits::StateMut, Account, WritableAccount},
4530        solana_accounts_db::accounts_db::{AccountsDbConfig, ACCOUNTS_DB_CONFIG_FOR_TESTING},
4531        solana_address_lookup_table_interface::{
4532            self as address_lookup_table,
4533            state::{AddressLookupTable, LookupTableMeta},
4534        },
4535        solana_compute_budget_interface::ComputeBudgetInstruction,
4536        solana_entry::entry::next_versioned_entry,
4537        solana_fee_calculator::FeeRateGovernor,
4538        solana_gossip::{contact_info::ContactInfo, socketaddr},
4539        solana_instruction::{error::InstructionError, AccountMeta, Instruction},
4540        solana_keypair::Keypair,
4541        solana_ledger::{
4542            blockstore_meta::PerfSampleV2,
4543            blockstore_processor::fill_blockstore_slot_with_ticks,
4544            genesis_utils::{create_genesis_config, GenesisConfigInfo},
4545            get_tmp_ledger_path,
4546        },
4547        solana_message::{
4548            v0::{self, MessageAddressTableLookup},
4549            Message, MessageHeader, SimpleAddressLoader, VersionedMessage,
4550        },
4551        solana_nonce::{self as nonce, state::DurableNonce},
4552        solana_program_option::COption,
4553        solana_program_runtime::{
4554            invoke_context::InvokeContext,
4555            loaded_programs::ProgramCacheEntry,
4556            solana_sbpf::{declare_builtin_function, memory_region::MemoryMapping},
4557        },
4558        solana_rpc_client_api::{
4559            custom_error::{
4560                JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE,
4561                JSON_RPC_SERVER_ERROR_TRANSACTION_HISTORY_NOT_AVAILABLE,
4562                JSON_RPC_SERVER_ERROR_UNSUPPORTED_TRANSACTION_VERSION,
4563            },
4564            filter::MemcmpEncodedBytes,
4565        },
4566        solana_runtime::{
4567            bank::BankTestConfig,
4568            commitment::{BlockCommitment, CommitmentSlots},
4569            non_circulating_supply::non_circulating_accounts,
4570        },
4571        solana_sdk_ids::bpf_loader_upgradeable,
4572        solana_send_transaction_service::{
4573            tpu_info::NullTpuInfo,
4574            transaction_client::{ConnectionCacheClient, TpuClientNextClient},
4575        },
4576        solana_sha256_hasher::hash,
4577        solana_signer::Signer,
4578        solana_svm::account_loader::TRANSACTION_ACCOUNT_BASE_SIZE,
4579        solana_svm_log_collector::ic_logger_msg,
4580        solana_system_interface::{instruction as system_instruction, program as system_program},
4581        solana_system_transaction as system_transaction,
4582        solana_sysvar::slot_hashes::SlotHashes,
4583        solana_time_utils::slot_duration_from_slots_per_year,
4584        solana_transaction::{versioned::TransactionVersion, Transaction},
4585        solana_transaction_error::TransactionError,
4586        solana_transaction_status::{
4587            EncodedConfirmedBlock, EncodedTransaction, EncodedTransactionWithStatusMeta,
4588            TransactionDetails,
4589        },
4590        solana_vote_interface::state::VoteStateV4,
4591        solana_vote_program::{
4592            vote_instruction,
4593            vote_state::{TowerSync, VoteInit, VoteStateVersions, MAX_LOCKOUT_HISTORY},
4594        },
4595        spl_pod::optional_keys::OptionalNonZeroPubkey,
4596        spl_token_2022_interface::{
4597            extension::{
4598                immutable_owner::ImmutableOwner, memo_transfer::MemoTransfer,
4599                mint_close_authority::MintCloseAuthority, BaseStateWithExtensionsMut,
4600                ExtensionType, StateWithExtensionsMut,
4601            },
4602            state::{AccountState as TokenAccountState, Mint},
4603        },
4604        std::{borrow::Cow, collections::HashMap, net::Ipv4Addr},
4605        test_case::test_case,
4606    };
4607
4608    const TEST_MINT_LAMPORTS: u64 = 1_000_000_000;
4609    const TEST_SIGNATURE_FEE: u64 = 5_000;
4610    const TEST_SLOTS_PER_EPOCH: u64 = DELINQUENT_VALIDATOR_SLOT_DISTANCE + 1;
4611
4612    pub(crate) fn new_test_cluster_info() -> ClusterInfo {
4613        let keypair = Arc::new(Keypair::new());
4614        let contact_info = ContactInfo::new_localhost(
4615            &keypair.pubkey(),
4616            solana_time_utils::timestamp(), // wallclock
4617        );
4618        ClusterInfo::new(contact_info, keypair, SocketAddrSpace::Unspecified)
4619    }
4620
4621    fn create_test_request(method: &str, params: Option<serde_json::Value>) -> serde_json::Value {
4622        json!({
4623            "jsonrpc": "2.0",
4624            "id": 1u64,
4625            "method": method,
4626            "params": params,
4627        })
4628    }
4629
4630    fn parse_success_result<T: DeserializeOwned>(response: Response) -> T {
4631        if let Response::Single(output) = response {
4632            match output {
4633                Output::Success(success) => serde_json::from_value(success.result).unwrap(),
4634                Output::Failure(failure) => {
4635                    panic!("Expected success but received: {failure:?}");
4636                }
4637            }
4638        } else {
4639            panic!("Expected single response");
4640        }
4641    }
4642
4643    fn parse_failure_response(response: Response) -> (i64, String) {
4644        if let Response::Single(output) = response {
4645            match output {
4646                Output::Success(success) => {
4647                    panic!("Expected failure but received: {success:?}");
4648                }
4649                Output::Failure(failure) => (failure.error.code.code(), failure.error.message),
4650            }
4651        } else {
4652            panic!("Expected single response");
4653        }
4654    }
4655
4656    fn expected_loaded_accounts_data_size(bank: &Bank, tx: &Transaction) -> u32 {
4657        let mut loaded_accounts_data_size = 0;
4658        for key in tx.message.account_keys.iter() {
4659            if let Some(account) = bank.get_account(key) {
4660                assert!(
4661                    *account.owner() != bpf_loader_upgradeable::id(),
4662                    "LoaderV3 is not supported; to add it, parse the program account and add its \
4663                     programdata size.",
4664                );
4665                loaded_accounts_data_size +=
4666                    (account.data().len() + TRANSACTION_ACCOUNT_BASE_SIZE) as u32;
4667            }
4668        }
4669
4670        loaded_accounts_data_size
4671    }
4672
4673    fn test_builtin_processor(
4674        invoke_context: &mut InvokeContext,
4675    ) -> std::result::Result<u64, Box<dyn std::error::Error>> {
4676        let log_collector = invoke_context.get_log_collector();
4677        invoke_context.consume_checked(TestBuiltinEntrypoint::COMPUTE_UNITS)?;
4678
4679        let transaction_context = &invoke_context.transaction_context;
4680        let instruction_context = transaction_context.get_current_instruction_context()?;
4681
4682        let instruction_data = instruction_context.get_instruction_data();
4683        let (lamports, space) = {
4684            let (l_bytes, s_bytes) = instruction_data.split_at(8);
4685            let lamports = u64::from_le_bytes(l_bytes.try_into().unwrap());
4686            let space = u64::from_le_bytes(s_bytes.try_into().unwrap());
4687            (lamports, space)
4688        };
4689
4690        ic_logger_msg!(log_collector, "I am logging from a builtin program!");
4691        ic_logger_msg!(log_collector, "I am about to CPI to System!");
4692
4693        let from_pubkey = *instruction_context.get_key_of_instruction_account(0)?;
4694        let to_pubkey = *instruction_context.get_key_of_instruction_account(1)?;
4695        let owner_pubkey = *instruction_context.get_key_of_instruction_account(2)?;
4696
4697        invoke_context.native_invoke(
4698            system_instruction::create_account(
4699                &from_pubkey,
4700                &to_pubkey,
4701                lamports,
4702                space,
4703                &owner_pubkey,
4704            ),
4705            &[],
4706        )?;
4707
4708        ic_logger_msg!(log_collector, "All done!");
4709        Ok(0)
4710    }
4711
4712    declare_builtin_function!(
4713        TestBuiltinEntrypoint,
4714        fn rust(
4715            invoke_context: &mut InvokeContext,
4716            _arg0: u64,
4717            _arg1: u64,
4718            _arg2: u64,
4719            _arg3: u64,
4720            _arg4: u64,
4721            _memory_mapping: &mut MemoryMapping,
4722        ) -> std::result::Result<u64, Box<dyn std::error::Error>> {
4723            test_builtin_processor(invoke_context)
4724        }
4725    );
4726
4727    impl TestBuiltinEntrypoint {
4728        const COMPUTE_UNITS: u64 = 800;
4729        const NAME: &str = "test_builtin";
4730        const PROGRAM_ID: Pubkey =
4731            solana_pubkey::pubkey!("TestProgram11111111111111111111111111111111");
4732
4733        fn cache_entry() -> ProgramCacheEntry {
4734            ProgramCacheEntry::new_builtin(0, Self::NAME.len(), Self::vm)
4735        }
4736
4737        fn instruction(
4738            from: &Pubkey,
4739            to: &Pubkey,
4740            lamports: u64,
4741            space: u64,
4742            owner: &Pubkey,
4743        ) -> Instruction {
4744            let data = {
4745                let mut data = vec![0; 16];
4746                data[0..8].copy_from_slice(&lamports.to_le_bytes());
4747                data[8..16].copy_from_slice(&space.to_le_bytes());
4748                data
4749            };
4750            Instruction::new_with_bytes(
4751                Self::PROGRAM_ID,
4752                &data,
4753                vec![
4754                    AccountMeta::new(*from, true),
4755                    AccountMeta::new(*to, true),
4756                    AccountMeta::new_readonly(*owner, false),
4757                    AccountMeta::new_readonly(system_program::id(), false),
4758                ],
4759            )
4760        }
4761    }
4762
4763    struct RpcHandler {
4764        io: MetaIoHandler<JsonRpcRequestProcessor>,
4765        meta: JsonRpcRequestProcessor,
4766        identity: Pubkey,
4767        mint_keypair: Keypair,
4768        leader_vote_keypair: Arc<Keypair>,
4769        blockstore: Arc<Blockstore>,
4770        bank_forks: Arc<RwLock<BankForks>>,
4771        max_slots: Arc<MaxSlots>,
4772        max_complete_transaction_status_slot: Arc<AtomicU64>,
4773        block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
4774    }
4775
4776    impl RpcHandler {
4777        fn start() -> Self {
4778            Self::start_with_config(JsonRpcConfig {
4779                enable_rpc_transaction_history: true,
4780                ..JsonRpcConfig::default()
4781            })
4782        }
4783
4784        fn start_with_config(config: JsonRpcConfig) -> Self {
4785            let (bank_forks, mint_keypair, leader_vote_keypair) =
4786                new_bank_forks_with_config(BankTestConfig {
4787                    accounts_db_config: AccountsDbConfig {
4788                        account_indexes: Some(config.account_indexes.clone()),
4789                        ..ACCOUNTS_DB_CONFIG_FOR_TESTING
4790                    },
4791                });
4792
4793            let ledger_path = get_tmp_ledger_path!();
4794            let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
4795            let bank = bank_forks.read().unwrap().working_bank();
4796
4797            let leader_pubkey = *bank.collector_id();
4798            let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
4799            let exit = Arc::new(AtomicBool::new(false));
4800            let validator_exit = create_validator_exit(exit);
4801            let cluster_info = Arc::new(new_test_cluster_info());
4802            let identity = cluster_info.id();
4803            cluster_info.insert_info(ContactInfo::new_with_socketaddr(
4804                &leader_pubkey,
4805                &socketaddr!(Ipv4Addr::LOCALHOST, 1234),
4806            ));
4807            let max_slots = Arc::new(MaxSlots::default());
4808            // note that this means that slot 0 will always be considered complete
4809            let max_complete_transaction_status_slot = Arc::new(AtomicU64::new(0));
4810            let optimistically_confirmed_bank =
4811                OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
4812
4813            let JsonRpcConfig {
4814                rpc_threads,
4815                rpc_blocking_threads,
4816                rpc_niceness_adj,
4817                ..
4818            } = config;
4819            let meta = JsonRpcRequestProcessor::new(
4820                config,
4821                None,
4822                bank_forks.clone(),
4823                block_commitment_cache.clone(),
4824                blockstore.clone(),
4825                validator_exit,
4826                RpcHealth::stub(optimistically_confirmed_bank.clone(), blockstore.clone()),
4827                cluster_info,
4828                Hash::default(),
4829                None,
4830                optimistically_confirmed_bank,
4831                Arc::new(RwLock::new(LargestAccountsCache::new(30))),
4832                max_slots.clone(),
4833                Arc::new(LeaderScheduleCache::new_from_bank(&bank)),
4834                max_complete_transaction_status_slot.clone(),
4835                Arc::new(PrioritizationFeeCache::default()),
4836                service_runtime(rpc_threads, rpc_blocking_threads, rpc_niceness_adj),
4837            )
4838            .0;
4839
4840            let mut io = MetaIoHandler::default();
4841            io.extend_with(rpc_minimal::MinimalImpl.to_delegate());
4842            io.extend_with(rpc_bank::BankDataImpl.to_delegate());
4843            io.extend_with(rpc_accounts::AccountsDataImpl.to_delegate());
4844            io.extend_with(rpc_accounts_scan::AccountsScanImpl.to_delegate());
4845            io.extend_with(rpc_full::FullImpl.to_delegate());
4846            Self {
4847                io,
4848                meta,
4849                identity,
4850                mint_keypair,
4851                leader_vote_keypair,
4852                bank_forks,
4853                blockstore,
4854                max_slots,
4855                max_complete_transaction_status_slot,
4856                block_commitment_cache,
4857            }
4858        }
4859
4860        fn handle_request_sync(&self, req: serde_json::Value) -> Response {
4861            let response = &self
4862                .io
4863                .handle_request_sync(&req.to_string(), self.meta.clone())
4864                .expect("no response");
4865            serde_json::from_str(response).expect("failed to deserialize response")
4866        }
4867
4868        fn overwrite_working_bank_entries(&self, entries: Vec<Entry>) {
4869            populate_blockstore_for_tests(
4870                entries,
4871                self.working_bank(),
4872                self.blockstore.clone(),
4873                self.max_complete_transaction_status_slot.clone(),
4874            );
4875        }
4876
4877        fn create_test_transactions_and_populate_blockstore(&self) -> Vec<Signature> {
4878            let mint_keypair = &self.mint_keypair;
4879            let keypair1 = Keypair::new();
4880            let keypair2 = Keypair::new();
4881            let keypair3 = Keypair::new();
4882            let bank = self.working_bank();
4883            let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
4884            bank.transfer(
4885                rent_exempt_amount + TEST_SIGNATURE_FEE,
4886                mint_keypair,
4887                &keypair2.pubkey(),
4888            )
4889            .unwrap();
4890
4891            let (entries, signatures) = create_test_transaction_entries(
4892                vec![&self.mint_keypair, &keypair1, &keypair2, &keypair3],
4893                bank,
4894            );
4895            self.overwrite_working_bank_entries(entries);
4896            signatures
4897        }
4898
4899        fn create_test_versioned_transactions_and_populate_blockstore(
4900            &self,
4901            address_table_key: Option<Pubkey>,
4902        ) -> Vec<Signature> {
4903            let address_table_key =
4904                address_table_key.unwrap_or_else(|| self.store_address_lookup_table());
4905
4906            let bank = self.working_bank();
4907            let recent_blockhash = bank.confirmed_last_blockhash();
4908            let legacy_message = VersionedMessage::Legacy(Message {
4909                header: MessageHeader {
4910                    num_required_signatures: 1,
4911                    num_readonly_signed_accounts: 0,
4912                    num_readonly_unsigned_accounts: 0,
4913                },
4914                recent_blockhash,
4915                account_keys: vec![self.mint_keypair.pubkey()],
4916                instructions: vec![],
4917            });
4918            let version_0_message = VersionedMessage::V0(v0::Message {
4919                header: MessageHeader {
4920                    num_required_signatures: 1,
4921                    num_readonly_signed_accounts: 0,
4922                    num_readonly_unsigned_accounts: 0,
4923                },
4924                recent_blockhash,
4925                account_keys: vec![self.mint_keypair.pubkey()],
4926                address_table_lookups: vec![MessageAddressTableLookup {
4927                    account_key: address_table_key,
4928                    writable_indexes: vec![0],
4929                    readonly_indexes: vec![],
4930                }],
4931                instructions: vec![],
4932            });
4933
4934            let mut signatures = Vec::new();
4935            let legacy_tx =
4936                VersionedTransaction::try_new(legacy_message, &[&self.mint_keypair]).unwrap();
4937            signatures.push(legacy_tx.signatures[0]);
4938            let version_0_tx =
4939                VersionedTransaction::try_new(version_0_message, &[&self.mint_keypair]).unwrap();
4940            signatures.push(version_0_tx.signatures[0]);
4941            let entry1 = next_versioned_entry(&recent_blockhash, 1, vec![legacy_tx]);
4942            let entry2 = next_versioned_entry(&entry1.hash, 1, vec![version_0_tx]);
4943            let entries = vec![entry1, entry2];
4944            self.overwrite_working_bank_entries(entries);
4945            signatures
4946        }
4947
4948        fn store_address_lookup_table(&self) -> Pubkey {
4949            let bank = self.working_bank();
4950            let address_table_pubkey = Pubkey::new_unique();
4951            let address_table_account = {
4952                let address_table_state = AddressLookupTable {
4953                    meta: LookupTableMeta {
4954                        // ensure that active address length is 1 at slot 0
4955                        last_extended_slot_start_index: 1,
4956                        ..LookupTableMeta::default()
4957                    },
4958                    addresses: Cow::Owned(vec![Pubkey::new_unique()]),
4959                };
4960                let address_table_data = address_table_state.serialize_for_tests().unwrap();
4961                let min_balance_lamports =
4962                    bank.get_minimum_balance_for_rent_exemption(address_table_data.len());
4963                AccountSharedData::create(
4964                    min_balance_lamports,
4965                    address_table_data,
4966                    address_lookup_table::program::id(),
4967                    false,
4968                    0,
4969                )
4970            };
4971            bank.store_account(&address_table_pubkey, &address_table_account);
4972            address_table_pubkey
4973        }
4974
4975        fn add_roots_to_blockstore(&self, mut roots: Vec<Slot>) {
4976            roots.retain(|&slot| slot > 0);
4977            if roots.is_empty() {
4978                return;
4979            }
4980
4981            let mut parent_bank = self.bank_forks.read().unwrap().working_bank();
4982            for (i, root) in roots.iter().enumerate() {
4983                let new_bank =
4984                    Bank::new_from_parent(parent_bank.clone(), parent_bank.collector_id(), *root);
4985                parent_bank = self
4986                    .bank_forks
4987                    .write()
4988                    .unwrap()
4989                    .insert(new_bank)
4990                    .clone_without_scheduler();
4991                let parent = if i > 0 { roots[i - 1] } else { 0 };
4992                fill_blockstore_slot_with_ticks(
4993                    &self.blockstore,
4994                    5,
4995                    *root,
4996                    parent,
4997                    Hash::default(),
4998                );
4999            }
5000            self.blockstore.set_roots(roots.iter()).unwrap();
5001            let new_bank = Bank::new_from_parent(
5002                parent_bank.clone(),
5003                parent_bank.collector_id(),
5004                roots.iter().max().unwrap() + 1,
5005            );
5006            self.bank_forks.write().unwrap().insert(new_bank);
5007
5008            for root in roots.iter() {
5009                self.bank_forks
5010                    .write()
5011                    .unwrap()
5012                    .set_root(*root, None, Some(0));
5013                let block_time = self
5014                    .bank_forks
5015                    .read()
5016                    .unwrap()
5017                    .get(*root)
5018                    .unwrap()
5019                    .clock()
5020                    .unix_timestamp;
5021                self.blockstore.set_block_time(*root, block_time).unwrap();
5022            }
5023        }
5024
5025        fn advance_bank_to_confirmed_slot(&self, slot: Slot) -> Arc<Bank> {
5026            let parent_bank = self.working_bank();
5027            let bank = self
5028                .bank_forks
5029                .write()
5030                .unwrap()
5031                .insert(Bank::new_from_parent(parent_bank, &Pubkey::default(), slot))
5032                .clone_without_scheduler();
5033
5034            let new_block_commitment = BlockCommitmentCache::new(
5035                HashMap::new(),
5036                0,
5037                CommitmentSlots::new_from_slot(self.bank_forks.read().unwrap().highest_slot()),
5038            );
5039            *self.block_commitment_cache.write().unwrap() = new_block_commitment;
5040            bank
5041        }
5042
5043        fn store_vote_account(&self, vote_pubkey: &Pubkey, vote_state: VoteStateV4) {
5044            let bank = self.working_bank();
5045            let versioned = VoteStateVersions::new_v4(vote_state);
5046            let space = VoteStateV4::size_of();
5047            let balance = bank.get_minimum_balance_for_rent_exemption(space);
5048            let mut vote_account =
5049                AccountSharedData::new(balance, space, &solana_vote_program::id());
5050            vote_account.set_state(&versioned).unwrap();
5051            bank.store_account(vote_pubkey, &vote_account);
5052        }
5053
5054        fn update_prioritization_fee_cache(&self, transactions: Vec<Transaction>) {
5055            let bank = self.working_bank();
5056
5057            let transactions: Vec<_> = transactions
5058                .into_iter()
5059                .map(RuntimeTransaction::from_transaction_for_tests)
5060                .collect();
5061
5062            let prioritization_fee_cache = &self.meta.prioritization_fee_cache;
5063            prioritization_fee_cache.update(&bank, transactions.iter());
5064        }
5065
5066        fn get_prioritization_fee_cache(&self) -> &PrioritizationFeeCache {
5067            &self.meta.prioritization_fee_cache
5068        }
5069
5070        fn working_bank(&self) -> Arc<Bank> {
5071            self.bank_forks.read().unwrap().working_bank()
5072        }
5073
5074        fn leader_pubkey(&self) -> Pubkey {
5075            *self.working_bank().collector_id()
5076        }
5077    }
5078
5079    fn rpc_request_processor_new<Client: ClientWithCreator>() {
5080        let bob_pubkey = solana_pubkey::new_rand();
5081        let genesis = create_genesis_config(100);
5082        let bank = Bank::new_for_tests(&genesis.genesis_config);
5083        let meta =
5084            JsonRpcRequestProcessor::new_from_bank::<Client>(bank, SocketAddrSpace::Unspecified);
5085
5086        let bank = meta.bank_forks.read().unwrap().root_bank();
5087        bank.transfer(20, &genesis.mint_keypair, &bob_pubkey)
5088            .unwrap();
5089
5090        assert_eq!(
5091            meta.get_transaction_count(RpcContextConfig::default())
5092                .unwrap(),
5093            1
5094        );
5095    }
5096
5097    // we cannot use async tests because the JsonRpcRequestProcessor owns runtime
5098    #[test]
5099    fn test_rpc_request_processor_new_connection_cache() {
5100        rpc_request_processor_new::<ConnectionCacheClient<NullTpuInfo>>();
5101    }
5102
5103    #[test]
5104    fn test_rpc_request_processor_new_tpu_client_next() {
5105        rpc_request_processor_new::<TpuClientNextClient>();
5106    }
5107
5108    fn rpc_get_balance<Client: ClientWithCreator>() {
5109        let genesis = create_genesis_config(20);
5110        let mint_pubkey = genesis.mint_keypair.pubkey();
5111        let bank = Bank::new_for_tests(&genesis.genesis_config);
5112        let meta =
5113            JsonRpcRequestProcessor::new_from_bank::<Client>(bank, SocketAddrSpace::Unspecified);
5114
5115        let mut io = MetaIoHandler::default();
5116        io.extend_with(rpc_minimal::MinimalImpl.to_delegate());
5117
5118        let req = format!(
5119            r#"{{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["{mint_pubkey}"]}}"#
5120        );
5121        let res = io.handle_request_sync(&req, meta);
5122        let expected = json!({
5123            "jsonrpc": "2.0",
5124            "result": {
5125                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
5126                "value":20,
5127                },
5128            "id": 1,
5129        });
5130        let result = serde_json::from_str::<Value>(&res.expect("actual response"))
5131            .expect("actual response deserialization");
5132        assert_eq!(result, expected);
5133    }
5134
5135    #[test]
5136    fn test_rpc_get_balance_new_connection_cache() {
5137        rpc_get_balance::<ConnectionCacheClient<NullTpuInfo>>();
5138    }
5139
5140    #[test]
5141    fn test_rpc_get_balance_new_tpu_client_next() {
5142        rpc_get_balance::<TpuClientNextClient>();
5143    }
5144
5145    fn rpc_get_balance_via_client<Client: ClientWithCreator>() {
5146        let genesis = create_genesis_config(20);
5147        let mint_pubkey = genesis.mint_keypair.pubkey();
5148        let bank = Bank::new_for_tests(&genesis.genesis_config);
5149        let meta =
5150            JsonRpcRequestProcessor::new_from_bank::<Client>(bank, SocketAddrSpace::Unspecified);
5151
5152        let mut io = MetaIoHandler::default();
5153        io.extend_with(rpc_minimal::MinimalImpl.to_delegate());
5154
5155        async fn use_client(client: rpc_minimal::gen_client::Client, mint_pubkey: Pubkey) -> u64 {
5156            client
5157                .get_balance(mint_pubkey.to_string(), None)
5158                .await
5159                .unwrap()
5160                .value
5161        }
5162
5163        let fut = async {
5164            let (client, server) =
5165                local::connect_with_metadata::<rpc_minimal::gen_client::Client, _, _>(&io, meta);
5166            let client = use_client(client, mint_pubkey);
5167
5168            futures::join!(client, server)
5169        };
5170        let (response, _) = futures::executor::block_on(fut);
5171        assert_eq!(response, 20);
5172    }
5173
5174    #[test]
5175    fn test_rpc_get_balance_via_client_connection_cache() {
5176        rpc_get_balance_via_client::<ConnectionCacheClient<NullTpuInfo>>();
5177    }
5178
5179    #[test]
5180    fn test_rpc_get_balance_via_client_tpu_client_next() {
5181        rpc_get_balance_via_client::<TpuClientNextClient>();
5182    }
5183
5184    #[test]
5185    fn test_rpc_get_cluster_nodes() {
5186        let rpc = RpcHandler::start();
5187        let version = solana_version::Version::default();
5188        let request = create_test_request("getClusterNodes", None);
5189        let result: Value = parse_success_result(rpc.handle_request_sync(request));
5190        let expected = json!([{
5191            "pubkey": rpc.identity.to_string(),
5192            "gossip": "127.0.0.1:8000",
5193            "shredVersion": 0u16,
5194            "tvu": "127.0.0.1:8001",
5195            "tpu": "127.0.0.1:8003",
5196            "tpuQuic": "127.0.0.1:8009",
5197            "tpuForwards": "127.0.0.1:8004",
5198            "tpuForwardsQuic": "127.0.0.1:8010",
5199            "tpuVote": "127.0.0.1:8005",
5200            "serveRepair": "127.0.0.1:8008",
5201            "rpc": format!("127.0.0.1:8899"),
5202            "pubsub": format!("127.0.0.1:8900"),
5203            "version": format!("{version}"),
5204            "featureSet": version.feature_set,
5205        }, {
5206            "pubkey": rpc.leader_pubkey().to_string(),
5207            "gossip": "127.0.0.1:1235",
5208            "shredVersion": 0u16,
5209            "tvu": "127.0.0.1:1236",
5210            "tpu": "127.0.0.1:1234",
5211            "tpuQuic": "127.0.0.1:1240",
5212            "tpuForwards": "127.0.0.1:1239",
5213            "tpuForwardsQuic": "127.0.0.1:1245",
5214            "tpuVote": "127.0.0.1:1241",
5215            "serveRepair": "127.0.0.1:1242",
5216            "rpc": format!("127.0.0.1:8899"),
5217            "pubsub": format!("127.0.0.1:8900"),
5218            "version": format!("{version}"),
5219            "featureSet": version.feature_set,
5220        }]);
5221        assert_eq!(result, expected);
5222    }
5223
5224    #[test]
5225    fn test_rpc_get_recent_performance_samples() {
5226        let rpc = RpcHandler::start();
5227
5228        let slot = 0;
5229        let num_slots = 1;
5230        let num_transactions = 4;
5231        let num_non_vote_transactions = 1;
5232        let sample_period_secs = 60;
5233        rpc.blockstore
5234            .write_perf_sample(
5235                slot,
5236                &PerfSampleV2 {
5237                    num_slots,
5238                    num_transactions,
5239                    num_non_vote_transactions,
5240                    sample_period_secs,
5241                },
5242            )
5243            .expect("write to blockstore");
5244
5245        let request = create_test_request("getRecentPerformanceSamples", None);
5246        let result: Value = parse_success_result(rpc.handle_request_sync(request));
5247        let expected = json!([{
5248            "slot": slot,
5249            "numSlots": num_slots,
5250            "numTransactions": num_transactions,
5251            "numNonVoteTransactions": num_non_vote_transactions,
5252            "samplePeriodSecs": sample_period_secs,
5253        }]);
5254        assert_eq!(result, expected);
5255    }
5256
5257    #[test]
5258    fn test_rpc_get_recent_performance_samples_invalid_limit() {
5259        let rpc = RpcHandler::start();
5260        let request = create_test_request("getRecentPerformanceSamples", Some(json!([10_000])));
5261        let response = parse_failure_response(rpc.handle_request_sync(request));
5262        let expected = (
5263            ErrorCode::InvalidParams.code(),
5264            String::from("Invalid limit; max 720"),
5265        );
5266        assert_eq!(response, expected);
5267    }
5268
5269    #[test]
5270    fn test_rpc_get_slot_leader() {
5271        let rpc = RpcHandler::start();
5272        let request = create_test_request("getSlotLeader", None);
5273        let result: String = parse_success_result(rpc.handle_request_sync(request));
5274        let expected = rpc.leader_pubkey().to_string();
5275        assert_eq!(result, expected);
5276    }
5277
5278    fn rpc_get_tx_count<Client: ClientWithCreator>() {
5279        let bob_pubkey = solana_pubkey::new_rand();
5280        let genesis = create_genesis_config(10);
5281        let bank = Bank::new_for_tests(&genesis.genesis_config);
5282        let meta =
5283            JsonRpcRequestProcessor::new_from_bank::<Client>(bank, SocketAddrSpace::Unspecified);
5284
5285        let mut io = MetaIoHandler::default();
5286        io.extend_with(rpc_minimal::MinimalImpl.to_delegate());
5287
5288        // Add 4 transactions
5289        let bank = meta.bank_forks.read().unwrap().root_bank();
5290        bank.transfer(1, &genesis.mint_keypair, &bob_pubkey)
5291            .unwrap();
5292        bank.transfer(2, &genesis.mint_keypair, &bob_pubkey)
5293            .unwrap();
5294        bank.transfer(3, &genesis.mint_keypair, &bob_pubkey)
5295            .unwrap();
5296        bank.transfer(4, &genesis.mint_keypair, &bob_pubkey)
5297            .unwrap();
5298
5299        let req = r#"{"jsonrpc":"2.0","id":1,"method":"getTransactionCount"}"#;
5300        let res = io.handle_request_sync(req, meta);
5301        let expected = r#"{"jsonrpc":"2.0","result":4,"id":1}"#;
5302        let expected: Response =
5303            serde_json::from_str(expected).expect("expected response deserialization");
5304        let result: Response = serde_json::from_str(&res.expect("actual response"))
5305            .expect("actual response deserialization");
5306        assert_eq!(result, expected);
5307    }
5308
5309    #[test]
5310    fn test_rpc_get_tx_count_connection_cache() {
5311        rpc_get_tx_count::<ConnectionCacheClient<NullTpuInfo>>();
5312    }
5313
5314    #[test]
5315    fn test_rpc_get_tx_count_tpu_client_next() {
5316        rpc_get_tx_count::<TpuClientNextClient>();
5317    }
5318
5319    #[test]
5320    fn test_rpc_minimum_ledger_slot() {
5321        let rpc = RpcHandler::start();
5322        // populate blockstore so that a minimum slot can be detected
5323        rpc.create_test_transactions_and_populate_blockstore();
5324        let request = create_test_request("minimumLedgerSlot", None);
5325        let result: Slot = parse_success_result(rpc.handle_request_sync(request));
5326        assert_eq!(0, result);
5327    }
5328
5329    #[test]
5330    fn test_get_supply() {
5331        let rpc = RpcHandler::start();
5332        let request = create_test_request("getSupply", None);
5333        let result = {
5334            let mut result: RpcResponse<RpcSupply> =
5335                parse_success_result(rpc.handle_request_sync(request));
5336            result.value.non_circulating_accounts.sort();
5337            result.value
5338        };
5339        let expected = {
5340            let mut non_circulating_accounts: Vec<String> = non_circulating_accounts()
5341                .iter()
5342                .map(|pubkey| pubkey.to_string())
5343                .collect();
5344            non_circulating_accounts.sort();
5345            let total_capitalization = rpc.working_bank().capitalization();
5346            RpcSupply {
5347                non_circulating: 0,
5348                circulating: total_capitalization,
5349                total: total_capitalization,
5350                non_circulating_accounts,
5351            }
5352        };
5353        assert_eq!(result, expected);
5354    }
5355
5356    #[test]
5357    fn test_get_supply_exclude_account_list() {
5358        let rpc = RpcHandler::start();
5359        let request = create_test_request(
5360            "getSupply",
5361            Some(json!([{"excludeNonCirculatingAccountsList": true}])),
5362        );
5363        let result: RpcResponse<RpcSupply> = parse_success_result(rpc.handle_request_sync(request));
5364        let expected = {
5365            let total_capitalization = rpc.working_bank().capitalization();
5366            RpcSupply {
5367                non_circulating: 0,
5368                circulating: total_capitalization,
5369                total: total_capitalization,
5370                non_circulating_accounts: vec![],
5371            }
5372        };
5373        assert_eq!(result.value, expected);
5374    }
5375
5376    #[test]
5377    fn test_get_largest_accounts() {
5378        let rpc = RpcHandler::start();
5379
5380        // make a non-circulating account one of the largest accounts
5381        let non_circulating_key = &non_circulating_accounts()[0];
5382        let bank = rpc.working_bank();
5383        bank.process_transaction(&system_transaction::transfer(
5384            &rpc.mint_keypair,
5385            non_circulating_key,
5386            500_000,
5387            bank.confirmed_last_blockhash(),
5388        ))
5389        .expect("process transaction");
5390
5391        let request = create_test_request("getLargestAccounts", None);
5392        let largest_accounts_result: RpcResponse<Vec<RpcAccountBalance>> =
5393            parse_success_result(rpc.handle_request_sync(request));
5394        assert_eq!(largest_accounts_result.value.len(), 20);
5395
5396        // Get mint balance
5397        let request = create_test_request(
5398            "getBalance",
5399            Some(json!([rpc.mint_keypair.pubkey().to_string()])),
5400        );
5401        let mint_balance_result: RpcResponse<u64> =
5402            parse_success_result(rpc.handle_request_sync(request));
5403        assert!(largest_accounts_result.value.contains(&RpcAccountBalance {
5404            address: rpc.mint_keypair.pubkey().to_string(),
5405            lamports: mint_balance_result.value,
5406        }));
5407
5408        // Get non-circulating account balance
5409        let request =
5410            create_test_request("getBalance", Some(json!([non_circulating_key.to_string()])));
5411        let non_circulating_balance_result: RpcResponse<u64> =
5412            parse_success_result(rpc.handle_request_sync(request));
5413        assert!(largest_accounts_result.value.contains(&RpcAccountBalance {
5414            address: non_circulating_key.to_string(),
5415            lamports: non_circulating_balance_result.value,
5416        }));
5417
5418        // Test Circulating/NonCirculating Filter
5419        let request = create_test_request(
5420            "getLargestAccounts",
5421            Some(json!([{"filter":"circulating"}])),
5422        );
5423        let largest_accounts_result: RpcResponse<Vec<RpcAccountBalance>> =
5424            parse_success_result(rpc.handle_request_sync(request));
5425        assert_eq!(largest_accounts_result.value.len(), 20);
5426        assert!(!largest_accounts_result.value.contains(&RpcAccountBalance {
5427            address: non_circulating_key.to_string(),
5428            lamports: non_circulating_balance_result.value,
5429        }));
5430
5431        let request = create_test_request(
5432            "getLargestAccounts",
5433            Some(json!([{"filter":"nonCirculating"}])),
5434        );
5435        let largest_accounts_result: RpcResponse<Vec<RpcAccountBalance>> =
5436            parse_success_result(rpc.handle_request_sync(request));
5437        assert_eq!(largest_accounts_result.value.len(), 1);
5438        assert!(largest_accounts_result.value.contains(&RpcAccountBalance {
5439            address: non_circulating_key.to_string(),
5440            lamports: non_circulating_balance_result.value,
5441        }));
5442    }
5443
5444    #[test]
5445    fn test_rpc_get_minimum_balance_for_rent_exemption() {
5446        let rpc = RpcHandler::start();
5447        let data_len = 50;
5448        let request =
5449            create_test_request("getMinimumBalanceForRentExemption", Some(json!([data_len])));
5450        let result: u64 = parse_success_result(rpc.handle_request_sync(request));
5451        let expected = rpc
5452            .working_bank()
5453            .get_minimum_balance_for_rent_exemption(data_len);
5454        assert_eq!(result, expected);
5455    }
5456
5457    #[test]
5458    fn test_rpc_get_inflation() {
5459        let rpc = RpcHandler::start();
5460        let bank = rpc.working_bank();
5461        let request = create_test_request("getInflationGovernor", None);
5462        let result: RpcInflationGovernor = parse_success_result(rpc.handle_request_sync(request));
5463        let expected: RpcInflationGovernor = bank.inflation().into();
5464        assert_eq!(result, expected);
5465
5466        // Query inflation rate for current epoch
5467        let request = create_test_request("getInflationRate", None);
5468        let result: RpcInflationRate = parse_success_result(rpc.handle_request_sync(request));
5469        let inflation = bank.inflation();
5470        let epoch = bank.epoch();
5471        let slot_in_year = bank.slot_in_year_for_inflation();
5472        let expected = RpcInflationRate {
5473            total: inflation.total(slot_in_year),
5474            validator: inflation.validator(slot_in_year),
5475            foundation: inflation.foundation(slot_in_year),
5476            epoch,
5477        };
5478        assert_eq!(result, expected);
5479    }
5480
5481    #[test]
5482    fn test_rpc_get_epoch_schedule() {
5483        let rpc = RpcHandler::start();
5484        let bank = rpc.working_bank();
5485        let request = create_test_request("getEpochSchedule", None);
5486        let result: EpochSchedule = parse_success_result(rpc.handle_request_sync(request));
5487        let expected = bank.epoch_schedule();
5488        assert_eq!(expected, &result);
5489    }
5490
5491    #[test]
5492    fn test_rpc_get_leader_schedule() {
5493        let rpc = RpcHandler::start();
5494
5495        for params in [
5496            None,
5497            Some(json!([0u64])),
5498            Some(json!([null, {"identity": rpc.leader_pubkey().to_string()}])),
5499            Some(json!([{"identity": rpc.leader_pubkey().to_string()}])),
5500        ] {
5501            let request = create_test_request("getLeaderSchedule", params);
5502            let result: Option<RpcLeaderSchedule> =
5503                parse_success_result(rpc.handle_request_sync(request));
5504            let expected = Some(HashMap::from_iter(std::iter::once((
5505                rpc.leader_pubkey().to_string(),
5506                Vec::from_iter(0..=128),
5507            ))));
5508            assert_eq!(result, expected);
5509        }
5510
5511        let request = create_test_request("getLeaderSchedule", Some(json!([42424242])));
5512        let result: Option<RpcLeaderSchedule> =
5513            parse_success_result(rpc.handle_request_sync(request));
5514        let expected: Option<RpcLeaderSchedule> = None;
5515        assert_eq!(result, expected);
5516
5517        let request = create_test_request(
5518            "getLeaderSchedule",
5519            Some(json!([{"identity": Pubkey::new_unique().to_string() }])),
5520        );
5521        let result: Option<RpcLeaderSchedule> =
5522            parse_success_result(rpc.handle_request_sync(request));
5523        let expected = Some(HashMap::default());
5524        assert_eq!(result, expected);
5525    }
5526
5527    #[test]
5528    fn test_rpc_get_slot_leaders() {
5529        let rpc = RpcHandler::start();
5530        let bank = rpc.working_bank();
5531
5532        // Test that slot leaders will be returned across epochs
5533        let query_start = 0;
5534        let query_limit = 2 * bank.epoch_schedule().slots_per_epoch;
5535
5536        let request =
5537            create_test_request("getSlotLeaders", Some(json!([query_start, query_limit])));
5538        let result: Vec<String> = parse_success_result(rpc.handle_request_sync(request));
5539        assert_eq!(result.len(), query_limit as usize);
5540
5541        // Test that invalid limit returns an error
5542        let query_start = 0;
5543        let query_limit = 5001;
5544
5545        let request =
5546            create_test_request("getSlotLeaders", Some(json!([query_start, query_limit])));
5547        let response = parse_failure_response(rpc.handle_request_sync(request));
5548        let expected = (
5549            ErrorCode::InvalidParams.code(),
5550            String::from("Invalid limit; max 5000"),
5551        );
5552        assert_eq!(response, expected);
5553
5554        // Test that invalid epoch returns an error
5555        let query_start = 2 * bank.epoch_schedule().slots_per_epoch;
5556        let query_limit = 10;
5557
5558        let request =
5559            create_test_request("getSlotLeaders", Some(json!([query_start, query_limit])));
5560        let response = parse_failure_response(rpc.handle_request_sync(request));
5561        let expected = (
5562            ErrorCode::InvalidParams.code(),
5563            String::from("Invalid slot range: leader schedule for epoch 2 is unavailable"),
5564        );
5565        assert_eq!(response, expected);
5566    }
5567
5568    #[test]
5569    fn test_rpc_get_account_info() {
5570        let rpc = RpcHandler::start();
5571        let bank = rpc.working_bank();
5572
5573        let request = create_test_request(
5574            "getAccountInfo",
5575            Some(json!([rpc.mint_keypair.pubkey().to_string()])),
5576        );
5577        let result: Value = parse_success_result(rpc.handle_request_sync(request));
5578        let expected = json!({
5579            "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
5580            "value":{
5581                "owner": "11111111111111111111111111111111",
5582                "lamports": TEST_MINT_LAMPORTS,
5583                "data": "",
5584                "executable": false,
5585                "rentEpoch": 0,
5586                "space": 0,
5587            },
5588        });
5589        assert_eq!(result, expected);
5590
5591        let pubkey = Pubkey::new_unique();
5592        let address = pubkey.to_string();
5593        let data = vec![1, 2, 3, 4, 5];
5594        let account = AccountSharedData::create(42, data.clone(), Pubkey::default(), false, 0);
5595        bank.store_account(&pubkey, &account);
5596
5597        let request = create_test_request(
5598            "getAccountInfo",
5599            Some(json!([address, {"encoding": "base64"}])),
5600        );
5601        let result: Value = parse_success_result(rpc.handle_request_sync(request));
5602        let expected = json!([BASE64_STANDARD.encode(&data), "base64"]);
5603        assert_eq!(result["value"]["data"], expected);
5604        assert_eq!(result["value"]["space"], 5);
5605
5606        let request = create_test_request(
5607            "getAccountInfo",
5608            Some(json!([address, {"encoding": "base64", "dataSlice": {"length": 2, "offset": 1}}])),
5609        );
5610        let result: Value = parse_success_result(rpc.handle_request_sync(request));
5611        let expected = json!([BASE64_STANDARD.encode(&data[1..3]), "base64"]);
5612        assert_eq!(result["value"]["data"], expected);
5613        assert_eq!(result["value"]["space"], 5);
5614
5615        let request = create_test_request(
5616            "getAccountInfo",
5617            Some(json!([address, {"encoding": "binary", "dataSlice": {"length": 2, "offset": 1}}])),
5618        );
5619        let result: Value = parse_success_result(rpc.handle_request_sync(request));
5620        let expected = bs58::encode(&data[1..3]).into_string();
5621        assert_eq!(result["value"]["data"], expected);
5622        assert_eq!(result["value"]["space"], 5);
5623
5624        let request = create_test_request(
5625            "getAccountInfo",
5626            Some(
5627                json!([address, {"encoding": "jsonParsed", "dataSlice": {"length": 2, "offset": 1}}]),
5628            ),
5629        );
5630        let result: Value = parse_success_result(rpc.handle_request_sync(request));
5631        let expected = json!([BASE64_STANDARD.encode(&data[1..3]), "base64"]);
5632        assert_eq!(
5633            result["value"]["data"], expected,
5634            "should use data slice if parsing fails"
5635        );
5636    }
5637
5638    #[test]
5639    fn test_encode_account_does_not_throw_when_slice_larger_than_account() {
5640        let data = vec![42; 5];
5641        let pubkey = Pubkey::new_unique();
5642        let account = AccountSharedData::create(42, data, pubkey, false, 0);
5643        let result = encode_account(
5644            &account,
5645            &pubkey,
5646            UiAccountEncoding::Base58,
5647            Some(UiDataSliceConfig {
5648                length: account.data().len() + 1,
5649                offset: 0,
5650            }),
5651        );
5652        assert!(result.is_ok());
5653    }
5654    #[test]
5655    #[should_panic(expected = "should be less than 128 bytes")] // If ever `MAX_BASE58_BYTES` changes, the expected error message will need to be updated.
5656    fn test_encode_account_throws_when_data_too_large_to_base58_encode() {
5657        let data = vec![42; MAX_BASE58_BYTES + 1];
5658        let pubkey = Pubkey::new_unique();
5659        let account = AccountSharedData::create(42, data, pubkey, false, 0);
5660        let _ = encode_account(&account, &pubkey, UiAccountEncoding::Base58, None).unwrap();
5661    }
5662
5663    #[test]
5664    fn test_encode_account_does_not_throw_despite_data_too_large_to_base58_encode_because_dataslice_makes_it_fit(
5665    ) {
5666        let data = vec![42; MAX_BASE58_BYTES + 1];
5667        let pubkey = Pubkey::new_unique();
5668        let account = AccountSharedData::create(42, data, pubkey, false, 0);
5669        let result = encode_account(
5670            &account,
5671            &pubkey,
5672            UiAccountEncoding::Base58,
5673            Some(UiDataSliceConfig {
5674                length: MAX_BASE58_BYTES,
5675                offset: 1,
5676            }),
5677        );
5678        assert!(result.is_ok());
5679    }
5680
5681    #[test]
5682    fn test_encode_account_does_not_throw_despite_dataslice_being_too_large_to_base58_encode_because_account_is_small_enough_to_fit(
5683    ) {
5684        let data = vec![42; MAX_BASE58_BYTES];
5685        let pubkey = Pubkey::new_unique();
5686        let account = AccountSharedData::create(42, data, pubkey, false, 0);
5687        let result = encode_account(
5688            &account,
5689            &pubkey,
5690            UiAccountEncoding::Base58,
5691            Some(UiDataSliceConfig {
5692                length: MAX_BASE58_BYTES + 1,
5693                offset: 0,
5694            }),
5695        );
5696        assert!(result.is_ok());
5697    }
5698
5699    #[test]
5700    fn test_encode_account_does_not_throw_despite_account_and_dataslice_being_too_large_to_base58_encode_because_their_intersection_fits(
5701    ) {
5702        let data = vec![42; MAX_BASE58_BYTES + 1];
5703        let pubkey = Pubkey::new_unique();
5704        let account = AccountSharedData::create(42, data, pubkey, false, 0);
5705        let result = encode_account(
5706            &account,
5707            &pubkey,
5708            UiAccountEncoding::Base58,
5709            Some(UiDataSliceConfig {
5710                length: MAX_BASE58_BYTES + 1,
5711                offset: 1,
5712            }),
5713        );
5714        assert!(result.is_ok());
5715    }
5716
5717    #[test]
5718    fn test_rpc_get_multiple_accounts() {
5719        let rpc = RpcHandler::start();
5720        let bank = rpc.working_bank();
5721
5722        let non_existent_pubkey = Pubkey::new_unique();
5723        let pubkey = Pubkey::new_unique();
5724        let address = pubkey.to_string();
5725        let data = vec![1, 2, 3, 4, 5];
5726        let account = AccountSharedData::create(42, data.clone(), Pubkey::default(), false, 0);
5727        bank.store_account(&pubkey, &account);
5728
5729        // Test 3 accounts, one empty, one non-existent, and one with data
5730        let request = create_test_request(
5731            "getMultipleAccounts",
5732            Some(json!([[
5733                rpc.mint_keypair.pubkey().to_string(),
5734                non_existent_pubkey.to_string(),
5735                address,
5736            ]])),
5737        );
5738        let result: RpcResponse<Value> = parse_success_result(rpc.handle_request_sync(request));
5739        let expected = json!([
5740            {
5741                "owner": "11111111111111111111111111111111",
5742                "lamports": TEST_MINT_LAMPORTS,
5743                "data": ["", "base64"],
5744                "executable": false,
5745                "rentEpoch": 0,
5746                "space": 0,
5747            },
5748            null,
5749            {
5750                "owner": "11111111111111111111111111111111",
5751                "lamports": 42,
5752                "data": [BASE64_STANDARD.encode(&data), "base64"],
5753                "executable": false,
5754                "rentEpoch": 0,
5755                "space": 5,
5756            }
5757        ]);
5758        assert_eq!(result.value, expected);
5759
5760        // Test config settings still work with multiple accounts
5761        let request = create_test_request(
5762            "getMultipleAccounts",
5763            Some(json!([
5764                [
5765                    rpc.mint_keypair.pubkey().to_string(),
5766                    non_existent_pubkey.to_string(),
5767                    address,
5768                ],
5769                {"encoding": "base58"},
5770            ])),
5771        );
5772        let result: RpcResponse<Value> = parse_success_result(rpc.handle_request_sync(request));
5773        let expected = json!([
5774            {
5775                "owner": "11111111111111111111111111111111",
5776                "lamports": TEST_MINT_LAMPORTS,
5777                "data": ["", "base58"],
5778                "executable": false,
5779                "rentEpoch": 0,
5780                "space": 0,
5781            },
5782            null,
5783            {
5784                "owner": "11111111111111111111111111111111",
5785                "lamports": 42,
5786                "data": [bs58::encode(&data).into_string(), "base58"],
5787                "executable": false,
5788                "rentEpoch": 0,
5789                "space": 5,
5790            }
5791        ]);
5792        assert_eq!(result.value, expected);
5793
5794        let request = create_test_request(
5795            "getMultipleAccounts",
5796            Some(json!([
5797                [
5798                    rpc.mint_keypair.pubkey().to_string(),
5799                    non_existent_pubkey.to_string(),
5800                    address,
5801                ],
5802                {"encoding": "jsonParsed", "dataSlice": {"length": 2, "offset": 1}},
5803            ])),
5804        );
5805        let result: RpcResponse<Value> = parse_success_result(rpc.handle_request_sync(request));
5806        let expected = json!([
5807            {
5808                "owner": "11111111111111111111111111111111",
5809                "lamports": TEST_MINT_LAMPORTS,
5810                "data": ["", "base64"],
5811                "executable": false,
5812                "rentEpoch": 0,
5813                "space": 0,
5814            },
5815            null,
5816            {
5817                "owner": "11111111111111111111111111111111",
5818                "lamports": 42,
5819                "data": [BASE64_STANDARD.encode(&data[1..3]), "base64"],
5820                "executable": false,
5821                "rentEpoch": 0,
5822                "space": 5,
5823            }
5824        ]);
5825        assert_eq!(
5826            result.value, expected,
5827            "should use data slice if parsing fails"
5828        );
5829    }
5830
5831    #[test]
5832    fn test_rpc_get_program_accounts() {
5833        let rpc = RpcHandler::start();
5834        let bank = rpc.working_bank();
5835
5836        let new_program_id = Pubkey::new_unique();
5837        let new_program_account_key = Pubkey::new_unique();
5838        let new_program_account = AccountSharedData::new(42, 0, &new_program_id);
5839        bank.store_account(&new_program_account_key, &new_program_account);
5840
5841        let request = create_test_request(
5842            "getProgramAccounts",
5843            Some(json!([new_program_id.to_string()])),
5844        );
5845        let result: Vec<RpcKeyedAccount> = parse_success_result(rpc.handle_request_sync(request));
5846        let expected_value = vec![RpcKeyedAccount {
5847            pubkey: new_program_account_key.to_string(),
5848            account: encode_ui_account(
5849                &new_program_account_key,
5850                &new_program_account,
5851                UiAccountEncoding::Binary,
5852                None,
5853                None,
5854            ),
5855        }];
5856        assert_eq!(result, expected_value);
5857
5858        // Test returns context
5859        let request = create_test_request(
5860            "getProgramAccounts",
5861            Some(json!([
5862                new_program_id.to_string(),
5863                {"withContext": true},
5864            ])),
5865        );
5866        let result: RpcResponse<Vec<RpcKeyedAccount>> =
5867            parse_success_result(rpc.handle_request_sync(request));
5868        let expected = RpcResponse {
5869            context: RpcResponseContext::new(0),
5870            value: expected_value,
5871        };
5872        assert_eq!(result, expected);
5873
5874        // Set up nonce accounts to test filters
5875        let nonce_authorities = (0..2)
5876            .map(|_| {
5877                let pubkey = Pubkey::new_unique();
5878                let authority = Pubkey::new_unique();
5879                let account = AccountSharedData::new_data(
5880                    42,
5881                    &nonce::versions::Versions::new(nonce::state::State::new_initialized(
5882                        &authority,
5883                        DurableNonce::default(),
5884                        1000,
5885                    )),
5886                    &system_program::id(),
5887                )
5888                .unwrap();
5889                bank.store_account(&pubkey, &account);
5890                authority
5891            })
5892            .collect::<Vec<_>>();
5893
5894        // Test memcmp filter; filter on Initialized state
5895        let request = create_test_request(
5896            "getProgramAccounts",
5897            Some(json!([
5898                system_program::id().to_string(),
5899                {"filters": [{
5900                    "memcmp": {
5901                        "offset": 4,
5902                        "bytes": bs58::encode(vec![1, 0, 0, 0]).into_string(),
5903                    },
5904                }]},
5905            ])),
5906        );
5907        let result: Vec<RpcKeyedAccount> = parse_success_result(rpc.handle_request_sync(request));
5908        assert_eq!(result.len(), 2);
5909
5910        let request = create_test_request(
5911            "getProgramAccounts",
5912            Some(json!([
5913                system_program::id().to_string(),
5914                {"filters": [{
5915                    "memcmp": {
5916                        "offset": 4,
5917                        "bytes": bs58::encode(vec![0, 0, 0, 0]).into_string(),
5918                    },
5919                }]},
5920            ])),
5921        );
5922        let result: Vec<RpcKeyedAccount> = parse_success_result(rpc.handle_request_sync(request));
5923        assert_eq!(result.len(), 0);
5924
5925        // Test dataSize filter
5926        let request = create_test_request(
5927            "getProgramAccounts",
5928            Some(json!([
5929                system_program::id().to_string(),
5930                {"filters": [{"dataSize": nonce::state::State::size()}]},
5931            ])),
5932        );
5933        let result: Vec<RpcKeyedAccount> = parse_success_result(rpc.handle_request_sync(request));
5934        assert_eq!(result.len(), 2);
5935
5936        let request = create_test_request(
5937            "getProgramAccounts",
5938            Some(json!([
5939                system_program::id().to_string(),
5940                {"filters": [{"dataSize": 1}]},
5941            ])),
5942        );
5943        let result: Vec<RpcKeyedAccount> = parse_success_result(rpc.handle_request_sync(request));
5944        assert_eq!(result.len(), 0);
5945
5946        // Test multiple filters
5947        let request = create_test_request(
5948            "getProgramAccounts",
5949            Some(json!([
5950                system_program::id().to_string(),
5951                {"filters": [{
5952                    "memcmp": {
5953                        "offset": 4,
5954                        "bytes": bs58::encode(vec![1, 0, 0, 0]).into_string(),
5955                    },
5956                }, {
5957                    "memcmp": {
5958                        "offset": 8,
5959                        "bytes": nonce_authorities[0].to_string(),
5960                    },
5961                }]}, // Filter on Initialized and Nonce authority
5962            ])),
5963        );
5964        let result: Vec<RpcKeyedAccount> = parse_success_result(rpc.handle_request_sync(request));
5965        assert_eq!(result.len(), 1);
5966
5967        let request = create_test_request(
5968            "getProgramAccounts",
5969            Some(json!([
5970                system_program::id().to_string(),
5971                {"filters": [{
5972                    "memcmp": {
5973                        "offset": 4,
5974                        "bytes": bs58::encode(vec![1, 0, 0, 0]).into_string(),
5975                    },
5976                }, {
5977                    "dataSize": 1,
5978                }]}, // Filter on Initialized and non-matching data size
5979            ])),
5980        );
5981        let result: Vec<RpcKeyedAccount> = parse_success_result(rpc.handle_request_sync(request));
5982        assert_eq!(result.len(), 0);
5983    }
5984
5985    #[test]
5986    fn test_rpc_simulate_transaction() {
5987        let rpc = RpcHandler::start();
5988        let bank = rpc.working_bank();
5989        let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
5990        let recent_blockhash = bank.confirmed_last_blockhash();
5991        let RpcHandler {
5992            ref meta, ref io, ..
5993        } = rpc;
5994
5995        let bob_pubkey = solana_pubkey::new_rand();
5996        let mut tx = system_transaction::transfer(
5997            &rpc.mint_keypair,
5998            &bob_pubkey,
5999            rent_exempt_amount,
6000            recent_blockhash,
6001        );
6002        let tx_serialized_encoded = bs58::encode(serialize(&tx).unwrap()).into_string();
6003        tx.signatures[0] = Signature::default();
6004        let tx_badsig_serialized_encoded = bs58::encode(serialize(&tx).unwrap()).into_string();
6005        tx.message.recent_blockhash = Hash::default();
6006        let tx_invalid_recent_blockhash = bs58::encode(serialize(&tx).unwrap()).into_string();
6007
6008        // Simulation bank must be frozen
6009        bank.freeze();
6010
6011        let loaded_accounts_data_size = expected_loaded_accounts_data_size(&bank, &tx);
6012
6013        // Good signature with sigVerify=true
6014        let req = format!(
6015            r#"{{"jsonrpc":"2.0",
6016                 "id":1,
6017                 "method":"simulateTransaction",
6018                 "params":[
6019                   "{}",
6020                   {{
6021                     "sigVerify": true,
6022                     "accounts": {{
6023                       "encoding": "jsonParsed",
6024                       "addresses": ["{}", "{}"]
6025                     }}
6026                   }}
6027                 ]
6028            }}"#,
6029            tx_serialized_encoded,
6030            solana_pubkey::new_rand(),
6031            bob_pubkey,
6032        );
6033        let res = io.handle_request_sync(&req, meta.clone());
6034        let expected = json!({
6035            "jsonrpc": "2.0",
6036            "result": {
6037                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
6038                "value":{
6039                    "accounts": [
6040                        null,
6041                        {
6042                            "data": ["", "base64"],
6043                            "executable": false,
6044                            "owner": "11111111111111111111111111111111",
6045                            "lamports": rent_exempt_amount,
6046                            "rentEpoch": u64::MAX,
6047                            "space": 0,
6048                        }
6049                    ],
6050                    "err":null,
6051                    "innerInstructions": null,
6052                    "loadedAccountsDataSize": loaded_accounts_data_size,
6053                    "fee": 5000,
6054                    "loadedAddresses": {"readonly": [], "writable": []},
6055                    "preBalances": [1000000000, 0, 1],
6056                    "postBalances": [999982200, 12800, 1],
6057                    "preTokenBalances": [],
6058                    "postTokenBalances": [],
6059                    "logs":[
6060                        "Program 11111111111111111111111111111111 invoke [1]",
6061                        "Program 11111111111111111111111111111111 success"
6062                    ],
6063                    "replacementBlockhash": null,
6064                    "returnData":null,
6065                    "unitsConsumed":150,
6066                }
6067            },
6068            "id": 1,
6069        });
6070        let expected: Response =
6071            serde_json::from_value(expected).expect("expected response deserialization");
6072        let result: Response = serde_json::from_str(&res.expect("actual response"))
6073            .expect("actual response deserialization");
6074        assert_eq!(result, expected);
6075
6076        // Too many input accounts...
6077        let req = format!(
6078            r#"{{"jsonrpc":"2.0",
6079                 "id":1,
6080                 "method":"simulateTransaction",
6081                 "params":[
6082                   "{tx_serialized_encoded}",
6083                   {{
6084                     "sigVerify": true,
6085                     "accounts": {{
6086                       "addresses": [
6087                          "11111111111111111111111111111111",
6088                          "11111111111111111111111111111111",
6089                          "11111111111111111111111111111111",
6090                          "11111111111111111111111111111111"
6091                        ]
6092                     }}
6093                   }}
6094                 ]
6095            }}"#,
6096        );
6097        let res = io.handle_request_sync(&req, meta.clone());
6098        let expected = json!({
6099            "jsonrpc":"2.0",
6100            "error": {
6101                "code": error::ErrorCode::InvalidParams.code(),
6102                "message": "Too many accounts provided; max 3"
6103            },
6104            "id":1
6105        });
6106        let expected: Response =
6107            serde_json::from_value(expected).expect("expected response deserialization");
6108        let result: Response = serde_json::from_str(&res.expect("actual response"))
6109            .expect("actual response deserialization");
6110        assert_eq!(result, expected);
6111
6112        // Bad signature with sigVerify=true
6113        let req = format!(
6114            r#"{{"jsonrpc":"2.0","id":1,"method":"simulateTransaction","params":["{tx_badsig_serialized_encoded}", {{"sigVerify": true}}]}}"#,
6115        );
6116        let res = io.handle_request_sync(&req, meta.clone());
6117        let expected = json!({
6118            "jsonrpc": "2.0",
6119            "result": {
6120                "context": { "slot": 0, "apiVersion": RpcApiVersion::default() },
6121                "value": {
6122                    "accounts": null,
6123                    "err": "SignatureFailure",
6124                    "innerInstructions": null,
6125                    "loadedAccountsDataSize": 0,
6126                    "fee": null,
6127                    "loadedAddresses": { "readonly": [], "writable": [] },
6128                    "preBalances": null,
6129                    "postBalances": null,
6130                    "preTokenBalances": null,
6131                    "postTokenBalances": null,
6132                    "logs": [],
6133                    "replacementBlockhash": null,
6134                    "returnData": null,
6135                    "unitsConsumed": 0,
6136                }
6137            },
6138            "id": 1,
6139        });
6140
6141        let expected: Response =
6142            serde_json::from_value(expected).expect("expected response deserialization");
6143        let result: Response = serde_json::from_str(&res.expect("actual response"))
6144            .expect("actual response deserialization");
6145        assert_eq!(result, expected);
6146
6147        // Bad signature with sigVerify=false
6148        let req = format!(
6149            r#"{{"jsonrpc":"2.0","id":1,"method":"simulateTransaction","params":["{tx_serialized_encoded}", {{"sigVerify": false}}]}}"#,
6150        );
6151        let res = io.handle_request_sync(&req, meta.clone());
6152        let expected = json!({
6153            "jsonrpc": "2.0",
6154            "result": {
6155                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
6156                "value":{
6157                    "accounts":null,
6158                    "err":null,
6159                    "innerInstructions":null,
6160                    "loadedAccountsDataSize": loaded_accounts_data_size,
6161                    "fee": 5000,
6162                    "loadedAddresses": {"readonly": [], "writable": []},
6163                    "preBalances": [1000000000, 0, 1],
6164                    "postBalances": [999982200, 12800, 1],
6165                    "preTokenBalances": [],
6166                    "postTokenBalances": [],
6167                    "logs":[
6168                        "Program 11111111111111111111111111111111 invoke [1]",
6169                        "Program 11111111111111111111111111111111 success"
6170                    ],
6171                    "replacementBlockhash": null,
6172                    "returnData":null,
6173                    "unitsConsumed":150,
6174                }
6175            },
6176            "id": 1,
6177        });
6178        let expected: Response =
6179            serde_json::from_value(expected).expect("expected response deserialization");
6180        let result: Response = serde_json::from_str(&res.expect("actual response"))
6181            .expect("actual response deserialization");
6182        assert_eq!(result, expected);
6183
6184        // Bad signature with default sigVerify setting (false)
6185        let req = format!(
6186            r#"{{"jsonrpc":"2.0","id":1,"method":"simulateTransaction","params":["{tx_serialized_encoded}"]}}"#,
6187        );
6188        let res = io.handle_request_sync(&req, meta.clone());
6189        let expected = json!({
6190            "jsonrpc": "2.0",
6191            "result": {
6192                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
6193                "value":{
6194                    "accounts":null,
6195                    "err":null,
6196                    "innerInstructions":null,
6197                    "loadedAccountsDataSize": loaded_accounts_data_size,
6198                    "fee": 5000,
6199                    "loadedAddresses": {"readonly": [], "writable": []},
6200                    "preBalances": [1000000000, 0, 1],
6201                    "postBalances": [999982200, 12800, 1],
6202                    "preTokenBalances": [],
6203                    "postTokenBalances": [],
6204                    "logs":[
6205                        "Program 11111111111111111111111111111111 invoke [1]",
6206                        "Program 11111111111111111111111111111111 success"
6207                    ],
6208                    "replacementBlockhash": null,
6209                    "returnData": null,
6210                    "unitsConsumed":150,
6211                }
6212            },
6213            "id": 1,
6214        });
6215        let expected: Response =
6216            serde_json::from_value(expected).expect("expected response deserialization");
6217        let result: Response = serde_json::from_str(&res.expect("actual response"))
6218            .expect("actual response deserialization");
6219        assert_eq!(result, expected);
6220
6221        // Enabled both sigVerify=true and replaceRecentBlockhash=true
6222        let req = format!(
6223            r#"{{"jsonrpc":"2.0","id":1,"method":"simulateTransaction","params":["{}", {}]}}"#,
6224            tx_serialized_encoded,
6225            json!({
6226                "sigVerify": true,
6227                "replaceRecentBlockhash": true,
6228            })
6229        );
6230        let res = io.handle_request_sync(&req, meta.clone());
6231        let expected = json!({
6232            "jsonrpc":"2.0",
6233            "error": {
6234                "code": ErrorCode::InvalidParams,
6235                "message": "sigVerify may not be used with replaceRecentBlockhash"
6236            },
6237            "id":1
6238        });
6239        let expected: Response =
6240            serde_json::from_value(expected).expect("expected response deserialization");
6241        let result: Response = serde_json::from_str(&res.expect("actual response"))
6242            .expect("actual response deserialization");
6243        assert_eq!(result, expected);
6244
6245        // Bad recent blockhash with replaceRecentBlockhash=false
6246        let req = format!(
6247            r#"{{"jsonrpc":"2.0","id":1,"method":"simulateTransaction","params":["{tx_invalid_recent_blockhash}", {{"replaceRecentBlockhash": false}}]}}"#,
6248        );
6249        let res = io.handle_request_sync(&req, meta.clone());
6250        let expected = json!({
6251            "jsonrpc":"2.0",
6252            "result": {
6253                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
6254                "value":{
6255                    "err":"BlockhashNotFound",
6256                    "accounts":null,
6257                    "innerInstructions":null,
6258                    "loadedAccountsDataSize":0,
6259                    "fee": null,
6260                    "loadedAddresses": {"readonly": [], "writable": []},
6261                    "preBalances": [1000000000, 0, 1],
6262                    "postBalances": [1000000000, 0, 1],
6263                    "preTokenBalances": [],
6264                    "postTokenBalances": [],
6265                    "logs":[],
6266                    "replacementBlockhash": null,
6267                    "returnData": null,
6268                    "unitsConsumed":0,
6269                }
6270            },
6271            "id":1
6272        });
6273
6274        let expected: Response =
6275            serde_json::from_value(expected).expect("expected response deserialization");
6276        let result: Response = serde_json::from_str(&res.expect("actual response"))
6277            .expect("actual response deserialization");
6278        assert_eq!(result, expected);
6279
6280        // Bad recent blockhash with replaceRecentBlockhash=true
6281        let req = format!(
6282            r#"{{"jsonrpc":"2.0","id":1,"method":"simulateTransaction","params":["{tx_invalid_recent_blockhash}", {{"replaceRecentBlockhash": true}}]}}"#,
6283        );
6284        let res = io.handle_request_sync(&req, meta.clone());
6285        let latest_blockhash = bank.confirmed_last_blockhash();
6286        let expiry_slot = bank
6287            .get_blockhash_last_valid_block_height(&latest_blockhash)
6288            .expect("blockhash exists");
6289
6290        let expected = json!({
6291            "jsonrpc": "2.0",
6292            "result": {
6293                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
6294                "value":{
6295                    "accounts":null,
6296                    "err":null,
6297                    "innerInstructions":null,
6298                    "loadedAccountsDataSize": loaded_accounts_data_size,
6299                    "fee": 5000,
6300                    "loadedAddresses": {"readonly": [], "writable": []},
6301                    "preBalances": [1000000000, 0, 1],
6302                    "postBalances": [999982200, 12800, 1],
6303                    "preTokenBalances": [],
6304                    "postTokenBalances": [],
6305                    "logs":[
6306                        "Program 11111111111111111111111111111111 invoke [1]",
6307                        "Program 11111111111111111111111111111111 success"
6308                    ],
6309                    "replacementBlockhash": {
6310                        "blockhash": latest_blockhash.to_string(),
6311                        "lastValidBlockHeight": expiry_slot
6312                    },
6313                    "returnData":null,
6314                    "unitsConsumed":150,
6315                }
6316            },
6317            "id": 1,
6318        });
6319
6320        let expected: Response =
6321            serde_json::from_value(expected).expect("expected response deserialization");
6322        let result: Response = serde_json::from_str(&res.expect("actual response"))
6323            .expect("actual response deserialization");
6324        assert_eq!(result, expected);
6325    }
6326
6327    #[test]
6328    fn test_rpc_simulate_transaction_with_parsing_token_accounts() {
6329        let rpc = RpcHandler::start();
6330        let bank = rpc.working_bank();
6331        let RpcHandler {
6332            ref meta, ref io, ..
6333        } = rpc;
6334
6335        // init mint
6336        let mint_rent_exempt_amount =
6337            bank.get_minimum_balance_for_rent_exemption(spl_token_interface::state::Mint::LEN);
6338        let mint_pubkey = Pubkey::from_str("mint111111111111111111111111111111111111111").unwrap();
6339        let mut mint_data = [0u8; spl_token_interface::state::Mint::LEN];
6340        Pack::pack_into_slice(
6341            &spl_token_interface::state::Mint {
6342                mint_authority: COption::None,
6343                supply: 0,
6344                decimals: 8,
6345                is_initialized: true,
6346                freeze_authority: COption::None,
6347            },
6348            &mut mint_data,
6349        );
6350        let account = AccountSharedData::create(
6351            mint_rent_exempt_amount,
6352            mint_data.into(),
6353            spl_token_interface::id(),
6354            false,
6355            0,
6356        );
6357        bank.store_account(&mint_pubkey, &account);
6358
6359        // init token account
6360        let token_account_rent_exempt_amount =
6361            bank.get_minimum_balance_for_rent_exemption(spl_token_interface::state::Account::LEN);
6362        let token_account_pubkey = Pubkey::new_unique();
6363        let owner_pubkey = Pubkey::from_str("owner11111111111111111111111111111111111111").unwrap();
6364        let mut token_account_data = [0u8; spl_token_interface::state::Account::LEN];
6365        Pack::pack_into_slice(
6366            &spl_token_interface::state::Account {
6367                mint: mint_pubkey,
6368                owner: owner_pubkey,
6369                amount: 1,
6370                delegate: COption::None,
6371                state: spl_token_interface::state::AccountState::Initialized,
6372                is_native: COption::None,
6373                delegated_amount: 0,
6374                close_authority: COption::None,
6375            },
6376            &mut token_account_data,
6377        );
6378        let account = AccountSharedData::create(
6379            token_account_rent_exempt_amount,
6380            token_account_data.into(),
6381            spl_token_interface::id(),
6382            false,
6383            0,
6384        );
6385        bank.store_account(&token_account_pubkey, &account);
6386
6387        // prepare tx
6388        let fee_payer = rpc.mint_keypair;
6389        let recent_blockhash = bank.confirmed_last_blockhash();
6390        let tx =
6391            system_transaction::transfer(&fee_payer, &token_account_pubkey, 1, recent_blockhash);
6392        let tx_serialized_encoded = bs58::encode(serialize(&tx).unwrap()).into_string();
6393
6394        // Simulation bank must be frozen
6395        bank.freeze();
6396
6397        let loaded_accounts_data_size = expected_loaded_accounts_data_size(&bank, &tx);
6398
6399        let req = format!(
6400            r#"{{"jsonrpc":"2.0",
6401                 "id":1,
6402                 "method":"simulateTransaction",
6403                 "params":[
6404                   "{}",
6405                   {{
6406                     "sigVerify": true,
6407                     "accounts": {{
6408                       "encoding": "jsonParsed",
6409                       "addresses": ["{}", "{}"]
6410                     }}
6411                   }}
6412                 ]
6413            }}"#,
6414            tx_serialized_encoded,
6415            solana_pubkey::new_rand(),
6416            token_account_pubkey,
6417        );
6418        let res = io.handle_request_sync(&req, meta.clone());
6419        let expected = json!({
6420            "jsonrpc": "2.0",
6421            "result": {
6422                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
6423                "value":{
6424                    "accounts": [
6425                        null,
6426                        {
6427                            "data": {
6428                                "parsed": {
6429                                  "info": {
6430                                    "isNative": false,
6431                                    "mint": "mint111111111111111111111111111111111111111",
6432                                    "owner": "owner11111111111111111111111111111111111111",
6433                                    "state": "initialized",
6434                                    "tokenAmount": {
6435                                      "amount": "1",
6436                                      "decimals": 8,
6437                                      "uiAmount": 0.00000001,
6438                                      "uiAmountString": "0.00000001"
6439                                    }
6440                                  },
6441                                  "type": "account"
6442                                },
6443                                "program": "spl-token",
6444                                "space": 165
6445                              },
6446                              "executable": false,
6447                              "lamports": (token_account_rent_exempt_amount + 1),
6448                              "owner": bs58::encode(spl_token_interface::id()).into_string(),
6449                              "rentEpoch": u64::MAX,
6450                              "space": spl_token_interface::state::Account::LEN
6451                        },
6452                    ],
6453                    "err": null,
6454                    "innerInstructions": null,
6455                    "loadedAccountsDataSize": loaded_accounts_data_size,
6456                    "fee": 5000,
6457                    "loadedAddresses": {"readonly": [], "writable": []},
6458                    "preBalances": [1000000000, 29300, 1],
6459                    "postBalances": [999994999, 29301, 1],
6460                    "preTokenBalances": [],
6461                    "postTokenBalances": [],
6462                    "logs":[
6463                        "Program 11111111111111111111111111111111 invoke [1]",
6464                        "Program 11111111111111111111111111111111 success"
6465                    ],
6466                    "replacementBlockhash": null,
6467                    "returnData": null,
6468                    "unitsConsumed": 150,
6469                }
6470            },
6471            "id": 1,
6472        });
6473        let expected: Response =
6474            serde_json::from_value(expected).expect("expected response deserialization");
6475        let result: Response = serde_json::from_str(&res.expect("actual response"))
6476            .expect("actual response deserialization");
6477        assert_eq!(result, expected);
6478    }
6479
6480    #[test]
6481    fn test_rpc_simulate_transaction_with_inner_instructions() {
6482        let rpc = RpcHandler::start();
6483        let bank = rpc.working_bank();
6484        let recent_blockhash = bank.confirmed_last_blockhash();
6485        let RpcHandler {
6486            ref meta, ref io, ..
6487        } = rpc;
6488
6489        let from = rpc.mint_keypair;
6490        let from_pubkey = from.pubkey();
6491        let to = Keypair::new();
6492        let to_pubkey = to.pubkey();
6493
6494        let space = 0;
6495        let lamports = bank.rent_collector().rent.minimum_balance(space);
6496        let owner_pubkey = Pubkey::new_unique();
6497
6498        let instruction = TestBuiltinEntrypoint::instruction(
6499            &from_pubkey,
6500            &to_pubkey,
6501            lamports,
6502            space as u64,
6503            &owner_pubkey,
6504        );
6505
6506        let tx = Transaction::new_signed_with_payer(
6507            &[instruction],
6508            Some(&from_pubkey),
6509            &[&from, &to],
6510            recent_blockhash,
6511        );
6512        let tx_serialized_encoded =
6513            base64::prelude::BASE64_STANDARD.encode(serialize(&tx).unwrap());
6514
6515        // Simulation bank must be frozen
6516        bank.freeze();
6517
6518        let loaded_accounts_data_size = expected_loaded_accounts_data_size(&bank, &tx);
6519
6520        // `innerInstructions` not provided, should not be in response
6521        let req = format!(
6522            r#"{{"jsonrpc":"2.0",
6523                 "id":1,
6524                 "method":"simulateTransaction",
6525                 "params":[
6526                   "{tx_serialized_encoded}",
6527                   {{ "encoding": "base64" }}
6528                 ]
6529            }}"#,
6530        );
6531        let res = io.handle_request_sync(&req, meta.clone());
6532        let expected = json!({
6533            "jsonrpc": "2.0",
6534            "result": {
6535                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
6536                "value":{
6537                    "accounts": null,
6538                    "err":null,
6539                    "innerInstructions": null,
6540                    "loadedAccountsDataSize": loaded_accounts_data_size,
6541                    "fee": 10000,
6542                    "loadedAddresses": {"readonly": [], "writable": []},
6543                    "preBalances": [1000000000, 0, 1, 0, 1],
6544                    "postBalances": [999977200, 12800, 1, 0, 1],
6545                    "preTokenBalances": [],
6546                    "postTokenBalances": [],
6547                    "logs":[
6548                        "Program TestProgram11111111111111111111111111111111 invoke [1]",
6549                        "I am logging from a builtin program!",
6550                        "I am about to CPI to System!",
6551                        "Program 11111111111111111111111111111111 invoke [2]",
6552                        "Program 11111111111111111111111111111111 success",
6553                        "All done!",
6554                        "Program TestProgram11111111111111111111111111111111 success"
6555                    ],
6556                    "replacementBlockhash": null,
6557                    "returnData":null,
6558                    "unitsConsumed":TestBuiltinEntrypoint::COMPUTE_UNITS + 150,
6559                }
6560            },
6561            "id": 1,
6562        });
6563        let expected: Response =
6564            serde_json::from_value(expected).expect("expected response deserialization");
6565        let result: Response = serde_json::from_str(&res.expect("actual response"))
6566            .expect("actual response deserialization");
6567        assert_eq!(result, expected);
6568
6569        // `innerInstructions` provided as `false`, should not be in response
6570        let req = format!(
6571            r#"{{"jsonrpc":"2.0",
6572                 "id":1,
6573                 "method":"simulateTransaction",
6574                 "params":[
6575                   "{tx_serialized_encoded}",
6576                   {{ "innerInstructions": false, "encoding": "base64" }}
6577                 ]
6578            }}"#,
6579        );
6580        let res = io.handle_request_sync(&req, meta.clone());
6581        let expected = json!({
6582            "jsonrpc": "2.0",
6583            "result": {
6584                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
6585                "value":{
6586                    "accounts": null,
6587                    "err":null,
6588                    "innerInstructions": null,
6589                    "loadedAccountsDataSize": loaded_accounts_data_size,
6590                    "fee": 10000,
6591                    "loadedAddresses": {"readonly": [], "writable": []},
6592                    "preBalances": [1000000000, 0, 1, 0, 1],
6593                    "postBalances": [999977200, 12800, 1, 0, 1],
6594                    "preTokenBalances": [],
6595                    "postTokenBalances": [],
6596                    "logs":[
6597                        "Program TestProgram11111111111111111111111111111111 invoke [1]",
6598                        "I am logging from a builtin program!",
6599                        "I am about to CPI to System!",
6600                        "Program 11111111111111111111111111111111 invoke [2]",
6601                        "Program 11111111111111111111111111111111 success",
6602                        "All done!",
6603                        "Program TestProgram11111111111111111111111111111111 success"
6604                    ],
6605                    "replacementBlockhash": null,
6606                    "returnData":null,
6607                    "unitsConsumed":TestBuiltinEntrypoint::COMPUTE_UNITS + 150,
6608                }
6609            },
6610            "id": 1,
6611        });
6612        let expected: Response =
6613            serde_json::from_value(expected).expect("expected response deserialization");
6614        let result: Response = serde_json::from_str(&res.expect("actual response"))
6615            .expect("actual response deserialization");
6616        assert_eq!(result, expected);
6617
6618        // `innerInstructions` provided as `true`, should have parsed inner instructions
6619        let req = format!(
6620            r#"{{"jsonrpc":"2.0",
6621                 "id":1,
6622                 "method":"simulateTransaction",
6623                 "params":[
6624                   "{tx_serialized_encoded}",
6625                   {{ "innerInstructions": true, "encoding": "base64" }}
6626                 ]
6627            }}"#,
6628        );
6629        let res = io.handle_request_sync(&req, meta.clone());
6630        let expected = json!({
6631            "jsonrpc": "2.0",
6632            "result": {
6633                "context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
6634                "value":{
6635                    "accounts": null,
6636                    "err":null,
6637                    "innerInstructions": [
6638                        {
6639                        "index": 0,
6640                        "instructions": [
6641                            {
6642                            "parsed": {
6643                                "info": {
6644                                    "lamports": lamports,
6645                                    "newAccount": to_pubkey.to_string(),
6646                                    "owner": owner_pubkey.to_string(),
6647                                    "source": from_pubkey.to_string(),
6648                                    "space": space,
6649                                },
6650                                "type": "createAccount"
6651                            },
6652                            "program": "system",
6653                            "programId": "11111111111111111111111111111111",
6654                            "stackHeight": 2
6655                            }
6656                        ]
6657                        }
6658                    ],
6659                    "loadedAccountsDataSize": loaded_accounts_data_size,
6660                    "fee": 10000,
6661                    "loadedAddresses": {"readonly": [], "writable": []},
6662                    "preBalances": [1000000000, 0, 1, 0, 1],
6663                    "postBalances": [999977200, 12800, 1, 0, 1],
6664                    "preTokenBalances": [],
6665                    "postTokenBalances": [],
6666                    "logs":[
6667                        "Program TestProgram11111111111111111111111111111111 invoke [1]",
6668                        "I am logging from a builtin program!",
6669                        "I am about to CPI to System!",
6670                        "Program 11111111111111111111111111111111 invoke [2]",
6671                        "Program 11111111111111111111111111111111 success",
6672                        "All done!",
6673                        "Program TestProgram11111111111111111111111111111111 success"
6674                    ],
6675                    "replacementBlockhash": null,
6676                    "returnData":null,
6677                    "unitsConsumed":TestBuiltinEntrypoint::COMPUTE_UNITS + 150,
6678                }
6679            },
6680            "id": 1,
6681        });
6682        let expected: Response =
6683            serde_json::from_value(expected).expect("expected response deserialization");
6684        let result: Response = serde_json::from_str(&res.expect("actual response"))
6685            .expect("actual response deserialization");
6686        assert_eq!(result, expected);
6687    }
6688
6689    #[test]
6690    #[should_panic(expected = "simulation bank must be frozen")]
6691    fn test_rpc_simulate_transaction_panic_on_unfrozen_bank() {
6692        let rpc = RpcHandler::start();
6693        let bank = rpc.working_bank();
6694        let recent_blockhash = bank.confirmed_last_blockhash();
6695        let RpcHandler {
6696            meta,
6697            io,
6698            mint_keypair,
6699            ..
6700        } = rpc;
6701
6702        let bob_pubkey = Pubkey::new_unique();
6703        let tx = system_transaction::transfer(&mint_keypair, &bob_pubkey, 1234, recent_blockhash);
6704        let tx_serialized_encoded = bs58::encode(serialize(&tx).unwrap()).into_string();
6705
6706        assert!(!bank.is_frozen());
6707
6708        let req = format!(
6709            r#"{{"jsonrpc":"2.0","id":1,"method":"simulateTransaction","params":["{tx_serialized_encoded}", {{"sigVerify": true}}]}}"#,
6710        );
6711
6712        // should panic because `bank` is not frozen
6713        let _ = io.handle_request_sync(&req, meta);
6714    }
6715
6716    #[test]
6717    fn test_rpc_get_signature_statuses() {
6718        let rpc = RpcHandler::start();
6719        let bank = rpc.working_bank();
6720        let recent_blockhash = bank.confirmed_last_blockhash();
6721        let confirmed_block_signatures = rpc.create_test_transactions_and_populate_blockstore();
6722        let RpcHandler {
6723            mut meta,
6724            io,
6725            mint_keypair,
6726            ..
6727        } = rpc;
6728
6729        let req = format!(
6730            r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatuses","params":[["{}"]]}}"#,
6731            confirmed_block_signatures[0]
6732        );
6733        let res = io.handle_request_sync(&req, meta.clone());
6734        let expected_res: transaction::Result<()> = Ok(());
6735        let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
6736        let result: Option<TransactionStatus> =
6737            serde_json::from_value(json["result"]["value"][0].clone())
6738                .expect("actual response deserialization");
6739        let result = result.as_ref().unwrap();
6740        assert_eq!(expected_res, result.status);
6741        assert_eq!(None, result.confirmations);
6742
6743        // Test getSignatureStatus request on unprocessed tx
6744        let bob_pubkey = solana_pubkey::new_rand();
6745        let tx = system_transaction::transfer(
6746            &mint_keypair,
6747            &bob_pubkey,
6748            bank.get_minimum_balance_for_rent_exemption(0) + 10,
6749            recent_blockhash,
6750        );
6751        let req = format!(
6752            r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatuses","params":[["{}"]]}}"#,
6753            tx.signatures[0]
6754        );
6755        let res = io.handle_request_sync(&req, meta.clone());
6756        let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
6757        let result: Option<TransactionStatus> =
6758            serde_json::from_value(json["result"]["value"][0].clone())
6759                .expect("actual response deserialization");
6760        assert!(result.is_none());
6761
6762        // Test getSignatureStatus request on a TransactionError
6763        let req = format!(
6764            r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatuses","params":[["{}"]]}}"#,
6765            confirmed_block_signatures[1]
6766        );
6767        let res = io.handle_request_sync(&req, meta.clone());
6768        let expected_res: transaction::Result<()> = Err(TransactionError::InstructionError(
6769            0,
6770            InstructionError::Custom(1),
6771        ));
6772        let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
6773        let result: Option<TransactionStatus> =
6774            serde_json::from_value(json["result"]["value"][0].clone())
6775                .expect("actual response deserialization");
6776        assert_eq!(expected_res, result.as_ref().unwrap().status);
6777
6778        // disable rpc-tx-history, but attempt historical query
6779        meta.config.enable_rpc_transaction_history = false;
6780        let req = format!(
6781            r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatuses","params":[["{}"], {{"searchTransactionHistory": true}}]}}"#,
6782            confirmed_block_signatures[1]
6783        );
6784        let res = io.handle_request_sync(&req, meta);
6785        assert_eq!(
6786            res,
6787            Some(
6788                r#"{"jsonrpc":"2.0","error":{"code":-32011,"message":"Transaction history is not available from this node"},"id":1}"#.to_string(),
6789            )
6790        );
6791    }
6792
6793    #[test]
6794    fn test_rpc_fail_request_airdrop() {
6795        let RpcHandler { meta, io, .. } = RpcHandler::start();
6796
6797        // Expect internal error because no faucet is available
6798        let bob_pubkey = solana_pubkey::new_rand();
6799        let req = format!(
6800            r#"{{"jsonrpc":"2.0","id":1,"method":"requestAirdrop","params":["{bob_pubkey}", 50]}}"#
6801        );
6802        let res = io.handle_request_sync(&req, meta);
6803        let expected =
6804            r#"{"jsonrpc":"2.0","error":{"code":-32600,"message":"Invalid request"},"id":1}"#;
6805        let expected: Response =
6806            serde_json::from_str(expected).expect("expected response deserialization");
6807        let result: Response = serde_json::from_str(&res.expect("actual response"))
6808            .expect("actual response deserialization");
6809        assert_eq!(result, expected);
6810    }
6811
6812    fn rpc_send_bad_tx<Client: ClientWithCreator>() {
6813        let genesis = create_genesis_config(100);
6814        let bank = Bank::new_for_tests(&genesis.genesis_config);
6815        let meta =
6816            JsonRpcRequestProcessor::new_from_bank::<Client>(bank, SocketAddrSpace::Unspecified);
6817
6818        let mut io = MetaIoHandler::default();
6819        io.extend_with(rpc_full::FullImpl.to_delegate());
6820
6821        let req = r#"{"jsonrpc":"2.0","id":1,"method":"sendTransaction","params":["37u9WtQpcm6ULa3Vmu7ySnANv"]}"#;
6822        let res = io.handle_request_sync(req, meta);
6823        let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
6824        let error = &json["error"];
6825        assert_eq!(error["code"], ErrorCode::InvalidParams.code());
6826    }
6827
6828    #[test]
6829    fn test_rpc_send_bad_tx_connection_cache() {
6830        rpc_send_bad_tx::<ConnectionCacheClient<NullTpuInfo>>();
6831    }
6832
6833    #[test]
6834    fn test_rpc_send_bad_tx_tpu_client_next() {
6835        rpc_send_bad_tx::<TpuClientNextClient>();
6836    }
6837
6838    fn rpc_send_transaction_preflight<Client: ClientWithCreator>() {
6839        let exit = Arc::new(AtomicBool::new(false));
6840        let validator_exit = create_validator_exit(exit.clone());
6841        let ledger_path = get_tmp_ledger_path!();
6842        let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
6843        let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
6844        let (bank_forks, mint_keypair, ..) = new_bank_forks();
6845        let optimistically_confirmed_bank =
6846            OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
6847        let health = RpcHealth::stub(optimistically_confirmed_bank.clone(), blockstore.clone());
6848        // Mark the node as healthy to start
6849        health.stub_set_health_status(Some(RpcHealthStatus::Ok));
6850
6851        // Freeze bank 0 to prevent a panic in `run_transaction_simulation()`
6852        bank_forks.write().unwrap().get(0).unwrap().freeze();
6853
6854        let mut io = MetaIoHandler::default();
6855        io.extend_with(rpc_full::FullImpl.to_delegate());
6856        let cluster_info = Arc::new({
6857            let keypair = Arc::new(Keypair::new());
6858            let contact_info = ContactInfo::new_with_socketaddr(
6859                &keypair.pubkey(),
6860                &socketaddr!(Ipv4Addr::LOCALHOST, 1234),
6861            );
6862            ClusterInfo::new(contact_info, keypair, SocketAddrSpace::Unspecified)
6863        });
6864        let my_tpu_address = cluster_info.my_contact_info().tpu(Protocol::QUIC).unwrap();
6865        let config = JsonRpcConfig::default();
6866        let JsonRpcConfig {
6867            rpc_threads,
6868            rpc_blocking_threads,
6869            rpc_niceness_adj,
6870            ..
6871        } = config;
6872        let runtime = service_runtime(rpc_threads, rpc_blocking_threads, rpc_niceness_adj);
6873        let (meta, receiver) = JsonRpcRequestProcessor::new(
6874            config,
6875            None,
6876            bank_forks.clone(),
6877            block_commitment_cache,
6878            blockstore,
6879            validator_exit,
6880            health.clone(),
6881            cluster_info,
6882            Hash::default(),
6883            None,
6884            optimistically_confirmed_bank,
6885            Arc::new(RwLock::new(LargestAccountsCache::new(30))),
6886            Arc::new(MaxSlots::default()),
6887            Arc::new(LeaderScheduleCache::default()),
6888            Arc::new(AtomicU64::default()),
6889            Arc::new(PrioritizationFeeCache::default()),
6890            runtime.clone(),
6891        );
6892
6893        let client = Client::create_client(Some(runtime.handle().clone()), my_tpu_address, None, 1);
6894        assert!(
6895            client.protocol() == Protocol::QUIC,
6896            "UDP is not supported by this test."
6897        );
6898        SendTransactionService::new_with_client(
6899            &bank_forks,
6900            receiver,
6901            client,
6902            SendTransactionServiceConfig {
6903                retry_rate_ms: 1_000,
6904                leader_forward_count: 1,
6905                ..SendTransactionServiceConfig::default()
6906            },
6907            exit.clone(),
6908        );
6909
6910        let mut bad_transaction = system_transaction::transfer(
6911            &mint_keypair,
6912            &solana_pubkey::new_rand(),
6913            42,
6914            Hash::default(),
6915        );
6916
6917        // sendTransaction will fail because the blockhash is invalid
6918        let req = format!(
6919            r#"{{"jsonrpc":"2.0","id":1,"method":"sendTransaction","params":["{}"]}}"#,
6920            bs58::encode(serialize(&bad_transaction).unwrap()).into_string()
6921        );
6922        let res = io.handle_request_sync(&req, meta.clone());
6923        assert_eq!(
6924            res,
6925            Some(
6926                r#"{"jsonrpc":"2.0","error":{"code":-32002,"message":"Transaction simulation failed: Blockhash not found","data":{"accounts":null,"err":"BlockhashNotFound","fee":null,"innerInstructions":null,"loadedAccountsDataSize":0,"loadedAddresses":null,"logs":[],"postBalances":null,"postTokenBalances":null,"preBalances":null,"preTokenBalances":null,"replacementBlockhash":null,"returnData":null,"unitsConsumed":0}},"id":1}"#.to_string(),
6927            )
6928        );
6929
6930        // sendTransaction will fail due to insanity
6931        bad_transaction.message.instructions[0].program_id_index = 0u8;
6932        let recent_blockhash = bank_forks.read().unwrap().root_bank().last_blockhash();
6933        bad_transaction.sign(&[&mint_keypair], recent_blockhash);
6934        let req = format!(
6935            r#"{{"jsonrpc":"2.0","id":1,"method":"sendTransaction","params":["{}"]}}"#,
6936            bs58::encode(serialize(&bad_transaction).unwrap()).into_string()
6937        );
6938        let res = io.handle_request_sync(&req, meta.clone());
6939        assert_eq!(
6940            res,
6941            Some(
6942                r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid transaction: Transaction failed to sanitize accounts offsets correctly"},"id":1}"#.to_string(),
6943            )
6944        );
6945        let mut bad_transaction = system_transaction::transfer(
6946            &mint_keypair,
6947            &solana_pubkey::new_rand(),
6948            42,
6949            recent_blockhash,
6950        );
6951
6952        // sendTransaction will fail due to poor node health
6953        health.stub_set_health_status(Some(RpcHealthStatus::Behind { num_slots: 42 }));
6954        let req = format!(
6955            r#"{{"jsonrpc":"2.0","id":1,"method":"sendTransaction","params":["{}"]}}"#,
6956            bs58::encode(serialize(&bad_transaction).unwrap()).into_string()
6957        );
6958        let res = io.handle_request_sync(&req, meta.clone());
6959        assert_eq!(
6960            res,
6961            Some(
6962                r#"{"jsonrpc":"2.0","error":{"code":-32005,"message":"Node is behind by 42 slots","data":{"numSlotsBehind":42}},"id":1}"#.to_string(),
6963            )
6964        );
6965        health.stub_set_health_status(Some(RpcHealthStatus::Ok));
6966
6967        // sendTransaction will fail due to invalid signature
6968        bad_transaction.signatures[0] = Signature::default();
6969
6970        let req = format!(
6971            r#"{{"jsonrpc":"2.0","id":1,"method":"sendTransaction","params":["{}"]}}"#,
6972            bs58::encode(serialize(&bad_transaction).unwrap()).into_string()
6973        );
6974        let res = io.handle_request_sync(&req, meta.clone());
6975        let expected = json!({
6976            "jsonrpc": "2.0",
6977            "error": {
6978                "code": -32002,
6979                "data": {
6980                    "accounts": null,
6981                    "err": "SignatureFailure",
6982                    "innerInstructions": null,
6983                    "loadedAccountsDataSize": 0,
6984                    "fee": null,
6985                    "loadedAddresses": null,
6986                    "preBalances": null,
6987                    "postBalances": null,
6988                    "preTokenBalances": null,
6989                    "postTokenBalances": null,
6990                    "logs": [],
6991                    "replacementBlockhash": null,
6992                    "returnData": null,
6993                    "unitsConsumed": 0,
6994                },
6995                "message": "Transaction simulation failed: Transaction did not pass signature verification",
6996            },
6997            "id": 1,
6998        });
6999
7000        let expected: Response =
7001            serde_json::from_value(expected).expect("expected response deserialization");
7002        let result: Response = serde_json::from_str(&res.expect("actual response"))
7003            .expect("actual response deserialization");
7004        assert_eq!(result, expected);
7005
7006        // sendTransaction will now succeed because skipPreflight=true even though it's a bad
7007        // transaction
7008        let req = format!(
7009            r#"{{"jsonrpc":"2.0","id":1,"method":"sendTransaction","params":["{}", {{"skipPreflight": true}}]}}"#,
7010            bs58::encode(serialize(&bad_transaction).unwrap()).into_string()
7011        );
7012        let res = io.handle_request_sync(&req, meta.clone());
7013        assert_eq!(
7014            res,
7015            Some(
7016                r#"{"jsonrpc":"2.0","result":"1111111111111111111111111111111111111111111111111111111111111111","id":1}"#.to_string(),
7017            )
7018        );
7019
7020        // sendTransaction will fail due to sanitization failure
7021        bad_transaction.signatures.clear();
7022        let req = format!(
7023            r#"{{"jsonrpc":"2.0","id":1,"method":"sendTransaction","params":["{}"]}}"#,
7024            bs58::encode(serialize(&bad_transaction).unwrap()).into_string()
7025        );
7026        let res = io.handle_request_sync(&req, meta);
7027        assert_eq!(
7028            res,
7029            Some(
7030                r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid transaction: Transaction failed to sanitize accounts offsets correctly"},"id":1}"#.to_string(),
7031            )
7032        );
7033    }
7034
7035    #[test]
7036    fn test_rpc_send_transaction_preflight_with_connection_cache() {
7037        rpc_send_transaction_preflight::<ConnectionCacheClient<NullTpuInfo>>();
7038    }
7039
7040    #[test]
7041    fn test_rpc_send_transaction_preflight_with_tpu_client_next() {
7042        rpc_send_transaction_preflight::<TpuClientNextClient>();
7043    }
7044
7045    #[test]
7046    fn test_rpc_verify_filter() {
7047        let filter = RpcFilterType::Memcmp(Memcmp::new(
7048            0,                                                                                      // offset
7049            MemcmpEncodedBytes::Base58("13LeFbG6m2EP1fqCj9k66fcXsoTHMMtgr7c78AivUrYD".to_string()), // encoded bytes
7050        ));
7051        assert_eq!(verify_filter(&filter), Ok(()));
7052        // Invalid base-58
7053        let filter = RpcFilterType::Memcmp(Memcmp::new(
7054            0,                                             // offset
7055            MemcmpEncodedBytes::Base58("III".to_string()), // encoded bytes
7056        ));
7057        assert!(verify_filter(&filter).is_err());
7058    }
7059
7060    #[test]
7061    fn test_rpc_verify_pubkey() {
7062        let pubkey = solana_pubkey::new_rand();
7063        assert_eq!(verify_pubkey(&pubkey.to_string()).unwrap(), pubkey);
7064        let bad_pubkey = "a1b2c3d4";
7065        assert_eq!(
7066            verify_pubkey(bad_pubkey),
7067            Err(Error::invalid_params("Invalid param: WrongSize"))
7068        );
7069    }
7070
7071    #[test]
7072    fn test_rpc_verify_signature() {
7073        let tx = system_transaction::transfer(
7074            &Keypair::new(),
7075            &solana_pubkey::new_rand(),
7076            20,
7077            hash(&[0]),
7078        );
7079        assert_eq!(
7080            verify_signature(&tx.signatures[0].to_string()).unwrap(),
7081            tx.signatures[0]
7082        );
7083        let bad_signature = "a1b2c3d4";
7084        assert_eq!(
7085            verify_signature(bad_signature),
7086            Err(Error::invalid_params("Invalid param: WrongSize"))
7087        );
7088    }
7089
7090    fn new_bank_forks() -> (Arc<RwLock<BankForks>>, Keypair, Arc<Keypair>) {
7091        new_bank_forks_with_config(BankTestConfig::default())
7092    }
7093
7094    fn new_bank_forks_with_config(
7095        config: BankTestConfig,
7096    ) -> (Arc<RwLock<BankForks>>, Keypair, Arc<Keypair>) {
7097        let GenesisConfigInfo {
7098            mut genesis_config,
7099            mint_keypair,
7100            voting_keypair,
7101            ..
7102        } = create_genesis_config(TEST_MINT_LAMPORTS);
7103
7104        genesis_config.rent.lamports_per_byte_year = 50;
7105        genesis_config.rent.exemption_threshold = 2.0;
7106        genesis_config.epoch_schedule =
7107            EpochSchedule::custom(TEST_SLOTS_PER_EPOCH, TEST_SLOTS_PER_EPOCH, false);
7108        genesis_config.fee_rate_governor = FeeRateGovernor::new(TEST_SIGNATURE_FEE, 0);
7109
7110        let bank = Bank::new_with_config_for_tests(&genesis_config, config);
7111
7112        // Add the test builtin.
7113        bank.add_builtin(
7114            TestBuiltinEntrypoint::PROGRAM_ID,
7115            TestBuiltinEntrypoint::NAME,
7116            TestBuiltinEntrypoint::cache_entry(),
7117        );
7118
7119        (
7120            BankForks::new_rw_arc(bank),
7121            mint_keypair,
7122            Arc::new(voting_keypair),
7123        )
7124    }
7125
7126    #[test]
7127    fn test_rpc_get_identity() {
7128        let rpc = RpcHandler::start();
7129        let request = create_test_request("getIdentity", None);
7130        let result: Value = parse_success_result(rpc.handle_request_sync(request));
7131        let expected: Value = json!({ "identity": rpc.identity.to_string() });
7132        assert_eq!(result, expected);
7133    }
7134
7135    #[test]
7136    fn test_rpc_get_max_slots() {
7137        let rpc = RpcHandler::start();
7138        rpc.max_slots.retransmit.store(42, Ordering::Relaxed);
7139        rpc.max_slots.shred_insert.store(43, Ordering::Relaxed);
7140
7141        let request = create_test_request("getMaxRetransmitSlot", None);
7142        let result: Slot = parse_success_result(rpc.handle_request_sync(request));
7143        assert_eq!(result, 42);
7144
7145        let request = create_test_request("getMaxShredInsertSlot", None);
7146        let result: Slot = parse_success_result(rpc.handle_request_sync(request));
7147        assert_eq!(result, 43);
7148    }
7149
7150    #[test]
7151    fn test_rpc_get_version() {
7152        let rpc = RpcHandler::start();
7153        let request = create_test_request("getVersion", None);
7154        let result: Value = parse_success_result(rpc.handle_request_sync(request));
7155        let expected = {
7156            let version = solana_version::Version::default();
7157            json!({
7158                "solana-core": version.to_string(),
7159                "feature-set": version.feature_set,
7160            })
7161        };
7162        assert_eq!(result, expected);
7163    }
7164
7165    fn rpc_processor_get_block_commitment<Client: ClientWithCreator>() {
7166        let exit = Arc::new(AtomicBool::new(false));
7167        let validator_exit = create_validator_exit(exit.clone());
7168        let bank_forks = new_bank_forks().0;
7169        let ledger_path = get_tmp_ledger_path!();
7170        let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
7171
7172        let commitment_slot0 = BlockCommitment::new([8; MAX_LOCKOUT_HISTORY + 1]);
7173        let commitment_slot1 = BlockCommitment::new([9; MAX_LOCKOUT_HISTORY + 1]);
7174        let mut block_commitment: HashMap<u64, BlockCommitment> = HashMap::new();
7175        block_commitment
7176            .entry(0)
7177            .or_insert_with(|| commitment_slot0.clone());
7178        block_commitment
7179            .entry(1)
7180            .or_insert_with(|| commitment_slot1.clone());
7181        let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::new(
7182            block_commitment,
7183            42,
7184            CommitmentSlots::new_from_slot(bank_forks.read().unwrap().highest_slot()),
7185        )));
7186
7187        let cluster_info = Arc::new(new_test_cluster_info());
7188        let my_tpu_address = cluster_info.my_contact_info().tpu(Protocol::QUIC).unwrap();
7189        let optimistically_confirmed_bank =
7190            OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
7191        let config = JsonRpcConfig::default();
7192        let JsonRpcConfig {
7193            rpc_threads,
7194            rpc_blocking_threads,
7195            rpc_niceness_adj,
7196            ..
7197        } = config;
7198        let runtime = service_runtime(rpc_threads, rpc_blocking_threads, rpc_niceness_adj);
7199        let client = Client::create_client(Some(runtime.handle().clone()), my_tpu_address, None, 1);
7200        let (request_processor, receiver) = JsonRpcRequestProcessor::new(
7201            config,
7202            None,
7203            bank_forks.clone(),
7204            block_commitment_cache,
7205            blockstore.clone(),
7206            validator_exit,
7207            RpcHealth::stub(optimistically_confirmed_bank.clone(), blockstore),
7208            cluster_info,
7209            Hash::default(),
7210            None,
7211            optimistically_confirmed_bank,
7212            Arc::new(RwLock::new(LargestAccountsCache::new(30))),
7213            Arc::new(MaxSlots::default()),
7214            Arc::new(LeaderScheduleCache::default()),
7215            Arc::new(AtomicU64::default()),
7216            Arc::new(PrioritizationFeeCache::default()),
7217            runtime,
7218        );
7219
7220        SendTransactionService::new_with_client(
7221            &bank_forks,
7222            receiver,
7223            client,
7224            SendTransactionServiceConfig {
7225                retry_rate_ms: 1_000,
7226                leader_forward_count: 1,
7227                ..SendTransactionServiceConfig::default()
7228            },
7229            exit.clone(),
7230        );
7231
7232        assert_eq!(
7233            request_processor.get_block_commitment(0),
7234            RpcBlockCommitment {
7235                commitment: Some(commitment_slot0.commitment),
7236                total_stake: 42,
7237            }
7238        );
7239        assert_eq!(
7240            request_processor.get_block_commitment(1),
7241            RpcBlockCommitment {
7242                commitment: Some(commitment_slot1.commitment),
7243                total_stake: 42,
7244            }
7245        );
7246        assert_eq!(
7247            request_processor.get_block_commitment(2),
7248            RpcBlockCommitment {
7249                commitment: None,
7250                total_stake: 42,
7251            }
7252        );
7253    }
7254
7255    #[test]
7256    fn test_rpc_processor_get_block_commitment_with_connection_cache() {
7257        rpc_processor_get_block_commitment::<ConnectionCacheClient<NullTpuInfo>>();
7258    }
7259
7260    #[test]
7261    fn test_rpc_processor_get_block_commitment_with_tpu_client_next() {
7262        rpc_processor_get_block_commitment::<TpuClientNextClient>();
7263    }
7264
7265    #[test]
7266    fn test_rpc_get_block_commitment() {
7267        let rpc = RpcHandler::start();
7268
7269        let expected_total_stake = 42;
7270        let mut block_0_commitment = BlockCommitment::default();
7271        block_0_commitment.increase_confirmation_stake(2, 9);
7272        let _ = std::mem::replace(
7273            &mut *rpc.block_commitment_cache.write().unwrap(),
7274            BlockCommitmentCache::new(
7275                HashMap::from_iter(std::iter::once((0, block_0_commitment.clone()))),
7276                expected_total_stake,
7277                CommitmentSlots::new_from_slot(0),
7278            ),
7279        );
7280
7281        let request = create_test_request("getBlockCommitment", Some(json!([0u64])));
7282        let result: RpcBlockCommitment<_> = parse_success_result(rpc.handle_request_sync(request));
7283        let expected = RpcBlockCommitment {
7284            commitment: Some(block_0_commitment.commitment),
7285            total_stake: expected_total_stake,
7286        };
7287        assert_eq!(result, expected);
7288
7289        let request = create_test_request("getBlockCommitment", Some(json!([1u64])));
7290        let result: Value = parse_success_result(rpc.handle_request_sync(request));
7291        let expected = json!({
7292            "commitment": null,
7293            "totalStake": expected_total_stake,
7294        });
7295        assert_eq!(result, expected);
7296    }
7297
7298    #[test]
7299    fn test_get_block_with_versioned_tx() {
7300        let rpc = RpcHandler::start();
7301
7302        let bank = rpc.working_bank();
7303        // Slot hashes is necessary for processing versioned txs.
7304        bank.set_sysvar_for_tests(&SlotHashes::default());
7305        // Add both legacy and version #0 transactions to the block
7306        rpc.create_test_versioned_transactions_and_populate_blockstore(None);
7307
7308        let request = create_test_request(
7309            "getBlock",
7310            Some(json!([
7311                0u64,
7312                {"maxSupportedTransactionVersion": 0},
7313            ])),
7314        );
7315        let result: Option<EncodedConfirmedBlock> =
7316            parse_success_result(rpc.handle_request_sync(request));
7317        let confirmed_block = result.unwrap();
7318        assert_eq!(confirmed_block.transactions.len(), 2);
7319        assert_eq!(
7320            confirmed_block.transactions[0].version,
7321            Some(TransactionVersion::LEGACY)
7322        );
7323        assert_eq!(
7324            confirmed_block.transactions[1].version,
7325            Some(TransactionVersion::Number(0))
7326        );
7327
7328        let request = create_test_request("getBlock", Some(json!([0u64,])));
7329        let response = parse_failure_response(rpc.handle_request_sync(request));
7330        let expected = (
7331            JSON_RPC_SERVER_ERROR_UNSUPPORTED_TRANSACTION_VERSION,
7332            String::from(
7333                "Transaction version (0) is not supported by the requesting client. Please try \
7334                 the request again with the following configuration parameter: \
7335                 \"maxSupportedTransactionVersion\": 0",
7336            ),
7337        );
7338        assert_eq!(response, expected);
7339    }
7340
7341    #[test]
7342    fn test_get_block() {
7343        let mut rpc = RpcHandler::start();
7344        let confirmed_block_signatures = rpc.create_test_transactions_and_populate_blockstore();
7345
7346        let request = create_test_request("getBlock", Some(json!([0u64])));
7347        let result: Option<EncodedConfirmedBlock> =
7348            parse_success_result(rpc.handle_request_sync(request));
7349
7350        let confirmed_block = result.unwrap();
7351        assert_eq!(confirmed_block.transactions.len(), 2);
7352        assert_eq!(confirmed_block.rewards, vec![]);
7353
7354        for EncodedTransactionWithStatusMeta {
7355            transaction,
7356            meta,
7357            version,
7358        } in confirmed_block.transactions.into_iter()
7359        {
7360            assert_eq!(
7361                version, None,
7362                "requests which don't set max_supported_transaction_version shouldn't receive a \
7363                 version"
7364            );
7365            if let EncodedTransaction::Json(transaction) = transaction {
7366                if transaction.signatures[0] == confirmed_block_signatures[0].to_string() {
7367                    let meta = meta.unwrap();
7368                    assert_eq!(meta.status, Ok(()));
7369                    assert_eq!(meta.err, None);
7370                } else if transaction.signatures[0] == confirmed_block_signatures[1].to_string() {
7371                    let meta = meta.unwrap();
7372                    assert_eq!(
7373                        meta.err,
7374                        Some(
7375                            TransactionError::InstructionError(0, InstructionError::Custom(1))
7376                                .into()
7377                        )
7378                    );
7379                    assert_eq!(
7380                        meta.status,
7381                        Err(
7382                            TransactionError::InstructionError(0, InstructionError::Custom(1))
7383                                .into()
7384                        ),
7385                    );
7386                } else {
7387                    assert_eq!(meta, None);
7388                }
7389            }
7390        }
7391
7392        let request = create_test_request("getBlock", Some(json!([0u64, "binary"])));
7393        let result: Option<EncodedConfirmedBlock> =
7394            parse_success_result(rpc.handle_request_sync(request));
7395        let confirmed_block = result.unwrap();
7396        assert_eq!(confirmed_block.transactions.len(), 2);
7397        assert_eq!(confirmed_block.rewards, vec![]);
7398
7399        for EncodedTransactionWithStatusMeta {
7400            transaction,
7401            meta,
7402            version,
7403        } in confirmed_block.transactions.into_iter()
7404        {
7405            assert_eq!(
7406                version, None,
7407                "requests which don't set max_supported_transaction_version shouldn't receive a \
7408                 version"
7409            );
7410            if let EncodedTransaction::LegacyBinary(transaction) = transaction {
7411                let decoded_transaction: Transaction =
7412                    deserialize(&bs58::decode(&transaction).into_vec().unwrap()).unwrap();
7413                if decoded_transaction.signatures[0] == confirmed_block_signatures[0] {
7414                    let meta = meta.unwrap();
7415                    assert_eq!(meta.status, Ok(()));
7416                    assert_eq!(meta.err, None);
7417                } else if decoded_transaction.signatures[0] == confirmed_block_signatures[1] {
7418                    let meta = meta.unwrap();
7419                    assert_eq!(
7420                        meta.err,
7421                        Some(
7422                            TransactionError::InstructionError(0, InstructionError::Custom(1))
7423                                .into()
7424                        )
7425                    );
7426                    assert_eq!(
7427                        meta.status,
7428                        Err(
7429                            TransactionError::InstructionError(0, InstructionError::Custom(1))
7430                                .into()
7431                        ),
7432                    );
7433                } else {
7434                    assert_eq!(meta, None);
7435                }
7436            }
7437        }
7438
7439        // disable rpc-tx-history
7440        rpc.meta.config.enable_rpc_transaction_history = false;
7441        let request = create_test_request("getBlock", Some(json!([0u64])));
7442        let response = parse_failure_response(rpc.handle_request_sync(request));
7443        let expected = (
7444            JSON_RPC_SERVER_ERROR_TRANSACTION_HISTORY_NOT_AVAILABLE,
7445            String::from("Transaction history is not available from this node"),
7446        );
7447        assert_eq!(response, expected);
7448    }
7449
7450    #[test]
7451    fn test_get_block_config() {
7452        let rpc = RpcHandler::start();
7453        let confirmed_block_signatures = rpc.create_test_transactions_and_populate_blockstore();
7454
7455        let request = create_test_request(
7456            "getBlock",
7457            Some(json!([
7458                0u64,
7459                RpcBlockConfig {
7460                    encoding: None,
7461                    transaction_details: Some(TransactionDetails::Signatures),
7462                    rewards: Some(false),
7463                    commitment: None,
7464                    max_supported_transaction_version: None,
7465                },
7466            ])),
7467        );
7468        let result: Option<UiConfirmedBlock> =
7469            parse_success_result(rpc.handle_request_sync(request));
7470
7471        let confirmed_block = result.unwrap();
7472        assert!(confirmed_block.transactions.is_none());
7473        assert!(confirmed_block.rewards.is_none());
7474        for (i, signature) in confirmed_block.signatures.unwrap()[..2].iter().enumerate() {
7475            assert_eq!(*signature, confirmed_block_signatures[i].to_string());
7476        }
7477
7478        let request = create_test_request(
7479            "getBlock",
7480            Some(json!([
7481                0u64,
7482                RpcBlockConfig {
7483                    encoding: None,
7484                    transaction_details: Some(TransactionDetails::None),
7485                    rewards: Some(true),
7486                    commitment: None,
7487                    max_supported_transaction_version: None,
7488                },
7489            ])),
7490        );
7491        let result: Option<UiConfirmedBlock> =
7492            parse_success_result(rpc.handle_request_sync(request));
7493        let confirmed_block = result.unwrap();
7494        assert!(confirmed_block.transactions.is_none());
7495        assert!(confirmed_block.signatures.is_none());
7496        assert_eq!(confirmed_block.rewards.unwrap(), vec![]);
7497    }
7498
7499    #[test]
7500    fn test_get_block_production() {
7501        let rpc = RpcHandler::start();
7502        rpc.add_roots_to_blockstore(vec![0, 1, 3, 4, 8]);
7503        rpc.block_commitment_cache
7504            .write()
7505            .unwrap()
7506            .set_highest_super_majority_root(8);
7507
7508        let request = create_test_request("getBlockProduction", Some(json!([])));
7509        let result: RpcResponse<RpcBlockProduction> =
7510            parse_success_result(rpc.handle_request_sync(request));
7511        let expected = RpcBlockProduction {
7512            by_identity: HashMap::from_iter(std::iter::once((
7513                rpc.leader_pubkey().to_string(),
7514                (9, 5),
7515            ))),
7516            range: RpcBlockProductionRange {
7517                first_slot: 0,
7518                last_slot: 8,
7519            },
7520        };
7521        assert_eq!(result.value, expected);
7522
7523        let request = create_test_request(
7524            "getBlockProduction",
7525            Some(json!([{
7526                "identity": rpc.leader_pubkey().to_string()
7527            }])),
7528        );
7529        let result: RpcResponse<RpcBlockProduction> =
7530            parse_success_result(rpc.handle_request_sync(request));
7531        assert_eq!(result.value, expected);
7532
7533        let request = create_test_request(
7534            "getBlockProduction",
7535            Some(json!([{
7536                "identity": Pubkey::new_unique().to_string(),
7537                "range": {
7538                    "firstSlot": 0u64,
7539                    "lastSlot": 4u64,
7540                },
7541            }])),
7542        );
7543        let result: RpcResponse<RpcBlockProduction> =
7544            parse_success_result(rpc.handle_request_sync(request));
7545        let expected = RpcBlockProduction {
7546            by_identity: HashMap::new(),
7547            range: RpcBlockProductionRange {
7548                first_slot: 0,
7549                last_slot: 4,
7550            },
7551        };
7552        assert_eq!(result.value, expected);
7553    }
7554
7555    #[test]
7556    fn test_get_blocks() {
7557        let rpc = RpcHandler::start();
7558        let _ = rpc.create_test_transactions_and_populate_blockstore();
7559        rpc.add_roots_to_blockstore(vec![0, 1, 3, 4, 8]);
7560        rpc.block_commitment_cache
7561            .write()
7562            .unwrap()
7563            .set_highest_super_majority_root(8);
7564
7565        let request = create_test_request("getBlocks", Some(json!([0u64])));
7566        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7567        assert_eq!(result, vec![0, 1, 3, 4, 8]);
7568
7569        let request = create_test_request("getBlocks", Some(json!([2u64])));
7570        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7571        assert_eq!(result, vec![3, 4, 8]);
7572
7573        let request = create_test_request("getBlocks", Some(json!([0u64, 4u64])));
7574        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7575        assert_eq!(result, vec![0, 1, 3, 4]);
7576
7577        let request = create_test_request("getBlocks", Some(json!([0u64, 7u64])));
7578        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7579        assert_eq!(result, vec![0, 1, 3, 4]);
7580
7581        let request = create_test_request("getBlocks", Some(json!([9u64, 11u64])));
7582        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7583        assert_eq!(result, Vec::<Slot>::new());
7584
7585        rpc.block_commitment_cache
7586            .write()
7587            .unwrap()
7588            .set_highest_super_majority_root(u64::MAX);
7589
7590        let request = create_test_request(
7591            "getBlocks",
7592            Some(json!([0u64, MAX_GET_CONFIRMED_BLOCKS_RANGE])),
7593        );
7594        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7595        assert_eq!(result, vec![0, 1, 3, 4, 8]);
7596
7597        let request = create_test_request(
7598            "getBlocks",
7599            Some(json!([0u64, MAX_GET_CONFIRMED_BLOCKS_RANGE + 1])),
7600        );
7601        let response = parse_failure_response(rpc.handle_request_sync(request));
7602        let expected = (
7603            ErrorCode::InvalidParams.code(),
7604            String::from("Slot range too large; max 500000"),
7605        );
7606        assert_eq!(response, expected);
7607    }
7608
7609    #[test]
7610    fn test_get_blocks_with_limit() {
7611        let rpc = RpcHandler::start();
7612        rpc.add_roots_to_blockstore(vec![0, 1, 3, 4, 8]);
7613        rpc.block_commitment_cache
7614            .write()
7615            .unwrap()
7616            .set_highest_super_majority_root(8);
7617
7618        let request = create_test_request("getBlocksWithLimit", Some(json!([0u64, 500_001u64])));
7619        let response = parse_failure_response(rpc.handle_request_sync(request));
7620        let expected = (
7621            ErrorCode::InvalidParams.code(),
7622            String::from("Limit too large; max 500000"),
7623        );
7624        assert_eq!(response, expected);
7625
7626        let request = create_test_request("getBlocksWithLimit", Some(json!([0u64, 0u64])));
7627        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7628        assert_eq!(result, Vec::<Slot>::new());
7629
7630        let request = create_test_request("getBlocksWithLimit", Some(json!([2u64, 2u64])));
7631        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7632        assert_eq!(result, vec![3, 4]);
7633
7634        let request = create_test_request("getBlocksWithLimit", Some(json!([2u64, 3u64])));
7635        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7636        assert_eq!(result, vec![3, 4, 8]);
7637
7638        let request = create_test_request("getBlocksWithLimit", Some(json!([2u64, 500_000u64])));
7639        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7640        assert_eq!(result, vec![3, 4, 8]);
7641
7642        let request = create_test_request("getBlocksWithLimit", Some(json!([9u64, 500_000u64])));
7643        let result: Vec<Slot> = parse_success_result(rpc.handle_request_sync(request));
7644        assert_eq!(result, Vec::<Slot>::new());
7645    }
7646
7647    #[test]
7648    fn test_get_block_time() {
7649        let rpc = RpcHandler::start();
7650        rpc.add_roots_to_blockstore(vec![1, 2, 3, 4, 5, 6, 7]);
7651
7652        let base_timestamp = rpc
7653            .bank_forks
7654            .read()
7655            .unwrap()
7656            .get(0)
7657            .unwrap()
7658            .unix_timestamp_from_genesis();
7659        rpc.block_commitment_cache
7660            .write()
7661            .unwrap()
7662            .set_highest_super_majority_root(7);
7663
7664        let slot_duration = slot_duration_from_slots_per_year(rpc.working_bank().slots_per_year());
7665
7666        let request = create_test_request("getBlockTime", Some(json!([2u64])));
7667        let result: Option<UnixTimestamp> = parse_success_result(rpc.handle_request_sync(request));
7668        let expected = Some(base_timestamp);
7669        assert_eq!(result, expected);
7670
7671        let request = create_test_request("getBlockTime", Some(json!([7u64])));
7672        let result: Option<UnixTimestamp> = parse_success_result(rpc.handle_request_sync(request));
7673        let expected = Some(base_timestamp + (7 * slot_duration).as_secs() as i64);
7674        assert_eq!(result, expected);
7675
7676        let request = create_test_request("getBlockTime", Some(json!([12345u64])));
7677        let response = parse_failure_response(rpc.handle_request_sync(request));
7678        let expected = (
7679            JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE,
7680            String::from("Block not available for slot 12345"),
7681        );
7682        assert_eq!(response, expected);
7683    }
7684
7685    #[test]
7686    fn test_get_vote_accounts() {
7687        let rpc = RpcHandler::start();
7688        let mut bank = rpc.working_bank();
7689        let RpcHandler {
7690            ref io,
7691            ref meta,
7692            ref mint_keypair,
7693            ref leader_vote_keypair,
7694            ..
7695        } = rpc;
7696
7697        assert_eq!(bank.vote_accounts().len(), 1);
7698
7699        // Create a vote account with no stake.
7700        let alice_vote_keypair = Keypair::new();
7701        let alice_vote_state = VoteStateV4::new(
7702            &alice_vote_keypair.pubkey(),
7703            &VoteInit {
7704                node_pubkey: mint_keypair.pubkey(),
7705                authorized_voter: alice_vote_keypair.pubkey(),
7706                authorized_withdrawer: alice_vote_keypair.pubkey(),
7707                commission: 0,
7708            },
7709            &bank.get_sysvar_cache_for_tests().get_clock().unwrap(),
7710        );
7711        rpc.store_vote_account(&alice_vote_keypair.pubkey(), alice_vote_state);
7712        assert_eq!(bank.vote_accounts().len(), 2);
7713
7714        // Check getVoteAccounts: the bootstrap validator vote account will be delinquent as it has
7715        // stake but has never voted, and the vote account with no stake should not be present.
7716        {
7717            let req = r#"{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts"}"#;
7718            let res = io.handle_request_sync(req, meta.clone());
7719            let result: Value = serde_json::from_str(&res.expect("actual response"))
7720                .expect("actual response deserialization");
7721
7722            let vote_account_status: RpcVoteAccountStatus =
7723                serde_json::from_value(result["result"].clone()).unwrap();
7724
7725            assert!(vote_account_status.current.is_empty());
7726            assert_eq!(vote_account_status.delinquent.len(), 1);
7727            for vote_account_info in vote_account_status.delinquent {
7728                assert_ne!(vote_account_info.activated_stake, 0);
7729            }
7730        }
7731
7732        let mut advance_bank = || {
7733            bank.freeze();
7734
7735            // Votes
7736            let instructions = [
7737                vote_instruction::tower_sync(
7738                    &leader_vote_keypair.pubkey(),
7739                    &leader_vote_keypair.pubkey(),
7740                    TowerSync::new_from_slot(bank.slot(), bank.hash()),
7741                ),
7742                vote_instruction::tower_sync(
7743                    &alice_vote_keypair.pubkey(),
7744                    &alice_vote_keypair.pubkey(),
7745                    TowerSync::new_from_slot(bank.slot(), bank.hash()),
7746                ),
7747            ];
7748
7749            bank = rpc.advance_bank_to_confirmed_slot(bank.slot() + 1);
7750
7751            let transaction = Transaction::new_signed_with_payer(
7752                &instructions,
7753                Some(&rpc.mint_keypair.pubkey()),
7754                &[&rpc.mint_keypair, leader_vote_keypair, &alice_vote_keypair],
7755                bank.last_blockhash(),
7756            );
7757
7758            bank.process_transaction(&transaction)
7759                .expect("process transaction");
7760        };
7761
7762        // Advance bank to the next epoch
7763        for _ in 0..TEST_SLOTS_PER_EPOCH {
7764            advance_bank();
7765        }
7766
7767        let req = format!(
7768            r#"{{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts","params":{}}}"#,
7769            json!([CommitmentConfig::processed()])
7770        );
7771
7772        let res = io.handle_request_sync(&req, meta.clone());
7773        let result: Value = serde_json::from_str(&res.expect("actual response"))
7774            .expect("actual response deserialization");
7775
7776        let vote_account_status: RpcVoteAccountStatus =
7777            serde_json::from_value(result["result"].clone()).unwrap();
7778
7779        // The vote account with no stake should not be present.
7780        assert!(vote_account_status.delinquent.is_empty());
7781
7782        // Both accounts should be active and have voting history.
7783        assert_eq!(vote_account_status.current.len(), 2);
7784        let leader_info = vote_account_status
7785            .current
7786            .iter()
7787            .find(|x| x.vote_pubkey == leader_vote_keypair.pubkey().to_string())
7788            .unwrap();
7789        assert_ne!(leader_info.activated_stake, 0);
7790        // Subtract one because the last vote always carries over to the next epoch
7791        // Each slot earned maximum credits
7792        let credits_per_slot =
7793            solana_vote_program::vote_state::VOTE_CREDITS_MAXIMUM_PER_SLOT as u64;
7794        let expected_credits =
7795            (TEST_SLOTS_PER_EPOCH - MAX_LOCKOUT_HISTORY as u64 - 1) * credits_per_slot;
7796        assert_eq!(
7797            leader_info.epoch_credits,
7798            vec![
7799                (0, expected_credits, 0),
7800                (1, expected_credits + credits_per_slot, expected_credits) // one vote in current epoch
7801            ]
7802        );
7803
7804        // Filter request based on the leader:
7805        {
7806            let req = format!(
7807                r#"{{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts","params":{}}}"#,
7808                json!([RpcGetVoteAccountsConfig {
7809                    vote_pubkey: Some(leader_vote_keypair.pubkey().to_string()),
7810                    commitment: Some(CommitmentConfig::processed()),
7811                    ..RpcGetVoteAccountsConfig::default()
7812                }])
7813            );
7814
7815            let res = io.handle_request_sync(&req, meta.clone());
7816            let result: Value = serde_json::from_str(&res.expect("actual response"))
7817                .expect("actual response deserialization");
7818
7819            let vote_account_status: RpcVoteAccountStatus =
7820                serde_json::from_value(result["result"].clone()).unwrap();
7821
7822            assert_eq!(vote_account_status.current.len(), 1);
7823            assert_eq!(vote_account_status.delinquent.len(), 0);
7824            for vote_account_info in vote_account_status.current {
7825                assert_eq!(
7826                    vote_account_info.vote_pubkey,
7827                    leader_vote_keypair.pubkey().to_string()
7828                );
7829            }
7830        }
7831
7832        // Overflow the epoch credits history and ensure only `MAX_RPC_VOTE_ACCOUNT_INFO_EPOCH_CREDITS_HISTORY`
7833        // results are returned
7834        for _ in
7835            0..(TEST_SLOTS_PER_EPOCH * (MAX_RPC_VOTE_ACCOUNT_INFO_EPOCH_CREDITS_HISTORY) as u64)
7836        {
7837            advance_bank();
7838        }
7839
7840        let req = format!(
7841            r#"{{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts","params":{}}}"#,
7842            json!([CommitmentConfig::processed()])
7843        );
7844
7845        let res = io.handle_request_sync(&req, meta.clone());
7846        let result: Value = serde_json::from_str(&res.expect("actual response"))
7847            .expect("actual response deserialization");
7848
7849        let vote_account_status: RpcVoteAccountStatus =
7850            serde_json::from_value(result["result"].clone()).unwrap();
7851
7852        assert!(vote_account_status.delinquent.is_empty());
7853        assert!(!vote_account_status
7854            .current
7855            .iter()
7856            .any(|x| x.epoch_credits.len() != MAX_RPC_VOTE_ACCOUNT_INFO_EPOCH_CREDITS_HISTORY));
7857
7858        // Advance bank with no voting
7859        rpc.advance_bank_to_confirmed_slot(bank.slot() + TEST_SLOTS_PER_EPOCH);
7860
7861        // The leader vote account should now be delinquent, and the other vote account disappears
7862        // because it's inactive with no stake
7863        {
7864            let req = format!(
7865                r#"{{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts","params":{}}}"#,
7866                json!([CommitmentConfig::processed()])
7867            );
7868
7869            let res = io.handle_request_sync(&req, meta.clone());
7870            let result: Value = serde_json::from_str(&res.expect("actual response"))
7871                .expect("actual response deserialization");
7872
7873            let vote_account_status: RpcVoteAccountStatus =
7874                serde_json::from_value(result["result"].clone()).unwrap();
7875
7876            assert!(vote_account_status.current.is_empty());
7877            assert_eq!(vote_account_status.delinquent.len(), 1);
7878            for vote_account_info in vote_account_status.delinquent {
7879                assert_eq!(
7880                    vote_account_info.vote_pubkey,
7881                    rpc.leader_vote_keypair.pubkey().to_string()
7882                );
7883            }
7884        }
7885    }
7886
7887    #[test]
7888    fn test_is_finalized() {
7889        let bank = Arc::new(Bank::default_for_tests());
7890        let ledger_path = get_tmp_ledger_path!();
7891        let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
7892        blockstore.set_roots([0, 1].iter()).unwrap();
7893        // Build BlockCommitmentCache with rooted slots
7894        let mut cache0 = BlockCommitment::default();
7895        cache0.increase_rooted_stake(50);
7896        let mut cache1 = BlockCommitment::default();
7897        cache1.increase_rooted_stake(40);
7898        let mut cache2 = BlockCommitment::default();
7899        cache2.increase_rooted_stake(20);
7900
7901        let mut block_commitment = HashMap::new();
7902        block_commitment.entry(1).or_insert(cache0);
7903        block_commitment.entry(2).or_insert(cache1);
7904        block_commitment.entry(3).or_insert(cache2);
7905        let highest_super_majority_root = 1;
7906        let block_commitment_cache = BlockCommitmentCache::new(
7907            block_commitment,
7908            50,
7909            CommitmentSlots {
7910                slot: bank.slot(),
7911                highest_super_majority_root,
7912                ..CommitmentSlots::default()
7913            },
7914        );
7915
7916        assert!(is_finalized(&block_commitment_cache, &bank, &blockstore, 0));
7917        assert!(is_finalized(&block_commitment_cache, &bank, &blockstore, 1));
7918        assert!(!is_finalized(
7919            &block_commitment_cache,
7920            &bank,
7921            &blockstore,
7922            2
7923        ));
7924        assert!(!is_finalized(
7925            &block_commitment_cache,
7926            &bank,
7927            &blockstore,
7928            3
7929        ));
7930    }
7931
7932    #[test]
7933    fn test_token_rpcs() {
7934        for program_id in solana_account_decoder::parse_token::spl_token_ids() {
7935            let rpc = RpcHandler::start();
7936            let bank = rpc.working_bank();
7937            let RpcHandler { io, meta, .. } = rpc;
7938            let mint = Pubkey::new_from_array([2; 32]);
7939            let owner = Pubkey::new_from_array([3; 32]);
7940            let delegate = Pubkey::new_from_array([4; 32]);
7941            let token_account_pubkey = solana_pubkey::new_rand();
7942            let token_with_different_mint_pubkey = solana_pubkey::new_rand();
7943            let new_mint = Pubkey::new_from_array([5; 32]);
7944            if program_id == spl_generic_token::token_2022::id() {
7945                // Add the token account
7946                let account_base = TokenAccount {
7947                    mint,
7948                    owner,
7949                    delegate: COption::Some(delegate),
7950                    amount: 420,
7951                    state: TokenAccountState::Initialized,
7952                    is_native: COption::None,
7953                    delegated_amount: 30,
7954                    close_authority: COption::Some(owner),
7955                };
7956                let account_size = ExtensionType::try_calculate_account_len::<TokenAccount>(&[
7957                    ExtensionType::ImmutableOwner,
7958                    ExtensionType::MemoTransfer,
7959                ])
7960                .unwrap();
7961                let mut account_data = vec![0; account_size];
7962                let mut account_state =
7963                    StateWithExtensionsMut::<TokenAccount>::unpack_uninitialized(&mut account_data)
7964                        .unwrap();
7965
7966                account_state.base = account_base;
7967                account_state.pack_base();
7968                account_state.init_account_type().unwrap();
7969                account_state
7970                    .init_extension::<ImmutableOwner>(true)
7971                    .unwrap();
7972                let memo_transfer = account_state.init_extension::<MemoTransfer>(true).unwrap();
7973                memo_transfer.require_incoming_transfer_memos = true.into();
7974
7975                let token_account = AccountSharedData::from(Account {
7976                    lamports: 111,
7977                    data: account_data.to_vec(),
7978                    owner: program_id,
7979                    ..Account::default()
7980                });
7981                bank.store_account(&token_account_pubkey, &token_account);
7982
7983                // Add the mint
7984                let mint_size = ExtensionType::try_calculate_account_len::<Mint>(&[
7985                    ExtensionType::MintCloseAuthority,
7986                ])
7987                .unwrap();
7988                let mint_base = Mint {
7989                    mint_authority: COption::Some(owner),
7990                    supply: 500,
7991                    decimals: 2,
7992                    is_initialized: true,
7993                    freeze_authority: COption::Some(owner),
7994                };
7995                let mut mint_data = vec![0; mint_size];
7996                let mut mint_state =
7997                    StateWithExtensionsMut::<Mint>::unpack_uninitialized(&mut mint_data).unwrap();
7998
7999                mint_state.base = mint_base;
8000                mint_state.pack_base();
8001                mint_state.init_account_type().unwrap();
8002                let mint_close_authority = mint_state
8003                    .init_extension::<MintCloseAuthority>(true)
8004                    .unwrap();
8005                mint_close_authority.close_authority =
8006                    OptionalNonZeroPubkey::try_from(Some(owner)).unwrap();
8007
8008                let mint_account = AccountSharedData::from(Account {
8009                    lamports: 111,
8010                    data: mint_data.to_vec(),
8011                    owner: program_id,
8012                    ..Account::default()
8013                });
8014                bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account);
8015
8016                // Add another token account with the same owner, delegate, and mint
8017                let other_token_account_pubkey = solana_pubkey::new_rand();
8018                bank.store_account(&other_token_account_pubkey, &token_account);
8019
8020                // Add another token account with the same owner and delegate but different mint
8021                let mut account_data = vec![0; TokenAccount::get_packed_len()];
8022                let token_account = TokenAccount {
8023                    mint: new_mint,
8024                    owner,
8025                    delegate: COption::Some(delegate),
8026                    amount: 42,
8027                    state: TokenAccountState::Initialized,
8028                    is_native: COption::None,
8029                    delegated_amount: 30,
8030                    close_authority: COption::Some(owner),
8031                };
8032                TokenAccount::pack(token_account, &mut account_data).unwrap();
8033                let token_account = AccountSharedData::from(Account {
8034                    lamports: 111,
8035                    data: account_data.to_vec(),
8036                    owner: program_id,
8037                    ..Account::default()
8038                });
8039                bank.store_account(&token_with_different_mint_pubkey, &token_account);
8040            } else {
8041                // Add the token account
8042                let mut account_data = vec![0; TokenAccount::get_packed_len()];
8043                let token_account = TokenAccount {
8044                    mint,
8045                    owner,
8046                    delegate: COption::Some(delegate),
8047                    amount: 420,
8048                    state: TokenAccountState::Initialized,
8049                    is_native: COption::None,
8050                    delegated_amount: 30,
8051                    close_authority: COption::Some(owner),
8052                };
8053                TokenAccount::pack(token_account, &mut account_data).unwrap();
8054                let token_account = AccountSharedData::from(Account {
8055                    lamports: 111,
8056                    data: account_data.to_vec(),
8057                    owner: program_id,
8058                    ..Account::default()
8059                });
8060                bank.store_account(&token_account_pubkey, &token_account);
8061
8062                // Add the mint
8063                let mut mint_data = vec![0; Mint::get_packed_len()];
8064                let mint_state = Mint {
8065                    mint_authority: COption::Some(owner),
8066                    supply: 500,
8067                    decimals: 2,
8068                    is_initialized: true,
8069                    freeze_authority: COption::Some(owner),
8070                };
8071                Mint::pack(mint_state, &mut mint_data).unwrap();
8072                let mint_account = AccountSharedData::from(Account {
8073                    lamports: 111,
8074                    data: mint_data.to_vec(),
8075                    owner: program_id,
8076                    ..Account::default()
8077                });
8078                bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account);
8079
8080                // Add another token account with the same owner, delegate, and mint
8081                let other_token_account_pubkey = solana_pubkey::new_rand();
8082                bank.store_account(&other_token_account_pubkey, &token_account);
8083
8084                // Add another token account with the same owner and delegate but different mint
8085                let mut account_data = vec![0; TokenAccount::get_packed_len()];
8086                let token_account = TokenAccount {
8087                    mint: new_mint,
8088                    owner,
8089                    delegate: COption::Some(delegate),
8090                    amount: 42,
8091                    state: TokenAccountState::Initialized,
8092                    is_native: COption::None,
8093                    delegated_amount: 30,
8094                    close_authority: COption::Some(owner),
8095                };
8096                TokenAccount::pack(token_account, &mut account_data).unwrap();
8097                let token_account = AccountSharedData::from(Account {
8098                    lamports: 111,
8099                    data: account_data.to_vec(),
8100                    owner: program_id,
8101                    ..Account::default()
8102                });
8103                bank.store_account(&token_with_different_mint_pubkey, &token_account);
8104            }
8105
8106            let req = format!(
8107                r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenAccountBalance","params":["{token_account_pubkey}"]}}"#,
8108            );
8109            let res = io.handle_request_sync(&req, meta.clone());
8110            let result: Value = serde_json::from_str(&res.expect("actual response"))
8111                .expect("actual response deserialization");
8112            let balance: UiTokenAmount =
8113                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8114            let error = f64::EPSILON;
8115            assert!((balance.ui_amount.unwrap() - 4.2).abs() < error);
8116            assert_eq!(balance.amount, 420.to_string());
8117            assert_eq!(balance.decimals, 2);
8118            assert_eq!(balance.ui_amount_string, "4.2".to_string());
8119
8120            // Test non-existent token account
8121            let req = format!(
8122                r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenAccountBalance","params":["{}"]}}"#,
8123                solana_pubkey::new_rand(),
8124            );
8125            let res = io.handle_request_sync(&req, meta.clone());
8126            let result: Value = serde_json::from_str(&res.expect("actual response"))
8127                .expect("actual response deserialization");
8128            assert!(result.get("error").is_some());
8129
8130            // Test get token supply, pulls supply from mint
8131            let req = format!(
8132                r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenSupply","params":["{mint}"]}}"#,
8133            );
8134            let res = io.handle_request_sync(&req, meta.clone());
8135            let result: Value = serde_json::from_str(&res.expect("actual response"))
8136                .expect("actual response deserialization");
8137            let supply: UiTokenAmount =
8138                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8139            let error = f64::EPSILON;
8140            assert!((supply.ui_amount.unwrap() - 5.0).abs() < error);
8141            assert_eq!(supply.amount, 500.to_string());
8142            assert_eq!(supply.decimals, 2);
8143            assert_eq!(supply.ui_amount_string, "5".to_string());
8144
8145            // Test non-existent mint address
8146            let req = format!(
8147                r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenSupply","params":["{}"]}}"#,
8148                solana_pubkey::new_rand(),
8149            );
8150            let res = io.handle_request_sync(&req, meta.clone());
8151            let result: Value = serde_json::from_str(&res.expect("actual response"))
8152                .expect("actual response deserialization");
8153            assert!(result.get("error").is_some());
8154
8155            // Test getTokenAccountsByOwner with Token program id returns all accounts, regardless of Mint address
8156            let req = format!(
8157                r#"{{
8158                    "jsonrpc":"2.0",
8159                    "id":1,
8160                    "method":"getTokenAccountsByOwner",
8161                    "params":["{owner}", {{"programId": "{program_id}"}}, {{"encoding":"base64"}}]
8162                }}"#,
8163            );
8164            let res = io.handle_request_sync(&req, meta.clone());
8165            let result: Value = serde_json::from_str(&res.expect("actual response"))
8166                .expect("actual response deserialization");
8167            let accounts: Vec<RpcKeyedAccount> =
8168                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8169            assert_eq!(accounts.len(), 3);
8170
8171            // Test getTokenAccountsByOwner with jsonParsed encoding doesn't return accounts with invalid mints
8172            let req = format!(
8173                r#"{{
8174                    "jsonrpc":"2.0",
8175                    "id":1,
8176                    "method":"getTokenAccountsByOwner",
8177                    "params":["{owner}", {{"programId": "{program_id}"}}, {{"encoding": "jsonParsed"}}]
8178                }}"#,
8179            );
8180            let res = io.handle_request_sync(&req, meta.clone());
8181            let result: Value = serde_json::from_str(&res.expect("actual response"))
8182                .expect("actual response deserialization");
8183            let accounts: Vec<RpcKeyedAccount> =
8184                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8185            assert_eq!(accounts.len(), 2);
8186
8187            // Test getProgramAccounts with jsonParsed encoding returns mints, but doesn't return accounts with invalid mints
8188            let req = format!(
8189                r#"{{
8190                    "jsonrpc":"2.0",
8191                    "id":1,
8192                    "method":"getProgramAccounts",
8193                    "params":["{program_id}", {{"encoding": "jsonParsed"}}]
8194                }}"#,
8195            );
8196            let res = io.handle_request_sync(&req, meta.clone());
8197            let result: Value = serde_json::from_str(&res.expect("actual response"))
8198                .expect("actual response deserialization");
8199            let accounts: Vec<RpcKeyedAccount> =
8200                serde_json::from_value(result["result"].clone()).unwrap();
8201            if program_id == spl_generic_token::token::id() {
8202                // native mint is included for token-v3
8203                assert_eq!(accounts.len(), 4);
8204            } else {
8205                assert_eq!(accounts.len(), 3);
8206            }
8207
8208            // Test returns only mint accounts
8209            let req = format!(
8210                r#"{{
8211                    "jsonrpc":"2.0",
8212                    "id":1,"method":"getTokenAccountsByOwner",
8213                    "params":["{owner}", {{"mint": "{mint}"}}, {{"encoding":"base64"}}]
8214                }}"#,
8215            );
8216            let res = io.handle_request_sync(&req, meta.clone());
8217            let result: Value = serde_json::from_str(&res.expect("actual response"))
8218                .expect("actual response deserialization");
8219            let accounts: Vec<RpcKeyedAccount> =
8220                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8221            assert_eq!(accounts.len(), 2);
8222
8223            // Test non-existent Mint/program id
8224            let req = format!(
8225                r#"{{
8226                    "jsonrpc":"2.0",
8227                    "id":1,
8228                    "method":"getTokenAccountsByOwner",
8229                    "params":["{}", {{"programId": "{}"}}]
8230                }}"#,
8231                owner,
8232                solana_pubkey::new_rand(),
8233            );
8234            let res = io.handle_request_sync(&req, meta.clone());
8235            let result: Value = serde_json::from_str(&res.expect("actual response"))
8236                .expect("actual response deserialization");
8237            assert!(result.get("error").is_some());
8238            let req = format!(
8239                r#"{{
8240                    "jsonrpc":"2.0",
8241                    "id":1,
8242                    "method":"getTokenAccountsByOwner",
8243                    "params":["{}", {{"mint": "{}"}}]
8244                }}"#,
8245                owner,
8246                solana_pubkey::new_rand(),
8247            );
8248            let res = io.handle_request_sync(&req, meta.clone());
8249            let result: Value = serde_json::from_str(&res.expect("actual response"))
8250                .expect("actual response deserialization");
8251            assert!(result.get("error").is_some());
8252
8253            // Test non-existent Owner
8254            let req = format!(
8255                r#"{{
8256                    "jsonrpc":"2.0",
8257                    "id":1,
8258                    "method":"getTokenAccountsByOwner",
8259                    "params":["{}", {{"programId": "{}"}}]
8260                }}"#,
8261                solana_pubkey::new_rand(),
8262                program_id,
8263            );
8264            let res = io.handle_request_sync(&req, meta.clone());
8265            let result: Value = serde_json::from_str(&res.expect("actual response"))
8266                .expect("actual response deserialization");
8267            let accounts: Vec<RpcKeyedAccount> =
8268                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8269            assert!(accounts.is_empty());
8270
8271            // Test getTokenAccountsByDelegate with Token program id returns all accounts, regardless of Mint address
8272            let req = format!(
8273                r#"{{
8274                    "jsonrpc":"2.0",
8275                    "id":1,
8276                    "method":"getTokenAccountsByDelegate",
8277                    "params":["{delegate}", {{"programId": "{program_id}"}}, {{"encoding":"base64"}}]
8278                }}"#,
8279            );
8280            let res = io.handle_request_sync(&req, meta.clone());
8281            let result: Value = serde_json::from_str(&res.expect("actual response"))
8282                .expect("actual response deserialization");
8283            let accounts: Vec<RpcKeyedAccount> =
8284                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8285            assert_eq!(accounts.len(), 3);
8286
8287            // Test returns only mint accounts
8288            let req = format!(
8289                r#"{{
8290                    "jsonrpc":"2.0",
8291                    "id":1,"method":
8292                    "getTokenAccountsByDelegate",
8293                    "params":["{delegate}", {{"mint": "{mint}"}}, {{"encoding":"base64"}}]
8294                }}"#,
8295            );
8296            let res = io.handle_request_sync(&req, meta.clone());
8297            let result: Value = serde_json::from_str(&res.expect("actual response"))
8298                .expect("actual response deserialization");
8299            let accounts: Vec<RpcKeyedAccount> =
8300                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8301            assert_eq!(accounts.len(), 2);
8302
8303            // Test non-existent Mint/program id
8304            let req = format!(
8305                r#"{{
8306                    "jsonrpc":"2.0",
8307                    "id":1,
8308                    "method":"getTokenAccountsByDelegate",
8309                    "params":["{}", {{"programId": "{}"}}]
8310                }}"#,
8311                delegate,
8312                solana_pubkey::new_rand(),
8313            );
8314            let res = io.handle_request_sync(&req, meta.clone());
8315            let result: Value = serde_json::from_str(&res.expect("actual response"))
8316                .expect("actual response deserialization");
8317            assert!(result.get("error").is_some());
8318            let req = format!(
8319                r#"{{
8320                    "jsonrpc":"2.0",
8321                    "id":1,
8322                    "method":"getTokenAccountsByDelegate",
8323                    "params":["{}", {{"mint": "{}"}}]
8324                }}"#,
8325                delegate,
8326                solana_pubkey::new_rand(),
8327            );
8328            let res = io.handle_request_sync(&req, meta.clone());
8329            let result: Value = serde_json::from_str(&res.expect("actual response"))
8330                .expect("actual response deserialization");
8331            assert!(result.get("error").is_some());
8332
8333            // Test non-existent Delegate
8334            let req = format!(
8335                r#"{{
8336                    "jsonrpc":"2.0",
8337                    "id":1,
8338                    "method":"getTokenAccountsByDelegate",
8339                    "params":["{}", {{"programId": "{}"}}]
8340                }}"#,
8341                solana_pubkey::new_rand(),
8342                program_id,
8343            );
8344            let res = io.handle_request_sync(&req, meta.clone());
8345            let result: Value = serde_json::from_str(&res.expect("actual response"))
8346                .expect("actual response deserialization");
8347            let accounts: Vec<RpcKeyedAccount> =
8348                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8349            assert!(accounts.is_empty());
8350
8351            // Add new_mint, and another token account on new_mint with different balance
8352            let mut mint_data = vec![0; Mint::get_packed_len()];
8353            let mint_state = Mint {
8354                mint_authority: COption::Some(owner),
8355                supply: 500,
8356                decimals: 2,
8357                is_initialized: true,
8358                freeze_authority: COption::Some(owner),
8359            };
8360            Mint::pack(mint_state, &mut mint_data).unwrap();
8361            let mint_account = AccountSharedData::from(Account {
8362                lamports: 111,
8363                data: mint_data.to_vec(),
8364                owner: program_id,
8365                ..Account::default()
8366            });
8367            bank.store_account(
8368                &Pubkey::from_str(&new_mint.to_string()).unwrap(),
8369                &mint_account,
8370            );
8371            let mut account_data = vec![0; TokenAccount::get_packed_len()];
8372            let token_account = TokenAccount {
8373                mint: new_mint,
8374                owner,
8375                delegate: COption::Some(delegate),
8376                amount: 10,
8377                state: TokenAccountState::Initialized,
8378                is_native: COption::None,
8379                delegated_amount: 30,
8380                close_authority: COption::Some(owner),
8381            };
8382            TokenAccount::pack(token_account, &mut account_data).unwrap();
8383            let token_account = AccountSharedData::from(Account {
8384                lamports: 111,
8385                data: account_data.to_vec(),
8386                owner: program_id,
8387                ..Account::default()
8388            });
8389            let token_with_smaller_balance = solana_pubkey::new_rand();
8390            bank.store_account(&token_with_smaller_balance, &token_account);
8391
8392            // Test largest token accounts
8393            let req = format!(
8394                r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenLargestAccounts","params":["{new_mint}"]}}"#,
8395            );
8396            let res = io.handle_request_sync(&req, meta);
8397            let result: Value = serde_json::from_str(&res.expect("actual response"))
8398                .expect("actual response deserialization");
8399            let largest_accounts: Vec<RpcTokenAccountBalance> =
8400                serde_json::from_value(result["result"]["value"].clone()).unwrap();
8401            assert_eq!(
8402                largest_accounts,
8403                vec![
8404                    RpcTokenAccountBalance {
8405                        address: token_with_different_mint_pubkey.to_string(),
8406                        amount: UiTokenAmount {
8407                            ui_amount: Some(0.42),
8408                            decimals: 2,
8409                            amount: "42".to_string(),
8410                            ui_amount_string: "0.42".to_string(),
8411                        }
8412                    },
8413                    RpcTokenAccountBalance {
8414                        address: token_with_smaller_balance.to_string(),
8415                        amount: UiTokenAmount {
8416                            ui_amount: Some(0.1),
8417                            decimals: 2,
8418                            amount: "10".to_string(),
8419                            ui_amount_string: "0.1".to_string(),
8420                        }
8421                    }
8422                ]
8423            );
8424        }
8425    }
8426
8427    #[test_case(spl_token_interface::id(), None, None; "spl_token")]
8428    #[test_case(spl_token_2022_interface::id(), Some(InterestBearingConfig { pre_update_average_rate: 500.into(), current_rate: 500.into(),..Default::default() }), None; "spl_token_2022_with _interest")]
8429    #[test_case(spl_token_2022_interface::id(), None, Some(ScaledUiAmountConfig { new_multiplier: 2.0f64.into(), ..Default::default() }); "spl-token-2022 with multiplier")]
8430    fn test_token_parsing(
8431        program_id: Pubkey,
8432        mut interest_bearing_config: Option<InterestBearingConfig>,
8433        scaled_ui_amount_config: Option<ScaledUiAmountConfig>,
8434    ) {
8435        let rpc = RpcHandler::start();
8436        let bank = rpc.working_bank();
8437        let RpcHandler { io, meta, .. } = rpc;
8438
8439        let mint = Pubkey::new_from_array([2; 32]);
8440        let owner = Pubkey::new_from_array([3; 32]);
8441        let delegate = Pubkey::new_from_array([4; 32]);
8442        let token_account_pubkey = solana_pubkey::new_rand();
8443        let amount = 420;
8444        let delegated_amount = 30;
8445        let rent_exempt_amount = 10;
8446        let supply = 500;
8447        let decimals = 2;
8448        let (program_name, account_size, mint_size, additional_data) = if program_id
8449            == spl_generic_token::token_2022::id()
8450        {
8451            let account_base = TokenAccount {
8452                mint,
8453                owner,
8454                delegate: COption::Some(delegate),
8455                amount,
8456                state: TokenAccountState::Initialized,
8457                is_native: COption::Some(rent_exempt_amount),
8458                delegated_amount,
8459                close_authority: COption::Some(owner),
8460            };
8461            let account_size = ExtensionType::try_calculate_account_len::<TokenAccount>(&[
8462                ExtensionType::ImmutableOwner,
8463                ExtensionType::MemoTransfer,
8464            ])
8465            .unwrap();
8466            let mut account_data = vec![0; account_size];
8467            let mut account_state =
8468                StateWithExtensionsMut::<TokenAccount>::unpack_uninitialized(&mut account_data)
8469                    .unwrap();
8470
8471            account_state.base = account_base;
8472            account_state.pack_base();
8473            account_state.init_account_type().unwrap();
8474            account_state
8475                .init_extension::<ImmutableOwner>(true)
8476                .unwrap();
8477            let memo_transfer = account_state.init_extension::<MemoTransfer>(true).unwrap();
8478            memo_transfer.require_incoming_transfer_memos = true.into();
8479
8480            let token_account = AccountSharedData::from(Account {
8481                lamports: 111,
8482                data: account_data.to_vec(),
8483                owner: program_id,
8484                ..Account::default()
8485            });
8486            bank.store_account(&token_account_pubkey, &token_account);
8487
8488            let mint_base = Mint {
8489                mint_authority: COption::Some(owner),
8490                supply,
8491                decimals,
8492                is_initialized: true,
8493                freeze_authority: COption::Some(owner),
8494            };
8495            let mut extensions = vec![ExtensionType::MintCloseAuthority];
8496            if interest_bearing_config.is_some() {
8497                extensions.push(ExtensionType::InterestBearingConfig);
8498            }
8499            if scaled_ui_amount_config.is_some() {
8500                extensions.push(ExtensionType::ScaledUiAmount);
8501            }
8502            let mint_size = ExtensionType::try_calculate_account_len::<Mint>(&extensions).unwrap();
8503            let mut mint_data = vec![0; mint_size];
8504            let mut mint_state =
8505                StateWithExtensionsMut::<Mint>::unpack_uninitialized(&mut mint_data).unwrap();
8506
8507            mint_state.base = mint_base;
8508            mint_state.pack_base();
8509            mint_state.init_account_type().unwrap();
8510            let mint_close_authority = mint_state
8511                .init_extension::<MintCloseAuthority>(true)
8512                .unwrap();
8513            mint_close_authority.close_authority =
8514                OptionalNonZeroPubkey::try_from(Some(owner)).unwrap();
8515            if let Some(interest_bearing_config) = interest_bearing_config.as_mut() {
8516                interest_bearing_config.initialization_timestamp =
8517                    bank.clock().unix_timestamp.saturating_sub(1_000_000).into();
8518                interest_bearing_config.last_update_timestamp = bank.clock().unix_timestamp.into();
8519                let extension = mint_state
8520                    .init_extension::<InterestBearingConfig>(true)
8521                    .unwrap();
8522                *extension = *interest_bearing_config;
8523            }
8524
8525            if let Some(scaled_ui_amount_config) = scaled_ui_amount_config.as_ref() {
8526                let extension = mint_state
8527                    .init_extension::<ScaledUiAmountConfig>(true)
8528                    .unwrap();
8529                *extension = *scaled_ui_amount_config;
8530            }
8531
8532            let additional_data = SplTokenAdditionalDataV2 {
8533                decimals,
8534                interest_bearing_config: interest_bearing_config
8535                    .map(|v| (v, bank.clock().unix_timestamp)),
8536                scaled_ui_amount_config: scaled_ui_amount_config
8537                    .map(|v| (v, bank.clock().unix_timestamp)),
8538            };
8539
8540            let mint_account = AccountSharedData::from(Account {
8541                lamports: 111,
8542                data: mint_data.to_vec(),
8543                owner: program_id,
8544                ..Account::default()
8545            });
8546            bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account);
8547            ("spl-token-2022", account_size, mint_size, additional_data)
8548        } else {
8549            let account_size = TokenAccount::get_packed_len();
8550            let mut account_data = vec![0; account_size];
8551            let token_account = TokenAccount {
8552                mint,
8553                owner,
8554                delegate: COption::Some(delegate),
8555                amount,
8556                state: TokenAccountState::Initialized,
8557                is_native: COption::Some(rent_exempt_amount),
8558                delegated_amount,
8559                close_authority: COption::Some(owner),
8560            };
8561            TokenAccount::pack(token_account, &mut account_data).unwrap();
8562            let token_account = AccountSharedData::from(Account {
8563                lamports: 111,
8564                data: account_data.to_vec(),
8565                owner: program_id,
8566                ..Account::default()
8567            });
8568            bank.store_account(&token_account_pubkey, &token_account);
8569
8570            // Add the mint
8571            let mint_size = Mint::get_packed_len();
8572            let mut mint_data = vec![0; mint_size];
8573            let mint_state = Mint {
8574                mint_authority: COption::Some(owner),
8575                supply,
8576                decimals,
8577                is_initialized: true,
8578                freeze_authority: COption::Some(owner),
8579            };
8580            Mint::pack(mint_state, &mut mint_data).unwrap();
8581            let mint_account = AccountSharedData::from(Account {
8582                lamports: 111,
8583                data: mint_data.to_vec(),
8584                owner: program_id,
8585                ..Account::default()
8586            });
8587            bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account);
8588            let additional_data = SplTokenAdditionalDataV2::with_decimals(decimals);
8589            ("spl-token", account_size, mint_size, additional_data)
8590        };
8591
8592        let req = format!(
8593            r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{token_account_pubkey}", {{"encoding": "jsonParsed"}}]}}"#,
8594        );
8595        let res = io.handle_request_sync(&req, meta.clone());
8596        let result: Value = serde_json::from_str(&res.expect("actual response"))
8597            .expect("actual response deserialization");
8598        let token_ui_amount = token_amount_to_ui_amount_v3(amount, &additional_data);
8599        let delegated_ui_amount = token_amount_to_ui_amount_v3(delegated_amount, &additional_data);
8600        let rent_exempt_ui_amount =
8601            token_amount_to_ui_amount_v3(rent_exempt_amount, &additional_data);
8602        let mut expected_value = json!({
8603            "program": program_name,
8604            "space": account_size,
8605            "parsed": {
8606                "type": "account",
8607                "info": {
8608                    "mint": mint.to_string(),
8609                    "owner": owner.to_string(),
8610                    "tokenAmount": json!(token_ui_amount),
8611                    "delegate": delegate.to_string(),
8612                    "state": "initialized",
8613                    "isNative": true,
8614                    "rentExemptReserve": json!(rent_exempt_ui_amount),
8615                    "delegatedAmount": json!(delegated_ui_amount),
8616                    "closeAuthority": owner.to_string(),
8617                }
8618            }
8619        });
8620        if program_id == spl_generic_token::token_2022::id() {
8621            expected_value["parsed"]["info"]["extensions"] = json!([
8622                {
8623                    "extension": "immutableOwner"
8624                },
8625                {
8626                    "extension": "memoTransfer",
8627                    "state": {
8628                        "requireIncomingTransferMemos": true
8629                    }
8630                },
8631            ]);
8632        }
8633        assert_eq!(result["result"]["value"]["data"], expected_value,);
8634
8635        // Test Mint
8636        let req = format!(
8637            r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{mint}", {{"encoding": "jsonParsed"}}]}}"#,
8638        );
8639        let res = io.handle_request_sync(&req, meta);
8640        let result: Value = serde_json::from_str(&res.expect("actual response"))
8641            .expect("actual response deserialization");
8642        let mut expected_value = json!({
8643            "program": program_name,
8644            "space": mint_size,
8645            "parsed": {
8646                "type": "mint",
8647                "info": {
8648                    "mintAuthority": owner.to_string(),
8649                    "decimals": 2,
8650                    "supply": "500".to_string(),
8651                    "isInitialized": true,
8652                    "freezeAuthority": owner.to_string(),
8653                }
8654            }
8655        });
8656        if program_id == spl_generic_token::token_2022::id() {
8657            if interest_bearing_config.is_some() {
8658                expected_value["parsed"]["info"]["extensions"] = json!([
8659                    {
8660                        "extension": "mintCloseAuthority",
8661                        "state": {
8662                            "closeAuthority": owner.to_string(),
8663                        }
8664                    },
8665                    {
8666                        "extension": "interestBearingConfig",
8667                        "state": {
8668                            "currentRate": 500,
8669                            "initializationTimestamp": bank.clock().unix_timestamp.saturating_sub(1_000_000),
8670                            "lastUpdateTimestamp": bank.clock().unix_timestamp,
8671                            "preUpdateAverageRate": 500,
8672                            "rateAuthority": null,
8673                        }
8674                    }
8675                ]);
8676            }
8677            if scaled_ui_amount_config.is_some() {
8678                expected_value["parsed"]["info"]["extensions"] = json!([
8679                    {
8680                        "extension": "mintCloseAuthority",
8681                        "state": {
8682                            "closeAuthority": owner.to_string(),
8683                        }
8684                    },
8685                    {
8686                        "extension": "scaledUiAmountConfig",
8687                        "state": {
8688                            "multiplier": "0",
8689                            "newMultiplier": "2",
8690                            "newMultiplierEffectiveTimestamp": 0,
8691                            "authority": null,
8692                        }
8693                    }
8694                ]);
8695            }
8696        }
8697        assert_eq!(result["result"]["value"]["data"], expected_value,);
8698    }
8699
8700    #[test]
8701    fn test_get_spl_token_owner_filter() {
8702        // Filtering on token-v3 length
8703        let owner = Pubkey::new_unique();
8704        assert_eq!(
8705            get_spl_token_owner_filter(
8706                &spl_token_interface::id(),
8707                &[
8708                    RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
8709                    RpcFilterType::DataSize(165)
8710                ],
8711            )
8712            .unwrap()
8713            .unwrap(),
8714            owner
8715        );
8716
8717        // Filtering on token-2022 account type
8718        assert_eq!(
8719            get_spl_token_owner_filter(
8720                &token_2022::id(),
8721                &[
8722                    RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
8723                    RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
8724                ],
8725            )
8726            .unwrap()
8727            .unwrap(),
8728            owner
8729        );
8730
8731        // Filtering on token account state
8732        assert_eq!(
8733            get_spl_token_owner_filter(
8734                &token_2022::id(),
8735                &[
8736                    RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
8737                    RpcFilterType::TokenAccountState,
8738                ],
8739            )
8740            .unwrap()
8741            .unwrap(),
8742            owner
8743        );
8744
8745        // Can't filter on account type for token-v3
8746        assert!(get_spl_token_owner_filter(
8747            &spl_generic_token::token::id(),
8748            &[
8749                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
8750                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
8751            ],
8752        )
8753        .unwrap()
8754        .is_none());
8755
8756        // Filtering on mint instead of owner
8757        assert!(get_spl_token_owner_filter(
8758            &spl_generic_token::token::id(),
8759            &[
8760                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, owner.to_bytes().to_vec())),
8761                RpcFilterType::DataSize(165)
8762            ],
8763        )
8764        .unwrap()
8765        .is_none());
8766
8767        // Wrong program id
8768        assert!(get_spl_token_owner_filter(
8769            &Pubkey::new_unique(),
8770            &[
8771                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
8772                RpcFilterType::DataSize(165)
8773            ],
8774        )
8775        .unwrap()
8776        .is_none());
8777        assert!(get_spl_token_owner_filter(
8778            &Pubkey::new_unique(),
8779            &[
8780                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
8781                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
8782            ],
8783        )
8784        .unwrap()
8785        .is_none());
8786
8787        // Test invalid filters
8788
8789        // Filtering on invalid length pubkey
8790        let owner = Pubkey::new_unique();
8791        let mut first_half_bytes = owner.to_bytes().to_vec();
8792        first_half_bytes.resize(16, 0);
8793        assert!(get_spl_token_owner_filter(
8794            &spl_generic_token::token::id(),
8795            &[
8796                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, first_half_bytes)),
8797                RpcFilterType::DataSize(165)
8798            ],
8799        )
8800        .is_err_and(|err| err.code == ErrorCode::InvalidParams
8801            && err.message == "Incorrect byte length 16 for SPL token owner filter, expected 32"));
8802    }
8803
8804    #[test]
8805    fn test_get_spl_token_mint_filter() {
8806        // Filtering on token-v3 length
8807        let mint = Pubkey::new_unique();
8808        assert_eq!(
8809            get_spl_token_mint_filter(
8810                &spl_generic_token::token::id(),
8811                &[
8812                    RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
8813                    RpcFilterType::DataSize(165)
8814                ],
8815            )
8816            .unwrap()
8817            .unwrap(),
8818            mint
8819        );
8820
8821        // Filtering on token-2022 account type
8822        assert_eq!(
8823            get_spl_token_mint_filter(
8824                &spl_generic_token::token_2022::id(),
8825                &[
8826                    RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
8827                    RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
8828                ],
8829            )
8830            .unwrap()
8831            .unwrap(),
8832            mint
8833        );
8834
8835        // Filtering on token account state
8836        assert_eq!(
8837            get_spl_token_mint_filter(
8838                &spl_generic_token::token::id(),
8839                &[
8840                    RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
8841                    RpcFilterType::TokenAccountState,
8842                ],
8843            )
8844            .unwrap()
8845            .unwrap(),
8846            mint
8847        );
8848
8849        // Can't filter on account type for token-v3
8850        assert!(get_spl_token_mint_filter(
8851            &spl_generic_token::token::id(),
8852            &[
8853                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
8854                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
8855            ],
8856        )
8857        .unwrap()
8858        .is_none());
8859
8860        // Filtering on owner instead of mint
8861        assert!(get_spl_token_mint_filter(
8862            &spl_generic_token::token::id(),
8863            &[
8864                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, mint.to_bytes().to_vec())),
8865                RpcFilterType::DataSize(165)
8866            ],
8867        )
8868        .unwrap()
8869        .is_none());
8870
8871        // Wrong program id
8872        assert!(get_spl_token_mint_filter(
8873            &Pubkey::new_unique(),
8874            &[
8875                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
8876                RpcFilterType::DataSize(165)
8877            ],
8878        )
8879        .unwrap()
8880        .is_none());
8881        assert!(get_spl_token_mint_filter(
8882            &Pubkey::new_unique(),
8883            &[
8884                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
8885                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
8886            ],
8887        )
8888        .unwrap()
8889        .is_none());
8890
8891        // Test invalid filters
8892
8893        // Filtering on invalid length pubkey
8894        let owner = Pubkey::new_unique();
8895        let mut first_half_bytes = owner.to_bytes().to_vec();
8896        first_half_bytes.resize(16, 0);
8897        assert!(get_spl_token_mint_filter(
8898            &spl_generic_token::token::id(),
8899            &[
8900                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, first_half_bytes)),
8901                RpcFilterType::DataSize(165)
8902            ],
8903        )
8904        .is_err_and(|err| {
8905            print!("{err:?}");
8906            err.code == ErrorCode::InvalidParams
8907                && err.message == "Incorrect byte length 16 for SPL token mint filter, expected 32"
8908        }));
8909    }
8910
8911    #[test]
8912    fn test_rpc_single_gossip() {
8913        let exit = Arc::new(AtomicBool::new(false));
8914        let validator_exit = create_validator_exit(exit.clone());
8915        let ledger_path = get_tmp_ledger_path!();
8916        let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
8917        let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
8918        let cluster_info = Arc::new(new_test_cluster_info());
8919        let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100);
8920        let bank = Bank::new_for_tests(&genesis_config);
8921
8922        let bank_forks = BankForks::new_rw_arc(bank);
8923        let bank0 = bank_forks.read().unwrap().get(0).unwrap();
8924        let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
8925        bank_forks.write().unwrap().insert(bank1);
8926        let bank1 = bank_forks.read().unwrap().get(1).unwrap();
8927        let bank2 = Bank::new_from_parent(bank1, &Pubkey::default(), 2);
8928        bank_forks.write().unwrap().insert(bank2);
8929        let bank2 = bank_forks.read().unwrap().get(2).unwrap();
8930        let bank3 = Bank::new_from_parent(bank2, &Pubkey::default(), 3);
8931        bank_forks.write().unwrap().insert(bank3);
8932
8933        let optimistically_confirmed_bank =
8934            OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
8935        let mut pending_optimistically_confirmed_banks = HashSet::new();
8936        let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
8937        let subscriptions = Arc::new(RpcSubscriptions::new_for_tests(
8938            exit,
8939            max_complete_transaction_status_slot.clone(),
8940            bank_forks.clone(),
8941            block_commitment_cache.clone(),
8942            optimistically_confirmed_bank.clone(),
8943        ));
8944
8945        let config = JsonRpcConfig::default();
8946        let JsonRpcConfig {
8947            rpc_threads,
8948            rpc_blocking_threads,
8949            rpc_niceness_adj,
8950            ..
8951        } = config;
8952        let (meta, _receiver) = JsonRpcRequestProcessor::new(
8953            config,
8954            None,
8955            bank_forks.clone(),
8956            block_commitment_cache,
8957            blockstore.clone(),
8958            validator_exit,
8959            RpcHealth::stub(optimistically_confirmed_bank.clone(), blockstore.clone()),
8960            cluster_info,
8961            Hash::default(),
8962            None,
8963            optimistically_confirmed_bank.clone(),
8964            Arc::new(RwLock::new(LargestAccountsCache::new(30))),
8965            Arc::new(MaxSlots::default()),
8966            Arc::new(LeaderScheduleCache::default()),
8967            max_complete_transaction_status_slot,
8968            Arc::new(PrioritizationFeeCache::default()),
8969            service_runtime(rpc_threads, rpc_blocking_threads, rpc_niceness_adj),
8970        );
8971
8972        let mut io = MetaIoHandler::default();
8973        io.extend_with(rpc_minimal::MinimalImpl.to_delegate());
8974        io.extend_with(rpc_full::FullImpl.to_delegate());
8975
8976        let req =
8977            r#"{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment":"confirmed"}]}"#;
8978        let res = io.handle_request_sync(req, meta.clone());
8979        let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
8980        let slot: Slot = serde_json::from_value(json["result"].clone()).unwrap();
8981        assert_eq!(slot, 0);
8982        let mut highest_confirmed_slot: Slot = 0;
8983        let mut highest_root_slot: Slot = 0;
8984        let mut last_notified_confirmed_slot: Slot = 0;
8985
8986        OptimisticallyConfirmedBankTracker::process_notification(
8987            (
8988                BankNotification::OptimisticallyConfirmed(2),
8989                None, /* no dependency work */
8990            ),
8991            &bank_forks,
8992            &optimistically_confirmed_bank,
8993            &subscriptions,
8994            &mut pending_optimistically_confirmed_banks,
8995            &mut last_notified_confirmed_slot,
8996            &mut highest_confirmed_slot,
8997            &mut highest_root_slot,
8998            &None,
8999            &PrioritizationFeeCache::default(),
9000            &None, // no dependency tracker
9001        );
9002        let req =
9003            r#"{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment": "confirmed"}]}"#;
9004        let res = io.handle_request_sync(req, meta.clone());
9005        let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
9006        let slot: Slot = serde_json::from_value(json["result"].clone()).unwrap();
9007        assert_eq!(slot, 2);
9008
9009        // Test rollback does not appear to happen, even if slots are notified out of order
9010        OptimisticallyConfirmedBankTracker::process_notification(
9011            (
9012                BankNotification::OptimisticallyConfirmed(1),
9013                None, /* no dependency work */
9014            ),
9015            &bank_forks,
9016            &optimistically_confirmed_bank,
9017            &subscriptions,
9018            &mut pending_optimistically_confirmed_banks,
9019            &mut last_notified_confirmed_slot,
9020            &mut highest_confirmed_slot,
9021            &mut highest_root_slot,
9022            &None,
9023            &PrioritizationFeeCache::default(),
9024            &None, // No dependency tracker
9025        );
9026        let req =
9027            r#"{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment": "confirmed"}]}"#;
9028        let res = io.handle_request_sync(req, meta.clone());
9029        let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
9030        let slot: Slot = serde_json::from_value(json["result"].clone()).unwrap();
9031        assert_eq!(slot, 2);
9032
9033        // Test bank will only be cached when frozen
9034        OptimisticallyConfirmedBankTracker::process_notification(
9035            (
9036                BankNotification::OptimisticallyConfirmed(3),
9037                None, /* no dependency work */
9038            ),
9039            &bank_forks,
9040            &optimistically_confirmed_bank,
9041            &subscriptions,
9042            &mut pending_optimistically_confirmed_banks,
9043            &mut last_notified_confirmed_slot,
9044            &mut highest_confirmed_slot,
9045            &mut highest_root_slot,
9046            &None,
9047            &PrioritizationFeeCache::default(),
9048            &None, // No dependency tracker
9049        );
9050        let req =
9051            r#"{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment": "confirmed"}]}"#;
9052        let res = io.handle_request_sync(req, meta.clone());
9053        let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
9054        let slot: Slot = serde_json::from_value(json["result"].clone()).unwrap();
9055        assert_eq!(slot, 2);
9056
9057        // Test freezing an optimistically confirmed bank will update cache
9058        let bank3 = bank_forks.read().unwrap().get(3).unwrap();
9059        OptimisticallyConfirmedBankTracker::process_notification(
9060            (
9061                BankNotification::Frozen(bank3),
9062                None, /* no dependency work */
9063            ),
9064            &bank_forks,
9065            &optimistically_confirmed_bank,
9066            &subscriptions,
9067            &mut pending_optimistically_confirmed_banks,
9068            &mut last_notified_confirmed_slot,
9069            &mut highest_confirmed_slot,
9070            &mut highest_root_slot,
9071            &None,
9072            &PrioritizationFeeCache::default(),
9073            &None, // No dependency tracker
9074        );
9075        let req =
9076            r#"{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment": "confirmed"}]}"#;
9077        let res = io.handle_request_sync(req, meta);
9078        let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
9079        let slot: Slot = serde_json::from_value(json["result"].clone()).unwrap();
9080        assert_eq!(slot, 3);
9081    }
9082
9083    #[test]
9084    fn test_worst_case_encoded_tx_goldens() {
9085        let ff_tx = vec![0xffu8; PACKET_DATA_SIZE];
9086        let tx58 = bs58::encode(&ff_tx).into_string();
9087        assert_eq!(tx58.len(), MAX_BASE58_SIZE);
9088        let tx64 = BASE64_STANDARD.encode(&ff_tx);
9089        assert_eq!(tx64.len(), MAX_BASE64_SIZE);
9090    }
9091
9092    #[test]
9093    fn test_decode_and_deserialize_too_large_payloads_fail() {
9094        // +2 because +1 still fits in base64 encoded worst-case
9095        let too_big = PACKET_DATA_SIZE + 2;
9096        let tx_ser = vec![0xffu8; too_big];
9097
9098        let tx58 = bs58::encode(&tx_ser).into_string();
9099        let tx58_len = tx58.len();
9100        assert_eq!(
9101            decode_and_deserialize::<Transaction>(tx58, TransactionBinaryEncoding::Base58)
9102                .unwrap_err(),
9103            Error::invalid_params(format!(
9104                "base58 encoded solana_transaction::Transaction too large: {tx58_len} bytes (max: \
9105                 encoded/raw {MAX_BASE58_SIZE}/{PACKET_DATA_SIZE})",
9106            ))
9107        );
9108
9109        let tx64 = BASE64_STANDARD.encode(&tx_ser);
9110        let tx64_len = tx64.len();
9111        assert_eq!(
9112            decode_and_deserialize::<Transaction>(tx64, TransactionBinaryEncoding::Base64)
9113                .unwrap_err(),
9114            Error::invalid_params(format!(
9115                "base64 encoded solana_transaction::Transaction too large: {tx64_len} bytes (max: \
9116                 encoded/raw {MAX_BASE64_SIZE}/{PACKET_DATA_SIZE})",
9117            ))
9118        );
9119
9120        let too_big = PACKET_DATA_SIZE + 1;
9121        let tx_ser = vec![0x00u8; too_big];
9122        let tx58 = bs58::encode(&tx_ser).into_string();
9123        assert_eq!(
9124            decode_and_deserialize::<Transaction>(tx58, TransactionBinaryEncoding::Base58)
9125                .unwrap_err(),
9126            Error::invalid_params(format!(
9127                "decoded solana_transaction::Transaction too large: {too_big} bytes (max: \
9128                 {PACKET_DATA_SIZE} bytes)"
9129            ))
9130        );
9131
9132        let tx64 = BASE64_STANDARD.encode(&tx_ser);
9133        assert_eq!(
9134            decode_and_deserialize::<Transaction>(tx64, TransactionBinaryEncoding::Base64)
9135                .unwrap_err(),
9136            Error::invalid_params(format!(
9137                "decoded solana_transaction::Transaction too large: {too_big} bytes (max: \
9138                 {PACKET_DATA_SIZE} bytes)"
9139            ))
9140        );
9141
9142        let tx_ser = vec![0xffu8; PACKET_DATA_SIZE - 2];
9143        let mut tx64 = BASE64_STANDARD.encode(&tx_ser);
9144        assert_eq!(
9145            decode_and_deserialize::<Transaction>(tx64.clone(), TransactionBinaryEncoding::Base64)
9146                .unwrap_err(),
9147            Error::invalid_params(
9148                "failed to deserialize solana_transaction::Transaction: invalid value: continue \
9149                 signal on byte-three, expected a terminal signal on or before byte-three"
9150                    .to_string()
9151            )
9152        );
9153
9154        tx64.push('!');
9155        assert_eq!(
9156            decode_and_deserialize::<Transaction>(tx64, TransactionBinaryEncoding::Base64)
9157                .unwrap_err(),
9158            Error::invalid_params("invalid base64 encoding: InvalidByte(1640, 33)".to_string())
9159        );
9160
9161        let mut tx58 = bs58::encode(&tx_ser).into_string();
9162        assert_eq!(
9163            decode_and_deserialize::<Transaction>(tx58.clone(), TransactionBinaryEncoding::Base58)
9164                .unwrap_err(),
9165            Error::invalid_params(
9166                "failed to deserialize solana_transaction::Transaction: invalid value: continue \
9167                 signal on byte-three, expected a terminal signal on or before byte-three"
9168                    .to_string()
9169            )
9170        );
9171
9172        tx58.push('!');
9173        assert_eq!(
9174            decode_and_deserialize::<Transaction>(tx58, TransactionBinaryEncoding::Base58)
9175                .unwrap_err(),
9176            Error::invalid_params(
9177                "invalid base58 encoding: InvalidCharacter { character: '!', index: 1680 }"
9178                    .to_string(),
9179            )
9180        );
9181    }
9182
9183    #[test]
9184    fn test_sanitize_unsanitary() {
9185        let unsanitary_tx58 = "ju9xZWuDBX4pRxX2oZkTjxU5jB4SSTgEGhX8bQ8PURNzyzqKMPPpNvWihx8zUe\
9186             FfrbVNoAaEsNKZvGzAnTDy5bhNT9kt6KFCTBixpvrLCzg4M5UdFUQYrn1gdgjX\
9187             pLHxcaShD81xBNaFDgnA2nkkdHnKtZt4hVSfKAmw3VRZbjrZ7L2fKZBx21CwsG\
9188             hD6onjM2M3qZW5C8J6d1pj41MxKmZgPBSha3MyKkNLkAGFASK"
9189            .to_string();
9190
9191        let unsanitary_versioned_tx = decode_and_deserialize::<VersionedTransaction>(
9192            unsanitary_tx58,
9193            TransactionBinaryEncoding::Base58,
9194        )
9195        .unwrap()
9196        .1;
9197        let expect58 = Error::invalid_params(
9198            "invalid transaction: Transaction failed to sanitize accounts offsets correctly"
9199                .to_string(),
9200        );
9201        assert_eq!(
9202            sanitize_transaction(
9203                unsanitary_versioned_tx,
9204                SimpleAddressLoader::Disabled,
9205                &ReservedAccountKeys::empty_key_set(),
9206                true,
9207            )
9208            .unwrap_err(),
9209            expect58
9210        );
9211    }
9212
9213    #[test]
9214    fn test_sanitize_unsupported_transaction_version() {
9215        let versioned_tx = VersionedTransaction {
9216            signatures: vec![Signature::default()],
9217            message: VersionedMessage::V0(v0::Message {
9218                header: MessageHeader {
9219                    num_required_signatures: 1,
9220                    ..MessageHeader::default()
9221                },
9222                account_keys: vec![Pubkey::new_unique()],
9223                ..v0::Message::default()
9224            }),
9225        };
9226
9227        assert_eq!(
9228            sanitize_transaction(
9229                versioned_tx,
9230                SimpleAddressLoader::Disabled,
9231                &ReservedAccountKeys::empty_key_set(),
9232                true,
9233            )
9234            .unwrap_err(),
9235            Error::invalid_params(
9236                "invalid transaction: Transaction version is unsupported".to_string(),
9237            )
9238        );
9239    }
9240
9241    #[test]
9242    fn test_rpc_get_stake_minimum_delegation() {
9243        let rpc = RpcHandler::start();
9244        let bank = rpc.working_bank();
9245        let expected_stake_minimum_delegation = stake_utils::get_minimum_delegation(
9246            bank.feature_set
9247                .is_active(&agave_feature_set::stake_raise_minimum_delegation_to_1_sol::id()),
9248        );
9249
9250        let request = create_test_request("getStakeMinimumDelegation", None);
9251        let response: RpcResponse<u64> = parse_success_result(rpc.handle_request_sync(request));
9252        let actual_stake_minimum_delegation = response.value;
9253
9254        assert_eq!(
9255            actual_stake_minimum_delegation,
9256            expected_stake_minimum_delegation
9257        );
9258    }
9259
9260    #[test]
9261    fn test_get_fee_for_message() {
9262        let rpc = RpcHandler::start();
9263        let bank = rpc.working_bank();
9264        // Slot hashes is necessary for processing versioned txs.
9265        bank.set_sysvar_for_tests(&SlotHashes::default());
9266        // Correct blockhash is needed because fees are specific to blockhashes
9267        let recent_blockhash = bank.last_blockhash();
9268
9269        {
9270            let legacy_msg = VersionedMessage::Legacy(Message {
9271                header: MessageHeader {
9272                    num_required_signatures: 1,
9273                    ..MessageHeader::default()
9274                },
9275                recent_blockhash,
9276                account_keys: vec![Pubkey::new_unique()],
9277                ..Message::default()
9278            });
9279
9280            let request = create_test_request(
9281                "getFeeForMessage",
9282                Some(json!([
9283                    BASE64_STANDARD.encode(serialize(&legacy_msg).unwrap())
9284                ])),
9285            );
9286            let response: RpcResponse<u64> = parse_success_result(rpc.handle_request_sync(request));
9287            assert_eq!(response.value, TEST_SIGNATURE_FEE);
9288        }
9289
9290        {
9291            let v0_msg = VersionedMessage::V0(v0::Message {
9292                header: MessageHeader {
9293                    num_required_signatures: 1,
9294                    ..MessageHeader::default()
9295                },
9296                recent_blockhash,
9297                account_keys: vec![Pubkey::new_unique()],
9298                ..v0::Message::default()
9299            });
9300
9301            let request = create_test_request(
9302                "getFeeForMessage",
9303                Some(json!([BASE64_STANDARD.encode(serialize(&v0_msg).unwrap())])),
9304            );
9305            let response: RpcResponse<u64> = parse_success_result(rpc.handle_request_sync(request));
9306            assert_eq!(response.value, TEST_SIGNATURE_FEE);
9307        }
9308    }
9309
9310    #[test]
9311    fn test_rpc_get_recent_prioritization_fees() {
9312        fn wait_for_cache_blocks(cache: &PrioritizationFeeCache, num_blocks: usize) {
9313            while cache.available_block_count() < num_blocks {
9314                std::thread::sleep(std::time::Duration::from_millis(100));
9315            }
9316        }
9317
9318        fn assert_fee_vec_eq(
9319            expected: &mut Vec<RpcPrioritizationFee>,
9320            actual: &mut Vec<RpcPrioritizationFee>,
9321        ) {
9322            expected.sort_by(|a, b| a.slot.partial_cmp(&b.slot).unwrap());
9323            actual.sort_by(|a, b| a.slot.partial_cmp(&b.slot).unwrap());
9324            assert_eq!(expected, actual);
9325        }
9326
9327        let rpc = RpcHandler::start();
9328        assert_eq!(
9329            rpc.get_prioritization_fee_cache().available_block_count(),
9330            0
9331        );
9332        let slot0 = rpc.working_bank().slot();
9333        let bank0_id = rpc.working_bank().bank_id();
9334        let account0 = Pubkey::new_unique();
9335        let account1 = Pubkey::new_unique();
9336        let account2 = Pubkey::new_unique();
9337        let price0 = 42;
9338        let transactions = vec![
9339            Transaction::new_unsigned(Message::new(
9340                &[
9341                    system_instruction::transfer(&account0, &account1, 1),
9342                    ComputeBudgetInstruction::set_compute_unit_price(price0),
9343                ],
9344                Some(&account0),
9345            )),
9346            Transaction::new_unsigned(Message::new(
9347                &[system_instruction::transfer(&account0, &account2, 1)],
9348                Some(&account0),
9349            )),
9350        ];
9351        rpc.update_prioritization_fee_cache(transactions);
9352        let cache = rpc.get_prioritization_fee_cache();
9353        cache.finalize_priority_fee(slot0, bank0_id);
9354        wait_for_cache_blocks(cache, 1);
9355
9356        let request = create_test_request("getRecentPrioritizationFees", None);
9357        let mut response: Vec<RpcPrioritizationFee> =
9358            parse_success_result(rpc.handle_request_sync(request));
9359        assert_fee_vec_eq(
9360            &mut response,
9361            &mut vec![RpcPrioritizationFee {
9362                slot: slot0,
9363                prioritization_fee: 0,
9364            }],
9365        );
9366
9367        let request = create_test_request(
9368            "getRecentPrioritizationFees",
9369            Some(json!([[account1.to_string()]])),
9370        );
9371        let mut response: Vec<RpcPrioritizationFee> =
9372            parse_success_result(rpc.handle_request_sync(request));
9373        assert_fee_vec_eq(
9374            &mut response,
9375            &mut vec![RpcPrioritizationFee {
9376                slot: slot0,
9377                prioritization_fee: price0,
9378            }],
9379        );
9380
9381        let request = create_test_request(
9382            "getRecentPrioritizationFees",
9383            Some(json!([[account2.to_string()]])),
9384        );
9385        let mut response: Vec<RpcPrioritizationFee> =
9386            parse_success_result(rpc.handle_request_sync(request));
9387        assert_fee_vec_eq(
9388            &mut response,
9389            &mut vec![RpcPrioritizationFee {
9390                slot: slot0,
9391                prioritization_fee: 0,
9392            }],
9393        );
9394
9395        rpc.advance_bank_to_confirmed_slot(1);
9396        let slot1 = rpc.working_bank().slot();
9397        let bank1_id = rpc.working_bank().bank_id();
9398        let price1 = 11;
9399        let transactions = vec![
9400            Transaction::new_unsigned(Message::new(
9401                &[
9402                    system_instruction::transfer(&account0, &account2, 1),
9403                    ComputeBudgetInstruction::set_compute_unit_price(price1),
9404                ],
9405                Some(&account0),
9406            )),
9407            Transaction::new_unsigned(Message::new(
9408                &[system_instruction::transfer(&account0, &account1, 1)],
9409                Some(&account0),
9410            )),
9411        ];
9412        rpc.update_prioritization_fee_cache(transactions);
9413        let cache = rpc.get_prioritization_fee_cache();
9414        cache.finalize_priority_fee(slot1, bank1_id);
9415        wait_for_cache_blocks(cache, 2);
9416
9417        let request = create_test_request("getRecentPrioritizationFees", None);
9418        let mut response: Vec<RpcPrioritizationFee> =
9419            parse_success_result(rpc.handle_request_sync(request));
9420        assert_fee_vec_eq(
9421            &mut response,
9422            &mut vec![
9423                RpcPrioritizationFee {
9424                    slot: slot0,
9425                    prioritization_fee: 0,
9426                },
9427                RpcPrioritizationFee {
9428                    slot: slot1,
9429                    prioritization_fee: 0,
9430                },
9431            ],
9432        );
9433
9434        let request = create_test_request(
9435            "getRecentPrioritizationFees",
9436            Some(json!([[account1.to_string()]])),
9437        );
9438        let mut response: Vec<RpcPrioritizationFee> =
9439            parse_success_result(rpc.handle_request_sync(request));
9440        assert_fee_vec_eq(
9441            &mut response,
9442            &mut vec![
9443                RpcPrioritizationFee {
9444                    slot: slot0,
9445                    prioritization_fee: price0,
9446                },
9447                RpcPrioritizationFee {
9448                    slot: slot1,
9449                    prioritization_fee: 0,
9450                },
9451            ],
9452        );
9453
9454        let request = create_test_request(
9455            "getRecentPrioritizationFees",
9456            Some(json!([[account2.to_string()]])),
9457        );
9458        let mut response: Vec<RpcPrioritizationFee> =
9459            parse_success_result(rpc.handle_request_sync(request));
9460        assert_fee_vec_eq(
9461            &mut response,
9462            &mut vec![
9463                RpcPrioritizationFee {
9464                    slot: slot0,
9465                    prioritization_fee: 0,
9466                },
9467                RpcPrioritizationFee {
9468                    slot: slot1,
9469                    prioritization_fee: price1,
9470                },
9471            ],
9472        );
9473    }
9474}