Create solana-rpc crate and move subscriptions (#17320)
* Move non_circulating_supply to runtime * Add solana-rpc crate and move max_slots * Move subscriptions to solana-rpc * Single use statements
This commit is contained in:
@ -33,8 +33,6 @@ jsonrpc-core = "17.0.0"
|
||||
jsonrpc-core-client = { version = "17.0.0", features = ["ipc", "ws"] }
|
||||
jsonrpc-derive = "17.0.0"
|
||||
jsonrpc-http-server = "17.0.0"
|
||||
jsonrpc-pubsub = "17.0.0"
|
||||
jsonrpc-ws-server = "17.0.0"
|
||||
libc = "0.2.81"
|
||||
log = "0.4.11"
|
||||
lru = "0.6.1"
|
||||
@ -65,6 +63,7 @@ solana-measure = { path = "../measure", version = "=1.7.0" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.7.0" }
|
||||
solana-perf = { path = "../perf", version = "=1.7.0" }
|
||||
solana-program-test = { path = "../program-test", version = "=1.7.0" }
|
||||
solana-rpc = { path = "../rpc", version = "=1.7.0" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.7.0" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.7.0" }
|
||||
solana-frozen-abi = { path = "../frozen-abi", version = "=1.7.0" }
|
||||
|
@ -6,7 +6,6 @@ extern crate test;
|
||||
use log::*;
|
||||
use solana_core::cluster_info::{ClusterInfo, Node};
|
||||
use solana_core::contact_info::ContactInfo;
|
||||
use solana_core::max_slots::MaxSlots;
|
||||
use solana_core::retransmit_stage::retransmitter;
|
||||
use solana_ledger::entry::Entry;
|
||||
use solana_ledger::genesis_utils::{create_genesis_config, GenesisConfigInfo};
|
||||
@ -14,6 +13,7 @@ use solana_ledger::leader_schedule_cache::LeaderScheduleCache;
|
||||
use solana_ledger::shred::Shredder;
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_perf::packet::{Packet, Packets};
|
||||
use solana_rpc::max_slots::MaxSlots;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::bank_forks::BankForks;
|
||||
use solana_sdk::hash::Hash;
|
||||
|
@ -3,11 +3,9 @@ use crate::{
|
||||
crds::Cursor,
|
||||
crds_value::CrdsValueLabel,
|
||||
optimistic_confirmation_verifier::OptimisticConfirmationVerifier,
|
||||
optimistically_confirmed_bank_tracker::{BankNotification, BankNotificationSender},
|
||||
poh_recorder::PohRecorder,
|
||||
replay_stage::DUPLICATE_THRESHOLD,
|
||||
result::{Error, Result},
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
sigverify,
|
||||
verified_vote_packets::VerifiedVotePackets,
|
||||
vote_stake_tracker::VoteStakeTracker,
|
||||
@ -20,6 +18,10 @@ use log::*;
|
||||
use solana_ledger::blockstore::Blockstore;
|
||||
use solana_metrics::inc_new_counter_debug;
|
||||
use solana_perf::packet::{self, Packets};
|
||||
use solana_rpc::{
|
||||
optimistically_confirmed_bank_tracker::{BankNotification, BankNotificationSender},
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
};
|
||||
use solana_runtime::{
|
||||
bank::Bank,
|
||||
bank_forks::BankForks,
|
||||
@ -824,8 +826,8 @@ impl ClusterInfoVoteListener {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank;
|
||||
use solana_perf::packet;
|
||||
use solana_rpc::optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank;
|
||||
use solana_runtime::{
|
||||
bank::Bank,
|
||||
commitment::BlockCommitmentCache,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{consensus::Stake, rpc_subscriptions::RpcSubscriptions};
|
||||
use crate::consensus::Stake;
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_metrics::datapoint_info;
|
||||
use solana_rpc::rpc_subscriptions::RpcSubscriptions;
|
||||
use solana_runtime::{
|
||||
bank::Bank,
|
||||
commitment::{BlockCommitment, BlockCommitmentCache, CommitmentSlots, VOTE_THRESHOLD_SIZE},
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{max_slots::MaxSlots, rpc_subscriptions::RpcSubscriptions};
|
||||
use crossbeam_channel::{Receiver, RecvTimeoutError, Sender};
|
||||
use solana_ledger::blockstore::{Blockstore, CompletedDataSetInfo};
|
||||
use solana_ledger::entry::Entry;
|
||||
use solana_rpc::{max_slots::MaxSlots, rpc_subscriptions::RpcSubscriptions};
|
||||
use solana_sdk::signature::Signature;
|
||||
use std::{
|
||||
sync::{
|
||||
|
@ -16,7 +16,6 @@ pub mod cluster_info_vote_listener;
|
||||
pub mod commitment_service;
|
||||
pub mod completed_data_sets_service;
|
||||
mod deprecated;
|
||||
pub mod max_slots;
|
||||
pub mod sample_performance_service;
|
||||
pub mod shred_fetch_stage;
|
||||
#[macro_use]
|
||||
@ -44,9 +43,7 @@ pub mod gossip_service;
|
||||
pub mod heaviest_subtree_fork_choice;
|
||||
pub mod latest_validator_votes_for_frozen_banks;
|
||||
pub mod ledger_cleanup_service;
|
||||
pub mod non_circulating_supply;
|
||||
pub mod optimistic_confirmation_verifier;
|
||||
pub mod optimistically_confirmed_bank_tracker;
|
||||
pub mod outstanding_requests;
|
||||
pub mod packet_hasher;
|
||||
pub mod ping_pong;
|
||||
@ -63,12 +60,8 @@ mod result;
|
||||
pub mod retransmit_stage;
|
||||
pub mod rewards_recorder_service;
|
||||
pub mod rpc;
|
||||
pub mod rpc_completed_slots_service;
|
||||
pub mod rpc_health;
|
||||
pub mod rpc_pubsub;
|
||||
pub mod rpc_pubsub_service;
|
||||
pub mod rpc_service;
|
||||
pub mod rpc_subscriptions;
|
||||
pub mod send_transaction_service;
|
||||
pub mod serve_repair;
|
||||
pub mod serve_repair_service;
|
||||
|
@ -1,7 +0,0 @@
|
||||
use std::sync::atomic::AtomicU64;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MaxSlots {
|
||||
pub retransmit: AtomicU64,
|
||||
pub shred_insert: AtomicU64,
|
||||
}
|
@ -1,299 +0,0 @@
|
||||
use solana_runtime::{
|
||||
accounts_index::{AccountIndex, IndexKey},
|
||||
bank::Bank,
|
||||
};
|
||||
use solana_sdk::{account::ReadableAccount, pubkey::Pubkey};
|
||||
use solana_stake_program::stake_state::StakeState;
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
pub struct NonCirculatingSupply {
|
||||
pub lamports: u64,
|
||||
pub accounts: Vec<Pubkey>,
|
||||
}
|
||||
|
||||
pub fn calculate_non_circulating_supply(bank: &Arc<Bank>) -> NonCirculatingSupply {
|
||||
debug!("Updating Bank supply, epoch: {}", bank.epoch());
|
||||
let mut non_circulating_accounts_set: HashSet<Pubkey> = HashSet::new();
|
||||
|
||||
for key in non_circulating_accounts() {
|
||||
non_circulating_accounts_set.insert(key);
|
||||
}
|
||||
let withdraw_authority_list = withdraw_authority();
|
||||
|
||||
let clock = bank.clock();
|
||||
let stake_accounts = if bank
|
||||
.rc
|
||||
.accounts
|
||||
.accounts_db
|
||||
.account_indexes
|
||||
.contains(&AccountIndex::ProgramId)
|
||||
{
|
||||
bank.get_filtered_indexed_accounts(
|
||||
&IndexKey::ProgramId(solana_stake_program::id()),
|
||||
// The program-id account index checks for Account owner on inclusion. However, due to
|
||||
// the current AccountsDb implementation, an account may remain in storage as a
|
||||
// zero-lamport Account::Default() after being wiped and reinitialized in later
|
||||
// updates. We include the redundant filter here to avoid returning these accounts.
|
||||
|account| account.owner() == &solana_stake_program::id(),
|
||||
)
|
||||
} else {
|
||||
bank.get_program_accounts(&solana_stake_program::id())
|
||||
};
|
||||
for (pubkey, account) in stake_accounts.iter() {
|
||||
let stake_account = StakeState::from(account).unwrap_or_default();
|
||||
match stake_account {
|
||||
StakeState::Initialized(meta) => {
|
||||
if meta.lockup.is_in_force(&clock, None)
|
||||
|| withdraw_authority_list.contains(&meta.authorized.withdrawer)
|
||||
{
|
||||
non_circulating_accounts_set.insert(*pubkey);
|
||||
}
|
||||
}
|
||||
StakeState::Stake(meta, _stake) => {
|
||||
if meta.lockup.is_in_force(&clock, None)
|
||||
|| withdraw_authority_list.contains(&meta.authorized.withdrawer)
|
||||
{
|
||||
non_circulating_accounts_set.insert(*pubkey);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let lamports = non_circulating_accounts_set
|
||||
.iter()
|
||||
.map(|pubkey| bank.get_balance(&pubkey))
|
||||
.sum();
|
||||
|
||||
NonCirculatingSupply {
|
||||
lamports,
|
||||
accounts: non_circulating_accounts_set.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
// Mainnet-beta accounts that should be considered non-circulating
|
||||
solana_sdk::pubkeys!(
|
||||
non_circulating_accounts,
|
||||
[
|
||||
"9huDUZfxoJ7wGMTffUE7vh1xePqef7gyrLJu9NApncqA",
|
||||
"GK2zqSsXLA2rwVZk347RYhh6jJpRsCA69FjLW93ZGi3B",
|
||||
"CWeRmXme7LmbaUWTZWFLt6FMnpzLCHaQLuR2TdgFn4Lq",
|
||||
"HCV5dGFJXRrJ3jhDYA4DCeb9TEDTwGGYXtT3wHksu2Zr",
|
||||
"14FUT96s9swbmH7ZjpDvfEDywnAYy9zaNhv4xvezySGu",
|
||||
"HbZ5FfmKWNHC7uwk6TF1hVi6TCs7dtYfdjEcuPGgzFAg",
|
||||
"C7C8odR8oashR5Feyrq2tJKaXL18id1dSj2zbkDGL2C2",
|
||||
"Eyr9P5XsjK2NUKNCnfu39eqpGoiLFgVAv1LSQgMZCwiQ",
|
||||
"DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ",
|
||||
"CakcnaRDHka2gXyfbEd2d3xsvkJkqsLw2akB3zsN1D2S",
|
||||
"7Np41oeYqPefeNQEHSv1UDhYrehxin3NStELsSKCT4K2",
|
||||
"GdnSyH3YtwcxFvQrVVJMm1JhTS4QVX7MFsX56uJLUfiZ",
|
||||
"Mc5XB47H3DKJHym5RLa9mPzWv5snERsF3KNv5AauXK8",
|
||||
"7cvkjYAkUYs4W8XcXsca7cBrEGFeSUjeZmKoNBvEwyri",
|
||||
"AG3m2bAibcY8raMt4oXEGqRHwX4FWKPPJVjZxn1LySDX",
|
||||
"5XdtyEDREHJXXW1CTtCsVjJRjBapAwK78ZquzvnNVRrV",
|
||||
"6yKHERk8rsbmJxvMpPuwPs1ct3hRiP7xaJF2tvnGU6nK",
|
||||
"CHmdL15akDcJgBkY6BP3hzs98Dqr6wbdDC5p8odvtSbq",
|
||||
"FR84wZQy3Y3j2gWz6pgETUiUoJtreMEuWfbg6573UCj9",
|
||||
"5q54XjQ7vDx4y6KphPeE97LUNiYGtP55spjvXAWPGBuf",
|
||||
"3o6xgkJ9sTmDeQWyfj3sxwon18fXJB9PV5LDc8sfgR4a",
|
||||
"GumSE5HsMV5HCwBTv2D2D81yy9x17aDkvobkqAfTRgmo",
|
||||
"AzVV9ZZDxTgW4wWfJmsG6ytaHpQGSe1yz76Nyy84VbQF",
|
||||
"8CUUMKYNGxdgYio5CLHRHyzMEhhVRMcqefgE6dLqnVRK",
|
||||
"CQDYc4ET2mbFhVpgj41gXahL6Exn5ZoPcGAzSHuYxwmE",
|
||||
"5PLJZLJiRR9vf7d1JCCg7UuWjtyN9nkab9uok6TqSyuP",
|
||||
"7xJ9CLtEAcEShw9kW2gSoZkRWL566Dg12cvgzANJwbTr",
|
||||
"BuCEvc9ze8UoAQwwsQLy8d447C8sA4zeVtVpc6m5wQeS",
|
||||
"8ndGYFjav6NDXvzYcxs449Aub3AxYv4vYpk89zRDwgj7",
|
||||
"8W58E8JVJjH1jCy5CeHJQgvwFXTyAVyesuXRZGbcSUGG",
|
||||
"GNiz4Mq886bTNDT3pijGsu2gbw6it7sqrwncro45USeB",
|
||||
"GhsotwFMH6XUrRLJCxcx62h7748N2Uq8mf87hUGkmPhg",
|
||||
"Fgyh8EeYGZtbW8sS33YmNQnzx54WXPrJ5KWNPkCfWPot",
|
||||
"8UVjvYyoqP6sqcctTso3xpCdCfgTMiv3VRh7vraC2eJk",
|
||||
"BhvLngiqqKeZ8rpxch2uGjeCiC88zzewoWPRuoxpp1aS",
|
||||
"63DtkW7zuARcd185EmHAkfF44bDcC2SiTSEj2spLP3iA",
|
||||
"GvpCiTgq9dmEeojCDBivoLoZqc4AkbUDACpqPMwYLWKh",
|
||||
"7Y8smnoUrYKGGuDq2uaFKVxJYhojgg7DVixHyAtGTYEV",
|
||||
"DUS1KxwUhUyDKB4A81E8vdnTe3hSahd92Abtn9CXsEcj",
|
||||
"F9MWFw8cnYVwsRq8Am1PGfFL3cQUZV37mbGoxZftzLjN",
|
||||
"8vqrX3H2BYLaXVintse3gorPEM4TgTwTFZNN1Fm9TdYs",
|
||||
"CUageMFi49kzoDqtdU8NvQ4Bq3sbtJygjKDAXJ45nmAi",
|
||||
"5smrYwb1Hr2T8XMnvsqccTgXxuqQs14iuE8RbHFYf2Cf",
|
||||
"xQadXQiUTCCFhfHjvQx1hyJK6KVWr1w2fD6DT3cdwj7",
|
||||
"8DE8fqPfv1fp9DHyGyDFFaMjpopMgDeXspzoi9jpBJjC",
|
||||
"3itU5ME8L6FDqtMiRoUiT1F7PwbkTtHBbW51YWD5jtjm",
|
||||
"AsrYX4FeLXnZcrjcZmrASY2Eq1jvEeQfwxtNTxS5zojA",
|
||||
"8rT45mqpuDBR1vcnDc9kwP9DrZAXDR4ZeuKWw3u1gTGa",
|
||||
"nGME7HgBT6tAJN1f6YuCCngpqT5cvSTndZUVLjQ4jwA",
|
||||
"CzAHrrrHKx9Lxf6wdCMrsZkLvk74c7J2vGv8VYPUmY6v",
|
||||
"AzHQ8Bia1grVVbcGyci7wzueSWkgvu7YZVZ4B9rkL5P6",
|
||||
"FiWYY85b58zEEcPtxe3PuqzWPjqBJXqdwgZeqSBmT9Cn",
|
||||
"GpxpMVhrBBBEYbEJxdR62w3daWz444V7m6dxYDZKH77D",
|
||||
"3bTGcGB9F98XxnrBNftmmm48JGfPgi5sYxDEKiCjQYk3",
|
||||
"8pNBEppa1VcFAsx4Hzq9CpdXUXZjUXbvQwLX2K7QsCwb",
|
||||
"HKJgYGTTYYR2ZkfJKHbn58w676fKueQXmvbtpyvrSM3N",
|
||||
"3jnknRabs7G2V9dKhxd2KP85pNWXKXiedYnYxtySnQMs",
|
||||
"4sxwau4mdqZ8zEJsfryXq4QFYnMJSCp3HWuZQod8WU5k",
|
||||
"Fg12tB1tz8w6zJSQ4ZAGotWoCztdMJF9hqK8R11pakog",
|
||||
"GEWSkfWgHkpiLbeKaAnwvqnECGdRNf49at5nFccVey7c",
|
||||
"CND6ZjRTzaCFVdX7pSSWgjTfHZuhxqFDoUBqWBJguNoA",
|
||||
"2WWb1gRzuXDd5viZLQF7pNRR6Y7UiyeaPpaL35X6j3ve",
|
||||
"BUnRE27mYXN9p8H1Ay24GXhJC88q2CuwLoNU2v2CrW4W",
|
||||
"CsUqV42gVQLJwQsKyjWHqGkfHarxn9hcY4YeSjgaaeTd",
|
||||
"5khMKAcvmsFaAhoKkdg3u5abvKsmjUQNmhTNP624WB1F",
|
||||
"GpYnVDgB7dzvwSgsjQFeHznjG6Kt1DLBFYrKxjGU1LuD",
|
||||
"DQQGPtj7pphPHCLzzBuEyDDQByUcKGrsJdsH7SP3hAug",
|
||||
"FwfaykN7ACnsEUDHANzGHqTGQZMcGnUSsahAHUqbdPrz",
|
||||
"JCwT5Ygmq3VeBEbDjL8s8E82Ra2rP9bq45QfZE7Xyaq7",
|
||||
"H3Ni7vG1CsmJZdTvxF7RkAf9UM5qk4RsohJsmPvtZNnu",
|
||||
"CVgyXrbEd1ctEuvq11QdpnCQVnPit8NLdhyqXQHLprM2",
|
||||
"EAJJD6nDqtXcZ4DnQb19F9XEz8y8bRDHxbWbahatZNbL",
|
||||
"6o5v1HC7WhBnLfRHp8mQTtCP2khdXXjhuyGyYEoy2Suy",
|
||||
"3ZrsTmNM6AkMcqFfv3ryfhQ2jMfqP64RQbqVyAaxqhrQ",
|
||||
"6zw7em7uQdmMpuS9fGz8Nq9TLHa5YQhEKKwPjo5PwDK4",
|
||||
"CuatS6njAcfkFHnvai7zXCs7syA9bykXWsDCJEWfhjHG",
|
||||
"Hz9nydgN1k15wnwffKX7CSmZp4VFTnTwLXAEdomFGNXy",
|
||||
"Ep5Y58PaSyALPrdFxDVAdfKtVdP55vApvsWjb3jSmXsG",
|
||||
"EziVYi3Sv5kJWxmU77PnbrT8jmkVuqwdiFLLzZpLVEn7",
|
||||
"H1rt8KvXkNhQExTRfkY8r9wjZbZ8yCih6J4wQ5Fz9HGP",
|
||||
"6nN69B4uZuESZYxr9nrLDjmKRtjDZQXrehwkfQTKw62U",
|
||||
"Hm9JW7of5i9dnrboS8pCUCSeoQUPh7JsP1rkbJnW7An4",
|
||||
"5D5NxsNVTgXHyVziwV7mDFwVDS6voaBsyyGxUbhQrhNW",
|
||||
"EMAY24PrS6rWfvpqffFCsTsFJypeeYYmtUc26wdh3Wup",
|
||||
"Br3aeVGapRb2xTq17RU2pYZCoJpWA7bq6TKBCcYtMSmt",
|
||||
"BUjkdqUuH5Lz9XzcMcR4DdEMnFG6r8QzUMBm16Rfau96",
|
||||
"Es13uD2p64UVPFpEWfDtd6SERdoNR2XVgqBQBZcZSLqW",
|
||||
"AVYpwVou2BhdLivAwLxKPALZQsY7aZNkNmGbP2fZw7RU",
|
||||
"DrKzW5koKSZp4mg4BdHLwr72MMXscd2kTiWgckCvvPXz",
|
||||
"9hknftBZAQL4f48tWfk3bUEV5YSLcYYtDRqNmpNnhCWG",
|
||||
]
|
||||
);
|
||||
|
||||
// Withdraw authority for autostaked accounts on mainnet-beta
|
||||
solana_sdk::pubkeys!(
|
||||
withdraw_authority,
|
||||
[
|
||||
"8CUUMKYNGxdgYio5CLHRHyzMEhhVRMcqefgE6dLqnVRK",
|
||||
"3FFaheyqtyAXZSYxDzsr5CVKvJuvZD1WE1VEsBtDbRqB",
|
||||
"FdGYQdiRky8NZzN9wZtczTBcWLYYRXrJ3LMDhqDPn5rM",
|
||||
"4e6KwQpyzGQPfgVr5Jn3g5jLjbXB4pKPa2jRLohEb1QA",
|
||||
"FjiEiVKyMGzSLpqoB27QypukUfyWHrwzPcGNtopzZVdh",
|
||||
"DwbVjia1mYeSGoJipzhaf4L5hfer2DJ1Ys681VzQm5YY",
|
||||
"GeMGyvsTEsANVvcT5cme65Xq5MVU8fVVzMQ13KAZFNS2",
|
||||
"Bj3aQ2oFnZYfNR1njzRjmWizzuhvfcYLckh76cqsbuBM",
|
||||
"4ZJhPQAgUseCsWhKvJLTmmRRUV74fdoTpQLNfKoekbPY",
|
||||
]
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
account::AccountSharedData,
|
||||
epoch_schedule::EpochSchedule,
|
||||
genesis_config::{ClusterType, GenesisConfig},
|
||||
};
|
||||
use solana_stake_program::stake_state::{Authorized, Lockup, Meta, StakeState};
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
|
||||
fn new_from_parent(parent: &Arc<Bank>) -> Bank {
|
||||
Bank::new_from_parent(parent, &Pubkey::default(), parent.slot() + 1)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calculate_non_circulating_supply() {
|
||||
let mut accounts: BTreeMap<Pubkey, Account> = BTreeMap::new();
|
||||
let balance = 10;
|
||||
let num_genesis_accounts = 10;
|
||||
for _ in 0..num_genesis_accounts {
|
||||
accounts.insert(
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
Account::new(balance, 0, &Pubkey::default()),
|
||||
);
|
||||
}
|
||||
let non_circulating_accounts = non_circulating_accounts();
|
||||
let num_non_circulating_accounts = non_circulating_accounts.len() as u64;
|
||||
for key in non_circulating_accounts.clone() {
|
||||
accounts.insert(key, Account::new(balance, 0, &Pubkey::default()));
|
||||
}
|
||||
|
||||
let num_stake_accounts = 3;
|
||||
for _ in 0..num_stake_accounts {
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let meta = Meta {
|
||||
authorized: Authorized::auto(&pubkey),
|
||||
lockup: Lockup {
|
||||
epoch: 1,
|
||||
..Lockup::default()
|
||||
},
|
||||
..Meta::default()
|
||||
};
|
||||
let stake_account = Account::new_data_with_space(
|
||||
balance,
|
||||
&StakeState::Initialized(meta),
|
||||
std::mem::size_of::<StakeState>(),
|
||||
&solana_stake_program::id(),
|
||||
)
|
||||
.unwrap();
|
||||
accounts.insert(pubkey, stake_account);
|
||||
}
|
||||
|
||||
let slots_per_epoch = 32;
|
||||
let genesis_config = GenesisConfig {
|
||||
accounts,
|
||||
epoch_schedule: EpochSchedule::new(slots_per_epoch),
|
||||
cluster_type: ClusterType::MainnetBeta,
|
||||
..GenesisConfig::default()
|
||||
};
|
||||
let mut bank = Arc::new(Bank::new(&genesis_config));
|
||||
let sysvar_and_native_program_delta = 10;
|
||||
assert_eq!(
|
||||
bank.capitalization(),
|
||||
(num_genesis_accounts + num_non_circulating_accounts + num_stake_accounts) * balance
|
||||
+ sysvar_and_native_program_delta,
|
||||
);
|
||||
|
||||
let non_circulating_supply = calculate_non_circulating_supply(&bank);
|
||||
assert_eq!(
|
||||
non_circulating_supply.lamports,
|
||||
(num_non_circulating_accounts + num_stake_accounts) * balance
|
||||
);
|
||||
assert_eq!(
|
||||
non_circulating_supply.accounts.len(),
|
||||
num_non_circulating_accounts as usize + num_stake_accounts as usize
|
||||
);
|
||||
|
||||
bank = Arc::new(new_from_parent(&bank));
|
||||
let new_balance = 11;
|
||||
for key in non_circulating_accounts {
|
||||
bank.store_account(
|
||||
&key,
|
||||
&AccountSharedData::new(new_balance, 0, &Pubkey::default()),
|
||||
);
|
||||
}
|
||||
let non_circulating_supply = calculate_non_circulating_supply(&bank);
|
||||
assert_eq!(
|
||||
non_circulating_supply.lamports,
|
||||
(num_non_circulating_accounts * new_balance) + (num_stake_accounts * balance)
|
||||
);
|
||||
assert_eq!(
|
||||
non_circulating_supply.accounts.len(),
|
||||
num_non_circulating_accounts as usize + num_stake_accounts as usize
|
||||
);
|
||||
|
||||
// Advance bank an epoch, which should unlock stakes
|
||||
for _ in 0..slots_per_epoch {
|
||||
bank = Arc::new(new_from_parent(&bank));
|
||||
}
|
||||
assert_eq!(bank.epoch(), 1);
|
||||
let non_circulating_supply = calculate_non_circulating_supply(&bank);
|
||||
assert_eq!(
|
||||
non_circulating_supply.lamports,
|
||||
num_non_circulating_accounts * new_balance
|
||||
);
|
||||
assert_eq!(
|
||||
non_circulating_supply.accounts.len(),
|
||||
num_non_circulating_accounts as usize
|
||||
);
|
||||
}
|
||||
}
|
@ -1,324 +0,0 @@
|
||||
//! The `optimistically_confirmed_bank_tracker` module implements a threaded service to track the
|
||||
//! most recent optimistically confirmed bank for use in rpc services, and triggers gossip
|
||||
//! subscription notifications
|
||||
|
||||
use crate::rpc_subscriptions::RpcSubscriptions;
|
||||
use crossbeam_channel::{Receiver, RecvTimeoutError, Sender};
|
||||
use solana_client::rpc_response::{SlotTransactionStats, SlotUpdate};
|
||||
use solana_runtime::{bank::Bank, bank_forks::BankForks};
|
||||
use solana_sdk::{clock::Slot, timing::timestamp};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, RwLock,
|
||||
},
|
||||
thread::{self, Builder, JoinHandle},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub struct OptimisticallyConfirmedBank {
|
||||
pub bank: Arc<Bank>,
|
||||
}
|
||||
|
||||
impl OptimisticallyConfirmedBank {
|
||||
pub fn locked_from_bank_forks_root(bank_forks: &Arc<RwLock<BankForks>>) -> Arc<RwLock<Self>> {
|
||||
Arc::new(RwLock::new(Self {
|
||||
bank: bank_forks.read().unwrap().root_bank(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum BankNotification {
|
||||
OptimisticallyConfirmed(Slot),
|
||||
Frozen(Arc<Bank>),
|
||||
Root(Arc<Bank>),
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for BankNotification {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
BankNotification::OptimisticallyConfirmed(slot) => {
|
||||
write!(f, "OptimisticallyConfirmed({:?})", slot)
|
||||
}
|
||||
BankNotification::Frozen(bank) => write!(f, "Frozen({})", bank.slot()),
|
||||
BankNotification::Root(bank) => write!(f, "Root({})", bank.slot()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type BankNotificationReceiver = Receiver<BankNotification>;
|
||||
pub type BankNotificationSender = Sender<BankNotification>;
|
||||
|
||||
pub struct OptimisticallyConfirmedBankTracker {
|
||||
thread_hdl: JoinHandle<()>,
|
||||
}
|
||||
|
||||
impl OptimisticallyConfirmedBankTracker {
|
||||
pub fn new(
|
||||
receiver: BankNotificationReceiver,
|
||||
exit: &Arc<AtomicBool>,
|
||||
bank_forks: Arc<RwLock<BankForks>>,
|
||||
optimistically_confirmed_bank: Arc<RwLock<OptimisticallyConfirmedBank>>,
|
||||
subscriptions: Arc<RpcSubscriptions>,
|
||||
) -> Self {
|
||||
let exit_ = exit.clone();
|
||||
let mut pending_optimistically_confirmed_banks = HashSet::new();
|
||||
let thread_hdl = Builder::new()
|
||||
.name("solana-optimistic-bank-tracker".to_string())
|
||||
.spawn(move || loop {
|
||||
if exit_.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
|
||||
if let Err(RecvTimeoutError::Disconnected) = Self::recv_notification(
|
||||
&receiver,
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
) {
|
||||
break;
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
Self { thread_hdl }
|
||||
}
|
||||
|
||||
fn recv_notification(
|
||||
receiver: &Receiver<BankNotification>,
|
||||
bank_forks: &Arc<RwLock<BankForks>>,
|
||||
optimistically_confirmed_bank: &Arc<RwLock<OptimisticallyConfirmedBank>>,
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
mut pending_optimistically_confirmed_banks: &mut HashSet<Slot>,
|
||||
) -> Result<(), RecvTimeoutError> {
|
||||
let notification = receiver.recv_timeout(Duration::from_secs(1))?;
|
||||
Self::process_notification(
|
||||
notification,
|
||||
bank_forks,
|
||||
optimistically_confirmed_bank,
|
||||
subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn process_notification(
|
||||
notification: BankNotification,
|
||||
bank_forks: &Arc<RwLock<BankForks>>,
|
||||
optimistically_confirmed_bank: &Arc<RwLock<OptimisticallyConfirmedBank>>,
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
pending_optimistically_confirmed_banks: &mut HashSet<Slot>,
|
||||
) {
|
||||
debug!("received bank notification: {:?}", notification);
|
||||
match notification {
|
||||
BankNotification::OptimisticallyConfirmed(slot) => {
|
||||
if let Some(bank) = bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(slot)
|
||||
.filter(|b| b.is_frozen())
|
||||
{
|
||||
let mut w_optimistically_confirmed_bank =
|
||||
optimistically_confirmed_bank.write().unwrap();
|
||||
if bank.slot() > w_optimistically_confirmed_bank.bank.slot() {
|
||||
w_optimistically_confirmed_bank.bank = bank.clone();
|
||||
subscriptions.notify_gossip_subscribers(slot);
|
||||
}
|
||||
drop(w_optimistically_confirmed_bank);
|
||||
} else if slot > bank_forks.read().unwrap().root_bank().slot() {
|
||||
pending_optimistically_confirmed_banks.insert(slot);
|
||||
} else {
|
||||
inc_new_counter_info!("dropped-already-rooted-optimistic-bank-notification", 1);
|
||||
}
|
||||
|
||||
// Send slot notification regardless of whether the bank is replayed
|
||||
subscriptions.notify_slot_update(SlotUpdate::OptimisticConfirmation {
|
||||
slot,
|
||||
timestamp: timestamp(),
|
||||
});
|
||||
}
|
||||
BankNotification::Frozen(bank) => {
|
||||
let frozen_slot = bank.slot();
|
||||
if let Some(parent) = bank.parent() {
|
||||
let num_successful_transactions = bank
|
||||
.transaction_count()
|
||||
.saturating_sub(parent.transaction_count());
|
||||
subscriptions.notify_slot_update(SlotUpdate::Frozen {
|
||||
slot: frozen_slot,
|
||||
timestamp: timestamp(),
|
||||
stats: SlotTransactionStats {
|
||||
num_transaction_entries: bank.transaction_entries_count(),
|
||||
num_successful_transactions,
|
||||
num_failed_transactions: bank.transaction_error_count(),
|
||||
max_transactions_per_entry: bank.transactions_per_entry_max(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if pending_optimistically_confirmed_banks.remove(&bank.slot()) {
|
||||
let mut w_optimistically_confirmed_bank =
|
||||
optimistically_confirmed_bank.write().unwrap();
|
||||
if frozen_slot > w_optimistically_confirmed_bank.bank.slot() {
|
||||
w_optimistically_confirmed_bank.bank = bank;
|
||||
subscriptions.notify_gossip_subscribers(frozen_slot);
|
||||
}
|
||||
drop(w_optimistically_confirmed_bank);
|
||||
}
|
||||
}
|
||||
BankNotification::Root(bank) => {
|
||||
let root_slot = bank.slot();
|
||||
let mut w_optimistically_confirmed_bank =
|
||||
optimistically_confirmed_bank.write().unwrap();
|
||||
if root_slot > w_optimistically_confirmed_bank.bank.slot() {
|
||||
w_optimistically_confirmed_bank.bank = bank;
|
||||
}
|
||||
drop(w_optimistically_confirmed_bank);
|
||||
pending_optimistically_confirmed_banks.retain(|&s| s > root_slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(self) -> thread::Result<()> {
|
||||
self.join()
|
||||
}
|
||||
|
||||
pub fn join(self) -> thread::Result<()> {
|
||||
self.thread_hdl.join()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use solana_ledger::genesis_utils::{create_genesis_config, GenesisConfigInfo};
|
||||
use solana_runtime::{
|
||||
accounts_background_service::AbsRequestSender, commitment::BlockCommitmentCache,
|
||||
};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
#[test]
|
||||
fn test_process_notification() {
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||
let bank0 = bank_forks.read().unwrap().get(0).unwrap().clone();
|
||||
let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
|
||||
bank_forks.write().unwrap().insert(bank1);
|
||||
let bank1 = bank_forks.read().unwrap().get(1).unwrap().clone();
|
||||
let bank2 = Bank::new_from_parent(&bank1, &Pubkey::default(), 2);
|
||||
bank_forks.write().unwrap().insert(bank2);
|
||||
let bank2 = bank_forks.read().unwrap().get(2).unwrap().clone();
|
||||
let bank3 = Bank::new_from_parent(&bank2, &Pubkey::default(), 3);
|
||||
bank_forks.write().unwrap().insert(bank3);
|
||||
|
||||
let optimistically_confirmed_bank =
|
||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||
|
||||
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks.clone(),
|
||||
block_commitment_cache,
|
||||
optimistically_confirmed_bank.clone(),
|
||||
));
|
||||
let mut pending_optimistically_confirmed_banks = HashSet::new();
|
||||
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 0);
|
||||
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(2),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 2);
|
||||
|
||||
// Test max optimistically confirmed bank remains in the cache
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(1),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 2);
|
||||
|
||||
// Test bank will only be cached when frozen
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(3),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 2);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.len(), 1);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.contains(&3), true);
|
||||
|
||||
// Test bank will only be cached when frozen
|
||||
let bank3 = bank_forks.read().unwrap().get(3).unwrap().clone();
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::Frozen(bank3),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 3);
|
||||
|
||||
// Test higher root will be cached and clear pending_optimistically_confirmed_banks
|
||||
let bank3 = bank_forks.read().unwrap().get(3).unwrap().clone();
|
||||
let bank4 = Bank::new_from_parent(&bank3, &Pubkey::default(), 4);
|
||||
bank_forks.write().unwrap().insert(bank4);
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(4),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 3);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.len(), 1);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.contains(&4), true);
|
||||
|
||||
let bank4 = bank_forks.read().unwrap().get(4).unwrap().clone();
|
||||
let bank5 = Bank::new_from_parent(&bank4, &Pubkey::default(), 5);
|
||||
bank_forks.write().unwrap().insert(bank5);
|
||||
let bank5 = bank_forks.read().unwrap().get(5).unwrap().clone();
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::Root(bank5),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 5);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.len(), 0);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.contains(&4), false);
|
||||
|
||||
// Banks <= root do not get added to pending list, even if not frozen
|
||||
let bank5 = bank_forks.read().unwrap().get(5).unwrap().clone();
|
||||
let bank6 = Bank::new_from_parent(&bank5, &Pubkey::default(), 6);
|
||||
bank_forks.write().unwrap().insert(bank6);
|
||||
let bank5 = bank_forks.read().unwrap().get(5).unwrap().clone();
|
||||
let bank7 = Bank::new_from_parent(&bank5, &Pubkey::default(), 7);
|
||||
bank_forks.write().unwrap().insert(bank7);
|
||||
bank_forks
|
||||
.write()
|
||||
.unwrap()
|
||||
.set_root(7, &AbsRequestSender::default(), None);
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(6),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 5);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.len(), 0);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.contains(&6), false);
|
||||
}
|
||||
}
|
@ -16,13 +16,11 @@ use crate::{
|
||||
fork_choice::{ForkChoice, SelectVoteAndResetForkResult},
|
||||
heaviest_subtree_fork_choice::HeaviestSubtreeForkChoice,
|
||||
latest_validator_votes_for_frozen_banks::LatestValidatorVotesForFrozenBanks,
|
||||
optimistically_confirmed_bank_tracker::{BankNotification, BankNotificationSender},
|
||||
poh_recorder::{PohRecorder, GRACE_TICKS_FACTOR, MAX_GRACE_SLOTS},
|
||||
progress_map::{DuplicateStats, ForkProgress, ProgressMap, PropagatedStats},
|
||||
repair_service::DuplicateSlotsResetReceiver,
|
||||
result::Result,
|
||||
rewards_recorder_service::RewardsRecorderSender,
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
unfrozen_gossip_verified_vote_hashes::UnfrozenGossipVerifiedVoteHashes,
|
||||
window_service::DuplicateSlotReceiver,
|
||||
};
|
||||
@ -36,6 +34,10 @@ use solana_ledger::{
|
||||
};
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_metrics::inc_new_counter_info;
|
||||
use solana_rpc::{
|
||||
optimistically_confirmed_bank_tracker::{BankNotification, BankNotificationSender},
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
};
|
||||
use solana_runtime::{
|
||||
accounts_background_service::AbsRequestSender, bank::Bank, bank_forks::BankForks,
|
||||
commitment::BlockCommitmentCache, vote_sender_types::ReplayVoteSender,
|
||||
@ -2475,7 +2477,6 @@ pub(crate) mod tests {
|
||||
consensus::test::{initialize_state, VoteSimulator},
|
||||
consensus::Tower,
|
||||
crds::Cursor,
|
||||
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||
progress_map::ValidatorStakeInfo,
|
||||
replay_stage::ReplayStage,
|
||||
transaction_status_service::TransactionStatusService,
|
||||
@ -2493,6 +2494,7 @@ pub(crate) mod tests {
|
||||
SIZE_OF_COMMON_SHRED_HEADER, SIZE_OF_DATA_SHRED_HEADER, SIZE_OF_DATA_SHRED_PAYLOAD,
|
||||
},
|
||||
};
|
||||
use solana_rpc::optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank;
|
||||
use solana_runtime::{
|
||||
accounts_background_service::AbsRequestSender,
|
||||
commitment::BlockCommitment,
|
||||
|
@ -8,12 +8,9 @@ use crate::{
|
||||
cluster_slots_service::ClusterSlotsService,
|
||||
completed_data_sets_service::CompletedDataSetsSender,
|
||||
contact_info::ContactInfo,
|
||||
max_slots::MaxSlots,
|
||||
repair_service::DuplicateSlotsResetSender,
|
||||
repair_service::RepairInfo,
|
||||
result::{Error, Result},
|
||||
rpc_completed_slots_service::RpcCompletedSlotsService,
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
window_service::{should_retransmit_and_persist, WindowService},
|
||||
};
|
||||
use crossbeam_channel::{Receiver, Sender};
|
||||
@ -27,6 +24,10 @@ use solana_ledger::{
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_metrics::inc_new_counter_error;
|
||||
use solana_perf::packet::{Packet, Packets};
|
||||
use solana_rpc::{
|
||||
max_slots::MaxSlots, rpc_completed_slots_service::RpcCompletedSlotsService,
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
};
|
||||
use solana_runtime::{bank::Bank, bank_forks::BankForks};
|
||||
use solana_sdk::{clock::Slot, epoch_schedule::EpochSchedule, pubkey::Pubkey, timing::timestamp};
|
||||
use solana_streamer::streamer::PacketReceiver;
|
||||
|
106
core/src/rpc.rs
106
core/src/rpc.rs
@ -3,9 +3,6 @@
|
||||
use crate::{
|
||||
cluster_info::ClusterInfo,
|
||||
contact_info::ContactInfo,
|
||||
max_slots::MaxSlots,
|
||||
non_circulating_supply::calculate_non_circulating_supply,
|
||||
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||
rpc_health::*,
|
||||
send_transaction_service::{SendTransactionService, TransactionInfo},
|
||||
validator::ValidatorExit,
|
||||
@ -14,12 +11,8 @@ use bincode::{config::Options, serialize};
|
||||
use jsonrpc_core::{types::error, Error, Metadata, Result};
|
||||
use jsonrpc_derive::rpc;
|
||||
use solana_account_decoder::{
|
||||
parse_account_data::AccountAdditionalData,
|
||||
parse_token::{
|
||||
get_token_account_mint, spl_token_id_v2_0, spl_token_v2_0_native_mint,
|
||||
token_amount_to_ui_amount, UiTokenAmount,
|
||||
},
|
||||
UiAccount, UiAccountData, UiAccountEncoding, UiDataSliceConfig,
|
||||
parse_token::{spl_token_id_v2_0, token_amount_to_ui_amount, UiTokenAmount},
|
||||
UiAccount, UiAccountEncoding, UiDataSliceConfig,
|
||||
};
|
||||
use solana_client::{
|
||||
rpc_cache::LargestAccountsCache,
|
||||
@ -44,6 +37,10 @@ use solana_ledger::{
|
||||
};
|
||||
use solana_metrics::inc_new_counter_info;
|
||||
use solana_perf::packet::PACKET_DATA_SIZE;
|
||||
use solana_rpc::{
|
||||
max_slots::MaxSlots, optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||
parsed_token_accounts::*,
|
||||
};
|
||||
use solana_runtime::{
|
||||
accounts::AccountAddressFilter,
|
||||
accounts_index::{AccountIndex, AccountSecondaryIndexes, IndexKey},
|
||||
@ -51,6 +48,7 @@ use solana_runtime::{
|
||||
bank_forks::{BankForks, SnapshotConfig},
|
||||
commitment::{BlockCommitmentArray, BlockCommitmentCache, CommitmentSlots},
|
||||
inline_spl_token_v2_0::{SPL_TOKEN_ACCOUNT_MINT_OFFSET, SPL_TOKEN_ACCOUNT_OWNER_OFFSET},
|
||||
non_circulating_supply::calculate_non_circulating_supply,
|
||||
snapshot_utils::get_highest_snapshot_archive_path,
|
||||
};
|
||||
use solana_sdk::{
|
||||
@ -1991,62 +1989,6 @@ fn get_spl_token_mint_filter(program_id: &Pubkey, filters: &[RpcFilterType]) ->
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_parsed_token_account(
|
||||
bank: Arc<Bank>,
|
||||
pubkey: &Pubkey,
|
||||
account: AccountSharedData,
|
||||
) -> UiAccount {
|
||||
let additional_data = get_token_account_mint(&account.data())
|
||||
.and_then(|mint_pubkey| get_mint_owner_and_decimals(&bank, &mint_pubkey).ok())
|
||||
.map(|(_, decimals)| AccountAdditionalData {
|
||||
spl_token_decimals: Some(decimals),
|
||||
});
|
||||
|
||||
UiAccount::encode(
|
||||
pubkey,
|
||||
account,
|
||||
UiAccountEncoding::JsonParsed,
|
||||
additional_data,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn get_parsed_token_accounts<I>(
|
||||
bank: Arc<Bank>,
|
||||
keyed_accounts: I,
|
||||
) -> impl Iterator<Item = RpcKeyedAccount>
|
||||
where
|
||||
I: Iterator<Item = (Pubkey, AccountSharedData)>,
|
||||
{
|
||||
let mut mint_decimals: HashMap<Pubkey, u8> = HashMap::new();
|
||||
keyed_accounts.filter_map(move |(pubkey, account)| {
|
||||
let additional_data = get_token_account_mint(&account.data()).map(|mint_pubkey| {
|
||||
let spl_token_decimals = mint_decimals.get(&mint_pubkey).cloned().or_else(|| {
|
||||
let (_, decimals) = get_mint_owner_and_decimals(&bank, &mint_pubkey).ok()?;
|
||||
mint_decimals.insert(mint_pubkey, decimals);
|
||||
Some(decimals)
|
||||
});
|
||||
AccountAdditionalData { spl_token_decimals }
|
||||
});
|
||||
|
||||
let maybe_encoded_account = UiAccount::encode(
|
||||
&pubkey,
|
||||
account,
|
||||
UiAccountEncoding::JsonParsed,
|
||||
additional_data,
|
||||
None,
|
||||
);
|
||||
if let UiAccountData::Json(_) = &maybe_encoded_account.data {
|
||||
Some(RpcKeyedAccount {
|
||||
pubkey: pubkey.to_string(),
|
||||
account: maybe_encoded_account,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Analyze a passed Pubkey that may be a Token program id or Mint address to determine the program
|
||||
/// id and optional Mint
|
||||
fn get_token_program_id_and_mint(
|
||||
@ -2075,28 +2017,6 @@ fn get_token_program_id_and_mint(
|
||||
}
|
||||
}
|
||||
|
||||
/// Analyze a mint Pubkey that may be the native_mint and get the mint-account owner (token
|
||||
/// program_id) and decimals
|
||||
fn get_mint_owner_and_decimals(bank: &Arc<Bank>, mint: &Pubkey) -> Result<(Pubkey, u8)> {
|
||||
if mint == &spl_token_v2_0_native_mint() {
|
||||
Ok((spl_token_id_v2_0(), spl_token_v2_0::native_mint::DECIMALS))
|
||||
} else {
|
||||
let mint_account = bank.get_account(mint).ok_or_else(|| {
|
||||
Error::invalid_params("Invalid param: could not find mint".to_string())
|
||||
})?;
|
||||
let decimals = get_mint_decimals(&mint_account.data())?;
|
||||
Ok((*mint_account.owner(), decimals))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mint_decimals(data: &[u8]) -> Result<u8> {
|
||||
Mint::unpack(data)
|
||||
.map_err(|_| {
|
||||
Error::invalid_params("Invalid param: Token mint could not be unpacked".to_string())
|
||||
})
|
||||
.map(|mint| mint.decimals)
|
||||
}
|
||||
|
||||
fn _send_transaction(
|
||||
meta: JsonRpcRequestProcessor,
|
||||
transaction: Transaction,
|
||||
@ -3751,12 +3671,7 @@ pub mod tests {
|
||||
use super::{rpc_full::*, rpc_minimal::*, *};
|
||||
use crate::{
|
||||
contact_info::ContactInfo,
|
||||
non_circulating_supply::non_circulating_accounts,
|
||||
optimistically_confirmed_bank_tracker::{
|
||||
BankNotification, OptimisticallyConfirmedBankTracker,
|
||||
},
|
||||
replay_stage::tests::create_test_transactions_and_populate_blockstore,
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
};
|
||||
use bincode::deserialize;
|
||||
use jsonrpc_core::{futures, ErrorCode, MetaIoHandler, Output, Response, Value};
|
||||
@ -3767,8 +3682,15 @@ pub mod tests {
|
||||
blockstore_processor::fill_blockstore_slot_with_ticks,
|
||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||
};
|
||||
use solana_rpc::{
|
||||
optimistically_confirmed_bank_tracker::{
|
||||
BankNotification, OptimisticallyConfirmedBankTracker,
|
||||
},
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
};
|
||||
use solana_runtime::{
|
||||
accounts_background_service::AbsRequestSender, commitment::BlockCommitment,
|
||||
non_circulating_supply::non_circulating_accounts,
|
||||
};
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
|
@ -1,33 +0,0 @@
|
||||
use crate::rpc_subscriptions::RpcSubscriptions;
|
||||
use solana_client::rpc_response::SlotUpdate;
|
||||
use solana_ledger::blockstore::CompletedSlotsReceiver;
|
||||
use solana_sdk::timing::timestamp;
|
||||
use std::{
|
||||
sync::Arc,
|
||||
thread::{Builder, JoinHandle},
|
||||
};
|
||||
|
||||
pub struct RpcCompletedSlotsService;
|
||||
impl RpcCompletedSlotsService {
|
||||
pub fn spawn(
|
||||
completed_slots_receiver: CompletedSlotsReceiver,
|
||||
rpc_subscriptions: Option<Arc<RpcSubscriptions>>,
|
||||
) -> Option<JoinHandle<()>> {
|
||||
let rpc_subscriptions = rpc_subscriptions?;
|
||||
Some(
|
||||
Builder::new()
|
||||
.name("solana-rpc-completed-slots-service".to_string())
|
||||
.spawn(move || {
|
||||
for slots in completed_slots_receiver.iter() {
|
||||
for slot in slots {
|
||||
rpc_subscriptions.notify_slot_update(SlotUpdate::Completed {
|
||||
slot,
|
||||
timestamp: timestamp(),
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,141 +0,0 @@
|
||||
//! The `pubsub` module implements a threaded subscription service on client RPC request
|
||||
|
||||
use crate::{
|
||||
rpc_pubsub::{RpcSolPubSub, RpcSolPubSubImpl},
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
};
|
||||
use jsonrpc_pubsub::{PubSubHandler, Session};
|
||||
use jsonrpc_ws_server::{RequestContext, ServerBuilder};
|
||||
use std::{
|
||||
net::SocketAddr,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
thread::{self, sleep, Builder, JoinHandle},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PubSubConfig {
|
||||
pub enable_vote_subscription: bool,
|
||||
|
||||
// See the corresponding fields in
|
||||
// https://github.com/paritytech/ws-rs/blob/be4d47575bae55c60d9f51b47480d355492a94fc/src/lib.rs#L131
|
||||
// for a complete description of each field in this struct
|
||||
pub max_connections: usize,
|
||||
pub max_fragment_size: usize,
|
||||
pub max_in_buffer_capacity: usize,
|
||||
pub max_out_buffer_capacity: usize,
|
||||
}
|
||||
|
||||
impl Default for PubSubConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enable_vote_subscription: false,
|
||||
max_connections: 1000, // Arbitrary, default of 100 is too low
|
||||
max_fragment_size: 50 * 1024, // 50KB
|
||||
max_in_buffer_capacity: 50 * 1024, // 50KB
|
||||
max_out_buffer_capacity: 15 * 1024 * 1024, // max account size (10MB), then 5MB extra for base64 encoding overhead/etc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PubSubService {
|
||||
thread_hdl: JoinHandle<()>,
|
||||
}
|
||||
|
||||
impl PubSubService {
|
||||
pub fn new(
|
||||
pubsub_config: PubSubConfig,
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
pubsub_addr: SocketAddr,
|
||||
exit: &Arc<AtomicBool>,
|
||||
) -> Self {
|
||||
info!("rpc_pubsub bound to {:?}", pubsub_addr);
|
||||
let rpc = RpcSolPubSubImpl::new(subscriptions.clone());
|
||||
let exit_ = exit.clone();
|
||||
|
||||
let thread_hdl = Builder::new()
|
||||
.name("solana-pubsub".to_string())
|
||||
.spawn(move || {
|
||||
let mut io = PubSubHandler::default();
|
||||
io.extend_with(rpc.to_delegate());
|
||||
|
||||
let server = ServerBuilder::with_meta_extractor(io, |context: &RequestContext| {
|
||||
info!("New pubsub connection");
|
||||
let session = Arc::new(Session::new(context.sender()));
|
||||
session.on_drop(|| {
|
||||
info!("Pubsub connection dropped");
|
||||
});
|
||||
session
|
||||
})
|
||||
.max_connections(pubsub_config.max_connections)
|
||||
.max_payload(pubsub_config.max_fragment_size)
|
||||
.max_in_buffer_capacity(pubsub_config.max_in_buffer_capacity)
|
||||
.max_out_buffer_capacity(pubsub_config.max_out_buffer_capacity)
|
||||
.start(&pubsub_addr);
|
||||
|
||||
if let Err(e) = server {
|
||||
warn!(
|
||||
"Pubsub service unavailable error: {:?}. \n\
|
||||
Also, check that port {} is not already in use by another application",
|
||||
e,
|
||||
pubsub_addr.port()
|
||||
);
|
||||
return;
|
||||
}
|
||||
while !exit_.load(Ordering::Relaxed) {
|
||||
sleep(Duration::from_millis(100));
|
||||
}
|
||||
server.unwrap().close();
|
||||
})
|
||||
.unwrap();
|
||||
Self { thread_hdl }
|
||||
}
|
||||
|
||||
pub fn close(self) -> thread::Result<()> {
|
||||
self.join()
|
||||
}
|
||||
|
||||
pub fn join(self) -> thread::Result<()> {
|
||||
self.thread_hdl.join()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank;
|
||||
use solana_runtime::{
|
||||
bank::Bank,
|
||||
bank_forks::BankForks,
|
||||
commitment::BlockCommitmentCache,
|
||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||
};
|
||||
use std::{
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
sync::RwLock,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_pubsub_new() {
|
||||
let pubsub_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||
let optimistically_confirmed_bank =
|
||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks,
|
||||
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())),
|
||||
optimistically_confirmed_bank,
|
||||
));
|
||||
let pubsub_service =
|
||||
PubSubService::new(PubSubConfig::default(), &subscriptions, pubsub_addr, &exit);
|
||||
let thread = pubsub_service.thread_hdl.thread();
|
||||
assert_eq!(thread.name().unwrap(), "solana-pubsub");
|
||||
}
|
||||
}
|
@ -3,8 +3,6 @@
|
||||
use crate::{
|
||||
bigtable_upload_service::BigTableUploadService,
|
||||
cluster_info::ClusterInfo,
|
||||
max_slots::MaxSlots,
|
||||
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||
poh_recorder::PohRecorder,
|
||||
rpc::{rpc_deprecated_v1_7::*, rpc_full::*, rpc_minimal::*, rpc_obsolete_v1_7::*, *},
|
||||
rpc_health::*,
|
||||
@ -20,6 +18,9 @@ use regex::Regex;
|
||||
use solana_client::rpc_cache::LargestAccountsCache;
|
||||
use solana_ledger::{blockstore::Blockstore, leader_schedule_cache::LeaderScheduleCache};
|
||||
use solana_metrics::inc_new_counter_info;
|
||||
use solana_rpc::{
|
||||
max_slots::MaxSlots, optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||
};
|
||||
use solana_runtime::{
|
||||
bank_forks::{BankForks, SnapshotConfig},
|
||||
commitment::BlockCommitmentCache,
|
||||
@ -239,7 +240,8 @@ fn process_rest(bank_forks: &Arc<RwLock<BankForks>>, path: &str) -> Option<Strin
|
||||
let bank = r_bank_forks.root_bank();
|
||||
let total_supply = bank.capitalization();
|
||||
let non_circulating_supply =
|
||||
crate::non_circulating_supply::calculate_non_circulating_supply(&bank).lamports;
|
||||
solana_runtime::non_circulating_supply::calculate_non_circulating_supply(&bank)
|
||||
.lamports;
|
||||
Some(format!(
|
||||
"{}",
|
||||
lamports_to_sol(total_supply - non_circulating_supply)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -10,14 +10,16 @@ use crate::{
|
||||
VerifiedVoteSender, VoteTracker,
|
||||
},
|
||||
fetch_stage::FetchStage,
|
||||
optimistically_confirmed_bank_tracker::BankNotificationSender,
|
||||
poh_recorder::{PohRecorder, WorkingBankEntry},
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
sigverify::TransactionSigVerifier,
|
||||
sigverify_stage::SigVerifyStage,
|
||||
};
|
||||
use crossbeam_channel::unbounded;
|
||||
use solana_ledger::{blockstore::Blockstore, blockstore_processor::TransactionStatusSender};
|
||||
use solana_rpc::{
|
||||
optimistically_confirmed_bank_tracker::BankNotificationSender,
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
};
|
||||
use solana_runtime::{
|
||||
bank_forks::BankForks,
|
||||
vote_sender_types::{ReplayVoteReceiver, ReplayVoteSender},
|
||||
|
@ -14,13 +14,10 @@ use crate::{
|
||||
completed_data_sets_service::CompletedDataSetsSender,
|
||||
consensus::Tower,
|
||||
ledger_cleanup_service::LedgerCleanupService,
|
||||
max_slots::MaxSlots,
|
||||
optimistically_confirmed_bank_tracker::BankNotificationSender,
|
||||
poh_recorder::PohRecorder,
|
||||
replay_stage::{ReplayStage, ReplayStageConfig},
|
||||
retransmit_stage::RetransmitStage,
|
||||
rewards_recorder_service::RewardsRecorderSender,
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
shred_fetch_stage::ShredFetchStage,
|
||||
sigverify_shreds::ShredSigVerifier,
|
||||
sigverify_stage::SigVerifyStage,
|
||||
@ -32,6 +29,10 @@ use solana_ledger::{
|
||||
blockstore_processor::TransactionStatusSender,
|
||||
leader_schedule_cache::LeaderScheduleCache,
|
||||
};
|
||||
use solana_rpc::{
|
||||
max_slots::MaxSlots, optimistically_confirmed_bank_tracker::BankNotificationSender,
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
};
|
||||
use solana_runtime::{
|
||||
accounts_background_service::{
|
||||
AbsRequestHandler, AbsRequestSender, AccountsBackgroundService, SendDroppedBankCallback,
|
||||
@ -333,7 +334,6 @@ pub mod tests {
|
||||
use crate::{
|
||||
banking_stage::create_test_recorder,
|
||||
cluster_info::{ClusterInfo, Node},
|
||||
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||
};
|
||||
use serial_test::serial;
|
||||
use solana_ledger::{
|
||||
@ -341,6 +341,7 @@ pub mod tests {
|
||||
create_new_tmp_ledger,
|
||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||
};
|
||||
use solana_rpc::optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank;
|
||||
use solana_runtime::bank::Bank;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
|
@ -12,17 +12,11 @@ use crate::{
|
||||
consensus::{reconcile_blockstore_roots_with_tower, Tower},
|
||||
contact_info::ContactInfo,
|
||||
gossip_service::GossipService,
|
||||
max_slots::MaxSlots,
|
||||
optimistically_confirmed_bank_tracker::{
|
||||
OptimisticallyConfirmedBank, OptimisticallyConfirmedBankTracker,
|
||||
},
|
||||
poh_recorder::{PohRecorder, GRACE_TICKS_FACTOR, MAX_GRACE_SLOTS},
|
||||
poh_service::{self, PohService},
|
||||
rewards_recorder_service::{RewardsRecorderSender, RewardsRecorderService},
|
||||
rpc::JsonRpcConfig,
|
||||
rpc_pubsub_service::{PubSubConfig, PubSubService},
|
||||
rpc_service::JsonRpcService,
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
sample_performance_service::SamplePerformanceService,
|
||||
serve_repair::ServeRepair,
|
||||
serve_repair_service::ServeRepairService,
|
||||
@ -45,6 +39,14 @@ use solana_ledger::{
|
||||
};
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_metrics::datapoint_info;
|
||||
use solana_rpc::{
|
||||
max_slots::MaxSlots,
|
||||
optimistically_confirmed_bank_tracker::{
|
||||
OptimisticallyConfirmedBank, OptimisticallyConfirmedBankTracker,
|
||||
},
|
||||
rpc_pubsub_service::{PubSubConfig, PubSubService},
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
};
|
||||
use solana_runtime::{
|
||||
accounts_index::AccountSecondaryIndexes,
|
||||
bank::Bank,
|
||||
|
@ -1,9 +1,9 @@
|
||||
use solana_client::{pubsub_client::PubsubClient, rpc_client::RpcClient, rpc_response::SlotInfo};
|
||||
use solana_core::{
|
||||
use solana_core::test_validator::TestValidator;
|
||||
use solana_rpc::{
|
||||
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||
rpc_pubsub_service::{PubSubConfig, PubSubService},
|
||||
rpc_subscriptions::RpcSubscriptions,
|
||||
test_validator::TestValidator,
|
||||
};
|
||||
use solana_runtime::{
|
||||
bank::Bank,
|
||||
|
@ -11,7 +11,8 @@ use solana_client::{
|
||||
rpc_response::{Response, RpcSignatureResult, SlotUpdate},
|
||||
tpu_client::{TpuClient, TpuClientConfig},
|
||||
};
|
||||
use solana_core::{rpc_pubsub::gen_client::Client as PubsubClient, test_validator::TestValidator};
|
||||
use solana_core::test_validator::TestValidator;
|
||||
use solana_rpc::rpc_pubsub::gen_client::Client as PubsubClient;
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig,
|
||||
hash::Hash,
|
||||
|
Reference in New Issue
Block a user