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