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