Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
6672d640f5 | |||
b8b84a4c95 | |||
9677b602e7 | |||
771e1e3a71 | |||
c12ea7a112 | |||
6047796c24 | |||
11a0a9ac47 | |||
5fbe5aa22d | |||
8a879a52ef | |||
c7669d4afe | |||
1f81206210 | |||
5a2a34b035 | |||
2ef7579b6c | |||
fed7cfef58 | |||
8b2ad77699 | |||
abcabc18ac | |||
4e0a3862a6 | |||
2eaf47d563 | |||
31f7b3782e | |||
d6169f92c1 | |||
7df72d36c4 | |||
5318cdac8f | |||
00434d5e6e | |||
ebf644ddef | |||
5e4fe9c67b |
629
Cargo.lock
generated
629
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -51,6 +51,7 @@ members = [
|
||||
"vote-signer",
|
||||
"cli",
|
||||
"rayon-threadlimit",
|
||||
"watchtower",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-archiver"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -10,10 +10,10 @@ homepage = "https://solana.com/"
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
console = "0.9.1"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-core = { path = "../core", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-core = { path = "../core", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-banking-bench"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -10,11 +10,11 @@ homepage = "https://solana.com/"
|
||||
[dependencies]
|
||||
log = "0.4.6"
|
||||
rayon = "1.2.0"
|
||||
solana-core = { path = "../core", version = "0.21.3" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-measure = { path = "../measure", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-core = { path = "../core", version = "0.21.5" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-measure = { path = "../measure", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
rand = "0.6.5"
|
||||
crossbeam-channel = "0.3"
|
||||
|
@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-exchange"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -23,19 +23,19 @@ serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-core = { path = "../core", version = "0.21.3" }
|
||||
solana-genesis = { path = "../genesis", version = "0.21.3" }
|
||||
solana-client = { path = "../client", version = "0.21.3" }
|
||||
solana-drone = { path = "../drone", version = "0.21.3" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-core = { path = "../core", version = "0.21.5" }
|
||||
solana-genesis = { path = "../genesis", version = "0.21.5" }
|
||||
solana-client = { path = "../client", version = "0.21.5" }
|
||||
solana-drone = { path = "../drone", version = "0.21.5" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
untrusted = "0.7.0"
|
||||
ws = "0.9.1"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-local-cluster = { path = "../local-cluster", version = "0.21.3" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "0.21.5" }
|
||||
|
@ -2,14 +2,14 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-streamer"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-core = { path = "../core", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-core = { path = "../core", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.5" }
|
||||
|
@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-tps"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -16,24 +16,24 @@ serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-core = { path = "../core", version = "0.21.3" }
|
||||
solana-genesis = { path = "../genesis", version = "0.21.3" }
|
||||
solana-client = { path = "../client", version = "0.21.3" }
|
||||
solana-drone = { path = "../drone", version = "0.21.3" }
|
||||
solana-librapay-api = { path = "../programs/librapay_api", version = "0.21.3", optional = true }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-measure = { path = "../measure", version = "0.21.3" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-move-loader-program = { path = "../programs/move_loader", version = "0.21.3", optional = true }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-core = { path = "../core", version = "0.21.5" }
|
||||
solana-genesis = { path = "../genesis", version = "0.21.5" }
|
||||
solana-client = { path = "../client", version = "0.21.5" }
|
||||
solana-drone = { path = "../drone", version = "0.21.5" }
|
||||
solana-librapay-api = { path = "../programs/librapay_api", version = "0.21.5", optional = true }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
solana-measure = { path = "../measure", version = "0.21.5" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-move-loader-program = { path = "../programs/move_loader", version = "0.21.5", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.2.0"
|
||||
serial_test_derive = "0.2.0"
|
||||
solana-local-cluster = { path = "../local-cluster", version = "0.21.3" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
move = ["solana-librapay-api", "solana-move-loader-program"]
|
||||
|
@ -24,6 +24,7 @@ use std::{
|
||||
cmp,
|
||||
collections::VecDeque,
|
||||
net::SocketAddr,
|
||||
process::exit,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering},
|
||||
Arc, RwLock,
|
||||
@ -88,8 +89,13 @@ where
|
||||
let clients: Vec<_> = clients.into_iter().map(Arc::new).collect();
|
||||
let client = &clients[0];
|
||||
|
||||
let start = gen_keypairs.len() - (tx_count * 2) as usize;
|
||||
let keypairs = &gen_keypairs[start..];
|
||||
let mut source_keypair_chunks: Vec<Vec<&Keypair>> = Vec::new();
|
||||
let mut dest_keypair_chunks: Vec<VecDeque<&Keypair>> = Vec::new();
|
||||
assert!(gen_keypairs.len() >= 2 * tx_count);
|
||||
for chunk in gen_keypairs.chunks_exact(2 * tx_count) {
|
||||
source_keypair_chunks.push(chunk[..tx_count].iter().collect());
|
||||
dest_keypair_chunks.push(chunk[tx_count..].iter().collect());
|
||||
}
|
||||
|
||||
let first_tx_count = loop {
|
||||
match client.get_transaction_count() {
|
||||
@ -126,9 +132,23 @@ where
|
||||
|
||||
let shared_txs: SharedTransactions = Arc::new(RwLock::new(VecDeque::new()));
|
||||
|
||||
let recent_blockhash = Arc::new(RwLock::new(get_recent_blockhash(client.as_ref()).0));
|
||||
let shared_tx_active_thread_count = Arc::new(AtomicIsize::new(0));
|
||||
let total_tx_sent_count = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
let blockhash_thread = {
|
||||
let exit_signal = exit_signal.clone();
|
||||
let recent_blockhash = recent_blockhash.clone();
|
||||
let client = client.clone();
|
||||
let id = id.pubkey();
|
||||
Builder::new()
|
||||
.name("solana-blockhash-poller".to_string())
|
||||
.spawn(move || {
|
||||
poll_blockhash(&exit_signal, &recent_blockhash, &client, &id);
|
||||
})
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let s_threads: Vec<_> = (0..threads)
|
||||
.map(|_| {
|
||||
let exit_signal = exit_signal.clone();
|
||||
@ -154,58 +174,40 @@ where
|
||||
|
||||
// generate and send transactions for the specified duration
|
||||
let start = Instant::now();
|
||||
let keypair_chunks = source_keypair_chunks.len() as u64;
|
||||
let mut reclaim_lamports_back_to_source_account = false;
|
||||
let mut i = keypair0_balance;
|
||||
let mut blockhash = Hash::default();
|
||||
let mut blockhash_time;
|
||||
while start.elapsed() < duration {
|
||||
// ping-pong between source and destination accounts for each loop iteration
|
||||
// this seems to be faster than trying to determine the balance of individual
|
||||
// accounts
|
||||
let len = tx_count as usize;
|
||||
blockhash_time = Instant::now();
|
||||
if let Ok((new_blockhash, _fee_calculator)) = client.get_new_blockhash(&blockhash) {
|
||||
blockhash = new_blockhash;
|
||||
} else {
|
||||
if blockhash_time.elapsed().as_secs() > 30 {
|
||||
panic!("Blockhash is not updating");
|
||||
}
|
||||
sleep(Duration::from_millis(100));
|
||||
continue;
|
||||
}
|
||||
datapoint_debug!(
|
||||
"bench-tps-get_blockhash",
|
||||
("duration", duration_as_us(&blockhash_time.elapsed()), i64)
|
||||
);
|
||||
|
||||
blockhash_time = Instant::now();
|
||||
let balance = client.get_balance(&id.pubkey()).unwrap_or(0);
|
||||
metrics_submit_lamport_balance(balance);
|
||||
datapoint_debug!(
|
||||
"bench-tps-get_balance",
|
||||
("duration", duration_as_us(&blockhash_time.elapsed()), i64)
|
||||
);
|
||||
|
||||
let chunk_index = (i % keypair_chunks) as usize;
|
||||
generate_txs(
|
||||
&shared_txs,
|
||||
&blockhash,
|
||||
&keypairs[..len],
|
||||
&keypairs[len..],
|
||||
&recent_blockhash,
|
||||
&source_keypair_chunks[chunk_index],
|
||||
&dest_keypair_chunks[chunk_index],
|
||||
threads,
|
||||
reclaim_lamports_back_to_source_account,
|
||||
&libra_args,
|
||||
);
|
||||
// In sustained mode overlap the transfers with generation
|
||||
// this has higher average performance but lower peak performance
|
||||
// in tested environments.
|
||||
if !sustained {
|
||||
|
||||
// In sustained mode, overlap the transfers with generation. This has higher average
|
||||
// performance but lower peak performance in tested environments.
|
||||
if sustained {
|
||||
// Ensure that we don't generate more transactions than we can handle.
|
||||
while shared_txs.read().unwrap().len() > 2 * threads {
|
||||
sleep(Duration::from_millis(1));
|
||||
}
|
||||
} else {
|
||||
while shared_tx_active_thread_count.load(Ordering::Relaxed) > 0 {
|
||||
sleep(Duration::from_millis(1));
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate destination keypairs so that the next round of transactions will have different
|
||||
// transaction signatures even when blockhash is reused.
|
||||
dest_keypair_chunks[chunk_index].rotate_left(1);
|
||||
|
||||
i += 1;
|
||||
if should_switch_directions(num_lamports_per_account, i) {
|
||||
if should_switch_directions(num_lamports_per_account, keypair_chunks, i) {
|
||||
reclaim_lamports_back_to_source_account = !reclaim_lamports_back_to_source_account;
|
||||
}
|
||||
}
|
||||
@ -228,6 +230,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
info!("Waiting for blockhash thread...");
|
||||
if let Err(err) = blockhash_thread.join() {
|
||||
info!(" join() failed with: {:?}", err);
|
||||
}
|
||||
|
||||
let balance = client.get_balance(&id.pubkey()).unwrap_or(0);
|
||||
metrics_submit_lamport_balance(balance);
|
||||
|
||||
@ -252,8 +259,8 @@ fn metrics_submit_lamport_balance(lamport_balance: u64) {
|
||||
|
||||
#[cfg(feature = "move")]
|
||||
fn generate_move_txs(
|
||||
source: &[Keypair],
|
||||
dest: &[Keypair],
|
||||
source: &[&Keypair],
|
||||
dest: &VecDeque<&Keypair>,
|
||||
reclaim: bool,
|
||||
move_keypairs: &[Keypair],
|
||||
libra_pay_program_id: &Pubkey,
|
||||
@ -297,8 +304,8 @@ fn generate_move_txs(
|
||||
}
|
||||
|
||||
fn generate_system_txs(
|
||||
source: &[Keypair],
|
||||
dest: &[Keypair],
|
||||
source: &[&Keypair],
|
||||
dest: &VecDeque<&Keypair>,
|
||||
reclaim: bool,
|
||||
blockhash: &Hash,
|
||||
) -> Vec<(Transaction, u64)> {
|
||||
@ -321,15 +328,19 @@ fn generate_system_txs(
|
||||
|
||||
fn generate_txs(
|
||||
shared_txs: &SharedTransactions,
|
||||
blockhash: &Hash,
|
||||
source: &[Keypair],
|
||||
dest: &[Keypair],
|
||||
blockhash: &Arc<RwLock<Hash>>,
|
||||
source: &[&Keypair],
|
||||
dest: &VecDeque<&Keypair>,
|
||||
threads: usize,
|
||||
reclaim: bool,
|
||||
libra_args: &Option<LibraKeys>,
|
||||
) {
|
||||
let blockhash = *blockhash.read().unwrap();
|
||||
let tx_count = source.len();
|
||||
info!("Signing transactions... {} (reclaim={})", tx_count, reclaim);
|
||||
info!(
|
||||
"Signing transactions... {} (reclaim={}, blockhash={})",
|
||||
tx_count, reclaim, &blockhash
|
||||
);
|
||||
let signing_start = Instant::now();
|
||||
|
||||
let transactions = if let Some((
|
||||
@ -353,11 +364,11 @@ fn generate_txs(
|
||||
&_libra_keys,
|
||||
_libra_pay_program_id,
|
||||
&_libra_genesis_keypair.pubkey(),
|
||||
blockhash,
|
||||
&blockhash,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
generate_system_txs(source, dest, reclaim, blockhash)
|
||||
generate_system_txs(source, dest, reclaim, &blockhash)
|
||||
};
|
||||
|
||||
let duration = signing_start.elapsed();
|
||||
@ -386,6 +397,48 @@ fn generate_txs(
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_blockhash<T: Client>(
|
||||
exit_signal: &Arc<AtomicBool>,
|
||||
blockhash: &Arc<RwLock<Hash>>,
|
||||
client: &Arc<T>,
|
||||
id: &Pubkey,
|
||||
) {
|
||||
let mut blockhash_last_updated = Instant::now();
|
||||
let mut last_error_log = Instant::now();
|
||||
loop {
|
||||
let blockhash_updated = {
|
||||
let old_blockhash = *blockhash.read().unwrap();
|
||||
if let Ok((new_blockhash, _fee)) = client.get_new_blockhash(&old_blockhash) {
|
||||
*blockhash.write().unwrap() = new_blockhash;
|
||||
blockhash_last_updated = Instant::now();
|
||||
true
|
||||
} else {
|
||||
if blockhash_last_updated.elapsed().as_secs() > 120 {
|
||||
eprintln!("Blockhash is stuck");
|
||||
exit(1)
|
||||
} else if blockhash_last_updated.elapsed().as_secs() > 30
|
||||
&& last_error_log.elapsed().as_secs() >= 1
|
||||
{
|
||||
last_error_log = Instant::now();
|
||||
error!("Blockhash is not updating");
|
||||
}
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
if blockhash_updated {
|
||||
let balance = client.get_balance(id).unwrap_or(0);
|
||||
metrics_submit_lamport_balance(balance);
|
||||
}
|
||||
|
||||
if exit_signal.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(50));
|
||||
}
|
||||
}
|
||||
|
||||
fn do_tx_transfers<T: Client>(
|
||||
exit_signal: &Arc<AtomicBool>,
|
||||
shared_txs: &SharedTransactions,
|
||||
@ -398,11 +451,10 @@ fn do_tx_transfers<T: Client>(
|
||||
if thread_batch_sleep_ms > 0 {
|
||||
sleep(Duration::from_millis(thread_batch_sleep_ms as u64));
|
||||
}
|
||||
let txs;
|
||||
{
|
||||
let txs = {
|
||||
let mut shared_txs_wl = shared_txs.write().expect("write lock in do_tx_transfers");
|
||||
txs = shared_txs_wl.pop_front();
|
||||
}
|
||||
shared_txs_wl.pop_front()
|
||||
};
|
||||
if let Some(txs0) = txs {
|
||||
shared_tx_thread_count.fetch_add(1, Ordering::Relaxed);
|
||||
info!(
|
||||
@ -758,11 +810,15 @@ fn compute_and_report_stats(
|
||||
);
|
||||
}
|
||||
|
||||
// First transfer 3/4 of the lamports to the dest accounts
|
||||
// then ping-pong 1/4 of the lamports back to the other account
|
||||
// this leaves 1/4 lamport buffer in each account
|
||||
fn should_switch_directions(num_lamports_per_account: u64, i: u64) -> bool {
|
||||
i % (num_lamports_per_account / 4) == 0 && (i >= (3 * num_lamports_per_account) / 4)
|
||||
// First transfer 2/3 of the lamports to the dest accounts
|
||||
// then ping-pong 1/3 of the lamports back to the other account
|
||||
// this leaves 1/3 lamport buffer in each account
|
||||
fn should_switch_directions(num_lamports_per_account: u64, keypair_chunks: u64, i: u64) -> bool {
|
||||
if i < keypair_chunks * (2 * num_lamports_per_account) / 3 {
|
||||
return false;
|
||||
}
|
||||
|
||||
i % (keypair_chunks * num_lamports_per_account / 3) == 0
|
||||
}
|
||||
|
||||
pub fn generate_keypairs(seed_keypair: &Keypair, count: u64) -> (Vec<Keypair>, u64) {
|
||||
@ -897,9 +953,12 @@ fn fund_move_keys<T: Client>(
|
||||
info!("funded libra funding key {}", i);
|
||||
}
|
||||
|
||||
let tx_count = keypairs.len();
|
||||
let amount = total / (tx_count as u64);
|
||||
for (i, keys) in keypairs[..tx_count].chunks(NUM_FUNDING_KEYS).enumerate() {
|
||||
let keypair_count = keypairs.len();
|
||||
let amount = total / (keypair_count as u64);
|
||||
for (i, keys) in keypairs[..keypair_count]
|
||||
.chunks(NUM_FUNDING_KEYS)
|
||||
.enumerate()
|
||||
{
|
||||
for (j, key) in keys.iter().enumerate() {
|
||||
let tx = librapay_transaction::transfer(
|
||||
libra_pay_program_id,
|
||||
@ -949,18 +1008,18 @@ pub fn generate_and_fund_keypairs<T: Client>(
|
||||
client: &T,
|
||||
drone_addr: Option<SocketAddr>,
|
||||
funding_key: &Keypair,
|
||||
tx_count: usize,
|
||||
keypair_count: usize,
|
||||
lamports_per_account: u64,
|
||||
use_move: bool,
|
||||
) -> Result<(Vec<Keypair>, Option<LibraKeys>, u64)> {
|
||||
info!("Creating {} keypairs...", tx_count * 2);
|
||||
let (mut keypairs, extra) = generate_keypairs(funding_key, tx_count as u64 * 2);
|
||||
info!("Creating {} keypairs...", keypair_count);
|
||||
let (mut keypairs, extra) = generate_keypairs(funding_key, keypair_count as u64);
|
||||
info!("Get lamports...");
|
||||
|
||||
// Sample the first keypair, see if it has lamports, if so then resume.
|
||||
// This logic is to prevent lamport loss on repeated solana-bench-tps executions
|
||||
let last_keypair_balance = client
|
||||
.get_balance(&keypairs[tx_count * 2 - 1].pubkey())
|
||||
.get_balance(&keypairs[keypair_count - 1].pubkey())
|
||||
.unwrap_or(0);
|
||||
|
||||
#[cfg(feature = "move")]
|
||||
@ -999,7 +1058,7 @@ pub fn generate_and_fund_keypairs<T: Client>(
|
||||
// Still fund the solana ones which will be used for fees.
|
||||
let seed = [0u8; 32];
|
||||
let mut rnd = GenKeys::new(seed);
|
||||
let move_keypairs = rnd.gen_n_keypairs(tx_count as u64 * 2);
|
||||
let move_keypairs = rnd.gen_n_keypairs(keypair_count as u64);
|
||||
fund_move_keys(
|
||||
client,
|
||||
funding_key,
|
||||
@ -1032,7 +1091,7 @@ pub fn generate_and_fund_keypairs<T: Client>(
|
||||
}
|
||||
|
||||
// 'generate_keypairs' generates extra keys to be able to have size-aligned funding batches for fund_keys.
|
||||
keypairs.truncate(2 * tx_count);
|
||||
keypairs.truncate(keypair_count);
|
||||
|
||||
Ok((keypairs, move_keypairs_ret, last_keypair_balance))
|
||||
}
|
||||
@ -1048,17 +1107,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_switch_directions() {
|
||||
assert_eq!(should_switch_directions(20, 0), false);
|
||||
assert_eq!(should_switch_directions(20, 1), false);
|
||||
assert_eq!(should_switch_directions(20, 14), false);
|
||||
assert_eq!(should_switch_directions(20, 15), true);
|
||||
assert_eq!(should_switch_directions(20, 16), false);
|
||||
assert_eq!(should_switch_directions(20, 19), false);
|
||||
assert_eq!(should_switch_directions(20, 20), true);
|
||||
assert_eq!(should_switch_directions(20, 21), false);
|
||||
assert_eq!(should_switch_directions(20, 99), false);
|
||||
assert_eq!(should_switch_directions(20, 100), true);
|
||||
assert_eq!(should_switch_directions(20, 101), false);
|
||||
assert_eq!(should_switch_directions(30, 1, 0), false);
|
||||
assert_eq!(should_switch_directions(30, 1, 1), false);
|
||||
assert_eq!(should_switch_directions(30, 1, 20), true);
|
||||
assert_eq!(should_switch_directions(30, 1, 21), false);
|
||||
assert_eq!(should_switch_directions(30, 1, 30), true);
|
||||
assert_eq!(should_switch_directions(30, 1, 90), true);
|
||||
assert_eq!(should_switch_directions(30, 1, 91), false);
|
||||
|
||||
assert_eq!(should_switch_directions(30, 2, 0), false);
|
||||
assert_eq!(should_switch_directions(30, 2, 1), false);
|
||||
assert_eq!(should_switch_directions(30, 2, 20), false);
|
||||
assert_eq!(should_switch_directions(30, 2, 40), true);
|
||||
assert_eq!(should_switch_directions(30, 2, 90), false);
|
||||
assert_eq!(should_switch_directions(30, 2, 100), true);
|
||||
assert_eq!(should_switch_directions(30, 2, 101), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1072,8 +1135,9 @@ mod tests {
|
||||
config.tx_count = 10;
|
||||
config.duration = Duration::from_secs(5);
|
||||
|
||||
let keypair_count = config.tx_count * config.keypair_multiplier;
|
||||
let (keypairs, _move_keypairs, _keypair_balance) =
|
||||
generate_and_fund_keypairs(&clients[0], None, &config.id, config.tx_count, 20, false)
|
||||
generate_and_fund_keypairs(&clients[0], None, &config.id, keypair_count, 20, false)
|
||||
.unwrap();
|
||||
|
||||
do_bench_tps(clients, config, keypairs, 0, None);
|
||||
@ -1084,11 +1148,11 @@ mod tests {
|
||||
let (genesis_config, id) = create_genesis_config(10_000);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let client = BankClient::new(bank);
|
||||
let tx_count = 10;
|
||||
let keypair_count = 20;
|
||||
let lamports = 20;
|
||||
|
||||
let (keypairs, _move_keypairs, _keypair_balance) =
|
||||
generate_and_fund_keypairs(&client, None, &id, tx_count, lamports, false).unwrap();
|
||||
generate_and_fund_keypairs(&client, None, &id, keypair_count, lamports, false).unwrap();
|
||||
|
||||
for kp in &keypairs {
|
||||
assert_eq!(
|
||||
@ -1107,11 +1171,11 @@ mod tests {
|
||||
genesis_config.fee_calculator = fee_calculator;
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let client = BankClient::new(bank);
|
||||
let tx_count = 10;
|
||||
let keypair_count = 20;
|
||||
let lamports = 20;
|
||||
|
||||
let (keypairs, _move_keypairs, _keypair_balance) =
|
||||
generate_and_fund_keypairs(&client, None, &id, tx_count, lamports, false).unwrap();
|
||||
generate_and_fund_keypairs(&client, None, &id, keypair_count, lamports, false).unwrap();
|
||||
|
||||
let max_fee = client
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
|
||||
|
@ -15,6 +15,7 @@ pub struct Config {
|
||||
pub num_nodes: usize,
|
||||
pub duration: Duration,
|
||||
pub tx_count: usize,
|
||||
pub keypair_multiplier: usize,
|
||||
pub thread_batch_sleep_ms: usize,
|
||||
pub sustained: bool,
|
||||
pub client_ids_and_stake_file: String,
|
||||
@ -36,6 +37,7 @@ impl Default for Config {
|
||||
num_nodes: 1,
|
||||
duration: Duration::new(std::u64::MAX, 0),
|
||||
tx_count: 50_000,
|
||||
keypair_multiplier: 8,
|
||||
thread_batch_sleep_ms: 1000,
|
||||
sustained: false,
|
||||
client_ids_and_stake_file: String::new(),
|
||||
@ -122,6 +124,13 @@ pub fn build_args<'a, 'b>(version: &'b str) -> App<'a, 'b> {
|
||||
.takes_value(true)
|
||||
.help("Number of transactions to send per batch")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("keypair_multiplier")
|
||||
.long("keypair-multiplier")
|
||||
.value_name("NUM")
|
||||
.takes_value(true)
|
||||
.help("Multiply by transaction count to determine number of keypairs to create")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("thread-batch-sleep-ms")
|
||||
.short("z")
|
||||
@ -208,7 +217,15 @@ pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
|
||||
}
|
||||
|
||||
if let Some(s) = matches.value_of("tx_count") {
|
||||
args.tx_count = s.to_string().parse().expect("can't parse tx_account");
|
||||
args.tx_count = s.to_string().parse().expect("can't parse tx_count");
|
||||
}
|
||||
|
||||
if let Some(s) = matches.value_of("keypair_multiplier") {
|
||||
args.keypair_multiplier = s
|
||||
.to_string()
|
||||
.parse()
|
||||
.expect("can't parse keypair-multiplier");
|
||||
assert!(args.keypair_multiplier >= 2);
|
||||
}
|
||||
|
||||
if let Some(t) = matches.value_of("thread-batch-sleep-ms") {
|
||||
|
@ -24,6 +24,7 @@ fn main() {
|
||||
id,
|
||||
num_nodes,
|
||||
tx_count,
|
||||
keypair_multiplier,
|
||||
client_ids_and_stake_file,
|
||||
write_to_client_file,
|
||||
read_from_client_file,
|
||||
@ -34,9 +35,10 @@ fn main() {
|
||||
..
|
||||
} = &cli_config;
|
||||
|
||||
let keypair_count = *tx_count * keypair_multiplier;
|
||||
if *write_to_client_file {
|
||||
info!("Generating {} keypairs", *tx_count * 2);
|
||||
let (keypairs, _) = generate_keypairs(&id, *tx_count as u64 * 2);
|
||||
info!("Generating {} keypairs", keypair_count);
|
||||
let (keypairs, _) = generate_keypairs(&id, keypair_count as u64);
|
||||
let num_accounts = keypairs.len() as u64;
|
||||
let max_fee =
|
||||
FeeCalculator::new(*target_lamports_per_signature, 0).max_lamports_per_signature;
|
||||
@ -102,10 +104,10 @@ fn main() {
|
||||
last_balance = primordial_account.balance;
|
||||
});
|
||||
|
||||
if keypairs.len() < tx_count * 2 {
|
||||
if keypairs.len() < keypair_count {
|
||||
eprintln!(
|
||||
"Expected {} accounts in {}, only received {} (--tx_count mismatch?)",
|
||||
tx_count * 2,
|
||||
keypair_count,
|
||||
client_ids_and_stake_file,
|
||||
keypairs.len(),
|
||||
);
|
||||
@ -121,7 +123,7 @@ fn main() {
|
||||
&client,
|
||||
Some(*drone_addr),
|
||||
&id,
|
||||
*tx_count,
|
||||
keypair_count,
|
||||
*num_lamports_per_account,
|
||||
*use_move,
|
||||
)
|
||||
|
@ -47,11 +47,12 @@ fn test_bench_tps_local_cluster(config: Config) {
|
||||
|
||||
let lamports_per_account = 100;
|
||||
|
||||
let keypair_count = config.tx_count * config.keypair_multiplier;
|
||||
let (keypairs, move_keypairs, _keypair_balance) = generate_and_fund_keypairs(
|
||||
&client,
|
||||
Some(drone_addr),
|
||||
&config.id,
|
||||
config.tx_count,
|
||||
keypair_count,
|
||||
lamports_per_account,
|
||||
config.use_move,
|
||||
)
|
||||
|
@ -177,7 +177,7 @@ $ solana send-timestamp <PUBKEY> <PROCESS_ID> --date 2018-12-24T23:59:00
|
||||
## Usage
|
||||
### solana-cli
|
||||
```text
|
||||
solana-cli 0.21.3
|
||||
solana-cli 0.21.5
|
||||
Blockchain, Rebuilt for Scale
|
||||
|
||||
USAGE:
|
||||
|
@ -21,6 +21,7 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
|
||||
* [getBlockTime](jsonrpc-api.md#getblocktime)
|
||||
* [getClusterNodes](jsonrpc-api.md#getclusternodes)
|
||||
* [getConfirmedBlock](jsonrpc-api.md#getconfirmedblock)
|
||||
* [getConfirmedBlocks](jsonrpc-api.md#getconfirmedblocks)
|
||||
* [getEpochInfo](jsonrpc-api.md#getepochinfo)
|
||||
* [getEpochSchedule](jsonrpc-api.md#getepochschedule)
|
||||
* [getGenesisHash](jsonrpc-api.md#getgenesishash)
|
||||
@ -156,7 +157,7 @@ The result value will be an RpcResponse JSON object containing an AccountInfo JS
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getAccountInfo", "params":["2gVkYWexTHR5Hb2aLeQN3tnngvWzisFKXDUPrgMHpdST"]}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":{"executable":false,"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0.21.3,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]}},"id":1}
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":{"executable":false,"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0.21.5,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]}},"id":1}
|
||||
```
|
||||
|
||||
### getBalance
|
||||
@ -295,6 +296,31 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"m
|
||||
{"jsonrpc":"2.0","result":{"blockhash":[165,245,120,183,32,205,89,222,249,114,229,49,250,231,149,122,156,232,181,83,238,194,157,153,7,213,180,54,177,6,25,101],"parentSlot":429,"previousBlockhash":[21,108,181,90,139,241,212,203,45,78,232,29,161,31,159,188,110,82,81,11,250,74,47,140,188,28,23,96,251,164,208,166],"transactions":[[{"message":{"accountKeys":[[5],[219,181,202,40,52,148,34,136,186,59,137,160,250,225,234,17,244,160,88,116,24,176,30,227,68,11,199,38,141,68,131,228],[233,48,179,56,91,40,254,206,53,48,196,176,119,248,158,109,121,77,11,69,108,160,128,27,228,122,146,249,53,184,68,87],[6,167,213,23,25,47,10,175,198,242,101,227,251,119,204,122,218,130,197,41,208,190,59,19,110,45,0,85,32,0,0,0],[6,167,213,23,24,199,116,201,40,86,99,152,105,29,94,182,139,94,184,163,155,75,109,92,115,85,91,33,0,0,0,0],[7,97,72,29,53,116,116,187,124,77,118,36,235,211,189,179,216,53,94,115,209,16,67,252,13,163,83,128,0,0,0,0]],"header":{"numReadonlySignedAccounts":0,"numReadonlyUnsignedAccounts":3,"numRequiredSignatures":2},"instructions":[[1],{"accounts":[[3],1,2,3],"data":[[52],2,0,0,0,1,0,0,0,0,0,0,0,173,1,0,0,0,0,0,0,86,55,9,248,142,238,135,114,103,83,247,124,67,68,163,233,55,41,59,129,64,50,110,221,234,234,27,213,205,193,219,50],"program_id_index":4}],"recentBlockhash":[21,108,181,90,139,241,212,203,45,78,232,29,161,31,159,188,110,82,81,11,250,74,47,140,188,28,23,96,251,164,208,166]},"signatures":[[2],[119,9,95,108,35,95,7,1,69,101,65,45,5,204,61,114,172,88,123,238,32,201,135,229,57,50,13,21,106,216,129,183,238,43,37,101,148,81,56,232,88,136,80,65,46,189,39,106,94,13,238,54,186,48,118,186,0,62,121,122,172,171,66,5],[78,40,77,250,10,93,6,157,48,173,100,40,251,9,7,218,7,184,43,169,76,240,254,34,235,48,41,175,119,126,75,107,106,248,45,161,119,48,174,213,57,69,111,225,245,60,148,73,124,82,53,6,203,126,120,180,111,169,89,64,29,23,237,13]]},{"fee":100000,"status":{"Ok":null}}]]},"id":1}
|
||||
```
|
||||
|
||||
### getConfirmedBlocks
|
||||
|
||||
Returns a list of confirmed blocks
|
||||
|
||||
#### Parameters:
|
||||
|
||||
* `integer` - start_slot, as u64 integer
|
||||
* `integer` - (optional) end_slot, as u64 integer
|
||||
|
||||
#### Results:
|
||||
|
||||
The result field will be an array of u64 integers listing confirmed blocks
|
||||
between start_slot and either end_slot, if provided, or latest confirmed block,
|
||||
inclusive.
|
||||
|
||||
#### Example:
|
||||
|
||||
```bash
|
||||
// Request
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedBlocks","params":[5, 10]}' localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":[5,6,7,8,9,10],"id":1}
|
||||
```
|
||||
|
||||
### getEpochInfo
|
||||
|
||||
Returns information about the current epoch
|
||||
@ -373,15 +399,18 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m
|
||||
|
||||
### getLeaderSchedule
|
||||
|
||||
Returns the leader schedule for the current epoch
|
||||
Returns the leader schedule for an epoch
|
||||
|
||||
#### Parameters:
|
||||
|
||||
* `slot` - (optional) Fetch the leader schedule for the epoch that corresponds to the provided slot. If unspecified, the leader schedule for the current epoch is fetched
|
||||
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
The result field will be an array of leader public keys \(as base-58 encoded strings\) for each slot in the current epoch
|
||||
The result field will be a dictionary of leader public keys \(as base-58 encoded
|
||||
strings\) and their corresponding leader slot indices as values (indices are to
|
||||
the first slot in the requested epoch)
|
||||
|
||||
#### Example:
|
||||
|
||||
@ -390,7 +419,7 @@ The result field will be an array of leader public keys \(as base-58 encoded str
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getLeaderSchedule"}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":[...],"id":1}
|
||||
{"jsonrpc":"2.0","result":{"4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63]},"id":1}
|
||||
```
|
||||
|
||||
### getMinimumBalanceForRentExemption
|
||||
@ -824,7 +853,7 @@ Subscribe to an account to receive notifications when the lamports or data for a
|
||||
#### Notification Format:
|
||||
|
||||
```bash
|
||||
{"jsonrpc": "2.0","method": "accountNotification", "params": {"result": {"executable":false,"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0.21.3,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]},"subscription":0}}
|
||||
{"jsonrpc": "2.0","method": "accountNotification", "params": {"result": {"executable":false,"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0.21.5,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]},"subscription":0}}
|
||||
```
|
||||
|
||||
### accountUnsubscribe
|
||||
@ -882,7 +911,7 @@ Subscribe to a program to receive notifications when the lamports or data for a
|
||||
* `object` - account info JSON object \(see [getAccountInfo](jsonrpc-api.md#getaccountinfo) for field details\)
|
||||
|
||||
```bash
|
||||
{"jsonrpc":"2.0","method":"programNotification","params":{{"result":["8Rshv2oMkPu5E4opXTRyuyBeZBqQ4S477VG26wUTFxUM",{"executable":false,"lamports":1,"owner":[129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"data":[1,1,1,0,0,0,0,0,0,0.21.3,0,0,0,0,0,0,50,48,49,56,45,49,50,45,50,52,84,50,51,58,53,57,58,48,48,90,235,233,39,152,15,44,117,176,41,89,100,86,45,61,2,44,251,46,212,37,35,118,163,189,247,84,27,235,178,62,55,89,0,0,0,0,50,0,0,0,0,0,0,0,235,233,39,152,15,44,117,176,41,89,100,86,45,61,2,44,251,46,212,37,35,118,163,189,247,84,27,235,178,62,45,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}],"subscription":0}}
|
||||
{"jsonrpc":"2.0","method":"programNotification","params":{{"result":["8Rshv2oMkPu5E4opXTRyuyBeZBqQ4S477VG26wUTFxUM",{"executable":false,"lamports":1,"owner":[129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"data":[1,1,1,0,0,0,0,0,0,0.21.5,0,0,0,0,0,0,50,48,49,56,45,49,50,45,50,52,84,50,51,58,53,57,58,48,48,90,235,233,39,152,15,44,117,176,41,89,100,86,45,61,2,44,251,46,212,37,35,118,163,189,247,84,27,235,178,62,55,89,0,0,0,0,50,0,0,0,0,0,0,0,235,233,39,152,15,44,117,176,41,89,100,86,45,61,2,44,251,46,212,37,35,118,163,189,247,84,27,235,178,62,45,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}],"subscription":0}}
|
||||
```
|
||||
|
||||
### programUnsubscribe
|
||||
|
@ -81,8 +81,8 @@ With a FEC rate: `16:4`
|
||||
|
||||
With FEC rate of `16:16`
|
||||
* `G = 12800`
|
||||
* `S = SUM of i=0 -> 32 for binomial(prob_failure = 0.2775, trials = 64, failures = i) = 0.0.21.3`
|
||||
* `B = (1 - 0.0.21.3) ^ (12800 / 32) = 0.42583`
|
||||
* `S = SUM of i=0 -> 32 for binomial(prob_failure = 0.2775, trials = 64, failures = i) = 0.0.21.5`
|
||||
* `B = (1 - 0.0.21.5) ^ (12800 / 32) = 0.42583`
|
||||
|
||||
With FEC rate of `32:32`
|
||||
* `G = 12800`
|
||||
|
@ -2,7 +2,7 @@
|
||||
Follow this guide to setup Solana's key generation tool called `solana-keygen`
|
||||
|
||||
{% hint style="warn" %}
|
||||
After installation, ensure your version is `0.21.3` or higher by running `solana-keygen -V`
|
||||
After installation, ensure your version is `0.21.5` or higher by running `solana-keygen -V`
|
||||
{% endhint %}
|
||||
|
||||
## Download
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-chacha-sys"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana chacha-sys"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@ -33,7 +33,7 @@ else
|
||||
fi
|
||||
|
||||
if [[ -z $CHANNEL_OR_TAG ]]; then
|
||||
echo +++ Unable to determine channel to publish into, exiting.
|
||||
echo +++ Unable to determine channel or tag to publish into, exiting.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-clap-utils"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana utilities for the clap"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,7 +12,7 @@ edition = "2018"
|
||||
clap = "2.33.0"
|
||||
rpassword = "4.0"
|
||||
semver = "0.9.0"
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
tiny-bip39 = "0.6.2"
|
||||
url = "2.1.0"
|
||||
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -28,24 +28,24 @@ serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-client = { path = "../client", version = "0.21.3" }
|
||||
solana-config-program = { path = "../programs/config", version = "0.21.3" }
|
||||
solana-drone = { path = "../drone", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.3" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.3" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "0.21.3" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.5" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-client = { path = "../client", version = "0.21.5" }
|
||||
solana-config-program = { path = "../programs/config", version = "0.21.5" }
|
||||
solana-drone = { path = "../drone", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.5" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.5" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "0.21.5" }
|
||||
url = "2.1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-core = { path = "../core", version = "0.21.3" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.3" }
|
||||
solana-core = { path = "../core", version = "0.21.5" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.5" }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[[bin]]
|
||||
|
@ -20,7 +20,7 @@ use solana_drone::drone::request_airdrop_transaction;
|
||||
use solana_drone::drone_mock::request_airdrop_transaction;
|
||||
use solana_sdk::{
|
||||
bpf_loader,
|
||||
clock::Slot,
|
||||
clock::{Epoch, Slot},
|
||||
commitment_config::CommitmentConfig,
|
||||
fee_calculator::FeeCalculator,
|
||||
hash::Hash,
|
||||
@ -100,6 +100,10 @@ pub enum CliCommand {
|
||||
timeout: Duration,
|
||||
commitment_config: CommitmentConfig,
|
||||
},
|
||||
ShowBlockProduction {
|
||||
epoch: Option<Epoch>,
|
||||
slot_limit: Option<u64>,
|
||||
},
|
||||
ShowGossip,
|
||||
ShowValidators {
|
||||
use_lamports_unit: bool,
|
||||
@ -173,7 +177,16 @@ pub enum CliCommand {
|
||||
aggregate: bool,
|
||||
span: Option<u64>,
|
||||
},
|
||||
VoteAuthorize(Pubkey, Pubkey, VoteAuthorize),
|
||||
VoteAuthorize {
|
||||
vote_account_pubkey: Pubkey,
|
||||
new_authorized_pubkey: Pubkey,
|
||||
vote_authorize: VoteAuthorize,
|
||||
},
|
||||
VoteUpdateValidator {
|
||||
vote_account_pubkey: Pubkey,
|
||||
new_identity_pubkey: Pubkey,
|
||||
authorized_voter: KeypairEq,
|
||||
},
|
||||
// Wallet Commands
|
||||
Address,
|
||||
Airdrop {
|
||||
@ -299,6 +312,7 @@ pub fn parse_command(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Box<dyn
|
||||
("get-slot", Some(matches)) => parse_get_slot(matches),
|
||||
("get-transaction-count", Some(matches)) => parse_get_transaction_count(matches),
|
||||
("ping", Some(matches)) => parse_cluster_ping(matches),
|
||||
("show-block-production", Some(matches)) => parse_show_block_production(matches),
|
||||
("show-gossip", Some(_matches)) => Ok(CliCommandInfo {
|
||||
command: CliCommand::ShowGossip,
|
||||
require_keypair: false,
|
||||
@ -346,6 +360,7 @@ pub fn parse_command(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Box<dyn
|
||||
},
|
||||
// Vote Commands
|
||||
("create-vote-account", Some(matches)) => parse_vote_create_account(matches),
|
||||
("vote-update-validator", Some(matches)) => parse_vote_update_validator(matches),
|
||||
("vote-authorize-voter", Some(matches)) => {
|
||||
parse_vote_authorize(matches, VoteAuthorize::Voter)
|
||||
}
|
||||
@ -1030,6 +1045,9 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
||||
timeout,
|
||||
commitment_config,
|
||||
),
|
||||
CliCommand::ShowBlockProduction { epoch, slot_limit } => {
|
||||
process_show_block_production(&rpc_client, *epoch, *slot_limit)
|
||||
}
|
||||
CliCommand::ShowGossip => process_show_gossip(&rpc_client),
|
||||
CliCommand::ShowValidators { use_lamports_unit } => {
|
||||
process_show_validators(&rpc_client, *use_lamports_unit)
|
||||
@ -1206,15 +1224,28 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
||||
&vote_account_pubkey,
|
||||
*use_lamports_unit,
|
||||
),
|
||||
CliCommand::VoteAuthorize(vote_account_pubkey, new_authorized_pubkey, vote_authorize) => {
|
||||
process_vote_authorize(
|
||||
&rpc_client,
|
||||
config,
|
||||
&vote_account_pubkey,
|
||||
&new_authorized_pubkey,
|
||||
*vote_authorize,
|
||||
)
|
||||
}
|
||||
CliCommand::VoteAuthorize {
|
||||
vote_account_pubkey,
|
||||
new_authorized_pubkey,
|
||||
vote_authorize,
|
||||
} => process_vote_authorize(
|
||||
&rpc_client,
|
||||
config,
|
||||
&vote_account_pubkey,
|
||||
&new_authorized_pubkey,
|
||||
*vote_authorize,
|
||||
),
|
||||
CliCommand::VoteUpdateValidator {
|
||||
vote_account_pubkey,
|
||||
new_identity_pubkey,
|
||||
authorized_voter,
|
||||
} => process_vote_update_validator(
|
||||
&rpc_client,
|
||||
config,
|
||||
&vote_account_pubkey,
|
||||
&new_identity_pubkey,
|
||||
authorized_voter,
|
||||
),
|
||||
CliCommand::Uptime {
|
||||
pubkey: vote_account_pubkey,
|
||||
aggregate,
|
||||
@ -2184,8 +2215,20 @@ mod tests {
|
||||
assert_eq!(signature.unwrap(), SIGNATURE.to_string());
|
||||
|
||||
let new_authorized_pubkey = Pubkey::new_rand();
|
||||
config.command =
|
||||
CliCommand::VoteAuthorize(bob_pubkey, new_authorized_pubkey, VoteAuthorize::Voter);
|
||||
config.command = CliCommand::VoteAuthorize {
|
||||
vote_account_pubkey: bob_pubkey,
|
||||
new_authorized_pubkey,
|
||||
vote_authorize: VoteAuthorize::Voter,
|
||||
};
|
||||
let signature = process_command(&config);
|
||||
assert_eq!(signature.unwrap(), SIGNATURE.to_string());
|
||||
|
||||
let new_identity_pubkey = Pubkey::new_rand();
|
||||
config.command = CliCommand::VoteUpdateValidator {
|
||||
vote_account_pubkey: bob_pubkey,
|
||||
new_identity_pubkey,
|
||||
authorized_voter: Keypair::new().into(),
|
||||
};
|
||||
let signature = process_command(&config);
|
||||
assert_eq!(signature.unwrap(), SIGNATURE.to_string());
|
||||
|
||||
@ -2368,7 +2411,18 @@ mod tests {
|
||||
};
|
||||
assert!(process_command(&config).is_err());
|
||||
|
||||
config.command = CliCommand::VoteAuthorize(bob_pubkey, bob_pubkey, VoteAuthorize::Voter);
|
||||
config.command = CliCommand::VoteAuthorize {
|
||||
vote_account_pubkey: bob_pubkey,
|
||||
new_authorized_pubkey: bob_pubkey,
|
||||
vote_authorize: VoteAuthorize::Voter,
|
||||
};
|
||||
assert!(process_command(&config).is_err());
|
||||
|
||||
config.command = CliCommand::VoteUpdateValidator {
|
||||
vote_account_pubkey: bob_pubkey,
|
||||
new_identity_pubkey: bob_pubkey,
|
||||
authorized_voter: Keypair::new().into(),
|
||||
};
|
||||
assert!(process_command(&config).is_err());
|
||||
|
||||
config.command = CliCommand::GetSlot {
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
},
|
||||
display::println_name_value,
|
||||
};
|
||||
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
|
||||
use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand};
|
||||
use console::{style, Emoji};
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use solana_clap_utils::{input_parsers::*, input_validators::*};
|
||||
@ -13,13 +13,14 @@ use solana_client::{rpc_client::RpcClient, rpc_request::RpcVoteAccountInfo};
|
||||
use solana_sdk::{
|
||||
clock::{self, Slot},
|
||||
commitment_config::CommitmentConfig,
|
||||
epoch_schedule::{Epoch, EpochSchedule},
|
||||
hash::Hash,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, KeypairUtil},
|
||||
system_transaction,
|
||||
};
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
collections::{HashMap, VecDeque},
|
||||
net::SocketAddr,
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
@ -147,6 +148,22 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
||||
),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("show-block-production")
|
||||
.about("Show information about block production")
|
||||
.arg(
|
||||
Arg::with_name("epoch")
|
||||
.long("epoch")
|
||||
.takes_value(true)
|
||||
.help("Epoch to show block production for [default: current epoch]"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("slot_limit")
|
||||
.long("slot-limit")
|
||||
.takes_value(true)
|
||||
.help("Limit results to this many slots from the end of the epoch [default: full epoch]"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("show-gossip")
|
||||
.about("Show the current gossip network nodes"),
|
||||
@ -260,6 +277,20 @@ fn new_spinner_progress_bar() -> ProgressBar {
|
||||
progress_bar
|
||||
}
|
||||
|
||||
/// Aggregate epoch credit stats and return (total credits, total slots, total epochs)
|
||||
pub fn aggregate_epoch_credits(
|
||||
epoch_credits: &[(Epoch, u64, u64)],
|
||||
epoch_schedule: &EpochSchedule,
|
||||
) -> (u64, u64, u64) {
|
||||
epoch_credits
|
||||
.iter()
|
||||
.fold((0, 0, 0), |acc, (epoch, credits, prev_credits)| {
|
||||
let credits_earned = credits - prev_credits;
|
||||
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(*epoch);
|
||||
(acc.0 + credits_earned, acc.1 + slots_in_epoch, acc.2 + 1)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process_catchup(rpc_client: &RpcClient, node_pubkey: &Pubkey) -> ProcessResult {
|
||||
let cluster_nodes = rpc_client.get_cluster_nodes()?;
|
||||
|
||||
@ -378,6 +409,149 @@ pub fn process_get_slot(
|
||||
Ok(slot.to_string())
|
||||
}
|
||||
|
||||
pub fn parse_show_block_production(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let epoch = value_t!(matches, "epoch", Epoch).ok();
|
||||
let slot_limit = value_t!(matches, "slot_limit", u64).ok();
|
||||
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::ShowBlockProduction { epoch, slot_limit },
|
||||
require_keypair: false,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process_show_block_production(
|
||||
rpc_client: &RpcClient,
|
||||
epoch: Option<Epoch>,
|
||||
slot_limit: Option<u64>,
|
||||
) -> ProcessResult {
|
||||
let epoch_schedule = rpc_client.get_epoch_schedule()?;
|
||||
let epoch_info = rpc_client.get_epoch_info_with_commitment(CommitmentConfig::max())?;
|
||||
|
||||
let epoch = epoch.unwrap_or(epoch_info.epoch);
|
||||
|
||||
if epoch > epoch_info.epoch {
|
||||
return Err(format!("Epoch {} is in the future", epoch).into());
|
||||
}
|
||||
|
||||
let end_slot = std::cmp::min(
|
||||
epoch_info.absolute_slot,
|
||||
epoch_schedule.get_last_slot_in_epoch(epoch),
|
||||
);
|
||||
let start_slot = {
|
||||
let start_slot = epoch_schedule.get_first_slot_in_epoch(epoch);
|
||||
std::cmp::max(
|
||||
end_slot.saturating_sub(slot_limit.unwrap_or(start_slot)),
|
||||
start_slot,
|
||||
)
|
||||
};
|
||||
|
||||
let progress_bar = new_spinner_progress_bar();
|
||||
progress_bar.set_message("Connecting...");
|
||||
progress_bar.set_message(&format!("Fetching leader schedule for epoch {}...", epoch));
|
||||
|
||||
progress_bar.set_message(&format!(
|
||||
"Fetching confirmed blocks between slots {} and {}...",
|
||||
start_slot, end_slot
|
||||
));
|
||||
let confirmed_blocks = rpc_client.get_confirmed_blocks(start_slot, Some(end_slot))?;
|
||||
|
||||
let total_slots = (end_slot - start_slot + 1) as usize;
|
||||
let total_blocks = confirmed_blocks.len();
|
||||
assert!(total_blocks <= total_slots);
|
||||
let total_slots_missed = total_slots - total_blocks;
|
||||
let mut leader_slot_count = HashMap::new();
|
||||
let mut leader_missed_slots = HashMap::new();
|
||||
|
||||
let leader_schedule = rpc_client
|
||||
.get_leader_schedule_with_commitment(Some(start_slot), CommitmentConfig::max())?;
|
||||
if leader_schedule.is_none() {
|
||||
return Err(format!("Unable to fetch leader schedule for slot {}", start_slot).into());
|
||||
}
|
||||
let leader_schedule = leader_schedule.unwrap();
|
||||
|
||||
let mut leader_per_slot_index = Vec::new();
|
||||
leader_per_slot_index.resize(total_slots, "");
|
||||
for (pubkey, leader_slots) in leader_schedule.iter() {
|
||||
for slot_index in leader_slots.iter() {
|
||||
if *slot_index < total_slots {
|
||||
leader_per_slot_index[*slot_index] = pubkey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progress_bar.set_message(&format!(
|
||||
"Processing {} slots containing {} blocks and {} empty slots...",
|
||||
total_slots, total_blocks, total_slots_missed
|
||||
));
|
||||
|
||||
let mut confirmed_blocks_index = 0;
|
||||
for (slot_index, leader) in leader_per_slot_index.iter().enumerate().take(total_slots) {
|
||||
let slot = start_slot + slot_index as u64;
|
||||
let slot_count = leader_slot_count.entry(leader).or_insert(0);
|
||||
*slot_count += 1;
|
||||
let missed_slots = leader_missed_slots.entry(leader).or_insert(0);
|
||||
|
||||
loop {
|
||||
if !confirmed_blocks.is_empty() {
|
||||
let slot_of_next_confirmed_block = confirmed_blocks[confirmed_blocks_index];
|
||||
if slot_of_next_confirmed_block < slot {
|
||||
confirmed_blocks_index += 1;
|
||||
continue;
|
||||
}
|
||||
if slot_of_next_confirmed_block == slot {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*missed_slots += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
progress_bar.finish_and_clear();
|
||||
println!(
|
||||
"\n{}",
|
||||
style(format!(
|
||||
" {:<44} {:>15} {:>15} {:>15} {:>23}",
|
||||
"Identity Pubkey",
|
||||
"Leader Slots",
|
||||
"Blocks Produced",
|
||||
"Missed Slots",
|
||||
"Missed Block Percentage",
|
||||
))
|
||||
.bold()
|
||||
);
|
||||
|
||||
let mut table = vec![];
|
||||
for (leader, leader_slots) in leader_slot_count.iter() {
|
||||
let missed_slots = leader_missed_slots.get(leader).unwrap();
|
||||
let blocks_produced = leader_slots - missed_slots;
|
||||
table.push(format!(
|
||||
" {:<44} {:>15} {:>15} {:>15} {:>22.2}%",
|
||||
leader,
|
||||
leader_slots,
|
||||
blocks_produced,
|
||||
missed_slots,
|
||||
*missed_slots as f64 / *leader_slots as f64 * 100.
|
||||
));
|
||||
}
|
||||
table.sort();
|
||||
|
||||
println!(
|
||||
"{}\n\n {:<44} {:>15} {:>15} {:>15} {:>22.2}%",
|
||||
table.join("\n"),
|
||||
format!("Epoch {} total:", epoch),
|
||||
total_slots,
|
||||
total_blocks,
|
||||
total_slots_missed,
|
||||
total_slots_missed as f64 / total_slots as f64 * 100.
|
||||
);
|
||||
println!(
|
||||
" (using data from {} slots: {} to {})",
|
||||
total_slots, start_slot, end_slot
|
||||
);
|
||||
Ok("".to_string())
|
||||
}
|
||||
|
||||
pub fn process_get_transaction_count(
|
||||
rpc_client: &RpcClient,
|
||||
commitment_config: &CommitmentConfig,
|
||||
@ -550,6 +724,7 @@ pub fn process_show_gossip(rpc_client: &RpcClient) -> ProcessResult {
|
||||
}
|
||||
|
||||
pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool) -> ProcessResult {
|
||||
let epoch_schedule = rpc_client.get_epoch_schedule()?;
|
||||
let vote_accounts = rpc_client.get_vote_accounts()?;
|
||||
let total_active_stake = vote_accounts
|
||||
.current
|
||||
@ -592,19 +767,21 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
|
||||
println!(
|
||||
"{}",
|
||||
style(format!(
|
||||
" {:<44} {:<44} {} {} {} {}",
|
||||
" {:<44} {:<44} {} {} {} {:>7} {}",
|
||||
"Identity Pubkey",
|
||||
"Vote Account Pubkey",
|
||||
"Commission",
|
||||
"Last Vote",
|
||||
"Root Block",
|
||||
"Uptime",
|
||||
"Active Stake",
|
||||
))
|
||||
.bold()
|
||||
);
|
||||
|
||||
fn print_vote_account(
|
||||
vote_account: &RpcVoteAccountInfo,
|
||||
vote_account: RpcVoteAccountInfo,
|
||||
epoch_schedule: &EpochSchedule,
|
||||
total_active_stake: f64,
|
||||
use_lamports_unit: bool,
|
||||
delinquent: bool,
|
||||
@ -616,8 +793,20 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
|
||||
format!("{}", v)
|
||||
}
|
||||
}
|
||||
|
||||
fn uptime(epoch_credits: Vec<(Epoch, u64, u64)>, epoch_schedule: &EpochSchedule) -> String {
|
||||
let (total_credits, total_slots, _) =
|
||||
aggregate_epoch_credits(&epoch_credits, &epoch_schedule);
|
||||
if total_slots > 0 {
|
||||
let total_uptime = 100_f64 * total_credits as f64 / total_slots as f64;
|
||||
format!("{:.2}%", total_uptime)
|
||||
} else {
|
||||
"-".into()
|
||||
}
|
||||
}
|
||||
|
||||
println!(
|
||||
"{} {:<44} {:<44} {:>9}% {:>8} {:>10} {:>12}",
|
||||
"{} {:<44} {:<44} {:>9}% {:>8} {:>10} {:>7} {}",
|
||||
if delinquent {
|
||||
WARNING.to_string()
|
||||
} else {
|
||||
@ -628,6 +817,7 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
|
||||
vote_account.commission,
|
||||
non_zero_or_dash(vote_account.last_vote),
|
||||
non_zero_or_dash(vote_account.root_slot),
|
||||
uptime(vote_account.epoch_credits, epoch_schedule),
|
||||
if vote_account.activated_stake > 0 {
|
||||
format!(
|
||||
"{} ({:.2}%)",
|
||||
@ -640,11 +830,23 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
|
||||
);
|
||||
}
|
||||
|
||||
for vote_account in vote_accounts.current.iter() {
|
||||
print_vote_account(vote_account, total_active_stake, use_lamports_unit, false);
|
||||
for vote_account in vote_accounts.current.into_iter() {
|
||||
print_vote_account(
|
||||
vote_account,
|
||||
&epoch_schedule,
|
||||
total_active_stake,
|
||||
use_lamports_unit,
|
||||
false,
|
||||
);
|
||||
}
|
||||
for vote_account in vote_accounts.delinquent.iter() {
|
||||
print_vote_account(vote_account, total_active_stake, use_lamports_unit, true);
|
||||
for vote_account in vote_accounts.delinquent.into_iter() {
|
||||
print_vote_account(
|
||||
vote_account,
|
||||
&epoch_schedule,
|
||||
total_active_stake,
|
||||
use_lamports_unit,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
Ok("".to_string())
|
||||
|
182
cli/src/vote.rs
182
cli/src/vote.rs
@ -1,6 +1,10 @@
|
||||
use crate::cli::{
|
||||
build_balance_message, check_account_for_fee, check_unique_pubkeys,
|
||||
log_instruction_custom_error, CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult,
|
||||
use crate::{
|
||||
cli::{
|
||||
build_balance_message, check_account_for_fee, check_unique_pubkeys,
|
||||
log_instruction_custom_error, CliCommand, CliCommandInfo, CliConfig, CliError,
|
||||
ProcessResult,
|
||||
},
|
||||
cluster_query::aggregate_epoch_credits,
|
||||
};
|
||||
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
|
||||
use solana_clap_utils::{input_parsers::*, input_validators::*};
|
||||
@ -34,9 +38,9 @@ impl VoteSubCommands for App<'_, '_> {
|
||||
.help("Vote account keypair to fund"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("node_pubkey")
|
||||
Arg::with_name("identity_pubkey")
|
||||
.index(2)
|
||||
.value_name("VALIDATOR PUBKEY")
|
||||
.value_name("VALIDATOR IDENTITY PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
@ -66,6 +70,37 @@ impl VoteSubCommands for App<'_, '_> {
|
||||
.help("Public key of the authorized withdrawer (defaults to cli config pubkey)"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("vote-update-validator")
|
||||
.about("Update the vote account's validator identity")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account to update"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("new_identity_pubkey")
|
||||
.index(2)
|
||||
.value_name("NEW VALIDATOR IDENTITY PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("New validator that will vote with this account"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("authorized_voter")
|
||||
.index(3)
|
||||
.value_name("AUTHORIZED VOTER KEYPAIR")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_keypair)
|
||||
.help("Authorized voter keypair"),
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("vote-authorize-voter")
|
||||
.about("Authorize a new vote signing keypair for the given vote account")
|
||||
@ -159,7 +194,7 @@ impl VoteSubCommands for App<'_, '_> {
|
||||
|
||||
pub fn parse_vote_create_account(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let vote_account = keypair_of(matches, "vote_account").unwrap();
|
||||
let node_pubkey = pubkey_of(matches, "node_pubkey").unwrap();
|
||||
let identity_pubkey = pubkey_of(matches, "identity_pubkey").unwrap();
|
||||
let commission = value_of(&matches, "commission").unwrap_or(0);
|
||||
let authorized_voter = pubkey_of(matches, "authorized_voter");
|
||||
let authorized_withdrawer = pubkey_of(matches, "authorized_withdrawer");
|
||||
@ -167,7 +202,7 @@ pub fn parse_vote_create_account(matches: &ArgMatches<'_>) -> Result<CliCommandI
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::CreateVoteAccount {
|
||||
vote_account: vote_account.into(),
|
||||
node_pubkey,
|
||||
node_pubkey: identity_pubkey,
|
||||
authorized_voter,
|
||||
authorized_withdrawer,
|
||||
commission,
|
||||
@ -184,11 +219,26 @@ pub fn parse_vote_authorize(
|
||||
let new_authorized_pubkey = pubkey_of(matches, "new_authorized_pubkey").unwrap();
|
||||
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::VoteAuthorize(
|
||||
command: CliCommand::VoteAuthorize {
|
||||
vote_account_pubkey,
|
||||
new_authorized_pubkey,
|
||||
vote_authorize,
|
||||
),
|
||||
},
|
||||
require_keypair: true,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_vote_update_validator(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap();
|
||||
let new_identity_pubkey = pubkey_of(matches, "new_identity_pubkey").unwrap();
|
||||
let authorized_voter = keypair_of(matches, "authorized_voter").unwrap();
|
||||
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::VoteUpdateValidator {
|
||||
vote_account_pubkey,
|
||||
new_identity_pubkey,
|
||||
authorized_voter: authorized_voter.into(),
|
||||
},
|
||||
require_keypair: true,
|
||||
})
|
||||
}
|
||||
@ -229,7 +279,7 @@ pub fn process_create_vote_account(
|
||||
rpc_client: &RpcClient,
|
||||
config: &CliConfig,
|
||||
vote_account: &Keypair,
|
||||
node_pubkey: &Pubkey,
|
||||
identity_pubkey: &Pubkey,
|
||||
authorized_voter: &Option<Pubkey>,
|
||||
authorized_withdrawer: &Option<Pubkey>,
|
||||
commission: u8,
|
||||
@ -237,7 +287,7 @@ pub fn process_create_vote_account(
|
||||
let vote_account_pubkey = vote_account.pubkey();
|
||||
check_unique_pubkeys(
|
||||
(&vote_account_pubkey, "vote_account_pubkey".to_string()),
|
||||
(&node_pubkey, "node_pubkey".to_string()),
|
||||
(&identity_pubkey, "identity_pubkey".to_string()),
|
||||
)?;
|
||||
check_unique_pubkeys(
|
||||
(&config.keypair.pubkey(), "cli keypair".to_string()),
|
||||
@ -251,7 +301,7 @@ pub fn process_create_vote_account(
|
||||
1
|
||||
};
|
||||
let vote_init = VoteInit {
|
||||
node_pubkey: *node_pubkey,
|
||||
node_pubkey: *identity_pubkey,
|
||||
authorized_voter: authorized_voter.unwrap_or(vote_account_pubkey),
|
||||
authorized_withdrawer: authorized_withdrawer.unwrap_or(config.keypair.pubkey()),
|
||||
commission,
|
||||
@ -313,6 +363,40 @@ pub fn process_vote_authorize(
|
||||
log_instruction_custom_error::<VoteError>(result)
|
||||
}
|
||||
|
||||
pub fn process_vote_update_validator(
|
||||
rpc_client: &RpcClient,
|
||||
config: &CliConfig,
|
||||
vote_account_pubkey: &Pubkey,
|
||||
new_identity_pubkey: &Pubkey,
|
||||
authorized_voter: &Keypair,
|
||||
) -> ProcessResult {
|
||||
check_unique_pubkeys(
|
||||
(vote_account_pubkey, "vote_account_pubkey".to_string()),
|
||||
(new_identity_pubkey, "new_identity_pubkey".to_string()),
|
||||
)?;
|
||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||
let ixs = vec![vote_instruction::update_node(
|
||||
vote_account_pubkey,
|
||||
&authorized_voter.pubkey(),
|
||||
new_identity_pubkey,
|
||||
)];
|
||||
|
||||
let mut tx = Transaction::new_signed_with_payer(
|
||||
ixs,
|
||||
Some(&config.keypair.pubkey()),
|
||||
&[&config.keypair, authorized_voter],
|
||||
recent_blockhash,
|
||||
);
|
||||
check_account_for_fee(
|
||||
rpc_client,
|
||||
&config.keypair.pubkey(),
|
||||
&fee_calculator,
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||
log_instruction_custom_error::<VoteError>(result)
|
||||
}
|
||||
|
||||
fn get_vote_account(
|
||||
rpc_client: &RpcClient,
|
||||
vote_account_pubkey: &Pubkey,
|
||||
@ -348,7 +432,7 @@ pub fn process_show_vote_account(
|
||||
"account balance: {}",
|
||||
build_balance_message(vote_account.lamports, use_lamports_unit, true)
|
||||
);
|
||||
println!("node id: {}", vote_state.node_pubkey);
|
||||
println!("validator identity: {}", vote_state.node_pubkey);
|
||||
println!("authorized voter: {}", vote_state.authorized_voter);
|
||||
println!(
|
||||
"authorized withdrawer: {}",
|
||||
@ -396,38 +480,42 @@ pub fn process_uptime(
|
||||
|
||||
let epoch_schedule = rpc_client.get_epoch_schedule()?;
|
||||
|
||||
println!("Node id: {}", vote_state.node_pubkey);
|
||||
println!("Authorized voter: {}", vote_state.authorized_voter);
|
||||
println!("validator identity: {}", vote_state.node_pubkey);
|
||||
println!("authorized voter: {}", vote_state.authorized_voter);
|
||||
if !vote_state.votes.is_empty() {
|
||||
println!("Uptime:");
|
||||
println!("uptime:");
|
||||
|
||||
let epoch_credits_vec: Vec<(u64, u64, u64)> = vote_state.epoch_credits().copied().collect();
|
||||
|
||||
let epoch_credits = if let Some(x) = span {
|
||||
epoch_credits_vec.iter().rev().take(x as usize)
|
||||
let epoch_credits: Vec<(u64, u64, u64)> = if let Some(x) = span {
|
||||
vote_state
|
||||
.epoch_credits()
|
||||
.iter()
|
||||
.rev()
|
||||
.take(x as usize)
|
||||
.cloned()
|
||||
.collect()
|
||||
} else {
|
||||
epoch_credits_vec.iter().rev().take(epoch_credits_vec.len())
|
||||
vote_state.epoch_credits().iter().rev().cloned().collect()
|
||||
};
|
||||
|
||||
if aggregate {
|
||||
let (credits_earned, slots_in_epoch, epochs): (u64, u64, u64) =
|
||||
epoch_credits.fold((0, 0, 0), |acc, (epoch, credits, prev_credits)| {
|
||||
let credits_earned = credits - prev_credits;
|
||||
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(*epoch);
|
||||
(acc.0 + credits_earned, acc.1 + slots_in_epoch, acc.2 + 1)
|
||||
});
|
||||
let total_uptime = credits_earned as f64 / slots_in_epoch as f64;
|
||||
println!("{:.2}% over {} epochs", total_uptime * 100_f64, epochs,);
|
||||
let (total_credits, total_slots, epochs) =
|
||||
aggregate_epoch_credits(&epoch_credits, &epoch_schedule);
|
||||
if total_slots > 0 {
|
||||
let total_uptime = 100_f64 * total_credits as f64 / total_slots as f64;
|
||||
println!("{:.2}% over {} epochs", total_uptime, epochs);
|
||||
} else {
|
||||
println!("Insufficient voting history available");
|
||||
}
|
||||
} else {
|
||||
for (epoch, credits, prev_credits) in epoch_credits {
|
||||
let credits_earned = credits - prev_credits;
|
||||
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(*epoch);
|
||||
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(epoch);
|
||||
let uptime = credits_earned as f64 / slots_in_epoch as f64;
|
||||
println!("- epoch: {} {:.2}% uptime", epoch, uptime * 100_f64,);
|
||||
}
|
||||
}
|
||||
if let Some(x) = span {
|
||||
if x > epoch_credits_vec.len() as u64 {
|
||||
if x > vote_state.epoch_credits().len() as u64 {
|
||||
println!("(span longer than available epochs)");
|
||||
}
|
||||
}
|
||||
@ -453,17 +541,24 @@ mod tests {
|
||||
let keypair = Keypair::new();
|
||||
let pubkey = keypair.pubkey();
|
||||
let pubkey_string = pubkey.to_string();
|
||||
let keypair2 = Keypair::new();
|
||||
let pubkey2 = keypair2.pubkey();
|
||||
let pubkey2_string = pubkey2.to_string();
|
||||
|
||||
let test_authorize_voter = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
"vote-authorize-voter",
|
||||
&pubkey_string,
|
||||
&pubkey_string,
|
||||
&pubkey2_string,
|
||||
]);
|
||||
assert_eq!(
|
||||
parse_command(&test_authorize_voter).unwrap(),
|
||||
CliCommandInfo {
|
||||
command: CliCommand::VoteAuthorize(pubkey, pubkey, VoteAuthorize::Voter),
|
||||
command: CliCommand::VoteAuthorize {
|
||||
vote_account_pubkey: pubkey,
|
||||
new_authorized_pubkey: pubkey2,
|
||||
vote_authorize: VoteAuthorize::Voter
|
||||
},
|
||||
require_keypair: true
|
||||
}
|
||||
);
|
||||
@ -574,6 +669,27 @@ mod tests {
|
||||
}
|
||||
);
|
||||
|
||||
let test_update_validator = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
"vote-update-validator",
|
||||
&pubkey_string,
|
||||
&pubkey2_string,
|
||||
&keypair_file,
|
||||
]);
|
||||
assert_eq!(
|
||||
parse_command(&test_update_validator).unwrap(),
|
||||
CliCommandInfo {
|
||||
command: CliCommand::VoteUpdateValidator {
|
||||
vote_account_pubkey: pubkey,
|
||||
new_identity_pubkey: pubkey2,
|
||||
authorized_voter: solana_sdk::signature::read_keypair_file(&keypair_file)
|
||||
.unwrap()
|
||||
.into(),
|
||||
},
|
||||
require_keypair: true
|
||||
}
|
||||
);
|
||||
|
||||
// Test Uptime Subcommand
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let matches = test_commands.clone().get_matches_from(vec![
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-client"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Client"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -19,10 +19,10 @@ reqwest = { version = "0.9.22", default-features = false, features = ["rustls-tl
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
jsonrpc-core = "14.0.3"
|
||||
jsonrpc-http-server = "14.0.3"
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
|
@ -1,12 +1,10 @@
|
||||
use crate::{client_error::ClientError, rpc_request::RpcRequest};
|
||||
use solana_sdk::commitment_config::CommitmentConfig;
|
||||
|
||||
pub(crate) trait GenericRpcClientRequest {
|
||||
fn send(
|
||||
&self,
|
||||
request: &RpcRequest,
|
||||
params: Option<serde_json::Value>,
|
||||
params: serde_json::Value,
|
||||
retries: usize,
|
||||
commitment_config: Option<CommitmentConfig>,
|
||||
) -> Result<serde_json::Value, ClientError>;
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ use crate::{
|
||||
};
|
||||
use serde_json::{Number, Value};
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig,
|
||||
fee_calculator::FeeCalculator,
|
||||
transaction::{self, TransactionError},
|
||||
};
|
||||
@ -28,17 +27,16 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
|
||||
fn send(
|
||||
&self,
|
||||
request: &RpcRequest,
|
||||
params: Option<serde_json::Value>,
|
||||
params: serde_json::Value,
|
||||
_retries: usize,
|
||||
_commitment_config: Option<CommitmentConfig>,
|
||||
) -> Result<serde_json::Value, ClientError> {
|
||||
if self.url == "fails" {
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
let val = match request {
|
||||
RpcRequest::ConfirmTransaction => {
|
||||
if let Some(Value::Array(param_array)) = params {
|
||||
if let Value::String(param_string) = ¶m_array[0] {
|
||||
if let Some(params_array) = params.as_array() {
|
||||
if let Value::String(param_string) = ¶ms_array[0] {
|
||||
Value::Bool(param_string == SIGNATURE)
|
||||
} else {
|
||||
Value::Null
|
||||
|
@ -4,7 +4,10 @@ use crate::{
|
||||
generic_rpc_client_request::GenericRpcClientRequest,
|
||||
mock_rpc_client_request::MockRpcClientRequest,
|
||||
rpc_client_request::RpcClientRequest,
|
||||
rpc_request::{RpcContactInfo, RpcEpochInfo, RpcRequest, RpcVersionInfo, RpcVoteAccountStatus},
|
||||
rpc_request::{
|
||||
RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo, RpcLeaderSchedule, RpcRequest,
|
||||
RpcVersionInfo, RpcVoteAccountStatus,
|
||||
},
|
||||
};
|
||||
use bincode::serialize;
|
||||
use log::*;
|
||||
@ -67,14 +70,12 @@ impl RpcClient {
|
||||
signature: &str,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> RpcResponse<bool> {
|
||||
let params = json!(signature);
|
||||
let response = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::ConfirmTransaction,
|
||||
Some(params),
|
||||
json!([signature, commitment_config]),
|
||||
0,
|
||||
Some(commitment_config),
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
@ -93,10 +94,9 @@ impl RpcClient {
|
||||
|
||||
pub fn send_transaction(&self, transaction: &Transaction) -> Result<String, ClientError> {
|
||||
let serialized = serialize(transaction).unwrap();
|
||||
let params = json!(serialized);
|
||||
let signature = self
|
||||
.client
|
||||
.send(&RpcRequest::SendTransaction, Some(params), 5, None)?;
|
||||
.send(&RpcRequest::SendTransaction, json!([serialized]), 5)?;
|
||||
if signature.as_str().is_none() {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -120,12 +120,10 @@ impl RpcClient {
|
||||
signature: &str,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Result<Option<transaction::Result<()>>, ClientError> {
|
||||
let params = json!(signature.to_string());
|
||||
let signature_status = self.client.send(
|
||||
&RpcRequest::GetSignatureStatus,
|
||||
Some(params),
|
||||
json!([signature.to_string(), commitment_config]),
|
||||
5,
|
||||
commitment_config.ok(),
|
||||
)?;
|
||||
let result: Option<transaction::Result<()>> =
|
||||
serde_json::from_value(signature_status).unwrap();
|
||||
@ -142,7 +140,7 @@ impl RpcClient {
|
||||
) -> io::Result<Slot> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetSlot, None, 0, commitment_config.ok())
|
||||
.send(&RpcRequest::GetSlot, json!([commitment_config]), 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -161,7 +159,7 @@ impl RpcClient {
|
||||
pub fn get_vote_accounts(&self) -> io::Result<RpcVoteAccountStatus> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetVoteAccounts, None, 0, None)
|
||||
.send(&RpcRequest::GetVoteAccounts, Value::Null, 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -180,7 +178,7 @@ impl RpcClient {
|
||||
pub fn get_cluster_nodes(&self) -> io::Result<Vec<RpcContactInfo>> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetClusterNodes, None, 0, None)
|
||||
.send(&RpcRequest::GetClusterNodes, Value::Null, 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -196,11 +194,56 @@ impl RpcClient {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_block_time(&self, slot: Slot) -> io::Result<UnixTimestamp> {
|
||||
let params = json!(slot);
|
||||
pub fn get_confirmed_block(&self, slot: Slot) -> io::Result<RpcConfirmedBlock> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetBlockTime, Some(params), 0, None);
|
||||
.send(&RpcRequest::GetConfirmedBlock, json!([slot]), 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GetConfirmedBlock request failure: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
serde_json::from_value(response).map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GetConfirmedBlock parse failure: {}", err),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_confirmed_blocks(
|
||||
&self,
|
||||
start_slot: Slot,
|
||||
end_slot: Option<Slot>,
|
||||
) -> io::Result<Vec<Slot>> {
|
||||
let response = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetConfirmedBlocks,
|
||||
json!([start_slot, end_slot]),
|
||||
0,
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GetConfirmedBlocks request failure: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
serde_json::from_value(response).map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GetConfirmedBlocks parse failure: {}", err),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_block_time(&self, slot: Slot) -> io::Result<UnixTimestamp> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetBlockTime, json!([slot]), 0);
|
||||
|
||||
response
|
||||
.map(|result_json| {
|
||||
@ -232,7 +275,7 @@ impl RpcClient {
|
||||
) -> io::Result<RpcEpochInfo> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetEpochInfo, None, 0, commitment_config.ok())
|
||||
.send(&RpcRequest::GetEpochInfo, json!([commitment_config]), 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -248,10 +291,41 @@ impl RpcClient {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_leader_schedule(&self, slot: Option<Slot>) -> io::Result<Option<RpcLeaderSchedule>> {
|
||||
self.get_leader_schedule_with_commitment(slot, CommitmentConfig::default())
|
||||
}
|
||||
|
||||
pub fn get_leader_schedule_with_commitment(
|
||||
&self,
|
||||
slot: Option<Slot>,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<Option<RpcLeaderSchedule>> {
|
||||
let response = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetLeaderSchedule,
|
||||
json!([slot, commitment_config]),
|
||||
0,
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GetLeaderSchedule request failure: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
serde_json::from_value(response).map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GetLeaderSchedule failure: {}", err),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_epoch_schedule(&self) -> io::Result<EpochSchedule> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetEpochSchedule, None, 0, None)
|
||||
.send(&RpcRequest::GetEpochSchedule, Value::Null, 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -270,7 +344,7 @@ impl RpcClient {
|
||||
pub fn get_inflation(&self) -> io::Result<Inflation> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetInflation, None, 0, None)
|
||||
.send(&RpcRequest::GetInflation, Value::Null, 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -289,7 +363,7 @@ impl RpcClient {
|
||||
pub fn get_version(&self) -> io::Result<RpcVersionInfo> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetVersion, None, 0, None)
|
||||
.send(&RpcRequest::GetVersion, Value::Null, 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -438,10 +512,13 @@ impl RpcClient {
|
||||
pubkey: &Pubkey,
|
||||
retries: usize,
|
||||
) -> Result<Option<u64>, Box<dyn error::Error>> {
|
||||
let params = json!(format!("{}", pubkey));
|
||||
let balance_json = self
|
||||
.client
|
||||
.send(&RpcRequest::GetBalance, Some(params), retries, None)
|
||||
.send(
|
||||
&RpcRequest::GetBalance,
|
||||
json!([pubkey.to_string()]),
|
||||
retries,
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -477,12 +554,10 @@ impl RpcClient {
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> RpcResponse<Option<Account>> {
|
||||
let params = json!(format!("{}", pubkey));
|
||||
let response = self.client.send(
|
||||
&RpcRequest::GetAccountInfo,
|
||||
Some(params),
|
||||
json!([pubkey.to_string(), commitment_config]),
|
||||
0,
|
||||
Some(commitment_config),
|
||||
);
|
||||
|
||||
response
|
||||
@ -510,14 +585,12 @@ impl RpcClient {
|
||||
}
|
||||
|
||||
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> io::Result<u64> {
|
||||
let params = json!(data_len);
|
||||
let minimum_balance_json = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetMinimumBalanceForRentExemption,
|
||||
Some(params),
|
||||
json!([data_len]),
|
||||
0,
|
||||
None,
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
@ -555,14 +628,12 @@ impl RpcClient {
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> RpcResponse<u64> {
|
||||
let params = json!(pubkey.to_string());
|
||||
let balance_json = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetBalance,
|
||||
Some(params),
|
||||
json!([pubkey.to_string(), commitment_config]),
|
||||
0,
|
||||
Some(commitment_config),
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
@ -580,10 +651,13 @@ impl RpcClient {
|
||||
}
|
||||
|
||||
pub fn get_program_accounts(&self, pubkey: &Pubkey) -> io::Result<Vec<(Pubkey, Account)>> {
|
||||
let params = json!(format!("{}", pubkey));
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetProgramAccounts, Some(params), 0, None)
|
||||
.send(
|
||||
&RpcRequest::GetProgramAccounts,
|
||||
json!([pubkey.to_string()]),
|
||||
0,
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -625,9 +699,8 @@ impl RpcClient {
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetTransactionCount,
|
||||
None,
|
||||
json!([commitment_config]),
|
||||
0,
|
||||
commitment_config.ok(),
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
@ -658,9 +731,8 @@ impl RpcClient {
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetRecentBlockhash,
|
||||
None,
|
||||
json!([commitment_config]),
|
||||
0,
|
||||
commitment_config.ok(),
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
@ -723,7 +795,7 @@ impl RpcClient {
|
||||
pub fn get_genesis_hash(&self) -> io::Result<Hash> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::GetGenesisHash, None, 0, None)
|
||||
.send(&RpcRequest::GetGenesisHash, Value::Null, 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -848,14 +920,12 @@ impl RpcClient {
|
||||
/// Check a signature in the bank.
|
||||
pub fn check_signature(&self, signature: &Signature) -> bool {
|
||||
trace!("check_signature: {:?}", signature);
|
||||
let params = json!(format!("{}", signature));
|
||||
|
||||
for _ in 0..30 {
|
||||
let response = self.client.send(
|
||||
&RpcRequest::ConfirmTransaction,
|
||||
Some(params.clone()),
|
||||
json!([signature.to_string(), CommitmentConfig::recent()]),
|
||||
0,
|
||||
Some(CommitmentConfig::recent()),
|
||||
);
|
||||
|
||||
match response {
|
||||
@ -942,16 +1012,14 @@ impl RpcClient {
|
||||
|
||||
pub fn get_num_blocks_since_signature_confirmation(
|
||||
&self,
|
||||
sig: &Signature,
|
||||
signature: &Signature,
|
||||
) -> io::Result<usize> {
|
||||
let params = json!(format!("{}", sig));
|
||||
let response = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetNumBlocksSinceSignatureConfirmation,
|
||||
Some(params.clone()),
|
||||
json!([signature.to_string(), CommitmentConfig::recent().ok()]),
|
||||
1,
|
||||
CommitmentConfig::recent().ok(),
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
@ -976,7 +1044,7 @@ impl RpcClient {
|
||||
pub fn validator_exit(&self) -> io::Result<bool> {
|
||||
let response = self
|
||||
.client
|
||||
.send(&RpcRequest::ValidatorExit, None, 0, None)
|
||||
.send(&RpcRequest::ValidatorExit, Value::Null, 0)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -994,11 +1062,11 @@ impl RpcClient {
|
||||
pub fn send(
|
||||
&self,
|
||||
request: &RpcRequest,
|
||||
params: Option<Value>,
|
||||
params: Value,
|
||||
retries: usize,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Value, ClientError> {
|
||||
self.client.send(request, params, retries, commitment)
|
||||
assert!(params.is_array() || params.is_null());
|
||||
self.client.send(request, params, retries)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1062,25 +1130,19 @@ mod tests {
|
||||
|
||||
let balance = rpc_client.send(
|
||||
&RpcRequest::GetBalance,
|
||||
Some(json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"])),
|
||||
json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"]),
|
||||
0,
|
||||
None,
|
||||
);
|
||||
assert_eq!(balance.unwrap().as_u64().unwrap(), 50);
|
||||
|
||||
let blockhash = rpc_client.send(&RpcRequest::GetRecentBlockhash, None, 0, None);
|
||||
let blockhash = rpc_client.send(&RpcRequest::GetRecentBlockhash, Value::Null, 0);
|
||||
assert_eq!(
|
||||
blockhash.unwrap().as_str().unwrap(),
|
||||
"deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"
|
||||
);
|
||||
|
||||
// Send erroneous parameter
|
||||
let blockhash = rpc_client.send(
|
||||
&RpcRequest::GetRecentBlockhash,
|
||||
Some(json!("parameter")),
|
||||
0,
|
||||
None,
|
||||
);
|
||||
let blockhash = rpc_client.send(&RpcRequest::GetRecentBlockhash, json!(["parameter"]), 0);
|
||||
assert_eq!(blockhash.is_err(), true);
|
||||
}
|
||||
|
||||
@ -1116,9 +1178,8 @@ mod tests {
|
||||
|
||||
let balance = rpc_client.send(
|
||||
&RpcRequest::GetBalance,
|
||||
Some(json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhw"])),
|
||||
json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhw"]),
|
||||
10,
|
||||
None,
|
||||
);
|
||||
assert_eq!(balance.unwrap().as_u64().unwrap(), 5);
|
||||
}
|
||||
|
@ -5,10 +5,7 @@ use crate::{
|
||||
};
|
||||
use log::*;
|
||||
use reqwest::{self, header::CONTENT_TYPE};
|
||||
use solana_sdk::{
|
||||
clock::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT},
|
||||
commitment_config::CommitmentConfig,
|
||||
};
|
||||
use solana_sdk::clock::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT};
|
||||
use std::{thread::sleep, time::Duration};
|
||||
|
||||
pub struct RpcClientRequest {
|
||||
@ -38,14 +35,13 @@ impl GenericRpcClientRequest for RpcClientRequest {
|
||||
fn send(
|
||||
&self,
|
||||
request: &RpcRequest,
|
||||
params: Option<serde_json::Value>,
|
||||
params: serde_json::Value,
|
||||
mut retries: usize,
|
||||
commitment_config: Option<CommitmentConfig>,
|
||||
) -> Result<serde_json::Value, ClientError> {
|
||||
// Concurrent requests are not supported so reuse the same request id for all requests
|
||||
let request_id = 1;
|
||||
|
||||
let request_json = request.build_request_json(request_id, params, commitment_config);
|
||||
let request_json = request.build_request_json(request_id, params);
|
||||
|
||||
loop {
|
||||
match self
|
||||
|
@ -2,11 +2,10 @@ use jsonrpc_core::Result as JsonResult;
|
||||
use serde_json::{json, Value};
|
||||
use solana_sdk::{
|
||||
clock::{Epoch, Slot},
|
||||
commitment_config::CommitmentConfig,
|
||||
hash::Hash,
|
||||
transaction::{Result, Transaction},
|
||||
};
|
||||
use std::{error, fmt, io, net::SocketAddr};
|
||||
use std::{collections::HashMap, error, fmt, io, net::SocketAddr};
|
||||
|
||||
pub type RpcResponseIn<T> = JsonResult<Response<T>>;
|
||||
pub type RpcResponse<T> = io::Result<Response<T>>;
|
||||
@ -49,6 +48,9 @@ pub struct RpcContactInfo {
|
||||
pub rpc: Option<SocketAddr>,
|
||||
}
|
||||
|
||||
/// Map of leader base58 identity pubkeys to the slot indices relative to the first epoch slot
|
||||
pub type RpcLeaderSchedule = HashMap<String, Vec<usize>>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcEpochInfo {
|
||||
@ -97,6 +99,10 @@ pub struct RpcVoteAccountInfo {
|
||||
/// Whether this account is staked for the current epoch
|
||||
pub epoch_vote_account: bool,
|
||||
|
||||
/// History of how many credits earned by the end of each epoch
|
||||
/// each tuple is (Epoch, credits, prev_credits)
|
||||
pub epoch_credits: Vec<(Epoch, u64, u64)>,
|
||||
|
||||
/// Most recent slot voted on by this vote account (0 if no votes exist)
|
||||
pub last_vote: u64,
|
||||
|
||||
@ -113,10 +119,13 @@ pub enum RpcRequest {
|
||||
GetBalance,
|
||||
GetBlockTime,
|
||||
GetClusterNodes,
|
||||
GetConfirmedBlock,
|
||||
GetConfirmedBlocks,
|
||||
GetEpochInfo,
|
||||
GetEpochSchedule,
|
||||
GetGenesisHash,
|
||||
GetInflation,
|
||||
GetLeaderSchedule,
|
||||
GetNumBlocksSinceSignatureConfirmation,
|
||||
GetProgramAccounts,
|
||||
GetRecentBlockhash,
|
||||
@ -138,12 +147,7 @@ pub enum RpcRequest {
|
||||
}
|
||||
|
||||
impl RpcRequest {
|
||||
pub(crate) fn build_request_json(
|
||||
&self,
|
||||
id: u64,
|
||||
params: Option<Value>,
|
||||
commitment_config: Option<CommitmentConfig>,
|
||||
) -> Value {
|
||||
pub(crate) fn build_request_json(&self, id: u64, params: Value) -> Value {
|
||||
let jsonrpc = "2.0";
|
||||
let method = match self {
|
||||
RpcRequest::ConfirmTransaction => "confirmTransaction",
|
||||
@ -153,10 +157,13 @@ impl RpcRequest {
|
||||
RpcRequest::GetBalance => "getBalance",
|
||||
RpcRequest::GetBlockTime => "getBlockTime",
|
||||
RpcRequest::GetClusterNodes => "getClusterNodes",
|
||||
RpcRequest::GetConfirmedBlock => "getConfirmedBlock",
|
||||
RpcRequest::GetConfirmedBlocks => "getConfirmedBlocks",
|
||||
RpcRequest::GetEpochInfo => "getEpochInfo",
|
||||
RpcRequest::GetEpochSchedule => "getEpochSchedule",
|
||||
RpcRequest::GetGenesisHash => "getGenesisHash",
|
||||
RpcRequest::GetInflation => "getInflation",
|
||||
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
|
||||
RpcRequest::GetNumBlocksSinceSignatureConfirmation => {
|
||||
"getNumBlocksSinceSignatureConfirmation"
|
||||
}
|
||||
@ -178,21 +185,12 @@ impl RpcRequest {
|
||||
RpcRequest::SignVote => "signVote",
|
||||
RpcRequest::GetMinimumBalanceForRentExemption => "getMinimumBalanceForRentExemption",
|
||||
};
|
||||
let mut request = json!({
|
||||
json!({
|
||||
"jsonrpc": jsonrpc,
|
||||
"id": id,
|
||||
"method": method,
|
||||
});
|
||||
if let Some(param_string) = params {
|
||||
if let Some(config) = commitment_config {
|
||||
request["params"] = json!([param_string, config]);
|
||||
} else {
|
||||
request["params"] = json!([param_string]);
|
||||
}
|
||||
} else if let Some(config) = commitment_config {
|
||||
request["params"] = json!([config]);
|
||||
}
|
||||
request
|
||||
"params": params,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,46 +219,46 @@ impl error::Error for RpcError {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use solana_sdk::commitment_config::CommitmentLevel;
|
||||
use solana_sdk::commitment_config::{CommitmentConfig, CommitmentLevel};
|
||||
|
||||
#[test]
|
||||
fn test_build_request_json() {
|
||||
let test_request = RpcRequest::GetAccountInfo;
|
||||
let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
|
||||
let request = test_request.build_request_json(1, Some(addr.clone()), None);
|
||||
let request = test_request.build_request_json(1, json!([addr.clone()]));
|
||||
assert_eq!(request["method"], "getAccountInfo");
|
||||
assert_eq!(request["params"], json!([addr]));
|
||||
|
||||
let test_request = RpcRequest::GetBalance;
|
||||
let request = test_request.build_request_json(1, Some(addr), None);
|
||||
let request = test_request.build_request_json(1, json!([addr]));
|
||||
assert_eq!(request["method"], "getBalance");
|
||||
|
||||
let test_request = RpcRequest::GetEpochInfo;
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
let request = test_request.build_request_json(1, Value::Null);
|
||||
assert_eq!(request["method"], "getEpochInfo");
|
||||
|
||||
let test_request = RpcRequest::GetInflation;
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
let request = test_request.build_request_json(1, Value::Null);
|
||||
assert_eq!(request["method"], "getInflation");
|
||||
|
||||
let test_request = RpcRequest::GetRecentBlockhash;
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
let request = test_request.build_request_json(1, Value::Null);
|
||||
assert_eq!(request["method"], "getRecentBlockhash");
|
||||
|
||||
let test_request = RpcRequest::GetSlot;
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
let request = test_request.build_request_json(1, Value::Null);
|
||||
assert_eq!(request["method"], "getSlot");
|
||||
|
||||
let test_request = RpcRequest::GetTransactionCount;
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
let request = test_request.build_request_json(1, Value::Null);
|
||||
assert_eq!(request["method"], "getTransactionCount");
|
||||
|
||||
let test_request = RpcRequest::RequestAirdrop;
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
let request = test_request.build_request_json(1, Value::Null);
|
||||
assert_eq!(request["method"], "requestAirdrop");
|
||||
|
||||
let test_request = RpcRequest::SendTransaction;
|
||||
let request = test_request.build_request_json(1, None, None);
|
||||
let request = test_request.build_request_json(1, Value::Null);
|
||||
assert_eq!(request["method"], "sendTransaction");
|
||||
}
|
||||
|
||||
@ -273,13 +271,13 @@ mod tests {
|
||||
|
||||
// Test request with CommitmentConfig and no params
|
||||
let test_request = RpcRequest::GetRecentBlockhash;
|
||||
let request = test_request.build_request_json(1, None, Some(commitment_config.clone()));
|
||||
let request = test_request.build_request_json(1, json!([commitment_config.clone()]));
|
||||
assert_eq!(request["params"], json!([commitment_config.clone()]));
|
||||
|
||||
// Test request with CommitmentConfig and params
|
||||
let test_request = RpcRequest::GetBalance;
|
||||
let request =
|
||||
test_request.build_request_json(1, Some(addr.clone()), Some(commitment_config.clone()));
|
||||
test_request.build_request_json(1, json!([addr.clone(), commitment_config.clone()]));
|
||||
assert_eq!(request["params"], json!([addr, commitment_config]));
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-core"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "../README.md"
|
||||
@ -41,25 +41,25 @@ rayon = "1.2.0"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-chacha-sys = { path = "../chacha-sys", version = "0.21.3" }
|
||||
solana-client = { path = "../client", version = "0.21.3" }
|
||||
solana-drone = { path = "../drone", version = "0.21.3" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.5" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-chacha-sys = { path = "../chacha-sys", version = "0.21.5" }
|
||||
solana-client = { path = "../client", version = "0.21.5" }
|
||||
solana-drone = { path = "../drone", version = "0.21.5" }
|
||||
ed25519-dalek = "1.0.0-pre.1"
|
||||
solana-ledger = { path = "../ledger", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-measure = { path = "../measure", version = "0.21.3" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.3" }
|
||||
solana-perf = { path = "../perf", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.3" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.3" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "0.21.3" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
solana-measure = { path = "../measure", version = "0.21.5" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.5" }
|
||||
solana-perf = { path = "../perf", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.5" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.5" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "0.21.5" }
|
||||
symlink = "0.1.0"
|
||||
sys-info = "0.5.8"
|
||||
tempfile = "3.1.0"
|
||||
@ -68,7 +68,7 @@ tokio-codec = "0.1"
|
||||
tokio-fs = "0.1"
|
||||
tokio-io = "0.1"
|
||||
untrusted = "0.7.0"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.3" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.5" }
|
||||
reed-solomon-erasure = { package = "solana-reed-solomon-erasure", version = "4.0.1-3", features = ["simd-accel"] }
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
|
@ -748,9 +748,8 @@ impl Archiver {
|
||||
Ok(rpc_client
|
||||
.send(
|
||||
&RpcRequest::GetSlotsPerSegment,
|
||||
None,
|
||||
serde_json::json!([client_commitment]),
|
||||
0,
|
||||
Some(client_commitment),
|
||||
)
|
||||
.map_err(|err| {
|
||||
warn!("Error while making rpc request {:?}", err);
|
||||
@ -803,7 +802,11 @@ impl Archiver {
|
||||
RpcClient::new_socket(rpc_peers[node_index].rpc)
|
||||
};
|
||||
let response = rpc_client
|
||||
.send(&RpcRequest::GetStorageTurn, None, 0, None)
|
||||
.send(
|
||||
&RpcRequest::GetStorageTurn,
|
||||
serde_json::value::Value::Null,
|
||||
0,
|
||||
)
|
||||
.map_err(|err| {
|
||||
warn!("Error while making rpc request {:?}", err);
|
||||
Error::IO(io::Error::new(ErrorKind::Other, "rpc error"))
|
||||
|
418
core/src/rpc.rs
418
core/src/rpc.rs
@ -12,11 +12,13 @@ use bincode::serialize;
|
||||
use jsonrpc_core::{Error, Metadata, Result};
|
||||
use jsonrpc_derive::rpc;
|
||||
use solana_client::rpc_request::{
|
||||
Response, RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo, RpcResponseContext, RpcVersionInfo,
|
||||
RpcVoteAccountInfo, RpcVoteAccountStatus,
|
||||
Response, RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo, RpcLeaderSchedule,
|
||||
RpcResponseContext, RpcVersionInfo, RpcVoteAccountInfo, RpcVoteAccountStatus,
|
||||
};
|
||||
use solana_drone::drone::request_airdrop_transaction;
|
||||
use solana_ledger::{bank_forks::BankForks, blocktree::Blocktree};
|
||||
use solana_ledger::{
|
||||
bank_forks::BankForks, blocktree::Blocktree, rooted_slot_iterator::RootedSlotIterator,
|
||||
};
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
@ -33,6 +35,7 @@ use solana_sdk::{
|
||||
};
|
||||
use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
net::{SocketAddr, UdpSocket},
|
||||
sync::{Arc, RwLock},
|
||||
thread::sleep,
|
||||
@ -251,14 +254,11 @@ impl JsonRpcRequestProcessor {
|
||||
activated_stake: *activated_stake,
|
||||
commission: vote_state.commission,
|
||||
root_slot: vote_state.root_slot.unwrap_or(0),
|
||||
epoch_credits: vote_state.epoch_credits().clone(),
|
||||
epoch_vote_account,
|
||||
last_vote,
|
||||
}
|
||||
})
|
||||
.filter(|vote_account_info| {
|
||||
// Remove vote accounts with no delegated stake that have never voted
|
||||
vote_account_info.last_vote != 0 || vote_account_info.activated_stake != 0
|
||||
})
|
||||
.partition(|vote_account_info| {
|
||||
if bank.slot() >= MAX_LOCKOUT_HISTORY as u64 {
|
||||
vote_account_info.last_vote > bank.slot() - MAX_LOCKOUT_HISTORY as u64
|
||||
@ -266,9 +266,15 @@ impl JsonRpcRequestProcessor {
|
||||
vote_account_info.last_vote > 0
|
||||
}
|
||||
});
|
||||
|
||||
let delinquent_staked_vote_accounts = delinquent_vote_accounts
|
||||
.into_iter()
|
||||
.filter(|vote_account_info| vote_account_info.activated_stake > 0)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(RpcVoteAccountStatus {
|
||||
current: current_vote_accounts,
|
||||
delinquent: delinquent_vote_accounts,
|
||||
delinquent: delinquent_staked_vote_accounts,
|
||||
})
|
||||
}
|
||||
|
||||
@ -310,6 +316,29 @@ impl JsonRpcRequestProcessor {
|
||||
Ok(self.blocktree.get_confirmed_block(slot).ok())
|
||||
}
|
||||
|
||||
pub fn get_confirmed_blocks(
|
||||
&self,
|
||||
start_slot: Slot,
|
||||
end_slot: Option<Slot>,
|
||||
) -> Result<Vec<Slot>> {
|
||||
let end_slot = end_slot.unwrap_or_else(|| self.bank(None).slot());
|
||||
if end_slot < start_slot {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
let start_slot = (start_slot..end_slot).find(|&slot| self.blocktree.is_root(slot));
|
||||
if let Some(start_slot) = start_slot {
|
||||
let mut slots: Vec<Slot> = RootedSlotIterator::new(start_slot, &self.blocktree)
|
||||
.unwrap()
|
||||
.map(|(slot, _)| slot)
|
||||
.collect();
|
||||
slots.retain(|&x| x <= end_slot);
|
||||
Ok(slots)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
// The `get_block_time` method is not fully implemented. It currently returns `slot` *
|
||||
// DEFAULT_MS_PER_SLOT offset from 0 for all requests, and null for any values that would
|
||||
// overflow.
|
||||
@ -415,7 +444,7 @@ pub trait RpcSol {
|
||||
fn get_block_commitment(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
block: u64,
|
||||
block: Slot,
|
||||
) -> Result<(Option<BlockCommitment>, u64)>;
|
||||
|
||||
#[rpc(meta, name = "getGenesisHash")]
|
||||
@ -425,8 +454,9 @@ pub trait RpcSol {
|
||||
fn get_leader_schedule(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
slot: Option<Slot>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<Vec<String>>>;
|
||||
) -> Result<Option<RpcLeaderSchedule>>;
|
||||
|
||||
#[rpc(meta, name = "getRecentBlockhash")]
|
||||
fn get_recent_blockhash(
|
||||
@ -536,6 +566,14 @@ pub trait RpcSol {
|
||||
|
||||
#[rpc(meta, name = "getBlockTime")]
|
||||
fn get_block_time(&self, meta: Self::Metadata, slot: Slot) -> Result<Option<UnixTimestamp>>;
|
||||
|
||||
#[rpc(meta, name = "getConfirmedBlocks")]
|
||||
fn get_confirmed_blocks(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
start_slot: Slot,
|
||||
end_slot: Option<Slot>,
|
||||
) -> Result<Vec<Slot>>;
|
||||
}
|
||||
|
||||
pub struct RpcSolImpl;
|
||||
@ -675,8 +713,9 @@ impl RpcSol for RpcSolImpl {
|
||||
) -> Result<RpcEpochInfo> {
|
||||
let bank = meta.request_processor.read().unwrap().bank(commitment);
|
||||
let epoch_schedule = bank.epoch_schedule();
|
||||
let (epoch, slot_index) = epoch_schedule.get_epoch_and_slot_index(bank.slot());
|
||||
|
||||
let slot = bank.slot();
|
||||
let (epoch, slot_index) = epoch_schedule.get_epoch_and_slot_index(slot);
|
||||
Ok(RpcEpochInfo {
|
||||
epoch,
|
||||
slot_index,
|
||||
@ -705,17 +744,25 @@ impl RpcSol for RpcSolImpl {
|
||||
fn get_leader_schedule(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
slot: Option<Slot>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Option<Vec<String>>> {
|
||||
) -> Result<Option<RpcLeaderSchedule>> {
|
||||
let bank = meta.request_processor.read().unwrap().bank(commitment);
|
||||
let slot = slot.unwrap_or_else(|| bank.slot());
|
||||
let epoch = bank.epoch_schedule().get_epoch(slot);
|
||||
|
||||
Ok(
|
||||
solana_ledger::leader_schedule_utils::leader_schedule(bank.epoch(), &bank).map(
|
||||
solana_ledger::leader_schedule_utils::leader_schedule(epoch, &bank).map(
|
||||
|leader_schedule| {
|
||||
leader_schedule
|
||||
.get_slot_leaders()
|
||||
.iter()
|
||||
.map(|pubkey| pubkey.to_string())
|
||||
.collect()
|
||||
let mut map = HashMap::new();
|
||||
|
||||
for (slot_index, pubkey) in
|
||||
leader_schedule.get_slot_leaders().iter().enumerate()
|
||||
{
|
||||
let pubkey = pubkey.to_string();
|
||||
map.entry(pubkey).or_insert_with(|| vec![]).push(slot_index);
|
||||
}
|
||||
map
|
||||
},
|
||||
),
|
||||
)
|
||||
@ -991,6 +1038,18 @@ impl RpcSol for RpcSolImpl {
|
||||
.get_confirmed_block(slot)
|
||||
}
|
||||
|
||||
fn get_confirmed_blocks(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
start_slot: Slot,
|
||||
end_slot: Option<Slot>,
|
||||
) -> Result<Vec<Slot>> {
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_confirmed_blocks(start_slot, end_slot)
|
||||
}
|
||||
|
||||
fn get_block_time(&self, meta: Self::Metadata, slot: Slot) -> Result<Option<UnixTimestamp>> {
|
||||
meta.request_processor.read().unwrap().get_block_time(slot)
|
||||
}
|
||||
@ -1005,7 +1064,10 @@ pub mod tests {
|
||||
replay_stage::tests::create_test_transactions_and_populate_blocktree,
|
||||
};
|
||||
use jsonrpc_core::{MetaIoHandler, Output, Response, Value};
|
||||
use solana_ledger::get_tmp_ledger_path;
|
||||
use solana_ledger::{
|
||||
blocktree::entries_to_test_shreds, blocktree_processor::fill_blocktree_slot_with_ticks,
|
||||
entry::next_entry_mut, get_tmp_ledger_path,
|
||||
};
|
||||
use solana_sdk::{
|
||||
fee_calculator::DEFAULT_BURN_PERCENT,
|
||||
hash::{hash, Hash},
|
||||
@ -1014,7 +1076,10 @@ pub mod tests {
|
||||
system_transaction,
|
||||
transaction::TransactionError,
|
||||
};
|
||||
use solana_vote_program::{vote_instruction, vote_state::VoteInit};
|
||||
use solana_vote_program::{
|
||||
vote_instruction,
|
||||
vote_state::{Vote, VoteInit, MAX_LOCKOUT_HISTORY},
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
@ -1022,20 +1087,30 @@ pub mod tests {
|
||||
};
|
||||
|
||||
const TEST_MINT_LAMPORTS: u64 = 1_000_000;
|
||||
const TEST_SLOTS_PER_EPOCH: u64 = 50;
|
||||
|
||||
struct RpcHandler {
|
||||
io: MetaIoHandler<Meta>,
|
||||
meta: Meta,
|
||||
bank: Arc<Bank>,
|
||||
bank_forks: Arc<RwLock<BankForks>>,
|
||||
blockhash: Hash,
|
||||
alice: Keypair,
|
||||
leader_pubkey: Pubkey,
|
||||
leader_vote_keypair: Keypair,
|
||||
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
||||
confirmed_block_signatures: Vec<Signature>,
|
||||
}
|
||||
|
||||
fn start_rpc_handler_with_tx(pubkey: &Pubkey) -> RpcHandler {
|
||||
let (bank_forks, alice) = new_bank_forks();
|
||||
start_rpc_handler_with_tx_and_blocktree(pubkey, vec![])
|
||||
}
|
||||
|
||||
fn start_rpc_handler_with_tx_and_blocktree(
|
||||
pubkey: &Pubkey,
|
||||
blocktree_roots: Vec<Slot>,
|
||||
) -> RpcHandler {
|
||||
let (bank_forks, alice, leader_vote_keypair) = new_bank_forks();
|
||||
let bank = bank_forks.read().unwrap().working_bank();
|
||||
|
||||
let commitment_slot0 = BlockCommitment::new([8; MAX_LOCKOUT_HISTORY]);
|
||||
@ -1064,6 +1139,55 @@ pub mod tests {
|
||||
blocktree.clone(),
|
||||
);
|
||||
|
||||
// Add timestamp vote to blocktree
|
||||
let vote = Vote {
|
||||
slots: vec![1],
|
||||
hash: Hash::default(),
|
||||
};
|
||||
let vote_ix = vote_instruction::vote(
|
||||
&leader_vote_keypair.pubkey(),
|
||||
&leader_vote_keypair.pubkey(),
|
||||
vote,
|
||||
);
|
||||
let vote_tx = Transaction::new_signed_instructions(
|
||||
&[&leader_vote_keypair],
|
||||
vec![vote_ix],
|
||||
Hash::default(),
|
||||
);
|
||||
let shreds = entries_to_test_shreds(
|
||||
vec![next_entry_mut(&mut Hash::default(), 0, vec![vote_tx])],
|
||||
1,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
);
|
||||
blocktree.insert_shreds(shreds, None, false).unwrap();
|
||||
blocktree.set_roots(&[1]).unwrap();
|
||||
|
||||
let mut roots = blocktree_roots.clone();
|
||||
if !roots.is_empty() {
|
||||
roots.retain(|&x| x > 1);
|
||||
let mut parent_bank = bank;
|
||||
for (i, root) in roots.iter().enumerate() {
|
||||
let new_bank =
|
||||
Bank::new_from_parent(&parent_bank, parent_bank.collector_id(), *root);
|
||||
parent_bank = bank_forks.write().unwrap().insert(new_bank);
|
||||
parent_bank.squash();
|
||||
bank_forks.write().unwrap().set_root(*root, &None);
|
||||
let parent = if i > 0 { roots[i - 1] } else { 1 };
|
||||
fill_blocktree_slot_with_ticks(&blocktree, 5, *root, parent, Hash::default());
|
||||
}
|
||||
blocktree.set_roots(&roots).unwrap();
|
||||
let new_bank = Bank::new_from_parent(
|
||||
&parent_bank,
|
||||
parent_bank.collector_id(),
|
||||
roots.iter().max().unwrap() + 1,
|
||||
);
|
||||
bank_forks.write().unwrap().insert(new_bank);
|
||||
}
|
||||
|
||||
let bank = bank_forks.read().unwrap().working_bank();
|
||||
|
||||
let leader_pubkey = *bank.collector_id();
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let validator_exit = create_validator_exit(&exit);
|
||||
@ -1077,7 +1201,7 @@ pub mod tests {
|
||||
|
||||
let request_processor = Arc::new(RwLock::new(JsonRpcRequestProcessor::new(
|
||||
JsonRpcConfig::default(),
|
||||
bank_forks,
|
||||
bank_forks.clone(),
|
||||
block_commitment_cache.clone(),
|
||||
blocktree,
|
||||
StorageState::default(),
|
||||
@ -1107,9 +1231,11 @@ pub mod tests {
|
||||
io,
|
||||
meta,
|
||||
bank,
|
||||
bank_forks,
|
||||
blockhash,
|
||||
alice,
|
||||
leader_pubkey,
|
||||
leader_vote_keypair,
|
||||
block_commitment_cache,
|
||||
confirmed_block_signatures,
|
||||
}
|
||||
@ -1120,7 +1246,7 @@ pub mod tests {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let validator_exit = create_validator_exit(&exit);
|
||||
let (bank_forks, alice) = new_bank_forks();
|
||||
let (bank_forks, alice, _) = new_bank_forks();
|
||||
let bank = bank_forks.read().unwrap().working_bank();
|
||||
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
@ -1326,6 +1452,62 @@ pub mod tests {
|
||||
assert_eq!(epoch_schedule, *bank.epoch_schedule());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_leader_schedule() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
for req in [
|
||||
r#"{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule", "params": [0]}"#,
|
||||
r#"{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule"}"#,
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
let rep = io.handle_request_sync(&req, meta.clone());
|
||||
let res: Response = serde_json::from_str(&rep.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
|
||||
let schedule: Option<RpcLeaderSchedule> = if let Response::Single(res) = res {
|
||||
if let Output::Success(res) = res {
|
||||
serde_json::from_value(res.result).unwrap()
|
||||
} else {
|
||||
panic!("Expected success for {}", req);
|
||||
}
|
||||
} else {
|
||||
panic!("Expected single response");
|
||||
};
|
||||
let schedule = schedule.expect("leader schedule");
|
||||
|
||||
let bob_schedule = schedule
|
||||
.get(&bank.collector_id().to_string())
|
||||
.expect("leader not in the leader schedule");
|
||||
|
||||
assert_eq!(
|
||||
bob_schedule.len(),
|
||||
solana_ledger::leader_schedule_utils::leader_schedule(bank.epoch(), &bank)
|
||||
.unwrap()
|
||||
.get_slot_leaders()
|
||||
.len()
|
||||
);
|
||||
}
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule", "params": [42424242]}"#;
|
||||
let rep = io.handle_request_sync(&req, meta);
|
||||
let res: Response = serde_json::from_str(&rep.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
|
||||
let schedule: Option<RpcLeaderSchedule> = if let Response::Single(res) = res {
|
||||
if let Output::Success(res) = res {
|
||||
serde_json::from_value(res.result).unwrap()
|
||||
} else {
|
||||
panic!("Expected success");
|
||||
}
|
||||
} else {
|
||||
panic!("Expected single response");
|
||||
};
|
||||
assert_eq!(schedule, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_account_info() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
@ -1630,20 +1812,23 @@ pub mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
fn new_bank_forks() -> (Arc<RwLock<BankForks>>, Keypair) {
|
||||
fn new_bank_forks() -> (Arc<RwLock<BankForks>>, Keypair, Keypair) {
|
||||
let GenesisConfigInfo {
|
||||
mut genesis_config,
|
||||
mint_keypair,
|
||||
..
|
||||
voting_keypair,
|
||||
} = create_genesis_config(TEST_MINT_LAMPORTS);
|
||||
|
||||
genesis_config.rent.lamports_per_byte_year = 50;
|
||||
genesis_config.rent.exemption_threshold = 2.0;
|
||||
genesis_config.epoch_schedule =
|
||||
EpochSchedule::custom(TEST_SLOTS_PER_EPOCH, TEST_SLOTS_PER_EPOCH, false);
|
||||
|
||||
let bank = Bank::new(&genesis_config);
|
||||
(
|
||||
Arc::new(RwLock::new(BankForks::new(bank.slot(), bank))),
|
||||
mint_keypair,
|
||||
voting_keypair,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1847,6 +2032,54 @@ pub mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_confirmed_blocks() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let roots = vec![0, 1, 3, 4, 8];
|
||||
let RpcHandler { io, meta, .. } =
|
||||
start_rpc_handler_with_tx_and_blocktree(&bob_pubkey, roots.clone());
|
||||
|
||||
let req =
|
||||
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0]}}"#);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
let confirmed_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
|
||||
assert_eq!(confirmed_blocks, roots);
|
||||
|
||||
let req =
|
||||
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[2]}}"#);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
let confirmed_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
|
||||
assert_eq!(confirmed_blocks, vec![3, 4, 8]);
|
||||
|
||||
let req =
|
||||
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0, 4]}}"#);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
let confirmed_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
|
||||
assert_eq!(confirmed_blocks, vec![0, 1, 3, 4]);
|
||||
|
||||
let req =
|
||||
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0, 7]}}"#);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
let confirmed_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
|
||||
assert_eq!(confirmed_blocks, vec![0, 1, 3, 4]);
|
||||
|
||||
let req =
|
||||
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[9, 11]}}"#);
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
let confirmed_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
|
||||
assert_eq!(confirmed_blocks, Vec::<Slot>::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_block_time() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
@ -1905,30 +2138,31 @@ pub mod tests {
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
bank,
|
||||
mut bank,
|
||||
bank_forks,
|
||||
alice,
|
||||
leader_vote_keypair,
|
||||
..
|
||||
} = start_rpc_handler_with_tx(&Pubkey::new_rand());
|
||||
|
||||
assert_eq!(bank.vote_accounts().len(), 1);
|
||||
|
||||
// Create a second vote account that has no stake. It should not be included in the
|
||||
// getVoteAccounts response
|
||||
let vote_keypair = Keypair::new();
|
||||
// Create a vote account with no stake.
|
||||
let alice_vote_keypair = Keypair::new();
|
||||
let instructions = vote_instruction::create_account(
|
||||
&alice.pubkey(),
|
||||
&vote_keypair.pubkey(),
|
||||
&alice_vote_keypair.pubkey(),
|
||||
&VoteInit {
|
||||
node_pubkey: alice.pubkey(),
|
||||
authorized_voter: vote_keypair.pubkey(),
|
||||
authorized_withdrawer: vote_keypair.pubkey(),
|
||||
authorized_voter: alice_vote_keypair.pubkey(),
|
||||
authorized_withdrawer: alice_vote_keypair.pubkey(),
|
||||
commission: 0,
|
||||
},
|
||||
bank.get_minimum_balance_for_rent_exemption(VoteState::size_of()),
|
||||
);
|
||||
|
||||
let transaction = Transaction::new_signed_instructions(
|
||||
&[&alice, &vote_keypair],
|
||||
&[&alice, &alice_vote_keypair],
|
||||
instructions,
|
||||
bank.last_blockhash(),
|
||||
);
|
||||
@ -1936,7 +2170,70 @@ pub mod tests {
|
||||
.expect("process transaction");
|
||||
assert_eq!(bank.vote_accounts().len(), 2);
|
||||
|
||||
let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts"}}"#);
|
||||
// Check getVoteAccounts: the bootstrap leader vote account will be delinquent as it has
|
||||
// stake but has never voted, and the vote account with no stake should not be present.
|
||||
{
|
||||
let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts"}}"#);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
|
||||
let vote_account_status: RpcVoteAccountStatus =
|
||||
serde_json::from_value(result["result"].clone()).unwrap();
|
||||
|
||||
assert!(vote_account_status.current.is_empty());
|
||||
assert_eq!(vote_account_status.delinquent.len(), 1);
|
||||
for vote_account_info in vote_account_status.delinquent {
|
||||
assert_ne!(vote_account_info.activated_stake, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Advance bank to the next epoch
|
||||
for _ in 0..TEST_SLOTS_PER_EPOCH {
|
||||
bank.freeze();
|
||||
|
||||
// Votes
|
||||
let instructions = vec![
|
||||
vote_instruction::vote(
|
||||
&leader_vote_keypair.pubkey(),
|
||||
&leader_vote_keypair.pubkey(),
|
||||
Vote {
|
||||
slots: vec![bank.slot()],
|
||||
hash: bank.hash(),
|
||||
},
|
||||
),
|
||||
vote_instruction::vote(
|
||||
&alice_vote_keypair.pubkey(),
|
||||
&alice_vote_keypair.pubkey(),
|
||||
Vote {
|
||||
slots: vec![bank.slot()],
|
||||
hash: bank.hash(),
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
bank = bank_forks.write().unwrap().insert(Bank::new_from_parent(
|
||||
&bank,
|
||||
&Pubkey::default(),
|
||||
bank.slot() + 1,
|
||||
));
|
||||
|
||||
let transaction = Transaction::new_signed_with_payer(
|
||||
instructions,
|
||||
Some(&alice.pubkey()),
|
||||
&[&alice, &leader_vote_keypair, &alice_vote_keypair],
|
||||
bank.last_blockhash(),
|
||||
);
|
||||
|
||||
bank.process_transaction(&transaction)
|
||||
.expect("process transaction");
|
||||
}
|
||||
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts","params":{}}}"#,
|
||||
json!([CommitmentConfig::recent()])
|
||||
);
|
||||
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
@ -1944,12 +2241,53 @@ pub mod tests {
|
||||
let vote_account_status: RpcVoteAccountStatus =
|
||||
serde_json::from_value(result["result"].clone()).unwrap();
|
||||
|
||||
// The bootstrap leader vote account will be delinquent as it has stake but has never
|
||||
// voted. The vote account with no stake should not be present.
|
||||
assert!(vote_account_status.current.is_empty());
|
||||
assert_eq!(vote_account_status.delinquent.len(), 1);
|
||||
for vote_account_info in vote_account_status.delinquent {
|
||||
assert_ne!(vote_account_info.activated_stake, 0);
|
||||
// The vote account with no stake should not be present.
|
||||
assert!(vote_account_status.delinquent.is_empty());
|
||||
|
||||
// Both accounts should be active and have voting history.
|
||||
assert_eq!(vote_account_status.current.len(), 2);
|
||||
//let leader_info = &vote_account_status.current[0];
|
||||
let leader_info = vote_account_status
|
||||
.current
|
||||
.iter()
|
||||
.find(|x| x.vote_pubkey == leader_vote_keypair.pubkey().to_string())
|
||||
.unwrap();
|
||||
assert_ne!(leader_info.activated_stake, 0);
|
||||
// Subtract one because the last vote always carries over to the next epoch
|
||||
let expected_credits = TEST_SLOTS_PER_EPOCH - MAX_LOCKOUT_HISTORY as u64 - 1;
|
||||
assert_eq!(leader_info.epoch_credits, vec![(0, expected_credits, 0)]);
|
||||
|
||||
// Advance bank with no voting
|
||||
bank.freeze();
|
||||
bank_forks.write().unwrap().insert(Bank::new_from_parent(
|
||||
&bank,
|
||||
&Pubkey::default(),
|
||||
bank.slot() + TEST_SLOTS_PER_EPOCH,
|
||||
));
|
||||
|
||||
// The leader vote account should now be delinquent, and the other vote account disappears
|
||||
// because it's inactive with no stake
|
||||
{
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts","params":{}}}"#,
|
||||
json!([CommitmentConfig::recent()])
|
||||
);
|
||||
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
|
||||
let vote_account_status: RpcVoteAccountStatus =
|
||||
serde_json::from_value(result["result"].clone()).unwrap();
|
||||
|
||||
assert!(vote_account_status.current.is_empty());
|
||||
assert_eq!(vote_account_status.delinquent.len(), 1);
|
||||
for vote_account_info in vote_account_status.delinquent {
|
||||
assert_eq!(
|
||||
vote_account_info.vote_pubkey,
|
||||
leader_vote_keypair.pubkey().to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-crate-features"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Crate Features"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-drone"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Drone"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -19,10 +19,10 @@ clap = "2.33"
|
||||
log = "0.4.8"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
tokio = "0.1"
|
||||
tokio-codec = "0.1"
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-fixed-buf"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "A fixed-size byte array that supports bincode serde"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-genesis-programs"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana genesis programs"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -10,16 +10,16 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = { version = "0.4.8" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "0.21.3" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.3" }
|
||||
solana-config-program = { path = "../programs/config", version = "0.21.3" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.3" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.3" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.3" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "0.21.5" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.5" }
|
||||
solana-config-program = { path = "../programs/config", version = "0.21.5" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.5" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.5" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-genesis"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -16,11 +16,11 @@ serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "0.21.3" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.3" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "0.21.5" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.5" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.5" }
|
||||
tempfile = "3.1.0"
|
||||
|
@ -3,19 +3,19 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-gossip"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-core = { path = "../core", version = "0.21.3" }
|
||||
solana-client = { path = "../client", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-core = { path = "../core", version = "0.21.5" }
|
||||
solana-client = { path = "../client", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-install"
|
||||
description = "The solana cluster software installer"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -26,11 +26,11 @@ reqwest = { version = "0.9.22", default-features = false, features = ["rustls-tl
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-client = { path = "../client", version = "0.21.3" }
|
||||
solana-config-program = { path = "../programs/config", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-client = { path = "../client", version = "0.21.5" }
|
||||
solana-config-program = { path = "../programs/config", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
tar = "0.4.26"
|
||||
tempdir = "0.3.7"
|
||||
url = "2.1.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-keygen"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana key generation utility"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -14,8 +14,8 @@ clap = "2.33"
|
||||
dirs = "2.0.2"
|
||||
num_cpus = "1.11.1"
|
||||
rpassword = "4.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
tiny-bip39 = "0.6.2"
|
||||
|
||||
[[bin]]
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-ledger-tool"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -15,12 +15,12 @@ serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "0.11"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-ledger"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana ledger"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -29,19 +29,19 @@ rayon = "1.2.0"
|
||||
reed-solomon-erasure = { package = "solana-reed-solomon-erasure", version = "4.0.1-3", features = ["simd-accel"] }
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-client = { path = "../client", version = "0.21.3" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-measure = { path = "../measure", version = "0.21.3" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-perf = { path = "../perf", version = "0.21.3" }
|
||||
solana-client = { path = "../client", version = "0.21.5" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-measure = { path = "../measure", version = "0.21.5" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
solana-perf = { path = "../perf", version = "0.21.5" }
|
||||
ed25519-dalek = "1.0.0-pre.1"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.3" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.5" }
|
||||
sys-info = "0.5.8"
|
||||
tar = "0.4.26"
|
||||
tempfile = "3.1.0"
|
||||
@ -56,7 +56,7 @@ features = ["lz4"]
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.3.0"
|
||||
matches = "0.1.6"
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.3" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@ -716,8 +716,15 @@ fn get_cf_options() -> Options {
|
||||
// 256 * 8 = 2GB. 6 of these columns should take at most 12GB of RAM
|
||||
options.set_max_write_buffer_number(8);
|
||||
options.set_write_buffer_size(MAX_WRITE_BUFFER_SIZE as usize);
|
||||
options.set_target_file_size_base(MAX_WRITE_BUFFER_SIZE / 10);
|
||||
options.set_max_bytes_for_level_base(MAX_WRITE_BUFFER_SIZE);
|
||||
let file_num_compaction_trigger = 4;
|
||||
// Recommend that this be around the size of level 0. Level 0 estimated size in stable state is
|
||||
// write_buffer_size * min_write_buffer_number_to_merge * level0_file_num_compaction_trigger
|
||||
// Source: https://docs.rs/rocksdb/0.6.0/rocksdb/struct.Options.html#method.set_level_zero_file_num_compaction_trigger
|
||||
let total_size_base = MAX_WRITE_BUFFER_SIZE * file_num_compaction_trigger;
|
||||
let file_size_base = total_size_base / 10;
|
||||
options.set_level_zero_file_num_compaction_trigger(file_num_compaction_trigger as i32);
|
||||
options.set_max_bytes_for_level_base(total_size_base);
|
||||
options.set_target_file_size_base(file_size_base);
|
||||
options
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-local-cluster"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -12,23 +12,23 @@ homepage = "https://solana.com/"
|
||||
itertools = "0.8.1"
|
||||
log = "0.4.8"
|
||||
rand = "0.6.5"
|
||||
solana-config-program = { path = "../programs/config", version = "0.21.3" }
|
||||
solana-core = { path = "../core", version = "0.21.3" }
|
||||
solana-client = { path = "../client", version = "0.21.3" }
|
||||
solana-drone = { path = "../drone", version = "0.21.3" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "0.21.3" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "0.21.3" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.3" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.3" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.3" }
|
||||
solana-config-program = { path = "../programs/config", version = "0.21.5" }
|
||||
solana-core = { path = "../core", version = "0.21.5" }
|
||||
solana-client = { path = "../client", version = "0.21.5" }
|
||||
solana-drone = { path = "../drone", version = "0.21.5" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "0.21.5" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "0.21.5" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.5" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.5" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.5" }
|
||||
symlink = "0.1.0"
|
||||
tempfile = "3.1.0"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.3" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.2.0"
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-log-analyzer"
|
||||
description = "The solana cluster network analysis tool"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -17,8 +17,8 @@ semver = "0.9.0"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
|
||||
[[bin]]
|
||||
name = "solana-log-analyzer"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-logger"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Logger"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-measure"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "../README.md"
|
||||
@ -11,4 +11,4 @@ license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-merkle-tree"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Merkle Tree"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -9,7 +9,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.4.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-metrics"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Metrics"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -13,7 +13,7 @@ env_logger = "0.7.1"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.8"
|
||||
reqwest = { version = "0.9.22", default-features = false, features = ["rustls-tls"] }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
sys-info = "0.5.8"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-net-shaper"
|
||||
description = "The solana cluster network shaping tool"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -16,8 +16,8 @@ semver = "0.9.0"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
rand = "0.6.5"
|
||||
|
||||
[[bin]]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-net-utils"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Network Utilities"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -18,8 +18,8 @@ rand = "0.6.1"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
socket2 = "0.3.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
tokio = "0.1"
|
||||
tokio-codec = "0.1"
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-perf"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Performance APIs"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -18,11 +18,11 @@ serde_derive = "1.0.102"
|
||||
dlopen_derive = "0.1.4"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.8"
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.3" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.5" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
name = "solana_perf"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-bpf-programs"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "README.md"
|
||||
@ -22,10 +22,10 @@ walkdir = "2"
|
||||
bincode = "1.1.4"
|
||||
byteorder = "1.3.2"
|
||||
elf = "0.0.10"
|
||||
solana-bpf-loader-program = { path = "../bpf_loader", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-bpf-loader-program = { path = "../bpf_loader", version = "0.21.5" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
solana_rbpf = "=0.1.19"
|
||||
|
||||
[[bench]]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-128bit"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,11 +12,11 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "0.21.5" }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-128bit-dep"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-alloc"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-dep-crate"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -13,10 +13,10 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
byteorder = { version = "1", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-external-spend"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-iter"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-many-args"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,11 +12,11 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "0.21.5" }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-many-args-dep"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-noop"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-panic"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-param-passing"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,11 +12,11 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "0.21.5" }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-param-passing-dep"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-sysval"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.3", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.21.5", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.3" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.21.5" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-loader-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF loader"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -14,8 +14,8 @@ byteorder = "1.3.2"
|
||||
libc = "0.2.65"
|
||||
log = "0.4.8"
|
||||
serde = "1.0.102"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
solana_rbpf = "=0.1.19"
|
||||
|
||||
[lib]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-btc-spv-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Bitcoin spv parsing program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -16,7 +16,7 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3"}
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5"}
|
||||
hex = "0.3.2"
|
||||
|
||||
[lib]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "btc_spv_bin"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Bitcoin spv parsing program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-budget-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Budget program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -16,10 +16,10 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-config-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Config program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -14,8 +14,8 @@ chrono = { version = "0.4.10", features = ["serde"] }
|
||||
log = "0.4.8"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-config-tests"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana config api tests"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -13,11 +13,11 @@ bincode = "1.2.0"
|
||||
log = "0.4.8"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-config-program = { path = "../config", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
solana-config-program = { path = "../config", version = "0.21.5" }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
assert_matches = "1.3.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-exchange-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Exchange program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -13,12 +13,12 @@ bincode = "1.2.0"
|
||||
log = "0.4.8"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-metrics = { path = "../../metrics", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-metrics = { path = "../../metrics", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-failure-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana failure program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -10,10 +10,10 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-librapay-api"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Libra Payment"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -11,10 +11,10 @@ edition = "2018"
|
||||
[dependencies]
|
||||
bincode = "1.2.0"
|
||||
log = "0.4.8"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-move-loader-program = { path = "../move_loader", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-move-loader-program = { path = "../move_loader", version = "0.21.5" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
language_e2e_tests = { version = "0.0.1-sol4", package = "solana_libra_language_e2e_tests" }
|
||||
types = { version = "0.0.1-sol4", package = "solana_libra_types" }
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-move-loader-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Move loader"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -18,8 +18,8 @@ serde = "1.0.102"
|
||||
serde_bytes = "0.11"
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
|
||||
bytecode_verifier = { version = "0.0.1-sol4", package = "solana_libra_bytecode_verifier" }
|
||||
canonical_serialization = { version = "0.0.1-sol4", package = "solana_libra_canonical_serialization" }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-noop-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Noop program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -10,8 +10,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-ownable-api"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "ownable program API"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,12 +12,12 @@ edition = "2018"
|
||||
bincode = "1.2.0"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-stake-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Stake program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -16,11 +16,11 @@ num-traits = "0.2"
|
||||
rand = "0.6.5"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-metrics = { path = "../../metrics", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../vote", version = "0.21.3" }
|
||||
solana-config-program = { path = "../config", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-metrics = { path = "../../metrics", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../vote", version = "0.21.5" }
|
||||
solana-config-program = { path = "../config", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-stake-tests"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana stake tests"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -10,11 +10,11 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-stake-program = { path = "../stake", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../vote", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
solana-stake-program = { path = "../stake", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../vote", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
assert_matches = "1.3.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-storage-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Storage program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -16,8 +16,8 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-storage-tests"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana storage tests"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -10,11 +10,11 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-storage-program = { path = "../storage", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
solana-storage-program = { path = "../storage", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
assert_matches = "1.3.0"
|
||||
bincode = "1.2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-vest-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Vest program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -16,11 +16,11 @@ num-derive = "0.2"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-config-program = { path = "../config", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
solana-config-program = { path = "../config", version = "0.21.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.3" }
|
||||
solana-runtime = { path = "../../runtime", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-vote-program"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana Vote program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -15,9 +15,9 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
solana-logger = { path = "../../logger", version = "0.21.3" }
|
||||
solana-metrics = { path = "../../metrics", version = "0.21.3" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.3" }
|
||||
solana-logger = { path = "../../logger", version = "0.21.5" }
|
||||
solana-metrics = { path = "../../metrics", version = "0.21.5" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@ -63,7 +63,7 @@ pub enum VoteInstruction {
|
||||
/// Withdraw some amount of funds
|
||||
Withdraw(u64),
|
||||
|
||||
/// Update the vote account's node id
|
||||
/// Update the vote account's validator identity (node id)
|
||||
UpdateNode(Pubkey),
|
||||
}
|
||||
|
||||
@ -108,11 +108,12 @@ pub fn authorize(
|
||||
}
|
||||
|
||||
pub fn update_node(
|
||||
vote_pubkey: &Pubkey, // vote account
|
||||
authorized_pubkey: &Pubkey, // currently authorized
|
||||
vote_pubkey: &Pubkey,
|
||||
authorized_voter_pubkey: &Pubkey,
|
||||
node_pubkey: &Pubkey,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_pubkey, false)].with_signer(authorized_pubkey);
|
||||
let account_metas =
|
||||
vec![AccountMeta::new(*vote_pubkey, false)].with_signer(authorized_voter_pubkey);
|
||||
|
||||
Instruction::new(
|
||||
id(),
|
||||
|
@ -315,8 +315,8 @@ impl VoteState {
|
||||
/// Each tuple of (Epoch, u64, u64) is read as (epoch, credits, prev_credits), where
|
||||
/// credits for each epoch is credits - prev_credits; while redundant this makes
|
||||
/// calculating rewards over partial epochs nice and simple
|
||||
pub fn epoch_credits(&self) -> impl Iterator<Item = &(Epoch, u64, u64)> {
|
||||
self.epoch_credits.iter()
|
||||
pub fn epoch_credits(&self) -> &Vec<(Epoch, u64, u64)> {
|
||||
&self.epoch_credits
|
||||
}
|
||||
|
||||
fn pop_expired_votes(&mut self, slot: Slot) {
|
||||
@ -1194,13 +1194,7 @@ mod tests {
|
||||
let mut vote_state = VoteState::default();
|
||||
|
||||
assert_eq!(vote_state.credits(), 0);
|
||||
assert_eq!(
|
||||
vote_state
|
||||
.epoch_credits()
|
||||
.cloned()
|
||||
.collect::<Vec<(Epoch, u64, u64)>>(),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(vote_state.epoch_credits().clone(), vec![]);
|
||||
|
||||
let mut expected = vec![];
|
||||
let mut credits = 0;
|
||||
@ -1218,45 +1212,18 @@ mod tests {
|
||||
}
|
||||
|
||||
assert_eq!(vote_state.credits(), credits);
|
||||
assert_eq!(
|
||||
vote_state
|
||||
.epoch_credits()
|
||||
.cloned()
|
||||
.collect::<Vec<(Epoch, u64, u64)>>(),
|
||||
expected
|
||||
);
|
||||
assert_eq!(vote_state.epoch_credits().clone(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vote_state_epoch0_no_credits() {
|
||||
let mut vote_state = VoteState::default();
|
||||
|
||||
assert_eq!(
|
||||
vote_state
|
||||
.epoch_credits()
|
||||
.cloned()
|
||||
.collect::<Vec<(Epoch, u64, u64)>>()
|
||||
.len(),
|
||||
0
|
||||
);
|
||||
assert_eq!(vote_state.epoch_credits().len(), 0);
|
||||
vote_state.increment_credits(1);
|
||||
assert_eq!(
|
||||
vote_state
|
||||
.epoch_credits()
|
||||
.cloned()
|
||||
.collect::<Vec<(Epoch, u64, u64)>>()
|
||||
.len(),
|
||||
0
|
||||
);
|
||||
assert_eq!(vote_state.epoch_credits().len(), 0);
|
||||
|
||||
vote_state.increment_credits(2);
|
||||
assert_eq!(
|
||||
vote_state
|
||||
.epoch_credits()
|
||||
.cloned()
|
||||
.collect::<Vec<(Epoch, u64, u64)>>()
|
||||
.len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(vote_state.epoch_credits().len(), 1);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-rayon-threadlimit"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "solana-rayon-threadlimit"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "../README.md"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-runtime"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana runtime"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -24,17 +24,17 @@ rayon = "1.2.0"
|
||||
serde = { version = "1.0.102", features = ["rc"] }
|
||||
serde_derive = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-measure = { path = "../measure", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.3" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-measure = { path = "../measure", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "0.21.5" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.5" }
|
||||
sys-info = "0.5.8"
|
||||
tempfile = "3.1.0"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.3" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.21.5" }
|
||||
itertools = "0.8.2"
|
||||
|
||||
[lib]
|
||||
@ -42,4 +42,4 @@ crate-type = ["lib"]
|
||||
name = "solana_runtime"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-noop-program = { path = "../programs/noop", version = "0.21.3" }
|
||||
solana-noop-program = { path = "../programs/noop", version = "0.21.5" }
|
||||
|
@ -11,7 +11,7 @@ pub struct AccountsIndex<T> {
|
||||
|
||||
pub roots: HashSet<Slot>,
|
||||
|
||||
//This value that needs to be stored to recover the index from AppendVec
|
||||
// This value that needs to be stored to recover the index from AppendVec
|
||||
pub last_root: Slot,
|
||||
}
|
||||
|
||||
|
@ -1378,7 +1378,12 @@ impl Bank {
|
||||
|
||||
pub fn get_account_modified_since_parent(&self, pubkey: &Pubkey) -> Option<(Account, Slot)> {
|
||||
let just_self: HashMap<u64, usize> = vec![(self.slot(), 0)].into_iter().collect();
|
||||
self.rc.accounts.load_slow(&just_self, pubkey)
|
||||
if let Some((account, slot)) = self.rc.accounts.load_slow(&just_self, pubkey) {
|
||||
if slot == self.slot() {
|
||||
return Some((account, slot));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn transaction_count(&self) -> u64 {
|
||||
@ -3272,6 +3277,39 @@ mod tests {
|
||||
assert_eq!(bank4.get_balance(&key1.pubkey()), 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bank_get_account_modified_since_parent() {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
|
||||
let (genesis_config, mint_keypair) = create_genesis_config(500);
|
||||
let bank1 = Arc::new(Bank::new(&genesis_config));
|
||||
bank1.transfer(1, &mint_keypair, &pubkey).unwrap();
|
||||
let result = bank1.get_account_modified_since_parent(&pubkey);
|
||||
assert!(result.is_some());
|
||||
let (account, slot) = result.unwrap();
|
||||
assert_eq!(account.lamports, 1);
|
||||
assert_eq!(slot, 0);
|
||||
|
||||
let bank2 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 1));
|
||||
assert!(bank2.get_account_modified_since_parent(&pubkey).is_none());
|
||||
bank2.transfer(100, &mint_keypair, &pubkey).unwrap();
|
||||
let result = bank1.get_account_modified_since_parent(&pubkey);
|
||||
assert!(result.is_some());
|
||||
let (account, slot) = result.unwrap();
|
||||
assert_eq!(account.lamports, 1);
|
||||
assert_eq!(slot, 0);
|
||||
let result = bank2.get_account_modified_since_parent(&pubkey);
|
||||
assert!(result.is_some());
|
||||
let (account, slot) = result.unwrap();
|
||||
assert_eq!(account.lamports, 101);
|
||||
assert_eq!(slot, 1);
|
||||
|
||||
bank1.squash();
|
||||
|
||||
let bank3 = Bank::new_from_parent(&bank2, &Pubkey::default(), 3);
|
||||
assert_eq!(None, bank3.get_account_modified_since_parent(&pubkey));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bank_epoch_vote_accounts() {
|
||||
let leader_pubkey = Pubkey::new_rand();
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-scripts"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
@ -83,6 +83,7 @@ BINS=(
|
||||
solana-net-shaper
|
||||
solana-archiver
|
||||
solana-validator
|
||||
solana-watchtower
|
||||
)
|
||||
|
||||
#XXX: Ensure `solana-genesis` is built LAST!
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-sdk-c"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana SDK C"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -18,7 +18,7 @@ bs58 = "0.3.0"
|
||||
libc = "0.2.65"
|
||||
rand_chacha = "0.1.1"
|
||||
rand_core = { version = ">=0.2, <0.4", default-features = false }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
ed25519-dalek = "1.0.0-pre.1"
|
||||
sha2 = "0.8.0"
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-sdk"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana SDK"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -46,8 +46,8 @@ serde_derive = "1.0.102"
|
||||
serde_json = { version = "1.0.41", optional = true }
|
||||
sha2 = "0.8.0"
|
||||
ed25519-dalek = { version = "1.0.0-pre.1", optional = true }
|
||||
solana-crate-features = { path = "../crate-features", version = "0.21.3", optional = true }
|
||||
solana-logger = { path = "../logger", version = "0.21.3", optional = true }
|
||||
solana-crate-features = { path = "../crate-features", version = "0.21.5", optional = true }
|
||||
solana-logger = { path = "../logger", version = "0.21.5", optional = true }
|
||||
solana-sdk-macro = { path = "macro" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-sdk-bpf-test"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana BPF SDK test utilities"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@ -5,8 +5,15 @@ cd "$(dirname "$0")"/../..
|
||||
eval "$(ci/channel-info.sh)"
|
||||
source ci/rust-version.sh
|
||||
|
||||
if [[ -z $CHANNEL ]]; then
|
||||
echo Unable to determine channel to publish into, exiting.
|
||||
CHANNEL_OR_TAG=
|
||||
if [[ -n "$CI_TAG" ]]; then
|
||||
CHANNEL_OR_TAG=$CI_TAG
|
||||
else
|
||||
CHANNEL_OR_TAG=$CHANNEL
|
||||
fi
|
||||
|
||||
if [[ -z $CHANNEL_OR_TAG ]]; then
|
||||
echo Unable to determine channel or tag to publish into, exiting.
|
||||
echo "^^^ +++"
|
||||
exit 0
|
||||
fi
|
||||
@ -18,7 +25,7 @@ rm -rf usr/
|
||||
|
||||
cp -f ../../run.sh usr/bin/solana-run.sh
|
||||
|
||||
docker build -t solanalabs/solana:"$CHANNEL" .
|
||||
docker build -t solanalabs/solana:"$CHANNEL_OR_TAG" .
|
||||
|
||||
maybeEcho=
|
||||
if [[ -z $CI ]]; then
|
||||
@ -32,4 +39,4 @@ else
|
||||
fi
|
||||
)
|
||||
fi
|
||||
$maybeEcho docker push solanalabs/solana:"$CHANNEL"
|
||||
$maybeEcho docker push solanalabs/solana:"$CHANNEL_OR_TAG"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-sdk-macro"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Solana SDK Macro"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@ -19,6 +19,12 @@ impl CommitmentConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max() -> Self {
|
||||
Self {
|
||||
commitment: CommitmentLevel::Max,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ok(&self) -> Option<Self> {
|
||||
if self == &Self::default() {
|
||||
None
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-upload-perf"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
description = "Metrics Upload Utility"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@ -12,7 +12,7 @@ publish = false
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
serde_json = "1.0.41"
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
|
||||
[[bin]]
|
||||
name = "solana-upload-perf"
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-validator"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -17,19 +17,19 @@ log = "0.4.8"
|
||||
indicatif = "0.13.0"
|
||||
reqwest = { version = "0.9.22", default-features = false }
|
||||
serde_json = "1.0.41"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-client = { path = "../client", version = "0.21.3" }
|
||||
solana-core = { path = "../core", version = "0.21.3" }
|
||||
solana-drone = { path = "../drone", version = "0.21.3" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.3" }
|
||||
solana-logger = { path = "../logger", version = "0.21.3" }
|
||||
solana-perf = { path = "../perf", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.3" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.3" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-client = { path = "../client", version = "0.21.5" }
|
||||
solana-core = { path = "../core", version = "0.21.5" }
|
||||
solana-drone = { path = "../drone", version = "0.21.5" }
|
||||
solana-ledger = { path = "../ledger", version = "0.21.5" }
|
||||
solana-logger = { path = "../logger", version = "0.21.5" }
|
||||
solana-perf = { path = "../perf", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
solana-net-utils = { path = "../net-utils", version = "0.21.5" }
|
||||
solana-runtime = { path = "../runtime", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.5" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "0.21.5" }
|
||||
tar = "0.4.26"
|
||||
tempfile = "3.1.0"
|
||||
|
||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-vote-signer"
|
||||
description = "Solana Vote Signing Service"
|
||||
version = "0.21.3"
|
||||
version = "0.21.5"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@ -17,9 +17,9 @@ jsonrpc-http-server = "14.0.3"
|
||||
log = "0.4.8"
|
||||
serde = "1.0.102"
|
||||
serde_json = "1.0.41"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.3" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.3" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.3" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "0.21.5" }
|
||||
solana-metrics = { path = "../metrics", version = "0.21.5" }
|
||||
solana-sdk = { path = "../sdk", version = "0.21.5" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user