Move Bank to its own crate

Also:
* counters.rs to solana_metrics
* genesis_block.rs to solana_sdk
This commit is contained in:
Greg Fitzgerald 2019-02-18 23:26:22 -07:00
parent 781f7ef570
commit dde886f058
61 changed files with 409 additions and 382 deletions

15
Cargo.lock generated
View File

@ -1940,10 +1940,8 @@ version = "0.12.0"
dependencies = [
"bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2075,6 +2073,7 @@ dependencies = [
"solana-logger 0.12.0",
"solana-metrics 0.12.0",
"solana-netutil 0.12.0",
"solana-runtime 0.12.0",
"solana-sdk 0.12.0",
"solana-vote-signer 0.12.0",
]
@ -2122,6 +2121,7 @@ dependencies = [
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
"solana 0.12.0",
"solana-logger 0.12.0",
"solana-runtime 0.12.0",
"solana-sdk 0.12.0",
]
@ -2187,6 +2187,7 @@ dependencies = [
"solana-bpfloader 0.12.0",
"solana-logger 0.12.0",
"solana-native-loader 0.12.0",
"solana-runtime 0.12.0",
"solana-sdk 0.12.0",
]
@ -2228,6 +2229,16 @@ dependencies = [
name = "solana-runtime"
version = "0.12.0"
dependencies = [
"bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
"solana-metrics 0.12.0",
"solana-native-loader 0.12.0",
"solana-sdk 0.12.0",
"solana-system-program 0.12.0",

View File

@ -26,10 +26,8 @@ unstable = []
[dependencies]
bincode = "1.1.2"
bs58 = "0.2.0"
bv = { version = "0.11.0", features = ["serde"] }
byteorder = "1.3.1"
chrono = { version = "0.4.0", features = ["serde"] }
fnv = "1.0.6"
hashbrown = "0.1.8"
indexmap = "1.0"
itertools = "0.8.0"
@ -66,9 +64,6 @@ untrusted = "0.6.2"
hex-literal = "0.1.2"
matches = "0.1.6"
[[bench]]
name = "bank"
[[bench]]
name = "banking_stage"

View File

@ -4,17 +4,17 @@ extern crate test;
use rand::{thread_rng, Rng};
use rayon::prelude::*;
use solana::bank::Bank;
use solana::banking_stage::BankingStage;
use solana::entry::Entry;
use solana::genesis_block::GenesisBlock;
use solana::last_id_queue::MAX_ENTRY_IDS;
use solana::packet::to_packets_chunked;
use solana::poh_service::PohServiceConfig;
use solana_runtime::bank::Bank;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{KeypairUtil, Signature};
use solana_sdk::system_transaction::SystemTransaction;
use solana_sdk::timing::MAX_ENTRY_IDS;
use std::iter;
use std::sync::mpsc::{channel, Receiver};
use std::sync::Arc;

View File

@ -18,6 +18,7 @@ solana-fullnode-config = { path = "../fullnode-config", version = "0.12.0" }
solana-logger = { path = "../logger", version = "0.12.0" }
solana-netutil = { path = "../netutil", version = "0.12.0" }
solana-metrics = { path = "../metrics", version = "0.12.0" }
solana-runtime = { path = "../runtime", version = "0.12.0" }
solana-sdk = { path = "../sdk", version = "0.12.0" }
solana-vote-signer = { path = "../vote-signer", version = "0.12.0" }

View File

@ -3,11 +3,11 @@ use log::*;
use solana::client::mk_client;
use solana::cluster_info::{Node, NodeInfo, FULLNODE_PORT_RANGE};
use solana::fullnode::{Fullnode, FullnodeConfig};
use solana::genesis_block::GenesisBlock;
use solana::local_vote_signer_service::LocalVoteSignerService;
use solana::socketaddr;
use solana::thin_client::{poll_gossip_for_leader, ThinClient};
use solana::voting_keypair::{RemoteVoteSigner, VotingKeypair};
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::vote_program::VoteState;

View File

@ -2,7 +2,7 @@
use clap::{crate_version, value_t_or_exit, App, Arg};
use solana::blocktree::create_new_ledger;
use solana::genesis_block::GenesisBlock;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
use std::error;

View File

@ -14,6 +14,7 @@ serde_json = "1.0.38"
solana = { path = "..", version = "0.12.0" }
solana-sdk = { path = "../sdk", version = "0.12.0" }
solana-logger = { path = "../logger", version = "0.12.0" }
solana-runtime = { path = "../runtime", version = "0.12.0" }
[dev-dependencies]
assert_cmd = "0.11"

View File

@ -1,8 +1,8 @@
use clap::{crate_version, App, Arg, SubCommand};
use solana::bank::Bank;
use solana::blocktree::Blocktree;
use solana::blocktree_processor;
use solana::genesis_block::GenesisBlock;
use solana_runtime::bank::Bank;
use solana_sdk::genesis_block::GenesisBlock;
use std::io::{stdout, Write};
use std::process::exit;

View File

@ -1,4 +1,5 @@
use solana_metrics::{influxdb, submit};
use crate::{influxdb, submit};
use log::{info, log_enabled};
use solana_sdk::timing;
use std::env;
use std::sync::atomic::{AtomicUsize, Ordering};
@ -16,6 +17,7 @@ pub struct Counter {
pub point: Option<influxdb::Point>,
}
#[macro_export]
macro_rules! create_counter {
($name:expr, $lograte:expr) => {
Counter {
@ -29,21 +31,14 @@ macro_rules! create_counter {
};
}
#[macro_export]
macro_rules! inc_counter {
($name:expr, $level:expr, $count:expr) => {
unsafe { $name.inc($level, $count) };
};
}
macro_rules! inc_new_counter_info {
($name:expr, $count:expr) => {{
inc_new_counter!($name, $count, Level::Info, 0);
}};
($name:expr, $count:expr, $lograte:expr) => {{
inc_new_counter!($name, $count, Level::Info, $lograte);
}};
}
#[macro_export]
macro_rules! inc_new_counter {
($name:expr, $count:expr, $level:expr, $lograte:expr) => {{
static mut INC_NEW_COUNTER: Counter = create_counter!($name, $lograte);
@ -57,6 +52,16 @@ macro_rules! inc_new_counter {
}};
}
#[macro_export]
macro_rules! inc_new_counter_info {
($name:expr, $count:expr) => {{
inc_new_counter!($name, $count, Level::Info, 0);
}};
($name:expr, $count:expr, $lograte:expr) => {{
inc_new_counter!($name, $count, Level::Info, $lograte);
}};
}
impl Counter {
fn default_log_rate() -> usize {
let v = env::var("SOLANA_DEFAULT_LOG_RATE")

View File

@ -1,3 +1,6 @@
#[macro_use]
pub mod counter;
mod metrics;
pub use crate::metrics::flush;

View File

@ -22,4 +22,5 @@ solana = { path = "..", version = "0.12.0" }
solana-bpfloader = { path = "native/bpf_loader", version = "0.12.0" }
solana-logger = { path = "../logger", version = "0.12.0" }
solana-native-loader = { path = "native/native_loader", version = "0.12.0" }
solana-runtime = { path = "../runtime", version = "0.12.0" }
solana-sdk = { path = "../sdk", version = "0.12.0" }

View File

@ -1,6 +1,6 @@
use solana_rewards_api::rewards_program;
use solana_rewards_api::rewards_transaction::RewardsTransaction;
use solana_runtime::{execute_transaction, RuntimeError};
use solana_runtime::runtime::{execute_transaction, RuntimeError};
use solana_sdk::account::Account;
use solana_sdk::hash::Hash;
use solana_sdk::native_loader::create_program_account;

View File

@ -1,5 +1,5 @@
use solana::bank::Bank;
use solana::genesis_block::GenesisBlock;
use solana_runtime::bank::Bank;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::loader_transaction::LoaderTransaction;
use solana_sdk::native_loader;
use solana_sdk::pubkey::Pubkey;

View File

@ -9,6 +9,16 @@ homepage = "https://solana.com/"
edition = "2018"
[dependencies]
bincode = "1.1.2"
bv = { version = "0.11.0", features = ["serde"] }
fnv = "1.0.6"
hashbrown = "0.1.8"
log = "0.4.2"
rand = "0.6.5"
serde = "1.0.88"
serde_derive = "1.0.88"
serde_json = "1.0.38"
solana-metrics = { path = "../metrics", version = "0.12.0" }
solana-sdk = { path = "../sdk", version = "0.12.0" }
solana-native-loader = { path = "../programs/native/native_loader", version = "0.12.0" }
solana-system-program = { path = "../programs/native/system", version = "0.12.0" }

View File

@ -2,9 +2,9 @@
extern crate test;
use solana::bank::*;
use solana::genesis_block::GenesisBlock;
use solana::last_id_queue::MAX_ENTRY_IDS;
use solana_runtime::bank::*;
use solana_runtime::last_id_queue::MAX_ENTRY_IDS;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::hash;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction::SystemTransaction;

View File

@ -3,7 +3,7 @@
extern crate test;
use bv::BitVec;
use fnv::FnvHasher;
use solana::bloom::{Bloom, BloomHashIndex};
use solana_runtime::bloom::{Bloom, BloomHashIndex};
use solana_sdk::hash::{hash, Hash};
use solana_sdk::signature::Signature;
//use std::collections::HashSet;

View File

@ -1,10 +1,9 @@
use crate::bank::BankError;
use crate::bank::Result;
use crate::counter::Counter;
use crate::bank::{BankError, Result};
use crate::runtime::has_duplicates;
use bincode::serialize;
use hashbrown::{HashMap, HashSet};
use log::Level;
use solana_runtime::has_duplicates;
use log::{debug, Level};
use solana_metrics::counter::Counter;
use solana_sdk::account::Account;
use solana_sdk::hash::{hash, Hash};
use solana_sdk::native_loader;
@ -256,13 +255,13 @@ impl AccountsDB {
pub fn transaction_count(&self) -> u64 {
self.transaction_count
}
pub fn account_values_slow(&self) -> Vec<(Pubkey, solana_sdk::account::Account)> {
self.accounts.iter().map(|(x, y)| (*x, y.clone())).collect()
}
fn merge(&mut self, other: Self) {
self.transaction_count += other.transaction_count;
self.accounts.extend(other.accounts)
}
//pub fn account_values_slow(&self) -> Vec<(Pubkey, solana_sdk::account::Account)> {
// self.accounts.iter().map(|(x, y)| (*x, y.clone())).collect()
//}
//fn merge(&mut self, other: Self) {
// self.transaction_count += other.transaction_count;
// self.accounts.extend(other.accounts)
//}
}
impl Accounts {
@ -390,27 +389,27 @@ impl Accounts {
pub fn transaction_count(&self) -> u64 {
self.accounts_db.read().unwrap().transaction_count()
}
/// accounts starts with an empty data structure for every fork
/// self is root, merge the fork into self
pub fn merge_into_root(&self, other: Self) {
assert!(other.account_locks.lock().unwrap().is_empty());
let db = other.accounts_db.into_inner().unwrap();
let mut mydb = self.accounts_db.write().unwrap();
mydb.merge(db)
}
pub fn copy_for_tpu(&self) -> Self {
//TODO: deprecate this in favor of forks and merge_into_root
let copy = Accounts::default();
///// accounts starts with an empty data structure for every fork
///// self is root, merge the fork into self
//pub fn merge_into_root(&self, other: Self) {
// assert!(other.account_locks.lock().unwrap().is_empty());
// let db = other.accounts_db.into_inner().unwrap();
// let mut mydb = self.accounts_db.write().unwrap();
// mydb.merge(db)
//}
//pub fn copy_for_tpu(&self) -> Self {
// //TODO: deprecate this in favor of forks and merge_into_root
// let copy = Accounts::default();
{
let mut accounts_db = copy.accounts_db.write().unwrap();
for (key, val) in self.accounts_db.read().unwrap().accounts.iter() {
accounts_db.accounts.insert(key.clone(), val.clone());
}
accounts_db.transaction_count = self.transaction_count();
}
copy
}
// {
// let mut accounts_db = copy.accounts_db.write().unwrap();
// for (key, val) in self.accounts_db.read().unwrap().accounts.iter() {
// accounts_db.accounts.insert(key.clone(), val.clone());
// }
// accounts_db.transaction_count = self.transaction_count();
// }
// copy
//}
}
#[cfg(test)]

View File

@ -4,16 +4,16 @@
//! already been signed and verified.
use crate::accounts::{Accounts, ErrorCounters, InstructionAccounts, InstructionLoaders};
use crate::counter::Counter;
use crate::genesis_block::GenesisBlock;
use crate::last_id_queue::{LastIdQueue, MAX_ENTRY_IDS};
use crate::last_id_queue::LastIdQueue;
use crate::runtime::{self, RuntimeError};
use crate::status_cache::StatusCache;
use bincode::{deserialize, serialize};
use log::Level;
use solana_runtime::{self, RuntimeError};
use log::{debug, info, Level};
use solana_metrics::counter::Counter;
use solana_sdk::account::Account;
use solana_sdk::bpf_loader;
use solana_sdk::budget_program;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::{extend_and_hash, Hash};
use solana_sdk::native_loader;
use solana_sdk::native_program::ProgramError;
@ -22,7 +22,7 @@ use solana_sdk::signature::{Keypair, Signature};
use solana_sdk::storage_program;
use solana_sdk::system_program;
use solana_sdk::system_transaction::SystemTransaction;
use solana_sdk::timing::{duration_as_us, NUM_TICKS_PER_SECOND};
use solana_sdk::timing::{duration_as_us, MAX_ENTRY_IDS, NUM_TICKS_PER_SECOND};
use solana_sdk::token_program;
use solana_sdk::transaction::Transaction;
use solana_sdk::vote_program::{self, VoteState};
@ -389,7 +389,7 @@ impl Bank {
.map(|(accs, tx)| match accs {
Err(e) => Err(e.clone()),
Ok((ref mut accounts, ref mut loaders)) => {
solana_runtime::execute_transaction(tx, loaders, accounts, tick_height).map_err(
runtime::execute_transaction(tx, loaders, accounts, tick_height).map_err(
|RuntimeError::ProgramError(index, err)| {
BankError::ProgramError(index, err)
},
@ -628,6 +628,7 @@ impl Bank {
mod tests {
use super::*;
use hashbrown::HashSet;
use solana_sdk::genesis_block::BOOTSTRAP_LEADER_TOKENS;
use solana_sdk::hash::hash;
use solana_sdk::native_program::ProgramError;
use solana_sdk::signature::Keypair;
@ -647,7 +648,7 @@ mod tests {
#[test]
fn test_bank_new_with_leader() {
let dummy_leader_id = Keypair::new().pubkey();
let dummy_leader_tokens = crate::genesis_block::BOOTSTRAP_LEADER_TOKENS;
let dummy_leader_tokens = BOOTSTRAP_LEADER_TOKENS;
let (genesis_block, _) =
GenesisBlock::new_with_leader(10_000, dummy_leader_id, dummy_leader_tokens);
assert_eq!(genesis_block.bootstrap_leader_tokens, dummy_leader_tokens);
@ -797,7 +798,7 @@ mod tests {
// Result failed, but signature is registered
assert!(res.is_err());
assert!(bank.has_signature(&signature));
assert_matches!(
assert_eq!(
bank.get_signature_status(&signature),
Some(Err(BankError::ProgramError(
0,
@ -833,7 +834,7 @@ mod tests {
.unwrap();
assert_eq!(bank.transaction_count(), 1);
assert_eq!(bank.get_balance(&pubkey), 1_000);
assert_matches!(
assert_eq!(
bank.transfer(10_001, &mint_keypair, pubkey, genesis_block.last_id()),
Err(BankError::ProgramError(
0,
@ -886,7 +887,6 @@ mod tests {
#[test]
fn test_process_genesis() {
solana_logger::setup();
let dummy_leader_id = Keypair::new().pubkey();
let dummy_leader_tokens = 2;
let (genesis_block, _) =
@ -931,10 +931,9 @@ mod tests {
bank.unlock_accounts(&pay_alice, &results_alice);
assert_matches!(
bank.transfer(2, &mint_keypair, bob.pubkey(), genesis_block.last_id()),
Ok(_)
);
assert!(bank
.transfer(2, &mint_keypair, bob.pubkey(), genesis_block.last_id())
.is_ok());
}
#[test]
@ -1000,7 +999,6 @@ mod tests {
#[test]
fn test_bank_storage() {
solana_logger::setup();
let (genesis_block, alice) = GenesisBlock::new(1000);
let bank = Bank::new(&genesis_block);

View File

@ -2,6 +2,7 @@
use bv::BitVec;
use fnv::FnvHasher;
use rand::{self, Rng};
use serde::{Deserialize, Serialize};
use std::cmp;
use std::hash::Hasher;
use std::marker::PhantomData;

View File

@ -1,14 +1,6 @@
use hashbrown::HashMap;
use solana_sdk::hash::Hash;
use solana_sdk::timing::{timestamp, NUM_TICKS_PER_SECOND};
/// The number of most recent `last_id` values that the bank will track the signatures
/// of. Once the bank discards a `last_id`, it will reject any transactions that use
/// that `last_id` in a transaction. Lowering this value reduces memory consumption,
/// but requires clients to update its `last_id` more frequently. Raising the value
/// lengthens the time a client must wait to be certain a missing transaction will
/// not be processed by the network.
pub const MAX_ENTRY_IDS: usize = NUM_TICKS_PER_SECOND * 120;
use solana_sdk::timing::{timestamp, MAX_ENTRY_IDS};
#[derive(Debug, PartialEq, Eq, Clone)]
struct LastIdEntry {
@ -48,6 +40,7 @@ impl LastIdQueue {
}
}
/// check if entry is valid
#[cfg(test)]
pub fn check_entry(&self, entry_id: Hash) -> bool {
self.entries.get(&entry_id).is_some()
}
@ -124,12 +117,14 @@ impl LastIdQueue {
None
}
#[cfg(test)]
pub fn clear(&mut self) {
self.entries = HashMap::new();
self.tick_height = 0;
self.last_id = None;
}
/// fork for LastIdQueue is a simple clone
#[cfg(test)]
pub fn fork(&self) -> Self {
Self {
entries: self.entries.clone(),
@ -138,6 +133,7 @@ impl LastIdQueue {
}
}
/// merge for entryq is a swap
#[cfg(test)]
pub fn merge_into_root(&mut self, other: Self) {
let (entries, tick_height, last_id) = { (other.entries, other.tick_height, other.last_id) };
self.entries = entries;

View File

@ -1,209 +1,9 @@
use solana_native_loader;
use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount};
use solana_sdk::native_program::ProgramError;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::system_program;
use solana_sdk::transaction::Transaction;
use solana_system_program;
mod accounts;
pub mod bank;
pub mod bloom;
mod last_id_queue;
pub mod runtime;
mod status_cache;
/// Reasons the runtime might have rejected a transaction.
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RuntimeError {
/// Executing the instruction at the given index produced an error.
ProgramError(u8, ProgramError),
}
/// Process an instruction
/// This method calls the instruction's program entrypoint method
fn process_instruction(
tx: &Transaction,
instruction_index: usize,
executable_accounts: &mut [(Pubkey, Account)],
program_accounts: &mut [&mut Account],
tick_height: u64,
) -> Result<(), ProgramError> {
let program_id = tx.program_id(instruction_index);
let mut keyed_accounts = create_keyed_accounts(executable_accounts);
let mut keyed_accounts2: Vec<_> = tx.instructions[instruction_index]
.accounts
.iter()
.map(|&index| {
let index = index as usize;
let key = &tx.account_keys[index];
(key, index < tx.signatures.len())
})
.zip(program_accounts.iter_mut())
.map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account))
.collect();
keyed_accounts.append(&mut keyed_accounts2);
if system_program::check_id(&program_id) {
solana_system_program::entrypoint(
&program_id,
&mut keyed_accounts[1..],
&tx.instructions[instruction_index].userdata,
tick_height,
)
} else {
solana_native_loader::entrypoint(
&program_id,
&mut keyed_accounts,
&tx.instructions[instruction_index].userdata,
tick_height,
)
}
}
fn verify_instruction(
program_id: &Pubkey,
pre_program_id: &Pubkey,
pre_tokens: u64,
account: &Account,
) -> Result<(), ProgramError> {
// Verify the transaction
// Make sure that program_id is still the same or this was just assigned by the system program
if *pre_program_id != account.owner && !system_program::check_id(&program_id) {
return Err(ProgramError::ModifiedProgramId);
}
// For accounts unassigned to the program, the individual balance of each accounts cannot decrease.
if *program_id != account.owner && pre_tokens > account.tokens {
return Err(ProgramError::ExternalAccountTokenSpend);
}
Ok(())
}
/// Execute an instruction
/// This method calls the instruction's program entrypoint method and verifies that the result of
/// the call does not violate the bank's accounting rules.
/// The accounts are committed back to the bank only if this function returns Ok(_).
fn execute_instruction(
tx: &Transaction,
instruction_index: usize,
executable_accounts: &mut [(Pubkey, Account)],
program_accounts: &mut [&mut Account],
tick_height: u64,
) -> Result<(), ProgramError> {
let program_id = tx.program_id(instruction_index);
// TODO: the runtime should be checking read/write access to memory
// we are trusting the hard-coded programs not to clobber or allocate
let pre_total: u64 = program_accounts.iter().map(|a| a.tokens).sum();
let pre_data: Vec<_> = program_accounts
.iter_mut()
.map(|a| (a.owner, a.tokens))
.collect();
process_instruction(
tx,
instruction_index,
executable_accounts,
program_accounts,
tick_height,
)?;
// Verify the instruction
for ((pre_program_id, pre_tokens), post_account) in pre_data.iter().zip(program_accounts.iter())
{
verify_instruction(&program_id, pre_program_id, *pre_tokens, post_account)?;
}
// The total sum of all the tokens in all the accounts cannot change.
let post_total: u64 = program_accounts.iter().map(|a| a.tokens).sum();
if pre_total != post_total {
return Err(ProgramError::UnbalancedInstruction);
}
Ok(())
}
/// Return true if the slice has any duplicate elements
pub fn has_duplicates<T: PartialEq>(xs: &[T]) -> bool {
// Note: This is an O(n^2) algorithm, but requires no heap allocations. The benchmark
// `bench_has_duplicates` in benches/runtime.rs shows that this implementation is
// ~50 times faster than using HashSet for very short slices.
for i in 1..xs.len() {
if xs[i..].contains(&xs[i - 1]) {
return true;
}
}
false
}
/// Get mut references to a subset of elements.
fn get_subset_unchecked_mut<'a, T>(xs: &'a mut [T], indexes: &[u8]) -> Vec<&'a mut T> {
// Since the compiler doesn't know the indexes are unique, dereferencing
// multiple mut elements is assumed to be unsafe. If, however, all
// indexes are unique, it's perfectly safe. The returned elements will share
// the liftime of the input slice.
// Make certain there are no duplicate indexes. If there are, panic because we
// can't return multiple mut references to the same element.
if has_duplicates(indexes) {
panic!("duplicate indexes");
}
indexes
.iter()
.map(|i| {
let ptr = &mut xs[*i as usize] as *mut T;
unsafe { &mut *ptr }
})
.collect()
}
/// Execute a transaction.
/// This method calls each instruction in the transaction over the set of loaded Accounts
/// The accounts are committed back to the bank only if every instruction succeeds
pub fn execute_transaction(
tx: &Transaction,
loaders: &mut [Vec<(Pubkey, Account)>],
tx_accounts: &mut [Account],
tick_height: u64,
) -> Result<(), RuntimeError> {
for (instruction_index, instruction) in tx.instructions.iter().enumerate() {
let executable_accounts = &mut (&mut loaders[instruction.program_ids_index as usize]);
let mut program_accounts = get_subset_unchecked_mut(tx_accounts, &instruction.accounts);
execute_instruction(
tx,
instruction_index,
executable_accounts,
&mut program_accounts,
tick_height,
)
.map_err(|err| RuntimeError::ProgramError(instruction_index as u8, err))?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_has_duplicates() {
assert!(!has_duplicates(&[1, 2]));
assert!(has_duplicates(&[1, 2, 1]));
}
#[test]
fn test_get_subset_unchecked_mut() {
assert_eq!(get_subset_unchecked_mut(&mut [7, 8], &[0]), vec![&mut 7]);
assert_eq!(
get_subset_unchecked_mut(&mut [7, 8], &[0, 1]),
vec![&mut 7, &mut 8]
);
}
#[test]
#[should_panic]
fn test_get_subset_unchecked_mut_duplicate_index() {
// This panics, because it assumes duplicate detection is done elsewhere.
get_subset_unchecked_mut(&mut [7, 8], &[0, 0]);
}
#[test]
#[should_panic]
fn test_get_subset_unchecked_mut_out_of_bounds() {
// This panics, because it assumes bounds validation is done elsewhere.
get_subset_unchecked_mut(&mut [7, 8], &[2]);
}
}
#[macro_use]
extern crate solana_metrics;

209
runtime/src/runtime.rs Normal file
View File

@ -0,0 +1,209 @@
use solana_native_loader;
use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount};
use solana_sdk::native_program::ProgramError;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::system_program;
use solana_sdk::transaction::Transaction;
use solana_system_program;
/// Reasons the runtime might have rejected a transaction.
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RuntimeError {
/// Executing the instruction at the given index produced an error.
ProgramError(u8, ProgramError),
}
/// Process an instruction
/// This method calls the instruction's program entrypoint method
fn process_instruction(
tx: &Transaction,
instruction_index: usize,
executable_accounts: &mut [(Pubkey, Account)],
program_accounts: &mut [&mut Account],
tick_height: u64,
) -> Result<(), ProgramError> {
let program_id = tx.program_id(instruction_index);
let mut keyed_accounts = create_keyed_accounts(executable_accounts);
let mut keyed_accounts2: Vec<_> = tx.instructions[instruction_index]
.accounts
.iter()
.map(|&index| {
let index = index as usize;
let key = &tx.account_keys[index];
(key, index < tx.signatures.len())
})
.zip(program_accounts.iter_mut())
.map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account))
.collect();
keyed_accounts.append(&mut keyed_accounts2);
if system_program::check_id(&program_id) {
solana_system_program::entrypoint(
&program_id,
&mut keyed_accounts[1..],
&tx.instructions[instruction_index].userdata,
tick_height,
)
} else {
solana_native_loader::entrypoint(
&program_id,
&mut keyed_accounts,
&tx.instructions[instruction_index].userdata,
tick_height,
)
}
}
fn verify_instruction(
program_id: &Pubkey,
pre_program_id: &Pubkey,
pre_tokens: u64,
account: &Account,
) -> Result<(), ProgramError> {
// Verify the transaction
// Make sure that program_id is still the same or this was just assigned by the system program
if *pre_program_id != account.owner && !system_program::check_id(&program_id) {
return Err(ProgramError::ModifiedProgramId);
}
// For accounts unassigned to the program, the individual balance of each accounts cannot decrease.
if *program_id != account.owner && pre_tokens > account.tokens {
return Err(ProgramError::ExternalAccountTokenSpend);
}
Ok(())
}
/// Execute an instruction
/// This method calls the instruction's program entrypoint method and verifies that the result of
/// the call does not violate the bank's accounting rules.
/// The accounts are committed back to the bank only if this function returns Ok(_).
fn execute_instruction(
tx: &Transaction,
instruction_index: usize,
executable_accounts: &mut [(Pubkey, Account)],
program_accounts: &mut [&mut Account],
tick_height: u64,
) -> Result<(), ProgramError> {
let program_id = tx.program_id(instruction_index);
// TODO: the runtime should be checking read/write access to memory
// we are trusting the hard-coded programs not to clobber or allocate
let pre_total: u64 = program_accounts.iter().map(|a| a.tokens).sum();
let pre_data: Vec<_> = program_accounts
.iter_mut()
.map(|a| (a.owner, a.tokens))
.collect();
process_instruction(
tx,
instruction_index,
executable_accounts,
program_accounts,
tick_height,
)?;
// Verify the instruction
for ((pre_program_id, pre_tokens), post_account) in pre_data.iter().zip(program_accounts.iter())
{
verify_instruction(&program_id, pre_program_id, *pre_tokens, post_account)?;
}
// The total sum of all the tokens in all the accounts cannot change.
let post_total: u64 = program_accounts.iter().map(|a| a.tokens).sum();
if pre_total != post_total {
return Err(ProgramError::UnbalancedInstruction);
}
Ok(())
}
/// Return true if the slice has any duplicate elements
pub fn has_duplicates<T: PartialEq>(xs: &[T]) -> bool {
// Note: This is an O(n^2) algorithm, but requires no heap allocations. The benchmark
// `bench_has_duplicates` in benches/runtime.rs shows that this implementation is
// ~50 times faster than using HashSet for very short slices.
for i in 1..xs.len() {
if xs[i..].contains(&xs[i - 1]) {
return true;
}
}
false
}
/// Get mut references to a subset of elements.
fn get_subset_unchecked_mut<'a, T>(xs: &'a mut [T], indexes: &[u8]) -> Vec<&'a mut T> {
// Since the compiler doesn't know the indexes are unique, dereferencing
// multiple mut elements is assumed to be unsafe. If, however, all
// indexes are unique, it's perfectly safe. The returned elements will share
// the liftime of the input slice.
// Make certain there are no duplicate indexes. If there are, panic because we
// can't return multiple mut references to the same element.
if has_duplicates(indexes) {
panic!("duplicate indexes");
}
indexes
.iter()
.map(|i| {
let ptr = &mut xs[*i as usize] as *mut T;
unsafe { &mut *ptr }
})
.collect()
}
/// Execute a transaction.
/// This method calls each instruction in the transaction over the set of loaded Accounts
/// The accounts are committed back to the bank only if every instruction succeeds
pub fn execute_transaction(
tx: &Transaction,
loaders: &mut [Vec<(Pubkey, Account)>],
tx_accounts: &mut [Account],
tick_height: u64,
) -> Result<(), RuntimeError> {
for (instruction_index, instruction) in tx.instructions.iter().enumerate() {
let executable_accounts = &mut (&mut loaders[instruction.program_ids_index as usize]);
let mut program_accounts = get_subset_unchecked_mut(tx_accounts, &instruction.accounts);
execute_instruction(
tx,
instruction_index,
executable_accounts,
&mut program_accounts,
tick_height,
)
.map_err(|err| RuntimeError::ProgramError(instruction_index as u8, err))?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_has_duplicates() {
assert!(!has_duplicates(&[1, 2]));
assert!(has_duplicates(&[1, 2, 1]));
}
#[test]
fn test_get_subset_unchecked_mut() {
assert_eq!(get_subset_unchecked_mut(&mut [7, 8], &[0]), vec![&mut 7]);
assert_eq!(
get_subset_unchecked_mut(&mut [7, 8], &[0, 1]),
vec![&mut 7, &mut 8]
);
}
#[test]
#[should_panic]
fn test_get_subset_unchecked_mut_duplicate_index() {
// This panics, because it assumes duplicate detection is done elsewhere.
get_subset_unchecked_mut(&mut [7, 8], &[0, 0]);
}
#[test]
#[should_panic]
fn test_get_subset_unchecked_mut_out_of_bounds() {
// This panics, because it assumes bounds validation is done elsewhere.
get_subset_unchecked_mut(&mut [7, 8], &[2]);
}
}

View File

@ -1,11 +1,12 @@
use crate::bloom::{Bloom, BloomHashIndex};
use crate::last_id_queue::MAX_ENTRY_IDS;
use hashbrown::HashMap;
use solana_sdk::hash::Hash;
use solana_sdk::signature::Signature;
use solana_sdk::timing::NUM_TICKS_PER_SECOND;
use solana_sdk::timing::{MAX_ENTRY_IDS, NUM_TICKS_PER_SECOND};
use std::collections::VecDeque;
use std::ops::{Deref, DerefMut};
use std::ops::Deref;
#[cfg(test)]
use std::ops::DerefMut;
/// This cache is designed to last 1 second
const MAX_CACHE_ENTRIES: usize = MAX_ENTRY_IDS / NUM_TICKS_PER_SECOND;
@ -85,6 +86,7 @@ impl<T: Clone> StatusCache<T> {
/// like accounts, status cache starts with an new data structure for every checkpoint
/// so only merge is implemented
/// but the merges maintains a history
#[cfg(test)]
pub fn merge_into_root(&mut self, other: Self) {
// merges should be empty for every other checkpoint accept the root
// which cannot be rolled back
@ -131,6 +133,7 @@ impl<T: Clone> StatusCache<T> {
}
false
}
#[cfg(test)]
pub fn clear_all<U>(checkpoints: &mut [U]) -> bool
where
U: DerefMut<Target = Self>,

View File

@ -1,8 +1,8 @@
//! The `genesis_block` module is a library for generating the chain's genesis block.
use solana_sdk::hash::{hash, Hash};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil};
use crate::hash::{hash, Hash};
use crate::pubkey::Pubkey;
use crate::signature::{Keypair, KeypairUtil};
use std::fs::File;
use std::io::Write;
use std::path::Path;

View File

@ -4,6 +4,7 @@ pub mod budget_expr;
pub mod budget_instruction;
pub mod budget_program;
pub mod budget_transaction;
pub mod genesis_block;
pub mod hash;
pub mod loader_instruction;
pub mod loader_transaction;

View File

@ -9,6 +9,14 @@ pub const NUM_TICKS_PER_SECOND: usize = 10;
pub const DEFAULT_TICKS_PER_SLOT: u64 = 8;
pub const DEFAULT_SLOTS_PER_EPOCH: u64 = 64;
/// The number of most recent `last_id` values that the bank will track the signatures
/// of. Once the bank discards a `last_id`, it will reject any transactions that use
/// that `last_id` in a transaction. Lowering this value reduces memory consumption,
/// but requires clients to update its `last_id` more frequently. Raising the value
/// lengthens the time a client must wait to be certain a missing transaction will
/// not be processed by the network.
pub const MAX_ENTRY_IDS: usize = NUM_TICKS_PER_SECOND * 120;
pub fn duration_as_us(d: &Duration) -> u64 {
(d.as_secs() * 1000 * 1000) + (u64::from(d.subsec_nanos()) / 1_000)
}

View File

@ -1,6 +1,6 @@
//! The `bank_forks` module implments BankForks a DAG of checkpointed Banks
use crate::bank::Bank;
use solana_runtime::bank::Bank;
use std::collections::HashMap;
use std::sync::Arc;

View File

@ -2,10 +2,7 @@
//! to contruct a software pipeline. The stage uses all available CPU cores and
//! can do its processing in parallel with signature verification on the GPU.
use crate::bank::{self, Bank, BankError};
use crate::counter::Counter;
use crate::entry::Entry;
use crate::last_id_queue::MAX_ENTRY_IDS;
use crate::leader_confirmation_service::LeaderConfirmationService;
use crate::packet::Packets;
use crate::packet::SharedPackets;
@ -16,9 +13,11 @@ use crate::service::Service;
use crate::sigverify_stage::VerifiedPackets;
use bincode::deserialize;
use log::Level;
use solana_metrics::counter::Counter;
use solana_runtime::bank::{self, Bank, BankError};
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::timing::{self, duration_as_us};
use solana_sdk::timing::{self, duration_as_us, MAX_ENTRY_IDS};
use solana_sdk::transaction::Transaction;
use std::sync::atomic::AtomicBool;
use std::sync::mpsc::{channel, Receiver, RecvTimeoutError};
@ -344,8 +343,8 @@ impl Service for BankingStage {
mod tests {
use super::*;
use crate::entry::EntrySlice;
use crate::genesis_block::GenesisBlock;
use crate::packet::to_packets;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::native_program::ProgramError;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction::SystemTransaction;

View File

@ -3,7 +3,6 @@
//! access read to a persistent file-based ledger.
use crate::entry::Entry;
use crate::genesis_block::GenesisBlock;
use crate::packet::{Blob, SharedBlob, BLOB_HEADER_SIZE};
use crate::result::{Error, Result};
use bincode::{deserialize, serialize};
@ -14,6 +13,7 @@ use rocksdb::{
};
use serde::de::DeserializeOwned;
use serde::Serialize;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil};

View File

@ -1,14 +1,14 @@
use crate::bank::{Bank, BankError, Result};
use crate::bank_forks::BankForks;
use crate::blocktree::Blocktree;
use crate::counter::Counter;
use crate::entry::{Entry, EntrySlice};
use crate::last_id_queue::MAX_ENTRY_IDS;
use crate::leader_scheduler::LeaderScheduler;
use itertools::Itertools;
use log::Level;
use rayon::prelude::*;
use solana_metrics::counter::Counter;
use solana_runtime::bank::{Bank, BankError, Result};
use solana_sdk::hash::Hash;
use solana_sdk::timing::MAX_ENTRY_IDS;
use std::sync::{Arc, RwLock};
pub const VERIFY_BLOCK_SIZE: usize = 16;
@ -202,7 +202,7 @@ mod tests {
use super::*;
use crate::entry::{next_entries, next_entry, Entry};
use crate::gen_keys::GenKeys;
use crate::genesis_block::GenesisBlock;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::native_program::ProgramError;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction::SystemTransaction;

View File

@ -1,9 +1,7 @@
//! The `broadcast_service` broadcasts data from a leader node to validators
//!
use crate::bank::Bank;
use crate::blocktree::Blocktree;
use crate::cluster_info::{ClusterInfo, ClusterInfoError, NodeInfo, DATA_PLANE_FANOUT};
use crate::counter::Counter;
use crate::entry::Entry;
use crate::entry::EntrySlice;
#[cfg(feature = "erasure")]
@ -14,7 +12,9 @@ use crate::result::{Error, Result};
use crate::service::Service;
use log::Level;
use rayon::prelude::*;
use solana_metrics::counter::Counter;
use solana_metrics::{influxdb, submit};
use solana_runtime::bank::Bank;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::timing::duration_as_ms;
use std::net::UdpSocket;

View File

@ -12,11 +12,8 @@
//! * layer 2 - Everyone else, if layer 1 is `2^10`, layer 2 should be able to fit `2^20` number of nodes.
//!
//! Bank needs to provide an interface for us to query the stake weight
use crate::bank::Bank;
use crate::blocktree::Blocktree;
use crate::bloom::Bloom;
use crate::contact_info::ContactInfo;
use crate::counter::Counter;
use crate::crds_gossip::CrdsGossip;
use crate::crds_gossip_error::CrdsGossipError;
use crate::crds_gossip_pull::CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS;
@ -31,8 +28,11 @@ use hashbrown::HashMap;
use log::Level;
use rand::{thread_rng, Rng};
use rayon::prelude::*;
use solana_metrics::counter::Counter;
use solana_metrics::{influxdb, submit};
use solana_netutil::{bind_in_range, bind_to, find_available_port_in_range, multi_bind_in_range};
use solana_runtime::bank::Bank;
use solana_runtime::bloom::Bloom;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil, Signable, Signature};

View File

@ -1,10 +1,10 @@
use crate::cluster_info::{ClusterInfo, GOSSIP_SLEEP_MILLIS};
use crate::counter::Counter;
use crate::packet;
use crate::result::Result;
use crate::service::Service;
use crate::streamer::PacketSender;
use log::Level;
use solana_metrics::counter::Counter;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock};
use std::thread::{self, sleep, Builder, JoinHandle};

View File

@ -3,12 +3,12 @@
//! designed to run with a simulator or over a UDP network connection with messages up to a
//! packet::BLOB_DATA_SIZE size.
use crate::bloom::Bloom;
use crate::crds::Crds;
use crate::crds_gossip_error::CrdsGossipError;
use crate::crds_gossip_pull::CrdsGossipPull;
use crate::crds_gossip_push::{CrdsGossipPush, CRDS_GOSSIP_NUM_ACTIVE};
use crate::crds_value::CrdsValue;
use solana_runtime::bloom::Bloom;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;

View File

@ -9,7 +9,6 @@
//! with random hash functions. So each subsequent request will have a different distribution
//! of false positives.
use crate::bloom::Bloom;
use crate::crds::Crds;
use crate::crds_gossip::CRDS_GOSSIP_BLOOM_SIZE;
use crate::crds_gossip_error::CrdsGossipError;
@ -19,6 +18,7 @@ use bincode::serialized_size;
use hashbrown::HashMap;
use rand;
use rand::distributions::{Distribution, WeightedIndex};
use solana_runtime::bloom::Bloom;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use std::cmp;

View File

@ -8,7 +8,6 @@
//! the local nodes wallclock window they are drooped silently.
//! 2. The prune set is stored in a Bloom filter.
use crate::bloom::Bloom;
use crate::contact_info::ContactInfo;
use crate::crds::{Crds, VersionedCrdsValue};
use crate::crds_gossip::CRDS_GOSSIP_BLOOM_SIZE;
@ -20,6 +19,7 @@ use hashbrown::HashMap;
use indexmap::map::IndexMap;
use rand;
use rand::seq::SliceRandom;
use solana_runtime::bloom::Bloom;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use std::cmp;

View File

@ -1,6 +1,5 @@
//! Set of functions for emulating windowing functions from a database ledger implementation
use crate::blocktree::*;
use crate::counter::Counter;
#[cfg(feature = "erasure")]
use crate::erasure;
use crate::leader_scheduler::LeaderScheduler;
@ -8,6 +7,7 @@ use crate::packet::{SharedBlob, BLOB_HEADER_SIZE};
use crate::result::Result;
use crate::streamer::BlobSender;
use log::Level;
use solana_metrics::counter::Counter;
use solana_metrics::{influxdb, submit};
use solana_sdk::pubkey::Pubkey;
use std::borrow::Borrow;

View File

@ -152,12 +152,12 @@ pub struct EntryStreamBlock {
#[cfg(test)]
mod test {
use super::*;
use crate::bank::Bank;
use crate::entry::Entry;
use crate::genesis_block::GenesisBlock;
use crate::leader_scheduler::LeaderSchedulerConfig;
use chrono::{DateTime, FixedOffset};
use serde_json::Value;
use solana_runtime::bank::Bank;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::Hash;
use std::collections::HashSet;

View File

@ -110,12 +110,12 @@ impl Service for EntryStreamStage {
#[cfg(test)]
mod test {
use super::*;
use crate::bank::Bank;
use crate::entry::Entry;
use crate::genesis_block::GenesisBlock;
use crate::leader_scheduler::LeaderSchedulerConfig;
use chrono::{DateTime, FixedOffset};
use serde_json::Value;
use solana_runtime::bank::Bank;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::Hash;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction::SystemTransaction;

View File

@ -1,12 +1,9 @@
//! The `fullnode` module hosts all the fullnode microservices.
use crate::bank::Bank;
use crate::bank_forks::BankForks;
use crate::blocktree::{Blocktree, BlocktreeConfig};
use crate::blocktree_processor;
use crate::cluster_info::{ClusterInfo, Node, NodeInfo};
use crate::counter::Counter;
use crate::genesis_block::GenesisBlock;
use crate::gossip_service::GossipService;
use crate::leader_scheduler::{LeaderScheduler, LeaderSchedulerConfig};
use crate::poh_service::PohServiceConfig;
@ -19,6 +16,9 @@ use crate::tpu::{Tpu, TpuRotationReceiver};
use crate::tvu::{Sockets, Tvu};
use crate::voting_keypair::VotingKeypair;
use log::Level;
use solana_metrics::counter::Counter;
use solana_runtime::bank::Bank;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil};

View File

@ -2,10 +2,9 @@
//! to generate a thread which regularly calculates the last confirmation times
//! observed by the leader
use crate::bank::Bank;
use crate::service::Service;
use solana_metrics::{influxdb, submit};
use solana_runtime::bank::Bank;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::timing;
use std::result;
@ -134,12 +133,10 @@ impl Service for LeaderConfirmationService {
#[cfg(test)]
pub mod tests {
use super::*;
use crate::bank::Bank;
use crate::voting_keypair::VotingKeypair;
use crate::genesis_block::GenesisBlock;
use crate::leader_scheduler::tests::new_vote_account;
use crate::voting_keypair::VotingKeypair;
use bincode::serialize;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::hash;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::vote_transaction::VoteTransaction;

View File

@ -1,12 +1,12 @@
//! The `leader_scheduler` module implements a structure and functions for tracking and
//! managing the schedule for leader rotation
use crate::bank::Bank;
use crate::entry::{create_ticks, next_entry_mut, Entry};
use crate::voting_keypair::VotingKeypair;
use bincode::serialize;
use byteorder::{LittleEndian, ReadBytesExt};
use hashbrown::HashSet;
use solana_runtime::bank::Bank;
use solana_sdk::hash::{hash, Hash};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil};
@ -435,8 +435,8 @@ pub fn make_active_set_entries(
#[cfg(test)]
pub mod tests {
use super::*;
use crate::genesis_block::{GenesisBlock, BOOTSTRAP_LEADER_TOKENS};
use hashbrown::HashSet;
use solana_sdk::genesis_block::{GenesisBlock, BOOTSTRAP_LEADER_TOKENS};
use std::hash::Hash as StdHash;
use std::iter::FromIterator;
use std::sync::RwLock;

View File

@ -7,14 +7,9 @@
//!
#![cfg_attr(feature = "unstable", feature(test))]
#[macro_use]
pub mod counter;
pub mod accounts;
pub mod bank;
pub mod bank_forks;
pub mod banking_stage;
pub mod blob_fetch_stage;
pub mod bloom;
pub mod broadcast_service;
#[cfg(feature = "chacha")]
pub mod chacha;
@ -42,9 +37,7 @@ pub mod erasure;
pub mod fetch_stage;
pub mod fullnode;
pub mod gen_keys;
pub mod genesis_block;
pub mod gossip_service;
pub mod last_id_queue;
pub mod leader_confirmation_service;
pub mod leader_scheduler;
pub mod local_vote_signer_service;
@ -69,7 +62,6 @@ pub mod rpc_subscriptions;
pub mod service;
pub mod sigverify;
pub mod sigverify_stage;
pub mod status_cache;
pub mod storage_stage;
pub mod streamer;
pub mod test_tx;
@ -95,6 +87,9 @@ extern crate serde_derive;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate solana_metrics;
#[cfg(test)]
#[macro_use]
extern crate matches;

View File

@ -1,11 +1,11 @@
//! The `packet` module defines data structures and methods to pull data from the network.
use crate::counter::Counter;
use crate::recvmmsg::{recv_mmsg, NUM_RCVMMSGS};
use crate::result::{Error, Result};
use bincode::{serialize, serialize_into};
use byteorder::{ByteOrder, LittleEndian};
use log::Level;
use serde::Serialize;
use solana_metrics::counter::Counter;
pub use solana_sdk::packet::PACKET_DATA_SIZE;
use std::cmp;
use std::fmt;

View File

@ -1,10 +1,10 @@
//! The `poh_recorder` module provides an object for synchronizing with Proof of History.
//! It synchronizes PoH, bank's register_tick and the ledger
//!
use crate::bank::Bank;
use crate::entry::Entry;
use crate::poh::Poh;
use crate::result::{Error, Result};
use solana_runtime::bank::Bank;
use solana_sdk::hash::Hash;
use solana_sdk::transaction::Transaction;
use std::sync::mpsc::Sender;
@ -116,8 +116,8 @@ impl PohRecorder {
#[cfg(test)]
mod tests {
use super::*;
use crate::genesis_block::GenesisBlock;
use crate::test_tx::test_tx;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::hash;
use std::sync::mpsc::channel;
use std::sync::Arc;

View File

@ -1,10 +1,10 @@
//! The `poh_service` module implements a service that records the passing of
//! "ticks", a measure of time in the PoH stream
use crate::bank::Bank;
use crate::poh_recorder::PohRecorder;
use crate::result::Result;
use crate::service::Service;
use solana_runtime::bank::Bank;
use solana_sdk::timing::NUM_TICKS_PER_SECOND;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
@ -108,9 +108,8 @@ impl Service for PohService {
#[cfg(test)]
mod tests {
use super::*;
use crate::bank::Bank;
use crate::genesis_block::GenesisBlock;
use crate::test_tx::test_tx;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::hash;
use std::sync::mpsc::channel;

View File

@ -1,10 +1,8 @@
//! The `replay_stage` replays transactions broadcast by the leader.
use crate::bank::Bank;
use crate::blocktree::Blocktree;
use crate::blocktree_processor;
use crate::cluster_info::ClusterInfo;
use crate::counter::Counter;
use crate::entry::{Entry, EntryReceiver, EntrySender, EntrySlice};
use crate::leader_scheduler::LeaderScheduler;
use crate::packet::BlobError;
@ -14,7 +12,9 @@ use crate::service::Service;
use crate::tvu::TvuRotationSender;
use crate::voting_keypair::VotingKeypair;
use log::Level;
use solana_metrics::counter::Counter;
use solana_metrics::{influxdb, submit};
use solana_runtime::bank::Bank;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::timing::duration_as_ms;
@ -341,7 +341,6 @@ impl Service for ReplayStage {
#[cfg(test)]
mod test {
use super::*;
use crate::bank::Bank;
use crate::blocktree::{
create_tmp_sample_ledger, Blocktree, BlocktreeConfig, DEFAULT_SLOT_HEIGHT,
};
@ -349,12 +348,12 @@ mod test {
use crate::entry::create_ticks;
use crate::entry::{next_entry_mut, Entry};
use crate::fullnode::new_bank_from_ledger;
use crate::genesis_block::GenesisBlock;
use crate::leader_scheduler::{
make_active_set_entries, LeaderScheduler, LeaderSchedulerConfig,
};
use crate::replay_stage::ReplayStage;
use crate::voting_keypair::VotingKeypair;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::Hash;
use solana_sdk::signature::{Keypair, KeypairUtil};
use std::fs::remove_dir_all;

View File

@ -1,6 +1,5 @@
//! The `result` module exposes a Result type that propagates one of many different Error types.
use crate::bank;
use crate::blocktree;
use crate::cluster_info;
#[cfg(feature = "erasure")]
@ -9,6 +8,7 @@ use crate::packet;
use crate::poh_recorder;
use bincode;
use serde_json;
use solana_runtime::bank;
use std;
use std::any::Any;

View File

@ -1,12 +1,10 @@
//! The `retransmit_stage` retransmits blobs between validators
use crate::bank::Bank;
use crate::blocktree::Blocktree;
use crate::cluster_info::{
compute_retransmit_peers, ClusterInfo, DATA_PLANE_FANOUT, GROW_LAYER_CAPACITY,
NEIGHBORHOOD_SIZE,
};
use crate::counter::Counter;
use crate::leader_scheduler::LeaderScheduler;
use crate::packet::SharedBlob;
use crate::result::{Error, Result};
@ -14,7 +12,9 @@ use crate::service::Service;
use crate::streamer::BlobReceiver;
use crate::window_service::WindowService;
use log::Level;
use solana_metrics::counter::Counter;
use solana_metrics::{influxdb, submit};
use solana_runtime::bank::Bank;
use std::net::UdpSocket;
use std::sync::atomic::AtomicBool;
use std::sync::mpsc::channel;

View File

@ -1,6 +1,5 @@
//! The `rpc` module implements the Solana RPC interface.
use crate::bank::{self, Bank, BankError};
use crate::cluster_info::ClusterInfo;
use crate::packet::PACKET_DATA_SIZE;
use crate::rpc_status::RpcSignatureStatus;
@ -10,6 +9,7 @@ use bs58;
use jsonrpc_core::{Error, ErrorCode, Metadata, Result};
use jsonrpc_derive::rpc;
use solana_drone::drone::request_airdrop_transaction;
use solana_runtime::bank::{self, Bank, BankError};
use solana_sdk::account::Account;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::Signature;
@ -328,10 +328,9 @@ impl RpcSol for RpcSolImpl {
#[cfg(test)]
mod tests {
use super::*;
use crate::bank::Bank;
use crate::cluster_info::NodeInfo;
use crate::genesis_block::GenesisBlock;
use jsonrpc_core::{MetaIoHandler, Response};
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::{hash, Hash};
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction::SystemTransaction;

View File

@ -161,13 +161,13 @@ impl RpcSolPubSub for RpcSolPubSubImpl {
#[cfg(test)]
mod tests {
use super::*;
use crate::bank::{self, Bank};
use crate::genesis_block::GenesisBlock;
use jsonrpc_core::futures::sync::mpsc;
use jsonrpc_core::Response;
use jsonrpc_pubsub::{PubSubHandler, Session};
use solana_runtime::bank::{self, Bank};
use solana_sdk::budget_program;
use solana_sdk::budget_transaction::BudgetTransaction;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction::SystemTransaction;
use solana_sdk::transaction::Transaction;

View File

@ -1,12 +1,12 @@
//! The `rpc_service` module implements the Solana JSON RPC service.
use crate::bank::Bank;
use crate::cluster_info::ClusterInfo;
use crate::rpc::*;
use crate::service::Service;
use crate::storage_stage::StorageState;
use jsonrpc_core::MetaIoHandler;
use jsonrpc_http_server::{hyper, AccessControlAllowOrigin, DomainsValidation, ServerBuilder};
use solana_runtime::bank::Bank;
use std::net::SocketAddr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock};
@ -101,9 +101,8 @@ impl Service for JsonRpcService {
#[cfg(test)]
mod tests {
use super::*;
use crate::bank::Bank;
use crate::cluster_info::NodeInfo;
use crate::genesis_block::GenesisBlock;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::signature::KeypairUtil;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

View File

@ -1,10 +1,10 @@
//! The `pubsub` module implements a threaded subscription service on client RPC request
use crate::bank::{self, Bank, BankError};
use crate::rpc_status::RpcSignatureStatus;
use jsonrpc_core::futures::Future;
use jsonrpc_pubsub::typed::Sink;
use jsonrpc_pubsub::SubscriptionId;
use solana_runtime::bank::{self, Bank, BankError};
use solana_sdk::account::Account;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::Signature;
@ -144,9 +144,9 @@ impl RpcSubscriptions {
#[cfg(test)]
mod tests {
use super::*;
use crate::genesis_block::GenesisBlock;
use jsonrpc_pubsub::typed::Subscriber;
use solana_sdk::budget_program;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction::SystemTransaction;
use tokio::prelude::{Async, Stream};

View File

@ -4,10 +4,10 @@
//! offloaded to the GPU.
//!
use crate::counter::Counter;
use crate::packet::{Packet, SharedPackets};
use crate::result::Result;
use log::Level;
use solana_metrics::counter::Counter;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::shortvec::decode_len;
use solana_sdk::signature::Signature;

View File

@ -5,8 +5,6 @@
//! transaction. All processing is done on the CPU by default and on a GPU
//! if the `cuda` feature is enabled with `--features=cuda`.
use crate::counter::Counter;
use crate::packet::SharedPackets;
use crate::result::{Error, Result};
use crate::service::Service;
@ -14,6 +12,7 @@ use crate::sigverify;
use crate::streamer::{self, PacketReceiver};
use log::Level;
use rand::{thread_rng, Rng};
use solana_metrics::counter::Counter;
use solana_metrics::{influxdb, submit};
use solana_sdk::timing;
use std::sync::mpsc::{channel, Receiver, RecvTimeoutError, Sender};

View File

@ -1,7 +1,6 @@
//! The `tpu` module implements the Transaction Processing Unit, a
//! multi-stage transaction processing pipeline in software.
use crate::bank::Bank;
use crate::banking_stage::{BankingStage, UnprocessedPackets};
use crate::blocktree::Blocktree;
use crate::broadcast_service::BroadcastService;
@ -13,6 +12,7 @@ use crate::poh_service::PohServiceConfig;
use crate::service::Service;
use crate::sigverify_stage::SigVerifyStage;
use crate::tpu_forwarder::TpuForwarder;
use solana_runtime::bank::Bank;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use std::net::UdpSocket;

View File

@ -5,10 +5,10 @@
use crate::banking_stage::UnprocessedPackets;
use crate::cluster_info::ClusterInfo;
use crate::contact_info::ContactInfo;
use crate::counter::Counter;
use crate::service::Service;
use crate::streamer::{self, PacketReceiver};
use log::Level;
use solana_metrics::counter::Counter;
use solana_sdk::pubkey::Pubkey;
use std::net::{SocketAddr, UdpSocket};
use std::sync::atomic::{AtomicBool, Ordering};

View File

@ -12,7 +12,6 @@
//! 4. StorageStage
//! - Generating the keys used to encrypt the ledger and sample it for storage mining.
use crate::bank::Bank;
use crate::blob_fetch_stage::BlobFetchStage;
use crate::blocktree::Blocktree;
use crate::cluster_info::ClusterInfo;
@ -25,6 +24,7 @@ use crate::service::Service;
use crate::storage_stage::{StorageStage, StorageState};
use crate::tpu::{TpuReturnType, TpuRotationReceiver, TpuRotationSender};
use crate::voting_keypair::VotingKeypair;
use solana_runtime::bank::Bank;
use solana_sdk::hash::Hash;
use solana_sdk::signature::{Keypair, KeypairUtil};
use std::net::UdpSocket;
@ -209,12 +209,11 @@ impl Service for Tvu {
#[cfg(test)]
pub mod tests {
use super::*;
use crate::bank::Bank;
use crate::blocktree::get_tmp_ledger_path;
use crate::cluster_info::{ClusterInfo, Node};
use crate::genesis_block::GenesisBlock;
use crate::leader_scheduler::LeaderSchedulerConfig;
use crate::storage_stage::STORAGE_ROTATE_TEST_COUNT;
use solana_sdk::genesis_block::GenesisBlock;
#[test]
fn test_tvu_exit() {

View File

@ -2,7 +2,6 @@
//!
use crate::blocktree::Blocktree;
use crate::cluster_info::ClusterInfo;
use crate::counter::Counter;
use crate::db_window::*;
use crate::leader_scheduler::LeaderScheduler;
use crate::repair_service::RepairService;
@ -10,6 +9,7 @@ use crate::result::{Error, Result};
use crate::service::Service;
use crate::streamer::{BlobReceiver, BlobSender};
use log::Level;
use solana_metrics::counter::Counter;
use solana_metrics::{influxdb, submit};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::timing::duration_as_ms;

View File

@ -1,12 +1,12 @@
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use rayon::prelude::*;
use solana::bank::Bank;
use solana::cluster_info::{
compute_retransmit_peers, ClusterInfo, DATA_PLANE_FANOUT, GROW_LAYER_CAPACITY,
NEIGHBORHOOD_SIZE,
};
use solana::contact_info::ContactInfo;
use solana::genesis_block::GenesisBlock;
use solana_runtime::bank::Bank;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil};
use std::collections::{HashMap, HashSet};

View File

@ -1,11 +1,9 @@
use log::trace;
use solana::bank::Bank;
use solana::blocktree::Blocktree;
use solana::blocktree::{get_tmp_ledger_path, BlocktreeConfig};
use solana::cluster_info::{ClusterInfo, Node};
use solana::entry::next_entry_mut;
use solana::entry::EntrySlice;
use solana::genesis_block::GenesisBlock;
use solana::gossip_service::GossipService;
use solana::leader_scheduler::LeaderScheduler;
use solana::leader_scheduler::LeaderSchedulerConfig;
@ -17,6 +15,8 @@ use solana::storage_stage::STORAGE_ROTATE_TEST_COUNT;
use solana::streamer;
use solana::tvu::{Sockets, Tvu};
use solana::voting_keypair::VotingKeypair;
use solana_runtime::bank::Bank;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::Hash;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction::SystemTransaction;