Compare commits
93 Commits
banking-be
...
v1.4.2
Author | SHA1 | Date | |
---|---|---|---|
|
a4ad2925a2 | ||
|
edfbd8d65a | ||
|
e0ae54fd7e | ||
|
60297951ec | ||
|
e0f9f72a2c | ||
|
5236acf4b0 | ||
|
5dd61b5db2 | ||
|
8752bf0826 | ||
|
b1712e80ec | ||
|
2fe1a4677c | ||
|
f76c128f4f | ||
|
b143b9c3c2 | ||
|
b4178b75e7 | ||
|
c54b751df7 | ||
|
0fde9e893f | ||
|
d24abbdac9 | ||
|
3b03985f28 | ||
|
d05bfa08c7 | ||
|
9da2ac7a44 | ||
|
9e95d0fb58 | ||
|
94cad9873c | ||
|
f33171b32f | ||
|
aa6406f263 | ||
|
77864a6bee | ||
|
b51715d33c | ||
|
7d395177d4 | ||
|
77ba6d6784 | ||
|
4bf0a54ed7 | ||
|
8a526f2f53 | ||
|
43f99bdb31 | ||
|
0008dc62e4 | ||
|
7e8174fb79 | ||
|
4ad2ebcde9 | ||
|
da183d655a | ||
|
2e449276be | ||
|
8cac6835c0 | ||
|
677c184e47 | ||
|
f36cfb92f7 | ||
|
e7062de05f | ||
|
a443e2e773 | ||
|
3a6db787e2 | ||
|
f3c986385f | ||
|
3df811348f | ||
|
e8c86ed3e5 | ||
|
489a7bb576 | ||
|
688dd85e61 | ||
|
fe54a30084 | ||
|
80942841a2 | ||
|
d2808a8e29 | ||
|
f8413a28b5 | ||
|
bc96332899 | ||
|
ceeeb3c9dd | ||
|
bd058ec8f1 | ||
|
4b5ac44fc8 | ||
|
fef979f0e5 | ||
|
cca2cdf39b | ||
|
6e91996606 | ||
|
99be00d61f | ||
|
68f808026e | ||
|
0c7ab0a1bb | ||
|
3d8ccbc079 | ||
|
275d096a46 | ||
|
6d70a06b23 | ||
|
7e68b2e1bd | ||
|
f0d761630e | ||
|
1986927eb6 | ||
|
9a0ea61007 | ||
|
51a70e52f2 | ||
|
9797c93db3 | ||
|
9598114658 | ||
|
d3ef061044 | ||
|
1f102d2617 | ||
|
5e97bd3d8a | ||
|
ed06e8b85d | ||
|
10b9225edb | ||
|
b1b5ddd2b9 | ||
|
6b9b107ead | ||
|
3fef98fd1e | ||
|
e999823b4b | ||
|
1e46a5b147 | ||
|
567a1cb944 | ||
|
2996cebfaa | ||
|
7a1889aaf9 | ||
|
9188153b7d | ||
|
4b9f2e987a | ||
|
bb5c76483a | ||
|
aafbb251b9 | ||
|
dd32540ceb | ||
|
e1a9cbaf3c | ||
|
83740246fc | ||
|
7a53ca18a6 | ||
|
c1a8637cb5 | ||
|
d6831309cd |
701
Cargo.lock
generated
701
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@ members = [
|
||||
"dos",
|
||||
"download-utils",
|
||||
"faucet",
|
||||
"frozen-abi",
|
||||
"perf",
|
||||
"validator",
|
||||
"genesis",
|
||||
@@ -30,6 +31,7 @@ members = [
|
||||
"merkle-tree",
|
||||
"stake-o-matic",
|
||||
"storage-bigtable",
|
||||
"storage-proto",
|
||||
"streamer",
|
||||
"measure",
|
||||
"metrics",
|
||||
@@ -51,6 +53,7 @@ members = [
|
||||
"ramp-tps",
|
||||
"runtime",
|
||||
"sdk",
|
||||
"sdk/cargo-build-bpf",
|
||||
"scripts",
|
||||
"stake-accounts",
|
||||
"stake-monitor",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-account-decoder"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
description = "Solana account decoder"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -18,11 +18,11 @@ lazy_static = "1.4.0"
|
||||
serde = "1.0.112"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-config-program = { path = "../programs/config", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
|
||||
spl-token-v2-0 = { package = "spl-token", version = "=2.0.6", features = ["skip-no-mangle"] }
|
||||
solana-config-program = { path = "../programs/config", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.4.2" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
|
||||
spl-token-v2-0 = { package = "spl-token", version = "=2.0.8" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
|
@@ -111,8 +111,8 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_parse_account_data() {
|
||||
let account_pubkey = Pubkey::new_rand();
|
||||
let other_program = Pubkey::new_rand();
|
||||
let account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let other_program = solana_sdk::pubkey::new_rand();
|
||||
let data = vec![0; 4];
|
||||
assert!(parse_account_data(&account_pubkey, &other_program, &data, None).is_err());
|
||||
|
||||
|
@@ -117,7 +117,7 @@ mod test {
|
||||
}))
|
||||
.unwrap(),
|
||||
};
|
||||
let info_pubkey = Pubkey::new_rand();
|
||||
let info_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let validator_info_config_account = create_config_account(
|
||||
vec![(validator_info::id(), false), (info_pubkey, true)],
|
||||
&validator_info,
|
||||
|
@@ -134,7 +134,6 @@ impl From<Delegation> for UiDelegation {
|
||||
mod test {
|
||||
use super::*;
|
||||
use bincode::serialize;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
#[test]
|
||||
fn test_parse_stake() {
|
||||
@@ -145,8 +144,8 @@ mod test {
|
||||
StakeAccountType::Uninitialized
|
||||
);
|
||||
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let custodian = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let custodian = solana_sdk::pubkey::new_rand();
|
||||
let authorized = Authorized::auto(&pubkey);
|
||||
let lockup = Lockup {
|
||||
unix_timestamp: 0,
|
||||
@@ -180,7 +179,7 @@ mod test {
|
||||
})
|
||||
);
|
||||
|
||||
let voter_pubkey = Pubkey::new_rand();
|
||||
let voter_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let stake = Stake {
|
||||
delegation: Delegation {
|
||||
voter_pubkey,
|
||||
|
@@ -319,7 +319,7 @@ mod test {
|
||||
}]),
|
||||
);
|
||||
|
||||
let bad_pubkey = Pubkey::new_rand();
|
||||
let bad_pubkey = solana_sdk::pubkey::new_rand();
|
||||
assert!(parse_sysvar(&stake_history_sysvar.data, &bad_pubkey).is_err());
|
||||
|
||||
let bad_data = vec![0; 4];
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-accounts-bench"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -11,11 +11,11 @@ publish = false
|
||||
[dependencies]
|
||||
log = "0.4.6"
|
||||
rayon = "1.4.0"
|
||||
solana-logger = { path = "../logger", version = "1.4.0" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
||||
solana-measure = { path = "../measure", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-version = { path = "../version", version = "1.4.0" }
|
||||
solana-logger = { path = "../logger", version = "1.4.2" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.2" }
|
||||
solana-measure = { path = "../measure", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-version = { path = "../version", version = "1.4.2" }
|
||||
rand = "0.7.0"
|
||||
clap = "2.33.1"
|
||||
crossbeam-channel = "0.4"
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-banking-bench"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -14,16 +14,16 @@ crossbeam-channel = "0.4"
|
||||
log = "0.4.6"
|
||||
rand = "0.7.0"
|
||||
rayon = "1.4.0"
|
||||
solana-core = { path = "../core", version = "1.4.0" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
|
||||
solana-streamer = { path = "../streamer", version = "1.4.0" }
|
||||
solana-perf = { path = "../perf", version = "1.4.0" }
|
||||
solana-ledger = { path = "../ledger", version = "1.4.0" }
|
||||
solana-logger = { path = "../logger", version = "1.4.0" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
||||
solana-measure = { path = "../measure", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-version = { path = "../version", version = "1.4.0" }
|
||||
solana-core = { path = "../core", version = "1.4.2" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
|
||||
solana-streamer = { path = "../streamer", version = "1.4.2" }
|
||||
solana-perf = { path = "../perf", version = "1.4.2" }
|
||||
solana-ledger = { path = "../ledger", version = "1.4.2" }
|
||||
solana-logger = { path = "../logger", version = "1.4.2" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.2" }
|
||||
solana-measure = { path = "../measure", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-version = { path = "../version", version = "1.4.2" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -20,7 +20,6 @@ use solana_perf::packet::to_packets_chunked;
|
||||
use solana_runtime::{bank::Bank, bank_forks::BankForks};
|
||||
use solana_sdk::{
|
||||
hash::Hash,
|
||||
pubkey::Pubkey,
|
||||
signature::Keypair,
|
||||
signature::Signature,
|
||||
system_transaction,
|
||||
@@ -69,7 +68,7 @@ fn make_accounts_txs(
|
||||
hash: Hash,
|
||||
same_payer: bool,
|
||||
) -> Vec<Transaction> {
|
||||
let to_pubkey = Pubkey::new_rand();
|
||||
let to_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let payer_key = Keypair::new();
|
||||
let dummy = system_transaction::transfer(&payer_key, &to_pubkey, 1, hash);
|
||||
(0..total_num_transactions)
|
||||
@@ -78,9 +77,9 @@ fn make_accounts_txs(
|
||||
let mut new = dummy.clone();
|
||||
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
|
||||
if !same_payer {
|
||||
new.message.account_keys[0] = Pubkey::new_rand();
|
||||
new.message.account_keys[0] = solana_sdk::pubkey::new_rand();
|
||||
}
|
||||
new.message.account_keys[1] = Pubkey::new_rand();
|
||||
new.message.account_keys[1] = solana_sdk::pubkey::new_rand();
|
||||
new.signatures = vec![Signature::new(&sig[0..64])];
|
||||
new
|
||||
})
|
||||
@@ -241,7 +240,7 @@ fn main() {
|
||||
let base_tx_count = bank.transaction_count();
|
||||
let mut txs_processed = 0;
|
||||
let mut root = 1;
|
||||
let collector = Pubkey::new_rand();
|
||||
let collector = solana_sdk::pubkey::new_rand();
|
||||
let config = Config {
|
||||
packets_per_batch: packets_per_chunk,
|
||||
chunk_len,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-banks-client"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
description = "Solana banks client"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,15 +12,15 @@ edition = "2018"
|
||||
async-trait = "0.1.36"
|
||||
bincode = "1.3.1"
|
||||
futures = "0.3"
|
||||
solana-banks-interface = { path = "../banks-interface", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-banks-interface = { path = "../banks-interface", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
tarpc = { version = "0.22.0", features = ["full"] }
|
||||
tokio = "0.2"
|
||||
tokio-serde = { version = "0.6", features = ["bincode"] }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
||||
solana-banks-server = { path = "../banks-server", version = "1.4.0" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.2" }
|
||||
solana-banks-server = { path = "../banks-server", version = "1.4.2" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -213,7 +213,7 @@ mod tests {
|
||||
use super::*;
|
||||
use solana_banks_server::banks_server::start_local_server;
|
||||
use solana_runtime::{bank::Bank, bank_forks::BankForks, genesis_utils::create_genesis_config};
|
||||
use solana_sdk::{message::Message, pubkey::Pubkey, signature::Signer, system_instruction};
|
||||
use solana_sdk::{message::Message, signature::Signer, system_instruction};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use tarpc::transport;
|
||||
use tokio::{runtime::Runtime, time::delay_for};
|
||||
@@ -235,7 +235,7 @@ mod tests {
|
||||
&genesis.genesis_config,
|
||||
))));
|
||||
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let mint_pubkey = genesis.mint_keypair.pubkey();
|
||||
let instruction = system_instruction::transfer(&mint_pubkey, &bob_pubkey, 1);
|
||||
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
||||
@@ -265,7 +265,7 @@ mod tests {
|
||||
))));
|
||||
|
||||
let mint_pubkey = &genesis.mint_keypair.pubkey();
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let instruction = system_instruction::transfer(&mint_pubkey, &bob_pubkey, 1);
|
||||
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-banks-interface"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
description = "Solana banks RPC interface"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.112", features = ["derive"] }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
tarpc = { version = "0.22.0", features = ["full"] }
|
||||
|
||||
[lib]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-banks-server"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
description = "Solana banks server"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ edition = "2018"
|
||||
bincode = "1.3.1"
|
||||
futures = "0.3"
|
||||
log = "0.4.8"
|
||||
solana-banks-interface = { path = "../banks-interface", version = "1.4.0" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-metrics = { path = "../metrics", version = "1.4.0" }
|
||||
solana-banks-interface = { path = "../banks-interface", version = "1.4.2" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-metrics = { path = "../metrics", version = "1.4.2" }
|
||||
tarpc = { version = "0.22.0", features = ["full"] }
|
||||
tokio = "0.2"
|
||||
tokio-serde = { version = "0.6", features = ["bincode"] }
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-exchange"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -18,21 +18,21 @@ rand = "0.7.0"
|
||||
rayon = "1.4.0"
|
||||
serde_json = "1.0.56"
|
||||
serde_yaml = "0.8.13"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
|
||||
solana-core = { path = "../core", version = "1.4.0" }
|
||||
solana-genesis = { path = "../genesis", version = "1.4.0" }
|
||||
solana-client = { path = "../client", version = "1.4.0" }
|
||||
solana-faucet = { path = "../faucet", version = "1.4.0" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.4.0" }
|
||||
solana-logger = { path = "../logger", version = "1.4.0" }
|
||||
solana-metrics = { path = "../metrics", version = "1.4.0" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-version = { path = "../version", version = "1.4.0" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
|
||||
solana-core = { path = "../core", version = "1.4.2" }
|
||||
solana-genesis = { path = "../genesis", version = "1.4.2" }
|
||||
solana-client = { path = "../client", version = "1.4.2" }
|
||||
solana-faucet = { path = "../faucet", version = "1.4.2" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.4.2" }
|
||||
solana-logger = { path = "../logger", version = "1.4.2" }
|
||||
solana-metrics = { path = "../metrics", version = "1.4.2" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-version = { path = "../version", version = "1.4.2" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.4.0" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.4.2" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-streamer"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -10,11 +10,11 @@ publish = false
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.1"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
|
||||
solana-streamer = { path = "../streamer", version = "1.4.0" }
|
||||
solana-logger = { path = "../logger", version = "1.4.0" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
|
||||
solana-version = { path = "../version", version = "1.4.0" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
|
||||
solana-streamer = { path = "../streamer", version = "1.4.2" }
|
||||
solana-logger = { path = "../logger", version = "1.4.2" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
|
||||
solana-version = { path = "../version", version = "1.4.2" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-tps"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -15,23 +15,23 @@ log = "0.4.8"
|
||||
rayon = "1.4.0"
|
||||
serde_json = "1.0.56"
|
||||
serde_yaml = "0.8.13"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
|
||||
solana-core = { path = "../core", version = "1.4.0" }
|
||||
solana-genesis = { path = "../genesis", version = "1.4.0" }
|
||||
solana-client = { path = "../client", version = "1.4.0" }
|
||||
solana-faucet = { path = "../faucet", version = "1.4.0" }
|
||||
solana-logger = { path = "../logger", version = "1.4.0" }
|
||||
solana-metrics = { path = "../metrics", version = "1.4.0" }
|
||||
solana-measure = { path = "../measure", version = "1.4.0" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-version = { path = "../version", version = "1.4.0" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
|
||||
solana-core = { path = "../core", version = "1.4.2" }
|
||||
solana-genesis = { path = "../genesis", version = "1.4.2" }
|
||||
solana-client = { path = "../client", version = "1.4.2" }
|
||||
solana-faucet = { path = "../faucet", version = "1.4.2" }
|
||||
solana-logger = { path = "../logger", version = "1.4.2" }
|
||||
solana-metrics = { path = "../metrics", version = "1.4.2" }
|
||||
solana-measure = { path = "../measure", version = "1.4.2" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-version = { path = "../version", version = "1.4.2" }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.4.0"
|
||||
serial_test_derive = "0.4.0"
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.4.0" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.4.2" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
31
cargo
Executable file
31
cargo
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=ci/rust-version.sh
|
||||
here=$(dirname "$0")
|
||||
|
||||
source "${here}"/ci/rust-version.sh all
|
||||
|
||||
toolchain=
|
||||
case "$1" in
|
||||
stable)
|
||||
# shellcheck disable=SC2054 # rust_stable is sourced from rust-version.sh
|
||||
toolchain="$rust_stable"
|
||||
shift
|
||||
;;
|
||||
nightly)
|
||||
# shellcheck disable=SC2054 # rust_nightly is sourced from rust-version.sh
|
||||
toolchain="$rust_nightly"
|
||||
shift
|
||||
;;
|
||||
+*)
|
||||
toolchain="${1#+}"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
# shellcheck disable=SC2054 # rust_stable is sourced from rust-version.sh
|
||||
toolchain="$rust_stable"
|
||||
;;
|
||||
esac
|
||||
|
||||
set -x
|
||||
exec cargo "+${toolchain}" "${@}"
|
5
cargo-build-bpf
Executable file
5
cargo-build-bpf
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
here=$(dirname "$0")
|
||||
set -x
|
||||
exec cargo run --manifest-path $here/sdk/cargo-build-bpf/Cargo.toml -- --bpf-sdk $here/sdk/bpf "$@"
|
@@ -26,6 +26,7 @@ declare print_free_tree=(
|
||||
':runtime/src/**.rs'
|
||||
':sdk/bpf/rust/rust-utils/**.rs'
|
||||
':sdk/**.rs'
|
||||
':^sdk/cargo-build-bpf/**.rs'
|
||||
':^sdk/src/program_option.rs'
|
||||
':^sdk/src/program_stubs.rs'
|
||||
':programs/**.rs'
|
||||
|
@@ -42,10 +42,10 @@ def get_packages():
|
||||
sys.exit(1)
|
||||
|
||||
# Order dependencies
|
||||
deleted_dependencies = []
|
||||
sorted_dependency_graph = []
|
||||
max_iterations = pow(len(dependency_graph),2)
|
||||
while len(deleted_dependencies) < len(dependency_graph):
|
||||
while dependency_graph:
|
||||
deleted_packages = []
|
||||
if max_iterations == 0:
|
||||
# One day be more helpful and find the actual cycle for the user...
|
||||
sys.exit('Error: Circular dependency suspected between these packages: \n {}\n'.format('\n '.join(dependency_graph.keys())))
|
||||
@@ -53,13 +53,17 @@ def get_packages():
|
||||
max_iterations -= 1
|
||||
|
||||
for package, dependencies in dependency_graph.items():
|
||||
if package in deleted_packages:
|
||||
continue
|
||||
for dependency in dependencies:
|
||||
if dependency in dependency_graph:
|
||||
break
|
||||
else:
|
||||
deleted_dependencies.append(package)
|
||||
deleted_packages.append(package)
|
||||
sorted_dependency_graph.append((package, manifest_path[package]))
|
||||
|
||||
dependency_graph = {p: d for p, d in dependency_graph.items() if not p in deleted_packages }
|
||||
|
||||
|
||||
return sorted_dependency_graph
|
||||
|
||||
|
@@ -85,23 +85,24 @@ echo --- Creating release tarball
|
||||
source ci/rust-version.sh stable
|
||||
scripts/cargo-install-all.sh +"$rust_stable" "${RELEASE_BASENAME}"
|
||||
|
||||
mkdir -p "${RELEASE_BASENAME}"/bin/sdk/bpf
|
||||
cp -a sdk/bpf/* "${RELEASE_BASENAME}"/bin/sdk/bpf
|
||||
|
||||
tar cvf "${TARBALL_BASENAME}"-$TARGET.tar "${RELEASE_BASENAME}"
|
||||
bzip2 "${TARBALL_BASENAME}"-$TARGET.tar
|
||||
cp "${RELEASE_BASENAME}"/bin/solana-install-init solana-install-init-$TARGET
|
||||
cp "${RELEASE_BASENAME}"/version.yml "${TARBALL_BASENAME}"-$TARGET.yml
|
||||
)
|
||||
|
||||
# Metrics tarball is platform agnostic, only publish it from Linux
|
||||
# Maybe tarballs are platform agnostic, only publish them from the Linux build
|
||||
MAYBE_TARBALLS=
|
||||
if [[ "$CI_OS_NAME" = linux ]]; then
|
||||
metrics/create-metrics-tarball.sh
|
||||
(
|
||||
set -x
|
||||
sdk/bpf/scripts/package.sh
|
||||
[[ -f bpf-sdk.tar.bz2 ]]
|
||||
|
||||
)
|
||||
MAYBE_TARBALLS="bpf-sdk.tar.bz2 solana-metrics.tar.bz2"
|
||||
MAYBE_TARBALLS="bpf-sdk.tar.bz2"
|
||||
fi
|
||||
|
||||
source ci/upload-ci-artifact.sh
|
||||
|
@@ -41,7 +41,7 @@ if [[ $CI_BASE_BRANCH = "$EDGE_CHANNEL" ]]; then
|
||||
echo "$0: [tree (for outdated Cargo.lock sync)|check (for compilation error)|update -p foo --precise x.y.z (for your Cargo.toml update)] ..." >&2
|
||||
exit "$check_status"
|
||||
fi
|
||||
|
||||
|
||||
# Ensure nightly and --benches
|
||||
_ scripts/cargo-for-all-lock-files.sh +"$rust_nightly" check --locked --all-targets
|
||||
else
|
||||
@@ -57,7 +57,18 @@ _ cargo +"$rust_nightly" clippy \
|
||||
-Zunstable-options --workspace --all-targets \
|
||||
-- --deny=warnings --allow=clippy::stable_sort_primitive
|
||||
|
||||
_ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit --ignore RUSTSEC-2020-0002 --ignore RUSTSEC-2020-0008
|
||||
cargo_audit_ignores=(
|
||||
# failure is officially deprecated/unmaintained
|
||||
#
|
||||
# Blocked on multiple upstream crates removing their `failure` dependency.
|
||||
--ignore RUSTSEC-2020-0036
|
||||
|
||||
# `net2` crate has been deprecated; use `socket2` instead
|
||||
#
|
||||
# Blocked on https://github.com/paritytech/jsonrpc/issues/575
|
||||
--ignore RUSTSEC-2020-0016
|
||||
)
|
||||
_ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit "${cargo_audit_ignores[@]}"
|
||||
|
||||
{
|
||||
cd programs/bpf
|
||||
@@ -68,7 +79,9 @@ _ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit --ignore RUSTSEC-202
|
||||
cd "$project"
|
||||
_ cargo +"$rust_stable" fmt -- --check
|
||||
_ cargo +"$rust_nightly" test
|
||||
_ cargo +"$rust_nightly" clippy -- --deny=warnings --allow=clippy::missing_safety_doc
|
||||
_ cargo +"$rust_nightly" clippy -- --deny=warnings \
|
||||
--allow=clippy::missing_safety_doc \
|
||||
--allow=clippy::stable_sort_primitive
|
||||
)
|
||||
done
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-clap-utils"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
description = "Solana utilities for the clap"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -11,8 +11,8 @@ edition = "2018"
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
rpassword = "4.0"
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
thiserror = "1.0.20"
|
||||
tiny-bip39 = "0.7.0"
|
||||
url = "2.1.0"
|
||||
|
@@ -228,8 +228,8 @@ mod tests {
|
||||
assert_eq!(values_of(&matches, "multiple"), Some(vec![50, 39]));
|
||||
assert_eq!(values_of::<u64>(&matches, "single"), None);
|
||||
|
||||
let pubkey0 = Pubkey::new_rand();
|
||||
let pubkey1 = Pubkey::new_rand();
|
||||
let pubkey0 = solana_sdk::pubkey::new_rand();
|
||||
let pubkey1 = solana_sdk::pubkey::new_rand();
|
||||
let matches = app().clone().get_matches_from(vec![
|
||||
"test",
|
||||
"--multiple",
|
||||
@@ -251,7 +251,7 @@ mod tests {
|
||||
assert_eq!(value_of(&matches, "single"), Some(50));
|
||||
assert_eq!(value_of::<u64>(&matches, "multiple"), None);
|
||||
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let matches = app()
|
||||
.clone()
|
||||
.get_matches_from(vec!["test", "--single", &pubkey.to_string()]);
|
||||
@@ -331,8 +331,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_pubkeys_sigs_of() {
|
||||
let key1 = Pubkey::new_rand();
|
||||
let key2 = Pubkey::new_rand();
|
||||
let key1 = solana_sdk::pubkey::new_rand();
|
||||
let key2 = solana_sdk::pubkey::new_rand();
|
||||
let sig1 = Keypair::new().sign_message(&[0u8]);
|
||||
let sig2 = Keypair::new().sign_message(&[1u8]);
|
||||
let signer1 = format!("{}={}", key1, sig1);
|
||||
|
@@ -298,7 +298,24 @@ pub fn keypair_from_seed_phrase(
|
||||
keypair_from_seed_phrase_and_passphrase(&seed_phrase, &passphrase)?
|
||||
} else {
|
||||
let sanitized = sanitize_seed_phrase(seed_phrase);
|
||||
let mnemonic = Mnemonic::from_phrase(&sanitized, Language::English)?;
|
||||
let parse_language_fn = || {
|
||||
for language in &[
|
||||
Language::English,
|
||||
Language::ChineseSimplified,
|
||||
Language::ChineseTraditional,
|
||||
Language::Japanese,
|
||||
Language::Spanish,
|
||||
Language::Korean,
|
||||
Language::French,
|
||||
Language::Italian,
|
||||
] {
|
||||
if let Ok(mnemonic) = Mnemonic::from_phrase(&sanitized, *language) {
|
||||
return Ok(mnemonic);
|
||||
}
|
||||
}
|
||||
Err("Can't get mnemonic from seed phrases")
|
||||
};
|
||||
let mnemonic = parse_language_fn()?;
|
||||
let passphrase = prompt_passphrase(&passphrase_prompt)?;
|
||||
let seed = Seed::new(&mnemonic, &passphrase);
|
||||
keypair_from_seed(seed.as_bytes())?
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli-config"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli-output"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -17,13 +17,13 @@ indicatif = "0.15.0"
|
||||
serde = "1.0.112"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.4.0" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
|
||||
solana-client = { path = "../client", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.4.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.4.2" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
|
||||
solana-client = { path = "../client", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.4.2" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.4.2" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -132,7 +132,7 @@ impl fmt::Display for CliBlockProduction {
|
||||
"{}",
|
||||
style(format!(
|
||||
" {:<44} {:>15} {:>15} {:>15} {:>23}",
|
||||
"Identity Pubkey",
|
||||
"Identity",
|
||||
"Leader Slots",
|
||||
"Blocks Produced",
|
||||
"Skipped Slots",
|
||||
@@ -301,7 +301,7 @@ pub struct CliValidatorsStakeByVersion {
|
||||
pub struct CliValidators {
|
||||
pub total_active_stake: u64,
|
||||
pub total_current_stake: u64,
|
||||
pub total_deliquent_stake: u64,
|
||||
pub total_delinquent_stake: u64,
|
||||
pub current_validators: Vec<CliValidator>,
|
||||
pub delinquent_validators: Vec<CliValidator>,
|
||||
pub stake_by_version: BTreeMap<String, CliValidatorsStakeByVersion>,
|
||||
@@ -360,7 +360,7 @@ impl fmt::Display for CliValidators {
|
||||
"Active Stake:",
|
||||
&build_balance_message(self.total_active_stake, self.use_lamports_unit, true),
|
||||
)?;
|
||||
if self.total_deliquent_stake > 0 {
|
||||
if self.total_delinquent_stake > 0 {
|
||||
writeln_name_value(
|
||||
f,
|
||||
"Current Stake:",
|
||||
@@ -376,11 +376,11 @@ impl fmt::Display for CliValidators {
|
||||
&format!(
|
||||
"{} ({:0.2}%)",
|
||||
&build_balance_message(
|
||||
self.total_deliquent_stake,
|
||||
self.total_delinquent_stake,
|
||||
self.use_lamports_unit,
|
||||
true
|
||||
),
|
||||
100. * self.total_deliquent_stake as f64 / self.total_active_stake as f64
|
||||
100. * self.total_delinquent_stake as f64 / self.total_active_stake as f64
|
||||
),
|
||||
)?;
|
||||
}
|
||||
@@ -412,8 +412,8 @@ impl fmt::Display for CliValidators {
|
||||
"{}",
|
||||
style(format!(
|
||||
" {:<44} {:<38} {} {} {} {:>10} {:^8} {}",
|
||||
"Identity Pubkey",
|
||||
"Vote Account Pubkey",
|
||||
"Identity",
|
||||
"Vote Account",
|
||||
"Commission",
|
||||
"Last Vote",
|
||||
"Root Block",
|
||||
@@ -661,13 +661,8 @@ impl fmt::Display for CliStakeState {
|
||||
if lockup.unix_timestamp != UnixTimestamp::default() {
|
||||
writeln!(
|
||||
f,
|
||||
"Lockup Timestamp: {} (UnixTimestamp: {})",
|
||||
DateTime::<Utc>::from_utc(
|
||||
NaiveDateTime::from_timestamp(lockup.unix_timestamp, 0),
|
||||
Utc
|
||||
)
|
||||
.to_rfc3339_opts(SecondsFormat::Secs, true),
|
||||
lockup.unix_timestamp
|
||||
"Lockup Timestamp: {}",
|
||||
unix_timestamp_to_string(lockup.unix_timestamp)
|
||||
)?;
|
||||
}
|
||||
if lockup.epoch != Epoch::default() {
|
||||
@@ -952,8 +947,8 @@ impl VerboseDisplay for CliValidatorInfo {}
|
||||
|
||||
impl fmt::Display for CliValidatorInfo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln_name_value(f, "Validator Identity Pubkey:", &self.identity_pubkey)?;
|
||||
writeln_name_value(f, " Info Pubkey:", &self.info_pubkey)?;
|
||||
writeln_name_value(f, "Validator Identity:", &self.identity_pubkey)?;
|
||||
writeln_name_value(f, " Info Address:", &self.info_pubkey)?;
|
||||
for (key, value) in self.info.iter() {
|
||||
writeln_name_value(
|
||||
f,
|
||||
@@ -1008,7 +1003,12 @@ impl fmt::Display for CliVoteAccount {
|
||||
None => "~".to_string(),
|
||||
}
|
||||
)?;
|
||||
writeln!(f, "Recent Timestamp: {:?}", self.recent_timestamp)?;
|
||||
writeln!(
|
||||
f,
|
||||
"Recent Timestamp: {} from slot {}",
|
||||
unix_timestamp_to_string(self.recent_timestamp.timestamp),
|
||||
self.recent_timestamp.slot
|
||||
)?;
|
||||
if !self.votes.is_empty() {
|
||||
writeln!(f, "Recent Votes:")?;
|
||||
for vote in &self.votes {
|
||||
@@ -1093,19 +1093,22 @@ pub struct CliBlockTime {
|
||||
impl QuietDisplay for CliBlockTime {}
|
||||
impl VerboseDisplay for CliBlockTime {}
|
||||
|
||||
fn unix_timestamp_to_string(unix_timestamp: UnixTimestamp) -> String {
|
||||
format!(
|
||||
"{} (UnixTimestamp: {})",
|
||||
match NaiveDateTime::from_timestamp_opt(unix_timestamp, 0) {
|
||||
Some(ndt) =>
|
||||
DateTime::<Utc>::from_utc(ndt, Utc).to_rfc3339_opts(SecondsFormat::Secs, true),
|
||||
None => "unknown".to_string(),
|
||||
},
|
||||
unix_timestamp,
|
||||
)
|
||||
}
|
||||
|
||||
impl fmt::Display for CliBlockTime {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln_name_value(f, "Block:", &self.slot.to_string())?;
|
||||
writeln_name_value(
|
||||
f,
|
||||
"Date:",
|
||||
&format!(
|
||||
"{} (UnixTimestamp: {})",
|
||||
DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(self.timestamp, 0), Utc)
|
||||
.to_rfc3339_opts(SecondsFormat::Secs, true),
|
||||
self.timestamp
|
||||
),
|
||||
)
|
||||
writeln_name_value(f, "Date:", &unix_timestamp_to_string(self.timestamp))
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -197,6 +197,15 @@ pub fn write_transaction<W: io::Write>(
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(log_messages) = &transaction_status.log_messages {
|
||||
if !log_messages.is_empty() {
|
||||
writeln!(w, "{}Log Messages:", prefix,)?;
|
||||
for log_message in log_messages {
|
||||
writeln!(w, "{} {}", prefix, log_message,)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeln!(w, "{}Status: Unavailable", prefix)?;
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -23,32 +23,35 @@ indicatif = "0.15.0"
|
||||
humantime = "2.0.1"
|
||||
num-traits = "0.2"
|
||||
pretty-hex = "0.1.1"
|
||||
reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
reqwest = { version = "0.10.8", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
serde = "1.0.112"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.4.0" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.4.0" }
|
||||
solana-cli-output = { path = "../cli-output", version = "1.4.0" }
|
||||
solana-client = { path = "../client", version = "1.4.0" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.4.0" }
|
||||
solana-faucet = { path = "../faucet", version = "1.4.0" }
|
||||
solana-logger = { path = "../logger", version = "1.4.0" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.0" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.4.0" }
|
||||
solana-version = { path = "../version", version = "1.4.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.4.0" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.4.2" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.4.2" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.4.2" }
|
||||
solana-cli-output = { path = "../cli-output", version = "1.4.2" }
|
||||
solana-client = { path = "../client", version = "1.4.2" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.4.2" }
|
||||
solana-faucet = { path = "../faucet", version = "1.4.2" }
|
||||
solana-logger = { path = "../logger", version = "1.4.2" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
|
||||
solana_rbpf = "=0.1.32"
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.2" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.4.2" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.4.2" }
|
||||
solana-version = { path = "../version", version = "1.4.2" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.4.2" }
|
||||
thiserror = "1.0.20"
|
||||
tiny-bip39 = "0.7.0"
|
||||
url = "2.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-core = { path = "../core", version = "1.4.0" }
|
||||
solana-core = { path = "../core", version = "1.4.2" }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -54,12 +54,42 @@ pub fn check_account_for_multiple_fees_with_commitment(
|
||||
fee_calculator: &FeeCalculator,
|
||||
messages: &[&Message],
|
||||
commitment: CommitmentConfig,
|
||||
) -> Result<(), CliError> {
|
||||
check_account_for_spend_multiple_fees_with_commitment(
|
||||
rpc_client,
|
||||
account_pubkey,
|
||||
0,
|
||||
fee_calculator,
|
||||
messages,
|
||||
commitment,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn check_account_for_spend_multiple_fees_with_commitment(
|
||||
rpc_client: &RpcClient,
|
||||
account_pubkey: &Pubkey,
|
||||
balance: u64,
|
||||
fee_calculator: &FeeCalculator,
|
||||
messages: &[&Message],
|
||||
commitment: CommitmentConfig,
|
||||
) -> Result<(), CliError> {
|
||||
let fee = calculate_fee(fee_calculator, messages);
|
||||
if !check_account_for_balance_with_commitment(rpc_client, account_pubkey, fee, commitment)
|
||||
.map_err(Into::<ClientError>::into)?
|
||||
if !check_account_for_balance_with_commitment(
|
||||
rpc_client,
|
||||
account_pubkey,
|
||||
balance + fee,
|
||||
commitment,
|
||||
)
|
||||
.map_err(Into::<ClientError>::into)?
|
||||
{
|
||||
return Err(CliError::InsufficientFundsForFee(lamports_to_sol(fee)));
|
||||
if balance > 0 {
|
||||
return Err(CliError::InsufficientFundsForSpendAndFee(
|
||||
lamports_to_sol(balance),
|
||||
lamports_to_sol(fee),
|
||||
));
|
||||
} else {
|
||||
return Err(CliError::InsufficientFundsForFee(lamports_to_sol(fee)));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -131,7 +161,7 @@ mod tests {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
value: json!(account_balance),
|
||||
});
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let fee_calculator = FeeCalculator::new(1);
|
||||
|
||||
let pubkey0 = Pubkey::new(&[0; 32]);
|
||||
@@ -191,7 +221,7 @@ mod tests {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
value: json!(account_balance),
|
||||
});
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let mut mocks = HashMap::new();
|
||||
mocks.insert(RpcRequest::GetBalance, account_balance_response);
|
||||
@@ -237,9 +267,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_check_unique_pubkeys() {
|
||||
let pubkey0 = Pubkey::new_rand();
|
||||
let pubkey0 = solana_sdk::pubkey::new_rand();
|
||||
let pubkey_clone = pubkey0;
|
||||
let pubkey1 = Pubkey::new_rand();
|
||||
let pubkey1 = solana_sdk::pubkey::new_rand();
|
||||
|
||||
check_unique_pubkeys((&pubkey0, "foo".to_string()), (&pubkey1, "bar".to_string()))
|
||||
.expect("unexpected result");
|
||||
|
115
cli/src/cli.rs
115
cli/src/cli.rs
@@ -2,11 +2,13 @@ use crate::{
|
||||
checks::*, cluster_query::*, feature::*, inflation::*, nonce::*, spend_utils::*, stake::*,
|
||||
validator_info::*, vote::*,
|
||||
};
|
||||
use bip39::{Language, Mnemonic, MnemonicType, Seed};
|
||||
use clap::{value_t_or_exit, App, AppSettings, Arg, ArgMatches, SubCommand};
|
||||
use log::*;
|
||||
use num_traits::FromPrimitive;
|
||||
use serde_json::{self, json, Value};
|
||||
use solana_account_decoder::{UiAccount, UiAccountEncoding};
|
||||
use solana_bpf_loader_program::bpf_verifier;
|
||||
use solana_clap_utils::{
|
||||
self,
|
||||
commitment::commitment_arg_with_default,
|
||||
@@ -36,6 +38,7 @@ use solana_client::{
|
||||
use solana_faucet::faucet::request_airdrop_transaction;
|
||||
#[cfg(test)]
|
||||
use solana_faucet::faucet_mock::request_airdrop_transaction;
|
||||
use solana_rbpf::vm::EbpfVm;
|
||||
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
|
||||
use solana_sdk::{
|
||||
bpf_loader, bpf_loader_deprecated,
|
||||
@@ -47,7 +50,7 @@ use solana_sdk::{
|
||||
loader_instruction,
|
||||
message::Message,
|
||||
pubkey::{Pubkey, MAX_SEED_LEN},
|
||||
signature::{Keypair, Signature, Signer, SignerError},
|
||||
signature::{keypair_from_seed, Keypair, Signature, Signer, SignerError},
|
||||
signers::Signers,
|
||||
system_instruction::{self, SystemError},
|
||||
system_program,
|
||||
@@ -98,7 +101,7 @@ pub enum CliCommand {
|
||||
Fees,
|
||||
FirstAvailableBlock,
|
||||
GetBlock {
|
||||
slot: Slot,
|
||||
slot: Option<Slot>,
|
||||
},
|
||||
GetBlockTime {
|
||||
slot: Option<Slot>,
|
||||
@@ -1130,7 +1133,48 @@ fn process_deploy(
|
||||
address: Option<SignerIndex>,
|
||||
use_deprecated_loader: bool,
|
||||
) -> ProcessResult {
|
||||
let new_keypair = Keypair::new(); // Create ephemeral keypair to use for program address, if not provided
|
||||
const WORDS: usize = 12;
|
||||
// Create ephemeral keypair to use for program address, if not provided
|
||||
let mnemonic = Mnemonic::new(MnemonicType::for_word_count(WORDS)?, Language::English);
|
||||
let seed = Seed::new(&mnemonic, "");
|
||||
let new_keypair = keypair_from_seed(seed.as_bytes())?;
|
||||
|
||||
let result = do_process_deploy(
|
||||
rpc_client,
|
||||
config,
|
||||
program_location,
|
||||
address,
|
||||
use_deprecated_loader,
|
||||
new_keypair,
|
||||
);
|
||||
|
||||
if result.is_err() && address.is_none() {
|
||||
let phrase: &str = mnemonic.phrase();
|
||||
let divider = String::from_utf8(vec![b'='; phrase.len()]).unwrap();
|
||||
eprintln!(
|
||||
"{}\nTo reuse this address, recover the ephemeral keypair file with",
|
||||
divider
|
||||
);
|
||||
eprintln!(
|
||||
"`solana-keygen recover` and the following {}-word seed phrase,",
|
||||
WORDS
|
||||
);
|
||||
eprintln!(
|
||||
"then pass it as the [ADDRESS_SIGNER] argument to `solana deploy ...`\n{}\n{}\n{}",
|
||||
divider, phrase, divider
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn do_process_deploy(
|
||||
rpc_client: &RpcClient,
|
||||
config: &CliConfig,
|
||||
program_location: &str,
|
||||
address: Option<SignerIndex>,
|
||||
use_deprecated_loader: bool,
|
||||
new_keypair: Keypair,
|
||||
) -> ProcessResult {
|
||||
let program_id = if let Some(i) = address {
|
||||
config.signers[i]
|
||||
} else {
|
||||
@@ -1144,6 +1188,9 @@ fn process_deploy(
|
||||
CliError::DynamicProgramError(format!("Unable to read program file: {}", err))
|
||||
})?;
|
||||
|
||||
EbpfVm::create_executable_from_elf(&program_data, Some(|x| bpf_verifier::check(x, true)))
|
||||
.map_err(|err| CliError::DynamicProgramError(format!("ELF error: {}", err)))?;
|
||||
|
||||
let loader_id = if use_deprecated_loader {
|
||||
bpf_loader_deprecated::id()
|
||||
} else {
|
||||
@@ -1154,11 +1201,12 @@ fn process_deploy(
|
||||
let signers = [config.signers[0], program_id];
|
||||
|
||||
// Check program account to see if partial initialization has occurred
|
||||
let initial_instructions = if let Some(account) = rpc_client
|
||||
let (initial_instructions, balance_needed) = if let Some(account) = rpc_client
|
||||
.get_account_with_commitment(&program_id.pubkey(), config.commitment)?
|
||||
.value
|
||||
{
|
||||
let mut instructions: Vec<Instruction> = vec![];
|
||||
let mut balance_needed = 0;
|
||||
if account.executable {
|
||||
return Err(CliError::DynamicProgramError(
|
||||
"Program account is already executable".to_string(),
|
||||
@@ -1182,21 +1230,26 @@ fn process_deploy(
|
||||
}
|
||||
}
|
||||
if account.lamports < minimum_balance {
|
||||
let balance = minimum_balance - account.lamports;
|
||||
instructions.push(system_instruction::transfer(
|
||||
&config.signers[0].pubkey(),
|
||||
&program_id.pubkey(),
|
||||
minimum_balance - account.lamports,
|
||||
balance,
|
||||
));
|
||||
balance_needed = balance;
|
||||
}
|
||||
instructions
|
||||
(instructions, balance_needed)
|
||||
} else {
|
||||
vec![system_instruction::create_account(
|
||||
&config.signers[0].pubkey(),
|
||||
&program_id.pubkey(),
|
||||
(
|
||||
vec![system_instruction::create_account(
|
||||
&config.signers[0].pubkey(),
|
||||
&program_id.pubkey(),
|
||||
minimum_balance,
|
||||
program_data.len() as u64,
|
||||
&loader_id,
|
||||
)],
|
||||
minimum_balance,
|
||||
program_data.len() as u64,
|
||||
&loader_id,
|
||||
)]
|
||||
)
|
||||
};
|
||||
let initial_message = if !initial_instructions.is_empty() {
|
||||
Some(Message::new(
|
||||
@@ -1239,9 +1292,10 @@ fn process_deploy(
|
||||
.get_recent_blockhash_with_commitment(config.commitment)?
|
||||
.value;
|
||||
|
||||
check_account_for_multiple_fees_with_commitment(
|
||||
check_account_for_spend_multiple_fees_with_commitment(
|
||||
rpc_client,
|
||||
&config.signers[0].pubkey(),
|
||||
balance_needed,
|
||||
&fee_calculator,
|
||||
&messages,
|
||||
config.commitment,
|
||||
@@ -1266,8 +1320,8 @@ fn process_deploy(
|
||||
config.commitment,
|
||||
config.send_transaction_config,
|
||||
);
|
||||
log_instruction_custom_error::<SystemError>(result, &config).map_err(|_| {
|
||||
CliError::DynamicProgramError("Program account allocation failed".to_string())
|
||||
log_instruction_custom_error::<SystemError>(result, &config).map_err(|err| {
|
||||
CliError::DynamicProgramError(format!("Program account allocation failed: {}", err))
|
||||
})?;
|
||||
}
|
||||
|
||||
@@ -2187,7 +2241,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
||||
.arg(
|
||||
Arg::with_name("address_signer")
|
||||
.index(2)
|
||||
.value_name("SIGNER_KEYPAIR")
|
||||
.value_name("ADDRESS_SIGNER")
|
||||
.takes_value(true)
|
||||
.validator(is_valid_signer)
|
||||
.help("The signer for the desired address of the program [default: new random address]")
|
||||
@@ -2355,7 +2409,10 @@ mod tests {
|
||||
.unwrap();
|
||||
assert_eq!(signer_info.signers.len(), 1);
|
||||
assert_eq!(signer_info.index_of(None), Some(0));
|
||||
assert_eq!(signer_info.index_of(Some(Pubkey::new_rand())), None);
|
||||
assert_eq!(
|
||||
signer_info.index_of(Some(solana_sdk::pubkey::new_rand())),
|
||||
None
|
||||
);
|
||||
|
||||
let keypair0 = keypair_from_seed(&[1u8; 32]).unwrap();
|
||||
let keypair0_pubkey = keypair0.pubkey();
|
||||
@@ -2411,7 +2468,7 @@ mod tests {
|
||||
fn test_cli_parse_command() {
|
||||
let test_commands = app("test", "desc", "version");
|
||||
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let pubkey_string = format!("{}", pubkey);
|
||||
|
||||
let default_keypair = Keypair::new();
|
||||
@@ -2507,7 +2564,7 @@ mod tests {
|
||||
assert!(parse_command(&test_bad_signature, &default_signer, &mut None).is_err());
|
||||
|
||||
// Test CreateAddressWithSeed
|
||||
let from_pubkey = Some(Pubkey::new_rand());
|
||||
let from_pubkey = Some(solana_sdk::pubkey::new_rand());
|
||||
let from_str = from_pubkey.unwrap().to_string();
|
||||
for (name, program_id) in &[
|
||||
("STAKE", solana_stake_program::id()),
|
||||
@@ -2664,7 +2721,7 @@ mod tests {
|
||||
let result = process_command(&config);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let new_authorized_pubkey = Pubkey::new_rand();
|
||||
let new_authorized_pubkey = solana_sdk::pubkey::new_rand();
|
||||
config.signers = vec![&bob_keypair];
|
||||
config.command = CliCommand::VoteAuthorize {
|
||||
vote_account_pubkey: bob_pubkey,
|
||||
@@ -2686,7 +2743,7 @@ mod tests {
|
||||
|
||||
let bob_keypair = Keypair::new();
|
||||
let bob_pubkey = bob_keypair.pubkey();
|
||||
let custodian = Pubkey::new_rand();
|
||||
let custodian = solana_sdk::pubkey::new_rand();
|
||||
config.command = CliCommand::CreateStakeAccount {
|
||||
stake_account: 1,
|
||||
seed: None,
|
||||
@@ -2709,8 +2766,8 @@ mod tests {
|
||||
let result = process_command(&config);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let stake_account_pubkey = Pubkey::new_rand();
|
||||
let to_pubkey = Pubkey::new_rand();
|
||||
let stake_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let to_pubkey = solana_sdk::pubkey::new_rand();
|
||||
config.command = CliCommand::WithdrawStake {
|
||||
stake_account_pubkey,
|
||||
destination_account_pubkey: to_pubkey,
|
||||
@@ -2727,7 +2784,7 @@ mod tests {
|
||||
let result = process_command(&config);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let stake_account_pubkey = Pubkey::new_rand();
|
||||
let stake_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
config.command = CliCommand::DeactivateStake {
|
||||
stake_account_pubkey,
|
||||
stake_authority: 0,
|
||||
@@ -2740,7 +2797,7 @@ mod tests {
|
||||
let result = process_command(&config);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let stake_account_pubkey = Pubkey::new_rand();
|
||||
let stake_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let split_stake_account = Keypair::new();
|
||||
config.command = CliCommand::SplitStake {
|
||||
stake_account_pubkey,
|
||||
@@ -2758,8 +2815,8 @@ mod tests {
|
||||
let result = process_command(&config);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let stake_account_pubkey = Pubkey::new_rand();
|
||||
let source_stake_account_pubkey = Pubkey::new_rand();
|
||||
let stake_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let source_stake_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let merge_stake_account = Keypair::new();
|
||||
config.command = CliCommand::MergeStake {
|
||||
stake_account_pubkey,
|
||||
@@ -2782,7 +2839,7 @@ mod tests {
|
||||
assert_eq!(process_command(&config).unwrap(), "1234");
|
||||
|
||||
// CreateAddressWithSeed
|
||||
let from_pubkey = Pubkey::new_rand();
|
||||
let from_pubkey = solana_sdk::pubkey::new_rand();
|
||||
config.signers = vec![];
|
||||
config.command = CliCommand::CreateAddressWithSeed {
|
||||
from_pubkey: Some(from_pubkey),
|
||||
@@ -2795,7 +2852,7 @@ mod tests {
|
||||
assert_eq!(address.unwrap(), expected_address.to_string());
|
||||
|
||||
// Need airdrop cases
|
||||
let to = Pubkey::new_rand();
|
||||
let to = solana_sdk::pubkey::new_rand();
|
||||
config.signers = vec![&keypair];
|
||||
config.command = CliCommand::Airdrop {
|
||||
faucet_host: None,
|
||||
|
@@ -73,8 +73,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
||||
.validator(is_slot)
|
||||
.value_name("SLOT")
|
||||
.takes_value(true)
|
||||
.index(1)
|
||||
.required(true),
|
||||
.index(1),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -363,7 +362,7 @@ pub fn parse_cluster_ping(
|
||||
}
|
||||
|
||||
pub fn parse_get_block(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let slot = value_t_or_exit!(matches, "slot", Slot);
|
||||
let slot = value_of(matches, "slot");
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::GetBlock { slot },
|
||||
signers: vec![],
|
||||
@@ -700,7 +699,17 @@ pub fn process_leader_schedule(rpc_client: &RpcClient) -> ProcessResult {
|
||||
Ok("".to_string())
|
||||
}
|
||||
|
||||
pub fn process_get_block(rpc_client: &RpcClient, _config: &CliConfig, slot: Slot) -> ProcessResult {
|
||||
pub fn process_get_block(
|
||||
rpc_client: &RpcClient,
|
||||
_config: &CliConfig,
|
||||
slot: Option<Slot>,
|
||||
) -> ProcessResult {
|
||||
let slot = if let Some(slot) = slot {
|
||||
slot
|
||||
} else {
|
||||
rpc_client.get_slot()?
|
||||
};
|
||||
|
||||
let mut block =
|
||||
rpc_client.get_confirmed_block_with_encoding(slot, UiTransactionEncoding::Base64)?;
|
||||
|
||||
@@ -716,18 +725,23 @@ pub fn process_get_block(rpc_client: &RpcClient, _config: &CliConfig, slot: Slot
|
||||
let mut total_rewards = 0;
|
||||
println!("Rewards:",);
|
||||
println!(
|
||||
" {:<44} {:<15} {:<13} {:>14}",
|
||||
"Address", "Amount", "New Balance", "Percent Change"
|
||||
" {:<44} {:^15} {:<15} {:<20} {:>14}",
|
||||
"Address", "Type", "Amount", "New Balance", "Percent Change"
|
||||
);
|
||||
for reward in block.rewards {
|
||||
let sign = if reward.lamports < 0 { "-" } else { "" };
|
||||
|
||||
total_rewards += reward.lamports;
|
||||
println!(
|
||||
" {:<44} {:>15} {}",
|
||||
" {:<44} {:^15} {:>15} {}",
|
||||
reward.pubkey,
|
||||
if let Some(reward_type) = reward.reward_type {
|
||||
format!("{}", reward_type)
|
||||
} else {
|
||||
"-".to_string()
|
||||
},
|
||||
format!(
|
||||
"{}◎{:<14.4}",
|
||||
"{}◎{:<14.9}",
|
||||
sign,
|
||||
lamports_to_sol(reward.lamports.abs() as u64)
|
||||
),
|
||||
@@ -735,7 +749,7 @@ pub fn process_get_block(rpc_client: &RpcClient, _config: &CliConfig, slot: Slot
|
||||
" - -".to_string()
|
||||
} else {
|
||||
format!(
|
||||
"◎{:<12.4} {:>13.4}%",
|
||||
"◎{:<19.9} {:>13.9}%",
|
||||
lamports_to_sol(reward.post_balance),
|
||||
reward.lamports.abs() as f64
|
||||
/ (reward.post_balance as f64 - reward.lamports as f64)
|
||||
@@ -746,7 +760,7 @@ pub fn process_get_block(rpc_client: &RpcClient, _config: &CliConfig, slot: Slot
|
||||
|
||||
let sign = if total_rewards < 0 { "-" } else { "" };
|
||||
println!(
|
||||
"Total Rewards: {}◎{:12.9}",
|
||||
"Total Rewards: {}◎{:<12.9}",
|
||||
sign,
|
||||
lamports_to_sol(total_rewards.abs() as u64)
|
||||
);
|
||||
@@ -1253,14 +1267,16 @@ pub fn process_show_gossip(rpc_client: &RpcClient, config: &CliConfig) -> Proces
|
||||
.into_iter()
|
||||
.map(|node| {
|
||||
format!(
|
||||
"{:15} | {:44} | {:6} | {:5} | {:5} | {}",
|
||||
"{:15} | {:44} | {:6} | {:5} | {:21} | {}",
|
||||
node.gossip
|
||||
.map(|addr| addr.ip().to_string())
|
||||
.unwrap_or_else(|| "none".to_string()),
|
||||
format_labeled_address(&node.pubkey, &config.address_labels),
|
||||
format_port(node.gossip),
|
||||
format_port(node.tpu),
|
||||
format_port(node.rpc),
|
||||
node.rpc
|
||||
.map(|addr| addr.to_string())
|
||||
.unwrap_or_else(|| "none".to_string()),
|
||||
node.version.unwrap_or_else(|| "unknown".to_string()),
|
||||
)
|
||||
})
|
||||
@@ -1268,9 +1284,9 @@ pub fn process_show_gossip(rpc_client: &RpcClient, config: &CliConfig) -> Proces
|
||||
|
||||
Ok(format!(
|
||||
"IP Address | Node identifier \
|
||||
| Gossip | TPU | RPC | Version\n\
|
||||
| Gossip | TPU | RPC Address | Version\n\
|
||||
----------------+----------------------------------------------+\
|
||||
--------+-------+-------+----------------\n\
|
||||
--------+-------+-----------------------+----------------\n\
|
||||
{}\n\
|
||||
Nodes: {}",
|
||||
s.join("\n"),
|
||||
@@ -1405,12 +1421,12 @@ pub fn process_show_validators(
|
||||
.map(|vote_account| vote_account.activated_stake)
|
||||
.sum();
|
||||
|
||||
let total_deliquent_stake = vote_accounts
|
||||
let total_delinquent_stake = vote_accounts
|
||||
.delinquent
|
||||
.iter()
|
||||
.map(|vote_account| vote_account.activated_stake)
|
||||
.sum();
|
||||
let total_current_stake = total_active_stake - total_deliquent_stake;
|
||||
let total_current_stake = total_active_stake - total_delinquent_stake;
|
||||
|
||||
let mut current = vote_accounts.current;
|
||||
current.sort_by(|a, b| b.activated_stake.cmp(&a.activated_stake));
|
||||
@@ -1464,7 +1480,7 @@ pub fn process_show_validators(
|
||||
let cli_validators = CliValidators {
|
||||
total_active_stake,
|
||||
total_current_stake,
|
||||
total_deliquent_stake,
|
||||
total_delinquent_stake,
|
||||
current_validators,
|
||||
delinquent_validators,
|
||||
stake_by_version,
|
||||
|
@@ -230,7 +230,7 @@ fn active_stake_by_feature_set(rpc_client: &RpcClient) -> Result<HashMap<u32, u6
|
||||
}
|
||||
|
||||
// Feature activation is only allowed when 95% of the active stake is on the current feature set
|
||||
fn feature_activation_allowed(rpc_client: &RpcClient) -> Result<bool, ClientError> {
|
||||
fn feature_activation_allowed(rpc_client: &RpcClient, quiet: bool) -> Result<bool, ClientError> {
|
||||
let my_feature_set = solana_version::Version::default().feature_set;
|
||||
|
||||
let active_stake_by_feature_set = active_stake_by_feature_set(rpc_client)?;
|
||||
@@ -240,8 +240,8 @@ fn feature_activation_allowed(rpc_client: &RpcClient) -> Result<bool, ClientErro
|
||||
.map(|percentage| *percentage >= 95)
|
||||
.unwrap_or(false);
|
||||
|
||||
if !feature_activation_allowed {
|
||||
println!("\n{}", style("Stake By Feature Set:").bold());
|
||||
if !feature_activation_allowed && !quiet {
|
||||
println!("{}", style("Stake By Feature Set:").bold());
|
||||
for (feature_set, percentage) in active_stake_by_feature_set.iter() {
|
||||
if *feature_set == 0 {
|
||||
println!("unknown - {}%", percentage);
|
||||
@@ -258,6 +258,7 @@ fn feature_activation_allowed(rpc_client: &RpcClient) -> Result<bool, ClientErro
|
||||
);
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
Ok(feature_activation_allowed)
|
||||
@@ -299,9 +300,10 @@ fn process_status(
|
||||
});
|
||||
}
|
||||
|
||||
let feature_activation_allowed = feature_activation_allowed(rpc_client, features.len() <= 1)?;
|
||||
let feature_set = CliFeatures {
|
||||
features,
|
||||
feature_activation_allowed: feature_activation_allowed(rpc_client)?,
|
||||
feature_activation_allowed,
|
||||
inactive,
|
||||
};
|
||||
Ok(config.output_format.formatted_string(&feature_set))
|
||||
@@ -323,7 +325,7 @@ fn process_activate(
|
||||
}
|
||||
}
|
||||
|
||||
if !feature_activation_allowed(rpc_client)? {
|
||||
if !feature_activation_allowed(rpc_client, false)? {
|
||||
return Err("Feature activation is not allowed at this time".into());
|
||||
}
|
||||
|
||||
|
@@ -833,7 +833,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_check_nonce_account() {
|
||||
let blockhash = Hash::default();
|
||||
let nonce_pubkey = Pubkey::new_rand();
|
||||
let nonce_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let data = Versions::new_current(State::Initialized(nonce::state::Data {
|
||||
authority: nonce_pubkey,
|
||||
blockhash,
|
||||
@@ -869,7 +869,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let data = Versions::new_current(State::Initialized(nonce::state::Data {
|
||||
authority: Pubkey::new_rand(),
|
||||
authority: solana_sdk::pubkey::new_rand(),
|
||||
blockhash,
|
||||
fee_calculator: FeeCalculator::default(),
|
||||
}));
|
||||
|
@@ -23,13 +23,17 @@ use solana_cli_output::{
|
||||
CliStakeType,
|
||||
};
|
||||
use solana_client::{
|
||||
blockhash_query::BlockhashQuery, nonce_utils, rpc_client::RpcClient,
|
||||
rpc_request::DELINQUENT_VALIDATOR_SLOT_DISTANCE,
|
||||
blockhash_query::BlockhashQuery,
|
||||
client_error::{ClientError, ClientErrorKind},
|
||||
nonce_utils,
|
||||
rpc_client::RpcClient,
|
||||
rpc_custom_error,
|
||||
rpc_request::{self, DELINQUENT_VALIDATOR_SLOT_DISTANCE},
|
||||
};
|
||||
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
|
||||
use solana_sdk::{
|
||||
account_utils::StateMut,
|
||||
clock::{Clock, Epoch, Slot, UnixTimestamp},
|
||||
clock::{Clock, Epoch, Slot, UnixTimestamp, SECONDS_PER_DAY},
|
||||
message::Message,
|
||||
pubkey::Pubkey,
|
||||
system_instruction::SystemError,
|
||||
@@ -1605,10 +1609,26 @@ pub(crate) fn fetch_epoch_rewards(
|
||||
.get(0)
|
||||
.ok_or_else(|| format!("Unable to fetch first confirmed block for epoch {}", epoch))?;
|
||||
|
||||
let first_confirmed_block = rpc_client.get_confirmed_block_with_encoding(
|
||||
let first_confirmed_block = match rpc_client.get_confirmed_block_with_encoding(
|
||||
first_confirmed_block_in_epoch,
|
||||
solana_transaction_status::UiTransactionEncoding::Base64,
|
||||
)?;
|
||||
) {
|
||||
Ok(first_confirmed_block) => first_confirmed_block,
|
||||
Err(ClientError {
|
||||
kind:
|
||||
ClientErrorKind::RpcError(rpc_request::RpcError::RpcResponseError {
|
||||
code: rpc_custom_error::JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE,
|
||||
message: _,
|
||||
}),
|
||||
request: _,
|
||||
}) => {
|
||||
// RPC node doesn't have this block
|
||||
break;
|
||||
}
|
||||
Err(err) => {
|
||||
return Err(err.into());
|
||||
}
|
||||
};
|
||||
|
||||
let epoch_start_time = if let Some(block_time) = first_confirmed_block.block_time {
|
||||
block_time
|
||||
@@ -1620,13 +1640,13 @@ pub(crate) fn fetch_epoch_rewards(
|
||||
let previous_epoch_rewards = first_confirmed_block.rewards;
|
||||
|
||||
if let Some((effective_slot, epoch_end_time, epoch_rewards)) = epoch_info {
|
||||
let wall_clock_epoch_duration =
|
||||
let wallclock_epoch_duration =
|
||||
{ Local.timestamp(epoch_end_time, 0) - Local.timestamp(epoch_start_time, 0) }
|
||||
.to_std()?
|
||||
.as_secs_f64();
|
||||
|
||||
const SECONDS_PER_YEAR: f64 = (24 * 60 * 60 * 356) as f64;
|
||||
let percent_of_year = SECONDS_PER_YEAR / wall_clock_epoch_duration;
|
||||
let wallclock_epochs_per_year =
|
||||
(SECONDS_PER_DAY * 356) as f64 / wallclock_epoch_duration;
|
||||
|
||||
if let Some(reward) = epoch_rewards
|
||||
.into_iter()
|
||||
@@ -1642,7 +1662,7 @@ pub(crate) fn fetch_epoch_rewards(
|
||||
amount: reward.lamports.abs() as u64,
|
||||
post_balance: reward.post_balance,
|
||||
percent_change: balance_increase_percent,
|
||||
apr: balance_increase_percent * percent_of_year,
|
||||
apr: balance_increase_percent * wallclock_epochs_per_year,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2406,9 +2426,9 @@ mod tests {
|
||||
);
|
||||
|
||||
// Test CreateStakeAccount SubCommand
|
||||
let custodian = Pubkey::new_rand();
|
||||
let custodian = solana_sdk::pubkey::new_rand();
|
||||
let custodian_string = format!("{}", custodian);
|
||||
let authorized = Pubkey::new_rand();
|
||||
let authorized = solana_sdk::pubkey::new_rand();
|
||||
let authorized_string = format!("{}", authorized);
|
||||
let test_create_stake_account = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
@@ -2546,7 +2566,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// Test DelegateStake Subcommand
|
||||
let vote_account_pubkey = Pubkey::new_rand();
|
||||
let vote_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let vote_account_string = vote_account_pubkey.to_string();
|
||||
let test_delegate_stake = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
@@ -2573,7 +2593,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// Test DelegateStake Subcommand w/ authority
|
||||
let vote_account_pubkey = Pubkey::new_rand();
|
||||
let vote_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let vote_account_string = vote_account_pubkey.to_string();
|
||||
let test_delegate_stake = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
@@ -2692,7 +2712,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// Test Delegate Subcommand w/ absent fee payer
|
||||
let key1 = Pubkey::new_rand();
|
||||
let key1 = solana_sdk::pubkey::new_rand();
|
||||
let sig1 = Keypair::new().sign_message(&[0u8]);
|
||||
let signer1 = format!("{}={}", key1, sig1);
|
||||
let test_delegate_stake = test_commands.clone().get_matches_from(vec![
|
||||
@@ -2732,7 +2752,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// Test Delegate Subcommand w/ absent fee payer and absent nonce authority
|
||||
let key2 = Pubkey::new_rand();
|
||||
let key2 = solana_sdk::pubkey::new_rand();
|
||||
let sig2 = Keypair::new().sign_message(&[0u8]);
|
||||
let signer2 = format!("{}={}", key2, sig2);
|
||||
let test_delegate_stake = test_commands.clone().get_matches_from(vec![
|
||||
@@ -3060,7 +3080,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// Test Deactivate Subcommand w/ absent fee payer
|
||||
let key1 = Pubkey::new_rand();
|
||||
let key1 = solana_sdk::pubkey::new_rand();
|
||||
let sig1 = Keypair::new().sign_message(&[0u8]);
|
||||
let signer1 = format!("{}={}", key1, sig1);
|
||||
let test_deactivate_stake = test_commands.clone().get_matches_from(vec![
|
||||
@@ -3097,7 +3117,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// Test Deactivate Subcommand w/ absent fee payer and nonce authority
|
||||
let key2 = Pubkey::new_rand();
|
||||
let key2 = solana_sdk::pubkey::new_rand();
|
||||
let sig2 = Keypair::new().sign_message(&[0u8]);
|
||||
let signer2 = format!("{}={}", key2, sig2);
|
||||
let test_deactivate_stake = test_commands.clone().get_matches_from(vec![
|
||||
@@ -3276,7 +3296,7 @@ mod tests {
|
||||
let stake_account_keypair = Keypair::new();
|
||||
write_keypair(&stake_account_keypair, tmp_file.as_file_mut()).unwrap();
|
||||
|
||||
let source_stake_account_pubkey = Pubkey::new_rand();
|
||||
let source_stake_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let test_merge_stake_account = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
"merge-stake",
|
||||
|
@@ -486,7 +486,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_validator_info() {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let keys = vec![(validator_info::id(), false), (pubkey, true)];
|
||||
let config = ConfigKeys { keys };
|
||||
|
||||
|
@@ -915,7 +915,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// test init with an authed voter
|
||||
let authed = Pubkey::new_rand();
|
||||
let authed = solana_sdk::pubkey::new_rand();
|
||||
let (keypair_file, mut tmp_file) = make_tmp_file();
|
||||
let keypair = Keypair::new();
|
||||
write_keypair(&keypair, tmp_file.as_file_mut()).unwrap();
|
||||
|
@@ -172,7 +172,7 @@ fn full_battery_tests(
|
||||
assert_ne!(first_nonce, third_nonce);
|
||||
|
||||
// Withdraw from nonce account
|
||||
let payee_pubkey = Pubkey::new_rand();
|
||||
let payee_pubkey = solana_sdk::pubkey::new_rand();
|
||||
config_payer.signers = authorized_signers;
|
||||
config_payer.command = CliCommand::WithdrawFromNonceAccount {
|
||||
nonce_account,
|
||||
|
@@ -12,7 +12,6 @@ use solana_faucet::faucet::run_local_faucet;
|
||||
use solana_sdk::{
|
||||
account_utils::StateMut,
|
||||
commitment_config::CommitmentConfig,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
};
|
||||
use solana_vote_program::vote_state::{VoteAuthorize, VoteState, VoteStateVersions};
|
||||
@@ -110,7 +109,7 @@ fn test_vote_authorize_and_withdraw() {
|
||||
assert_eq!(authorized_withdrawer, withdraw_authority.pubkey());
|
||||
|
||||
// Withdraw from vote account
|
||||
let destination_account = Pubkey::new_rand(); // Send withdrawal to new account to make balance check easy
|
||||
let destination_account = solana_sdk::pubkey::new_rand(); // Send withdrawal to new account to make balance check easy
|
||||
config.signers = vec![&default_signer, &withdraw_authority];
|
||||
config.command = CliCommand::WithdrawFromVoteAccount {
|
||||
vote_account_pubkey,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-client"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
description = "Solana Client"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -17,16 +17,18 @@ indicatif = "0.15.0"
|
||||
jsonrpc-core = "15.0.0"
|
||||
log = "0.4.8"
|
||||
rayon = "1.4.0"
|
||||
reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
reqwest = { version = "0.10.8", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
semver = "0.11.0"
|
||||
serde = "1.0.112"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.4.0" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.4.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.4.2" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.4.2" }
|
||||
solana-version = { path = "../version", version = "1.4.2" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
|
||||
thiserror = "1.0"
|
||||
tungstenite = "0.10.1"
|
||||
url = "2.1.1"
|
||||
@@ -35,7 +37,7 @@ url = "2.1.1"
|
||||
assert_matches = "1.3.0"
|
||||
jsonrpc-core = "15.0.0"
|
||||
jsonrpc-http-server = "15.0.0"
|
||||
solana-logger = { path = "../logger", version = "1.4.0" }
|
||||
solana-logger = { path = "../logger", version = "1.4.2" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -50,10 +50,10 @@ impl Into<TransportError> for ClientErrorKind {
|
||||
#[derive(Error, Debug)]
|
||||
#[error("{kind}")]
|
||||
pub struct ClientError {
|
||||
request: Option<rpc_request::RpcRequest>,
|
||||
pub request: Option<rpc_request::RpcRequest>,
|
||||
|
||||
#[source]
|
||||
kind: ClientErrorKind,
|
||||
pub kind: ClientErrorKind,
|
||||
}
|
||||
|
||||
impl ClientError {
|
||||
|
@@ -27,6 +27,13 @@ impl HttpSender {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct RpcErrorObject {
|
||||
code: i64,
|
||||
message: String,
|
||||
/*data field omitted*/
|
||||
}
|
||||
|
||||
impl RpcSender for HttpSender {
|
||||
fn send(&self, request: RpcRequest, params: serde_json::Value) -> Result<serde_json::Value> {
|
||||
// Concurrent requests are not supported so reuse the same request id for all requests
|
||||
@@ -63,11 +70,20 @@ impl RpcSender for HttpSender {
|
||||
|
||||
let json: serde_json::Value = serde_json::from_str(&response.text()?)?;
|
||||
if json["error"].is_object() {
|
||||
return Err(RpcError::RpcRequestError(format!(
|
||||
"RPC Error response: {}",
|
||||
serde_json::to_string(&json["error"]).unwrap()
|
||||
))
|
||||
.into());
|
||||
return match serde_json::from_value::<RpcErrorObject>(json["error"].clone())
|
||||
{
|
||||
Ok(rpc_error_object) => Err(RpcError::RpcResponseError {
|
||||
code: rpc_error_object.code,
|
||||
message: rpc_error_object.message,
|
||||
}
|
||||
.into()),
|
||||
Err(err) => Err(RpcError::RpcRequestError(format!(
|
||||
"Failed to deserialize RPC error response: {} [{}]",
|
||||
serde_json::to_string(&json["error"]).unwrap(),
|
||||
err
|
||||
))
|
||||
.into()),
|
||||
};
|
||||
}
|
||||
return Ok(json["result"].clone());
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ pub mod perf_utils;
|
||||
pub mod pubsub_client;
|
||||
pub mod rpc_client;
|
||||
pub mod rpc_config;
|
||||
pub mod rpc_custom_error;
|
||||
pub mod rpc_filter;
|
||||
pub mod rpc_request;
|
||||
pub mod rpc_response;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
use crate::{
|
||||
client_error::Result,
|
||||
rpc_request::RpcRequest,
|
||||
rpc_response::{Response, RpcResponseContext},
|
||||
rpc_response::{Response, RpcResponseContext, RpcVersionInfo},
|
||||
rpc_sender::RpcSender,
|
||||
};
|
||||
use serde_json::{Number, Value};
|
||||
use serde_json::{json, Number, Value};
|
||||
use solana_sdk::{
|
||||
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||
instruction::InstructionError,
|
||||
@@ -12,6 +12,7 @@ use solana_sdk::{
|
||||
transaction::{self, Transaction, TransactionError},
|
||||
};
|
||||
use solana_transaction_status::TransactionStatus;
|
||||
use solana_version::Version;
|
||||
use std::{collections::HashMap, sync::RwLock};
|
||||
|
||||
pub const PUBKEY: &str = "7RoSF9fUmdphVCpabEoefH81WwrW7orsWonXWqTXkKV8";
|
||||
@@ -112,13 +113,20 @@ impl RpcSender for MockSender {
|
||||
Signature::new(&[8; 64]).to_string()
|
||||
} else {
|
||||
let tx_str = params.as_array().unwrap()[0].as_str().unwrap().to_string();
|
||||
let data = bs58::decode(tx_str).into_vec().unwrap();
|
||||
let data = base64::decode(tx_str).unwrap();
|
||||
let tx: Transaction = bincode::deserialize(&data).unwrap();
|
||||
tx.signatures[0].to_string()
|
||||
};
|
||||
Value::String(signature)
|
||||
}
|
||||
RpcRequest::GetMinimumBalanceForRentExemption => Value::Number(Number::from(20)),
|
||||
RpcRequest::GetVersion => {
|
||||
let version = Version::default();
|
||||
json!(RpcVersionInfo {
|
||||
solana_core: version.to_string(),
|
||||
feature_set: Some(version.feature_set),
|
||||
})
|
||||
}
|
||||
_ => Value::Null,
|
||||
};
|
||||
Ok(val)
|
||||
|
@@ -41,12 +41,14 @@ use solana_transaction_status::{
|
||||
use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY;
|
||||
use std::{
|
||||
net::SocketAddr,
|
||||
sync::RwLock,
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
pub struct RpcClient {
|
||||
sender: Box<dyn RpcSender + Send + Sync + 'static>,
|
||||
default_cluster_transaction_encoding: RwLock<Option<UiTransactionEncoding>>,
|
||||
}
|
||||
|
||||
fn serialize_encode_transaction(
|
||||
@@ -73,6 +75,7 @@ impl RpcClient {
|
||||
pub fn new_sender<T: RpcSender + Send + Sync + 'static>(sender: T) -> Self {
|
||||
Self {
|
||||
sender: Box::new(sender),
|
||||
default_cluster_transaction_encoding: RwLock::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,12 +131,45 @@ impl RpcClient {
|
||||
self.send_transaction_with_config(transaction, RpcSendTransactionConfig::default())
|
||||
}
|
||||
|
||||
fn default_cluster_transaction_encoding(&self) -> Result<UiTransactionEncoding, RpcError> {
|
||||
let default_cluster_transaction_encoding =
|
||||
self.default_cluster_transaction_encoding.read().unwrap();
|
||||
if let Some(encoding) = *default_cluster_transaction_encoding {
|
||||
Ok(encoding)
|
||||
} else {
|
||||
drop(default_cluster_transaction_encoding);
|
||||
let cluster_version = self.get_version().map_err(|e| {
|
||||
RpcError::RpcRequestError(format!("cluster version query failed: {}", e))
|
||||
})?;
|
||||
let cluster_version =
|
||||
semver::Version::parse(&cluster_version.solana_core).map_err(|e| {
|
||||
RpcError::RpcRequestError(format!("failed to parse cluster version: {}", e))
|
||||
})?;
|
||||
// Prefer base64 since 1.3.16
|
||||
let encoding = if cluster_version < semver::Version::new(1, 3, 16) {
|
||||
UiTransactionEncoding::Base58
|
||||
} else {
|
||||
UiTransactionEncoding::Base64
|
||||
};
|
||||
*self.default_cluster_transaction_encoding.write().unwrap() = Some(encoding);
|
||||
Ok(encoding)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_transaction_with_config(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
config: RpcSendTransactionConfig,
|
||||
) -> ClientResult<Signature> {
|
||||
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
|
||||
let encoding = if let Some(encoding) = config.encoding {
|
||||
encoding
|
||||
} else {
|
||||
self.default_cluster_transaction_encoding()?
|
||||
};
|
||||
let config = RpcSendTransactionConfig {
|
||||
encoding: Some(encoding),
|
||||
..config
|
||||
};
|
||||
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?;
|
||||
let signature_base58_str: String = self.send(
|
||||
RpcRequest::SendTransaction,
|
||||
@@ -161,26 +197,28 @@ impl RpcClient {
|
||||
pub fn simulate_transaction(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
sig_verify: bool,
|
||||
) -> RpcResult<RpcSimulateTransactionResult> {
|
||||
self.simulate_transaction_with_config(
|
||||
transaction,
|
||||
sig_verify,
|
||||
RpcSimulateTransactionConfig::default(),
|
||||
)
|
||||
self.simulate_transaction_with_config(transaction, RpcSimulateTransactionConfig::default())
|
||||
}
|
||||
|
||||
pub fn simulate_transaction_with_config(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
sig_verify: bool,
|
||||
config: RpcSimulateTransactionConfig,
|
||||
) -> RpcResult<RpcSimulateTransactionResult> {
|
||||
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
|
||||
let encoding = if let Some(encoding) = config.encoding {
|
||||
encoding
|
||||
} else {
|
||||
self.default_cluster_transaction_encoding()?
|
||||
};
|
||||
let config = RpcSimulateTransactionConfig {
|
||||
encoding: Some(encoding),
|
||||
..config
|
||||
};
|
||||
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?;
|
||||
self.send(
|
||||
RpcRequest::SimulateTransaction,
|
||||
json!([serialized_encoded, { "sigVerify": sig_verify }]),
|
||||
json!([serialized_encoded, config]),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1418,7 +1456,7 @@ mod tests {
|
||||
let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||
|
||||
let key = Keypair::new();
|
||||
let to = Pubkey::new_rand();
|
||||
let to = solana_sdk::pubkey::new_rand();
|
||||
let blockhash = Hash::default();
|
||||
let tx = system_transaction::transfer(&key, &to, 50, blockhash);
|
||||
|
||||
@@ -1471,7 +1509,7 @@ mod tests {
|
||||
let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||
|
||||
let key = Keypair::new();
|
||||
let to = Pubkey::new_rand();
|
||||
let to = solana_sdk::pubkey::new_rand();
|
||||
let blockhash = Hash::default();
|
||||
let tx = system_transaction::transfer(&key, &to, 50, blockhash);
|
||||
let result = rpc_client.send_and_confirm_transaction(&tx);
|
||||
|
@@ -1,13 +1,15 @@
|
||||
//! Implementation defined RPC server errors
|
||||
|
||||
use crate::rpc_response::RpcSimulateTransactionResult;
|
||||
use jsonrpc_core::{Error, ErrorCode};
|
||||
use solana_client::rpc_response::RpcSimulateTransactionResult;
|
||||
use solana_sdk::clock::Slot;
|
||||
|
||||
const JSON_RPC_SERVER_ERROR_1: i64 = -32001;
|
||||
const JSON_RPC_SERVER_ERROR_2: i64 = -32002;
|
||||
const JSON_RPC_SERVER_ERROR_3: i64 = -32003;
|
||||
const JSON_RPC_SERVER_ERROR_4: i64 = -32004;
|
||||
const JSON_RPC_SERVER_ERROR_5: i64 = -32005;
|
||||
const JSON_RPC_SERVER_ERROR_6: i64 = -32006;
|
||||
pub const JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP: i64 = -32001;
|
||||
pub const JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE: i64 = -32002;
|
||||
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE: i64 = -32003;
|
||||
pub const JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE: i64 = -32004;
|
||||
pub const JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY: i64 = -32005;
|
||||
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64 = -32006;
|
||||
|
||||
pub enum RpcCustomError {
|
||||
BlockCleanedUp {
|
||||
@@ -33,7 +35,7 @@ impl From<RpcCustomError> for Error {
|
||||
slot,
|
||||
first_available_block,
|
||||
} => Self {
|
||||
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_1),
|
||||
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP),
|
||||
message: format!(
|
||||
"Block {} cleaned up, does not exist on node. First available block: {}",
|
||||
slot, first_available_block,
|
||||
@@ -41,27 +43,33 @@ impl From<RpcCustomError> for Error {
|
||||
data: None,
|
||||
},
|
||||
RpcCustomError::SendTransactionPreflightFailure { message, result } => Self {
|
||||
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_2),
|
||||
code: ErrorCode::ServerError(
|
||||
JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
|
||||
),
|
||||
message,
|
||||
data: Some(serde_json::json!(result)),
|
||||
},
|
||||
RpcCustomError::TransactionSignatureVerificationFailure => Self {
|
||||
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_3),
|
||||
code: ErrorCode::ServerError(
|
||||
JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE,
|
||||
),
|
||||
message: "Transaction signature verification failure".to_string(),
|
||||
data: None,
|
||||
},
|
||||
RpcCustomError::BlockNotAvailable { slot } => Self {
|
||||
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_4),
|
||||
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE),
|
||||
message: format!("Block not available for slot {}", slot),
|
||||
data: None,
|
||||
},
|
||||
RpcCustomError::RpcNodeUnhealthy => Self {
|
||||
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_5),
|
||||
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY),
|
||||
message: "RPC node is unhealthy".to_string(),
|
||||
data: None,
|
||||
},
|
||||
RpcCustomError::TransactionPrecompileVerificationFailure(e) => Self {
|
||||
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_6),
|
||||
code: ErrorCode::ServerError(
|
||||
JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE,
|
||||
),
|
||||
message: format!("Transaction precompile verification failure {:?}", e),
|
||||
data: None,
|
||||
},
|
@@ -140,8 +140,10 @@ impl RpcRequest {
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum RpcError {
|
||||
#[error("rpc request error: {0}")]
|
||||
#[error("RPC request error: {0}")]
|
||||
RpcRequestError(String),
|
||||
#[error("RPC response error {code}: {message}")]
|
||||
RpcResponseError { code: i64, message: String },
|
||||
#[error("parse error: expected {0}")]
|
||||
ParseError(String), /* "expected" */
|
||||
// Anything in a `ForUser` needs to die. The caller should be
|
||||
@@ -226,7 +228,7 @@ mod tests {
|
||||
|
||||
// Test request with CommitmentConfig and params
|
||||
let test_request = RpcRequest::GetTokenAccountsByOwner;
|
||||
let mint = Pubkey::new_rand();
|
||||
let mint = solana_sdk::pubkey::new_rand();
|
||||
let token_account_filter = RpcTokenAccountsFilter::Mint(mint.to_string());
|
||||
let request = test_request
|
||||
.build_request_json(1, json!([addr, token_account_filter, commitment_config]));
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-core"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "../README.md"
|
||||
@@ -39,48 +39,48 @@ num-traits = "0.2"
|
||||
rand = "0.7.0"
|
||||
rand_chacha = "0.2.2"
|
||||
raptorq = "1.4.2"
|
||||
rayon = "1.4.0"
|
||||
rayon = "1.4.1"
|
||||
regex = "1.3.9"
|
||||
serde = "1.0.112"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.4.0" }
|
||||
solana-banks-server = { path = "../banks-server", version = "1.4.0" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.4.0" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
|
||||
solana-client = { path = "../client", version = "1.4.0" }
|
||||
solana-faucet = { path = "../faucet", version = "1.4.0" }
|
||||
solana-ledger = { path = "../ledger", version = "1.4.0" }
|
||||
solana-logger = { path = "../logger", version = "1.4.0" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.4.0" }
|
||||
solana-metrics = { path = "../metrics", version = "1.4.0" }
|
||||
solana-measure = { path = "../measure", version = "1.4.0" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
|
||||
solana-perf = { path = "../perf", version = "1.4.0" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-sdk-macro-frozen-abi = { path = "../sdk/macro-frozen-abi", version = "1.4.0" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "1.4.0" }
|
||||
solana-streamer = { path = "../streamer", version = "1.4.0" }
|
||||
solana-sys-tuner = { path = "../sys-tuner", version = "1.4.0" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.4.0" }
|
||||
solana-version = { path = "../version", version = "1.4.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.4.0" }
|
||||
spl-token-v2-0 = { package = "spl-token", version = "=2.0.6", features = ["skip-no-mangle"] }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.4.2" }
|
||||
solana-banks-server = { path = "../banks-server", version = "1.4.2" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
|
||||
solana-client = { path = "../client", version = "1.4.2" }
|
||||
solana-faucet = { path = "../faucet", version = "1.4.2" }
|
||||
solana-frozen-abi = { path = "../frozen-abi", version = "1.4.2" }
|
||||
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "1.4.2" }
|
||||
solana-ledger = { path = "../ledger", version = "1.4.2" }
|
||||
solana-logger = { path = "../logger", version = "1.4.2" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.4.2" }
|
||||
solana-metrics = { path = "../metrics", version = "1.4.2" }
|
||||
solana-measure = { path = "../measure", version = "1.4.2" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
|
||||
solana-perf = { path = "../perf", version = "1.4.2" }
|
||||
solana-runtime = { path = "../runtime", version = "1.4.2" }
|
||||
solana-sdk = { path = "../sdk", version = "1.4.2" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.4.2" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "1.4.2" }
|
||||
solana-streamer = { path = "../streamer", version = "1.4.2" }
|
||||
solana-sys-tuner = { path = "../sys-tuner", version = "1.4.2" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.4.2" }
|
||||
solana-version = { path = "../version", version = "1.4.2" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.4.2" }
|
||||
spl-token-v2-0 = { package = "spl-token", version = "=2.0.8" }
|
||||
tempfile = "3.1.0"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "0.2.22", features = ["full"] }
|
||||
tokio_01 = { version = "0.1", package = "tokio" }
|
||||
tokio_fs_01 = { version = "0.1", package = "tokio-fs" }
|
||||
tokio_io_01 = { version = "0.1", package = "tokio-io" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.4.0" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.4.2" }
|
||||
trees = "0.2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
matches = "0.1.6"
|
||||
reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
reqwest = { version = "0.10.8", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
serial_test = "0.4.0"
|
||||
serial_test_derive = "0.4.0"
|
||||
systemstat = "0.1.5"
|
||||
|
@@ -20,7 +20,7 @@ use solana_runtime::bank::Bank;
|
||||
use solana_sdk::genesis_config::GenesisConfig;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::pubkey;
|
||||
use solana_sdk::signature::Keypair;
|
||||
use solana_sdk::signature::Signature;
|
||||
use solana_sdk::signature::Signer;
|
||||
@@ -56,7 +56,7 @@ fn bench_consume_buffered(bencher: &mut Bencher) {
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100_000);
|
||||
let bank = Arc::new(Bank::new(&genesis_config));
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let my_pubkey = Pubkey::new_rand();
|
||||
let my_pubkey = pubkey::new_rand();
|
||||
{
|
||||
let blockstore = Arc::new(
|
||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
|
||||
@@ -94,15 +94,15 @@ fn bench_consume_buffered(bencher: &mut Bencher) {
|
||||
}
|
||||
|
||||
fn make_accounts_txs(txes: usize, mint_keypair: &Keypair, hash: Hash) -> Vec<Transaction> {
|
||||
let to_pubkey = Pubkey::new_rand();
|
||||
let to_pubkey = pubkey::new_rand();
|
||||
let dummy = system_transaction::transfer(mint_keypair, &to_pubkey, 1, hash);
|
||||
(0..txes)
|
||||
.into_par_iter()
|
||||
.map(|_| {
|
||||
let mut new = dummy.clone();
|
||||
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
|
||||
new.message.account_keys[0] = Pubkey::new_rand();
|
||||
new.message.account_keys[1] = Pubkey::new_rand();
|
||||
new.message.account_keys[0] = pubkey::new_rand();
|
||||
new.message.account_keys[1] = pubkey::new_rand();
|
||||
new.signatures = vec![Signature::new(&sig[0..64])];
|
||||
new
|
||||
})
|
||||
@@ -117,7 +117,7 @@ fn make_programs_txs(txes: usize, hash: Hash) -> Vec<Transaction> {
|
||||
let mut instructions = vec![];
|
||||
let from_key = Keypair::new();
|
||||
for _ in 1..progs {
|
||||
let to_key = Pubkey::new_rand();
|
||||
let to_key = pubkey::new_rand();
|
||||
instructions.push(system_instruction::transfer(&from_key.pubkey(), &to_key, 1));
|
||||
}
|
||||
let message = Message::new(&instructions, Some(&from_key.pubkey()));
|
||||
|
@@ -8,7 +8,7 @@ use solana_core::broadcast_stage::{broadcast_shreds, get_broadcast_peers};
|
||||
use solana_core::cluster_info::{ClusterInfo, Node};
|
||||
use solana_core::contact_info::ContactInfo;
|
||||
use solana_ledger::shred::Shred;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::pubkey;
|
||||
use solana_sdk::timing::timestamp;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@@ -20,7 +20,7 @@ use test::Bencher;
|
||||
#[bench]
|
||||
fn broadcast_shreds_bench(bencher: &mut Bencher) {
|
||||
solana_logger::setup();
|
||||
let leader_pubkey = Pubkey::new_rand();
|
||||
let leader_pubkey = pubkey::new_rand();
|
||||
let leader_info = Node::new_localhost_with_pubkey(&leader_pubkey);
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(leader_info.info);
|
||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
@@ -30,7 +30,7 @@ fn broadcast_shreds_bench(bencher: &mut Bencher) {
|
||||
let mut stakes = HashMap::new();
|
||||
const NUM_PEERS: usize = 200;
|
||||
for _ in 0..NUM_PEERS {
|
||||
let id = Pubkey::new_rand();
|
||||
let id = pubkey::new_rand();
|
||||
let contact_info = ContactInfo::new_localhost(&id, timestamp());
|
||||
cluster_info.insert_info(contact_info);
|
||||
stakes.insert(id, thread_rng().gen_range(1, NUM_PEERS) as u64);
|
||||
|
@@ -8,13 +8,13 @@ use solana_core::cluster_info::MAX_BLOOM_SIZE;
|
||||
use solana_core::crds::Crds;
|
||||
use solana_core::crds_gossip_pull::{CrdsFilter, CrdsGossipPull};
|
||||
use solana_core::crds_value::CrdsValue;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::hash;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn bench_hash_as_u64(bencher: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
let hashes: Vec<_> = std::iter::repeat_with(|| Hash::new_rand(&mut rng))
|
||||
let hashes: Vec<_> = std::iter::repeat_with(|| hash::new_rand(&mut rng))
|
||||
.take(1000)
|
||||
.collect();
|
||||
bencher.iter(|| {
|
||||
@@ -34,7 +34,7 @@ fn bench_build_crds_filters(bencher: &mut Bencher) {
|
||||
for _ in 0..50_000 {
|
||||
crds_gossip_pull
|
||||
.purged_values
|
||||
.push_back((Hash::new_rand(&mut rng), rng.gen()));
|
||||
.push_back((solana_sdk::hash::new_rand(&mut rng), rng.gen()));
|
||||
}
|
||||
let mut num_inserts = 0;
|
||||
for _ in 0..90_000 {
|
||||
|
@@ -7,14 +7,14 @@ use solana_core::contact_info::ContactInfo;
|
||||
use solana_core::crds::VersionedCrdsValue;
|
||||
use solana_core::crds_shards::CrdsShards;
|
||||
use solana_core::crds_value::{CrdsData, CrdsValue};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::pubkey;
|
||||
use solana_sdk::timing::timestamp;
|
||||
use test::Bencher;
|
||||
|
||||
const CRDS_SHARDS_BITS: u32 = 8;
|
||||
|
||||
fn new_test_crds_value() -> VersionedCrdsValue {
|
||||
let data = CrdsData::ContactInfo(ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp()));
|
||||
let data = CrdsData::ContactInfo(ContactInfo::new_localhost(&pubkey::new_rand(), timestamp()));
|
||||
VersionedCrdsValue::new(timestamp(), CrdsValue::new_unsigned(data))
|
||||
}
|
||||
|
||||
|
@@ -14,7 +14,7 @@ use solana_perf::packet::to_packets_chunked;
|
||||
use solana_perf::test_tx::test_tx;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::bank_forks::BankForks;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::pubkey;
|
||||
use solana_sdk::timing::timestamp;
|
||||
use std::net::UdpSocket;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
@@ -34,7 +34,7 @@ fn bench_retransmitter(bencher: &mut Bencher) {
|
||||
const NUM_PEERS: usize = 4;
|
||||
let mut peer_sockets = Vec::new();
|
||||
for _ in 0..NUM_PEERS {
|
||||
let id = Pubkey::new_rand();
|
||||
let id = pubkey::new_rand();
|
||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
let mut contact_info = ContactInfo::new_localhost(&id, timestamp());
|
||||
contact_info.tvu = socket.local_addr().unwrap();
|
||||
|
@@ -1 +1 @@
|
||||
../sdk/build.rs
|
||||
../frozen-abi/build.rs
|
@@ -204,6 +204,7 @@ mod tests {
|
||||
{
|
||||
let message = make_accounts_hashes_message(&validator1, vec![(0, hash1)]).unwrap();
|
||||
cluster_info.push_message(message);
|
||||
cluster_info.flush_push_queue();
|
||||
}
|
||||
slot_to_hash.insert(0, hash2);
|
||||
trusted_validators.insert(validator1.pubkey());
|
||||
@@ -254,6 +255,7 @@ mod tests {
|
||||
100,
|
||||
);
|
||||
}
|
||||
cluster_info.flush_push_queue();
|
||||
let cluster_hashes = cluster_info
|
||||
.get_accounts_hash_for_node(&keypair.pubkey(), |c| c.clone())
|
||||
.unwrap();
|
||||
|
@@ -60,7 +60,7 @@ impl ForkChoice for BankWeightForkChoice {
|
||||
trace!("frozen_banks {}", frozen_banks.len());
|
||||
let num_old_banks = frozen_banks
|
||||
.iter()
|
||||
.filter(|b| b.slot() < tower.root().unwrap_or(0))
|
||||
.filter(|b| b.slot() < tower.root())
|
||||
.count();
|
||||
|
||||
let last_voted_slot = tower.last_voted_slot();
|
||||
|
@@ -534,13 +534,14 @@ impl BankingStage {
|
||||
mut loaded_accounts,
|
||||
results,
|
||||
inner_instructions,
|
||||
transaction_logs,
|
||||
mut retryable_txs,
|
||||
tx_count,
|
||||
signature_count,
|
||||
) = bank.load_and_execute_transactions(
|
||||
batch,
|
||||
MAX_PROCESSING_AGE,
|
||||
None,
|
||||
transaction_status_sender.is_some(),
|
||||
transaction_status_sender.is_some(),
|
||||
);
|
||||
load_execute_time.stop();
|
||||
@@ -580,6 +581,7 @@ impl BankingStage {
|
||||
tx_results.processing_results,
|
||||
TransactionBalancesSet::new(pre_balances, post_balances),
|
||||
inner_instructions,
|
||||
transaction_logs,
|
||||
sender,
|
||||
);
|
||||
}
|
||||
@@ -1244,16 +1246,16 @@ mod tests {
|
||||
bank.process_transaction(&fund_tx).unwrap();
|
||||
|
||||
// good tx
|
||||
let to = Pubkey::new_rand();
|
||||
let to = solana_sdk::pubkey::new_rand();
|
||||
let tx = system_transaction::transfer(&mint_keypair, &to, 1, start_hash);
|
||||
|
||||
// good tx, but no verify
|
||||
let to2 = Pubkey::new_rand();
|
||||
let to2 = solana_sdk::pubkey::new_rand();
|
||||
let tx_no_ver = system_transaction::transfer(&keypair, &to2, 2, start_hash);
|
||||
|
||||
// bad tx, AccountNotFound
|
||||
let keypair = Keypair::new();
|
||||
let to3 = Pubkey::new_rand();
|
||||
let to3 = solana_sdk::pubkey::new_rand();
|
||||
let tx_anf = system_transaction::transfer(&keypair, &to3, 1, start_hash);
|
||||
|
||||
// send 'em over
|
||||
@@ -1446,9 +1448,9 @@ mod tests {
|
||||
let poh_recorder = Arc::new(Mutex::new(poh_recorder));
|
||||
|
||||
poh_recorder.lock().unwrap().set_working_bank(working_bank);
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let keypair2 = Keypair::new();
|
||||
let pubkey2 = Pubkey::new_rand();
|
||||
let pubkey2 = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let transactions = vec![
|
||||
system_transaction::transfer(&mint_keypair, &pubkey, 1, genesis_config.hash()),
|
||||
@@ -1526,7 +1528,7 @@ mod tests {
|
||||
mint_keypair,
|
||||
..
|
||||
} = create_genesis_config(10_000);
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let transactions = vec![
|
||||
None,
|
||||
@@ -1607,7 +1609,7 @@ mod tests {
|
||||
mint_keypair,
|
||||
..
|
||||
} = create_genesis_config(10_000);
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let transactions = vec![
|
||||
system_transaction::transfer(&mint_keypair, &pubkey, 1, genesis_config.hash()),
|
||||
@@ -1678,8 +1680,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_should_process_or_forward_packets() {
|
||||
let my_pubkey = Pubkey::new_rand();
|
||||
let my_pubkey1 = Pubkey::new_rand();
|
||||
let my_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let my_pubkey1 = solana_sdk::pubkey::new_rand();
|
||||
|
||||
assert_eq!(
|
||||
BankingStage::consume_or_forward_packets(&my_pubkey, None, true, false,),
|
||||
@@ -1725,7 +1727,7 @@ mod tests {
|
||||
..
|
||||
} = create_genesis_config(10_000);
|
||||
let bank = Arc::new(Bank::new(&genesis_config));
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let transactions = vec![system_transaction::transfer(
|
||||
&mint_keypair,
|
||||
@@ -1822,8 +1824,8 @@ mod tests {
|
||||
..
|
||||
} = create_genesis_config(10_000);
|
||||
let bank = Arc::new(Bank::new(&genesis_config));
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey1 = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let pubkey1 = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let transactions = vec![
|
||||
system_transaction::transfer(&mint_keypair, &pubkey, 1, genesis_config.hash()),
|
||||
@@ -1918,7 +1920,7 @@ mod tests {
|
||||
} = create_genesis_config(10_000);
|
||||
let bank = Arc::new(Bank::new(&genesis_config));
|
||||
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let transactions =
|
||||
vec![
|
||||
@@ -1936,7 +1938,7 @@ mod tests {
|
||||
bank.slot(),
|
||||
Some((4, 4)),
|
||||
bank.ticks_per_slot(),
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
&Arc::new(blockstore),
|
||||
&Arc::new(LeaderScheduleCache::new_from_bank(&bank)),
|
||||
&Arc::new(PohConfig::default()),
|
||||
@@ -1976,8 +1978,8 @@ mod tests {
|
||||
..
|
||||
} = create_genesis_config(10_000);
|
||||
let bank = Arc::new(Bank::new(&genesis_config));
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey1 = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let pubkey1 = solana_sdk::pubkey::new_rand();
|
||||
let keypair1 = Keypair::new();
|
||||
|
||||
let success_tx =
|
||||
|
@@ -140,13 +140,12 @@ impl BroadcastRun for BroadcastFakeShredsRun {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::contact_info::ContactInfo;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
|
||||
#[test]
|
||||
fn test_tvu_peers_ordering() {
|
||||
let cluster = ClusterInfo::new_with_invalid_keypair(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
));
|
||||
cluster.insert_info(ContactInfo::new_with_socketaddr(&SocketAddr::new(
|
||||
|
@@ -92,7 +92,7 @@ mod tests {
|
||||
let bank0 = Arc::new(Bank::new(&genesis_config));
|
||||
let tx = system_transaction::transfer(
|
||||
&mint_keypair,
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
1,
|
||||
genesis_config.hash(),
|
||||
);
|
||||
|
@@ -21,6 +21,7 @@ use crate::{
|
||||
self, CrdsData, CrdsValue, CrdsValueLabel, EpochSlotsIndex, LowestSlot, SnapshotHash,
|
||||
Version, Vote, MAX_WALLCLOCK,
|
||||
},
|
||||
data_budget::DataBudget,
|
||||
epoch_slots::EpochSlots,
|
||||
result::{Error, Result},
|
||||
weighted_shuffle::weighted_shuffle,
|
||||
@@ -51,6 +52,7 @@ use solana_perf::packet::{
|
||||
};
|
||||
use solana_rayon_threadlimit::get_thread_count;
|
||||
use solana_runtime::bank_forks::BankForks;
|
||||
use solana_runtime::feature_set::{self, FeatureSet};
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::{
|
||||
clock::{Slot, DEFAULT_MS_PER_SLOT, DEFAULT_SLOTS_PER_EPOCH},
|
||||
@@ -103,12 +105,6 @@ pub enum ClusterInfoError {
|
||||
BadContactInfo,
|
||||
BadGossipAddress,
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct DataBudget {
|
||||
bytes: usize, // amount of bytes we have in the budget to send
|
||||
last_timestamp_ms: u64, // Last time that we upped the bytes count,
|
||||
// used to detect when to up the bytes budget again
|
||||
}
|
||||
|
||||
struct GossipWriteLock<'a> {
|
||||
gossip: RwLockWriteGuard<'a, CrdsGossip>,
|
||||
@@ -215,6 +211,7 @@ struct GossipStats {
|
||||
new_push_requests2: Counter,
|
||||
new_push_requests_num: Counter,
|
||||
filter_pull_response: Counter,
|
||||
process_gossip_packets_time: Counter,
|
||||
process_pull_response: Counter,
|
||||
process_pull_response_count: Counter,
|
||||
process_pull_response_len: Counter,
|
||||
@@ -252,11 +249,12 @@ pub struct ClusterInfo {
|
||||
pub(crate) keypair: Arc<Keypair>,
|
||||
/// The network entrypoint
|
||||
entrypoint: RwLock<Option<ContactInfo>>,
|
||||
outbound_budget: RwLock<DataBudget>,
|
||||
outbound_budget: DataBudget,
|
||||
my_contact_info: RwLock<ContactInfo>,
|
||||
id: Pubkey,
|
||||
stats: GossipStats,
|
||||
socket: UdpSocket,
|
||||
local_message_pending_push_queue: RwLock<Vec<(CrdsValue, u64)>>,
|
||||
}
|
||||
|
||||
impl Default for ClusterInfo {
|
||||
@@ -369,6 +367,59 @@ enum Protocol {
|
||||
PruneMessage(Pubkey, PruneData),
|
||||
}
|
||||
|
||||
impl Protocol {
|
||||
fn par_verify(self) -> Option<Self> {
|
||||
match self {
|
||||
Protocol::PullRequest(_, ref caller) => {
|
||||
if caller.verify() {
|
||||
Some(self)
|
||||
} else {
|
||||
inc_new_counter_info!("cluster_info-gossip_pull_request_verify_fail", 1);
|
||||
None
|
||||
}
|
||||
}
|
||||
Protocol::PullResponse(from, data) => {
|
||||
let size = data.len();
|
||||
let data: Vec<_> = data.into_par_iter().filter(Signable::verify).collect();
|
||||
if size != data.len() {
|
||||
inc_new_counter_info!(
|
||||
"cluster_info-gossip_pull_response_verify_fail",
|
||||
size - data.len()
|
||||
);
|
||||
}
|
||||
if data.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Protocol::PullResponse(from, data))
|
||||
}
|
||||
}
|
||||
Protocol::PushMessage(from, data) => {
|
||||
let size = data.len();
|
||||
let data: Vec<_> = data.into_par_iter().filter(Signable::verify).collect();
|
||||
if size != data.len() {
|
||||
inc_new_counter_info!(
|
||||
"cluster_info-gossip_push_msg_verify_fail",
|
||||
size - data.len()
|
||||
);
|
||||
}
|
||||
if data.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Protocol::PushMessage(from, data))
|
||||
}
|
||||
}
|
||||
Protocol::PruneMessage(_, ref data) => {
|
||||
if data.verify() {
|
||||
Some(self)
|
||||
} else {
|
||||
inc_new_counter_debug!("cluster_info-gossip_prune_msg_verify_fail", 1);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sanitize for Protocol {
|
||||
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
||||
match self {
|
||||
@@ -406,14 +457,12 @@ impl ClusterInfo {
|
||||
gossip: RwLock::new(CrdsGossip::default()),
|
||||
keypair,
|
||||
entrypoint: RwLock::new(None),
|
||||
outbound_budget: RwLock::new(DataBudget {
|
||||
bytes: 0,
|
||||
last_timestamp_ms: 0,
|
||||
}),
|
||||
outbound_budget: DataBudget::default(),
|
||||
my_contact_info: RwLock::new(contact_info),
|
||||
id,
|
||||
stats: GossipStats::default(),
|
||||
socket: UdpSocket::bind("0.0.0.0:0").unwrap(),
|
||||
local_message_pending_push_queue: RwLock::new(vec![]),
|
||||
};
|
||||
{
|
||||
let mut gossip = me.gossip.write().unwrap();
|
||||
@@ -435,11 +484,17 @@ impl ClusterInfo {
|
||||
gossip: RwLock::new(gossip),
|
||||
keypair: self.keypair.clone(),
|
||||
entrypoint: RwLock::new(self.entrypoint.read().unwrap().clone()),
|
||||
outbound_budget: RwLock::new(self.outbound_budget.read().unwrap().clone()),
|
||||
outbound_budget: self.outbound_budget.clone_non_atomic(),
|
||||
my_contact_info: RwLock::new(my_contact_info),
|
||||
id: *new_id,
|
||||
stats: GossipStats::default(),
|
||||
socket: UdpSocket::bind("0.0.0.0:0").unwrap(),
|
||||
local_message_pending_push_queue: RwLock::new(
|
||||
self.local_message_pending_push_queue
|
||||
.read()
|
||||
.unwrap()
|
||||
.clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,9 +517,14 @@ impl ClusterInfo {
|
||||
self.my_contact_info.write().unwrap().wallclock = now;
|
||||
let entry =
|
||||
CrdsValue::new_signed(CrdsData::ContactInfo(self.my_contact_info()), &self.keypair);
|
||||
let mut w_gossip = self.gossip.write().unwrap();
|
||||
w_gossip.refresh_push_active_set(stakes, gossip_validators);
|
||||
w_gossip.process_push_message(&self.id(), vec![entry], now);
|
||||
self.gossip
|
||||
.write()
|
||||
.unwrap()
|
||||
.refresh_push_active_set(stakes, gossip_validators);
|
||||
self.local_message_pending_push_queue
|
||||
.write()
|
||||
.unwrap()
|
||||
.push((entry, now));
|
||||
}
|
||||
|
||||
// TODO kill insert_info, only used by tests
|
||||
@@ -530,6 +590,70 @@ impl ClusterInfo {
|
||||
.unwrap_or_else(|| EpochSlots::new(self.id(), timestamp()))
|
||||
}
|
||||
|
||||
pub fn rpc_info_trace(&self) -> String {
|
||||
let now = timestamp();
|
||||
let my_pubkey = self.id();
|
||||
let my_shred_version = self.my_shred_version();
|
||||
let nodes: Vec<_> = self
|
||||
.all_peers()
|
||||
.into_iter()
|
||||
.filter_map(|(node, last_updated)| {
|
||||
if !ContactInfo::is_valid_address(&node.rpc) {
|
||||
info!("invalid rpc: {}", node.rpc.to_string());
|
||||
return None;
|
||||
}
|
||||
|
||||
let node_version = self.get_node_version(&node.id);
|
||||
if my_shred_version != 0
|
||||
&& (node.shred_version != 0 && node.shred_version != my_shred_version)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
fn addr_to_string(default_ip: &IpAddr, addr: &SocketAddr) -> String {
|
||||
if ContactInfo::is_valid_address(addr) {
|
||||
if &addr.ip() == default_ip {
|
||||
addr.port().to_string()
|
||||
} else {
|
||||
addr.to_string()
|
||||
}
|
||||
} else {
|
||||
"none".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
let rpc_addr = node.rpc.ip();
|
||||
Some(format!(
|
||||
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {}\n",
|
||||
rpc_addr.to_string(),
|
||||
if node.id == my_pubkey { "me" } else { "" }.to_string(),
|
||||
now.saturating_sub(last_updated),
|
||||
node.id.to_string(),
|
||||
if let Some(node_version) = node_version {
|
||||
node_version.to_string()
|
||||
} else {
|
||||
"-".to_string()
|
||||
},
|
||||
addr_to_string(&rpc_addr, &node.rpc),
|
||||
addr_to_string(&rpc_addr, &node.rpc_pubsub),
|
||||
addr_to_string(&rpc_addr, &node.rpc_banks),
|
||||
node.shred_version,
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
|
||||
format!(
|
||||
"RPC Address |Age(ms)| Node identifier \
|
||||
| Version | RPC |PubSub| Banks|ShredVer\n\
|
||||
------------------+-------+----------------------------------------------+---------+\
|
||||
------+------+------+--------\n\
|
||||
{}\
|
||||
RPC Enabled Nodes: {}",
|
||||
nodes.join(""),
|
||||
nodes.len(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn contact_info_trace(&self) -> String {
|
||||
let now = timestamp();
|
||||
let mut spy_nodes = 0;
|
||||
@@ -562,7 +686,7 @@ impl ClusterInfo {
|
||||
}
|
||||
let ip_addr = node.gossip.ip();
|
||||
Some(format!(
|
||||
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
|
||||
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
|
||||
if ContactInfo::is_valid_address(&node.gossip) {
|
||||
ip_addr.to_string()
|
||||
} else {
|
||||
@@ -583,9 +707,6 @@ impl ClusterInfo {
|
||||
addr_to_string(&ip_addr, &node.tvu_forwards),
|
||||
addr_to_string(&ip_addr, &node.repair),
|
||||
addr_to_string(&ip_addr, &node.serve_repair),
|
||||
addr_to_string(&ip_addr, &node.rpc),
|
||||
addr_to_string(&ip_addr, &node.rpc_pubsub),
|
||||
addr_to_string(&ip_addr, &node.rpc_banks),
|
||||
node.shred_version,
|
||||
))
|
||||
}
|
||||
@@ -594,9 +715,9 @@ impl ClusterInfo {
|
||||
|
||||
format!(
|
||||
"IP Address |Age(ms)| Node identifier \
|
||||
| Version |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR| RPC |PubSub|ShredVer\n\
|
||||
| Version |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR|ShredVer\n\
|
||||
------------------+-------+----------------------------------------------+---------+\
|
||||
------+------+------+------+------+------+------+------+------+--------\n\
|
||||
------+------+------+------+------+------+------+--------\n\
|
||||
{}\
|
||||
Nodes: {}{}{}",
|
||||
nodes.join(""),
|
||||
@@ -633,10 +754,10 @@ impl ClusterInfo {
|
||||
CrdsData::LowestSlot(0, LowestSlot::new(id, min, now)),
|
||||
&self.keypair,
|
||||
);
|
||||
self.gossip
|
||||
self.local_message_pending_push_queue
|
||||
.write()
|
||||
.unwrap()
|
||||
.process_push_message(&self.id(), vec![entry], now);
|
||||
.push((entry, now));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,8 +810,10 @@ impl ClusterInfo {
|
||||
let n = slots.fill(&update[num..], now);
|
||||
if n > 0 {
|
||||
let entry = CrdsValue::new_signed(CrdsData::EpochSlots(ix, slots), &self.keypair);
|
||||
self.time_gossip_write_lock("epcoh_slots_push", &self.stats.epoch_slots_push)
|
||||
.process_push_message(&self.id(), vec![entry], now);
|
||||
self.local_message_pending_push_queue
|
||||
.write()
|
||||
.unwrap()
|
||||
.push((entry, now));
|
||||
}
|
||||
num += n;
|
||||
if num < update.len() {
|
||||
@@ -718,9 +841,10 @@ impl ClusterInfo {
|
||||
|
||||
pub fn push_message(&self, message: CrdsValue) {
|
||||
let now = message.wallclock();
|
||||
let id = message.pubkey();
|
||||
self.time_gossip_write_lock("process_push_message", &self.stats.push_message)
|
||||
.process_push_message(&id, vec![message], now);
|
||||
self.local_message_pending_push_queue
|
||||
.write()
|
||||
.unwrap()
|
||||
.push((message, now));
|
||||
}
|
||||
|
||||
pub fn push_accounts_hashes(&self, accounts_hashes: Vec<(Slot, Hash)>) {
|
||||
@@ -761,8 +885,10 @@ impl ClusterInfo {
|
||||
CrdsValue::compute_vote_index(tower_index, current_votes)
|
||||
};
|
||||
let entry = CrdsValue::new_signed(CrdsData::Vote(vote_ix, vote), &self.keypair);
|
||||
self.time_gossip_write_lock("push_vote_process_push", &self.stats.vote_process_push)
|
||||
.process_push_message(&self.id(), vec![entry], now);
|
||||
self.local_message_pending_push_queue
|
||||
.write()
|
||||
.unwrap()
|
||||
.push((entry, now));
|
||||
}
|
||||
|
||||
pub fn send_vote(&self, vote: &Transaction) -> Result<()> {
|
||||
@@ -1425,11 +1551,21 @@ impl ClusterInfo {
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
fn drain_push_queue(&self) -> Vec<(CrdsValue, u64)> {
|
||||
let mut push_queue = self.local_message_pending_push_queue.write().unwrap();
|
||||
std::mem::take(&mut *push_queue)
|
||||
}
|
||||
#[cfg(test)]
|
||||
pub fn flush_push_queue(&self) {
|
||||
let pending_push_messages = self.drain_push_queue();
|
||||
let mut gossip = self.gossip.write().unwrap();
|
||||
gossip.process_push_messages(pending_push_messages);
|
||||
}
|
||||
fn new_push_requests(&self) -> Vec<(SocketAddr, Protocol)> {
|
||||
let self_id = self.id();
|
||||
let (_, push_messages) = self
|
||||
.time_gossip_write_lock("new_push_requests", &self.stats.new_push_requests)
|
||||
.new_push_messages(timestamp());
|
||||
.new_push_messages(self.drain_push_queue(), timestamp());
|
||||
let messages: Vec<_> = push_messages
|
||||
.into_iter()
|
||||
.filter_map(|(peer, messages)| {
|
||||
@@ -1580,7 +1716,11 @@ impl ClusterInfo {
|
||||
thread_mem_usage::datapoint("solana-gossip");
|
||||
if start - last_contact_info_trace > 10000 {
|
||||
// Log contact info every 10 seconds
|
||||
info!("\n{}", self.contact_info_trace());
|
||||
info!(
|
||||
"\n{}\n\n{}",
|
||||
self.contact_info_trace(),
|
||||
self.rpc_info_trace()
|
||||
);
|
||||
last_contact_info_trace = start;
|
||||
}
|
||||
|
||||
@@ -1629,8 +1769,9 @@ impl ClusterInfo {
|
||||
&self,
|
||||
recycler: &PacketsRecycler,
|
||||
stakes: &HashMap<Pubkey, u64>,
|
||||
packets: Packets,
|
||||
packets: Vec<(SocketAddr, Protocol)>,
|
||||
response_sender: &PacketSender,
|
||||
feature_set: Option<&FeatureSet>,
|
||||
epoch_time_ms: u64,
|
||||
) {
|
||||
// iter over the packets, collect pulls separately and process everything else
|
||||
@@ -1642,115 +1783,82 @@ impl ClusterInfo {
|
||||
.unwrap()
|
||||
.make_timeouts(&stakes, epoch_time_ms);
|
||||
let mut pull_responses = HashMap::new();
|
||||
packets.packets.iter().for_each(|packet| {
|
||||
let from_addr = packet.meta.addr();
|
||||
limited_deserialize(&packet.data[..packet.meta.size])
|
||||
.into_iter()
|
||||
.filter(|r: &Protocol| r.sanitize().is_ok())
|
||||
.for_each(|request| match request {
|
||||
Protocol::PullRequest(filter, caller) => {
|
||||
let start = allocated.get();
|
||||
if !caller.verify() {
|
||||
inc_new_counter_info!(
|
||||
"cluster_info-gossip_pull_request_verify_fail",
|
||||
1
|
||||
);
|
||||
} else if let Some(contact_info) = caller.contact_info() {
|
||||
if contact_info.id == self.id() {
|
||||
warn!("PullRequest ignored, I'm talking to myself");
|
||||
inc_new_counter_debug!("cluster_info-window-request-loopback", 1);
|
||||
} else if contact_info.shred_version == 0
|
||||
|| contact_info.shred_version == self.my_shred_version()
|
||||
|| self.my_shred_version() == 0
|
||||
{
|
||||
gossip_pull_data.push(PullData {
|
||||
from_addr,
|
||||
caller,
|
||||
filter,
|
||||
});
|
||||
} else {
|
||||
self.stats.skip_pull_shred_version.add_relaxed(1);
|
||||
}
|
||||
}
|
||||
datapoint_debug!(
|
||||
"solana-gossip-listen-memory",
|
||||
("pull_request", (allocated.get() - start) as i64, i64),
|
||||
);
|
||||
}
|
||||
Protocol::PullResponse(from, mut data) => {
|
||||
let start = allocated.get();
|
||||
data.retain(|v| {
|
||||
let ret = v.verify();
|
||||
if !ret {
|
||||
inc_new_counter_info!(
|
||||
"cluster_info-gossip_pull_response_verify_fail",
|
||||
1
|
||||
);
|
||||
}
|
||||
ret
|
||||
});
|
||||
let pull_entry = pull_responses.entry(from).or_insert_with(Vec::new);
|
||||
pull_entry.extend(data);
|
||||
datapoint_debug!(
|
||||
"solana-gossip-listen-memory",
|
||||
("pull_response", (allocated.get() - start) as i64, i64),
|
||||
);
|
||||
}
|
||||
Protocol::PushMessage(from, mut data) => {
|
||||
let start = allocated.get();
|
||||
data.retain(|v| {
|
||||
let ret = v.verify();
|
||||
if !ret {
|
||||
inc_new_counter_info!(
|
||||
"cluster_info-gossip_push_msg_verify_fail",
|
||||
1
|
||||
);
|
||||
}
|
||||
ret
|
||||
});
|
||||
let rsp = self.handle_push_message(recycler, &from, data, stakes);
|
||||
if let Some(rsp) = rsp {
|
||||
let _ignore_disconnect = response_sender.send(rsp);
|
||||
}
|
||||
datapoint_debug!(
|
||||
"solana-gossip-listen-memory",
|
||||
("push_message", (allocated.get() - start) as i64, i64),
|
||||
);
|
||||
}
|
||||
Protocol::PruneMessage(from, data) => {
|
||||
let start = allocated.get();
|
||||
if data.verify() {
|
||||
self.stats.prune_message_count.add_relaxed(1);
|
||||
self.stats
|
||||
.prune_message_len
|
||||
.add_relaxed(data.prunes.len() as u64);
|
||||
match self
|
||||
.time_gossip_write_lock("process_prune", &self.stats.process_prune)
|
||||
.process_prune_msg(
|
||||
&from,
|
||||
&data.destination,
|
||||
&data.prunes,
|
||||
data.wallclock,
|
||||
timestamp(),
|
||||
) {
|
||||
Err(CrdsGossipError::PruneMessageTimeout) => {
|
||||
inc_new_counter_debug!("cluster_info-prune_message_timeout", 1)
|
||||
}
|
||||
Err(CrdsGossipError::BadPruneDestination) => {
|
||||
inc_new_counter_debug!("cluster_info-bad_prune_destination", 1)
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
for (from_addr, packet) in packets {
|
||||
match packet {
|
||||
Protocol::PullRequest(filter, caller) => {
|
||||
let start = allocated.get();
|
||||
if let Some(contact_info) = caller.contact_info() {
|
||||
if contact_info.id == self.id() {
|
||||
warn!("PullRequest ignored, I'm talking to myself");
|
||||
inc_new_counter_debug!("cluster_info-window-request-loopback", 1);
|
||||
} else if contact_info.shred_version == 0
|
||||
|| contact_info.shred_version == self.my_shred_version()
|
||||
|| self.my_shred_version() == 0
|
||||
{
|
||||
gossip_pull_data.push(PullData {
|
||||
from_addr,
|
||||
caller,
|
||||
filter,
|
||||
});
|
||||
} else {
|
||||
inc_new_counter_debug!("cluster_info-gossip_prune_msg_verify_fail", 1);
|
||||
self.stats.skip_pull_shred_version.add_relaxed(1);
|
||||
}
|
||||
datapoint_debug!(
|
||||
"solana-gossip-listen-memory",
|
||||
("prune_message", (allocated.get() - start) as i64, i64),
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
datapoint_debug!(
|
||||
"solana-gossip-listen-memory",
|
||||
("pull_request", (allocated.get() - start) as i64, i64),
|
||||
);
|
||||
}
|
||||
Protocol::PullResponse(from, data) => {
|
||||
let start = allocated.get();
|
||||
let pull_entry = pull_responses.entry(from).or_insert_with(Vec::new);
|
||||
pull_entry.extend(data);
|
||||
datapoint_debug!(
|
||||
"solana-gossip-listen-memory",
|
||||
("pull_response", (allocated.get() - start) as i64, i64),
|
||||
);
|
||||
}
|
||||
Protocol::PushMessage(from, data) => {
|
||||
let start = allocated.get();
|
||||
let rsp = self.handle_push_message(recycler, &from, data, stakes);
|
||||
if let Some(rsp) = rsp {
|
||||
let _ignore_disconnect = response_sender.send(rsp);
|
||||
}
|
||||
datapoint_debug!(
|
||||
"solana-gossip-listen-memory",
|
||||
("push_message", (allocated.get() - start) as i64, i64),
|
||||
);
|
||||
}
|
||||
Protocol::PruneMessage(from, data) => {
|
||||
let start = allocated.get();
|
||||
self.stats.prune_message_count.add_relaxed(1);
|
||||
self.stats
|
||||
.prune_message_len
|
||||
.add_relaxed(data.prunes.len() as u64);
|
||||
match self
|
||||
.time_gossip_write_lock("process_prune", &self.stats.process_prune)
|
||||
.process_prune_msg(
|
||||
&from,
|
||||
&data.destination,
|
||||
&data.prunes,
|
||||
data.wallclock,
|
||||
timestamp(),
|
||||
) {
|
||||
Err(CrdsGossipError::PruneMessageTimeout) => {
|
||||
inc_new_counter_debug!("cluster_info-prune_message_timeout", 1)
|
||||
}
|
||||
Err(CrdsGossipError::BadPruneDestination) => {
|
||||
inc_new_counter_debug!("cluster_info-bad_prune_destination", 1)
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
datapoint_debug!(
|
||||
"solana-gossip-listen-memory",
|
||||
("prune_message", (allocated.get() - start) as i64, i64),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (from, data) in pull_responses {
|
||||
self.handle_pull_response(&from, data, &timeouts);
|
||||
@@ -1761,31 +1869,25 @@ impl ClusterInfo {
|
||||
self.stats
|
||||
.pull_requests_count
|
||||
.add_relaxed(gossip_pull_data.len() as u64);
|
||||
let rsp = self.handle_pull_requests(recycler, gossip_pull_data, stakes);
|
||||
let rsp = self.handle_pull_requests(recycler, gossip_pull_data, stakes, feature_set);
|
||||
if let Some(rsp) = rsp {
|
||||
let _ignore_disconnect = response_sender.send(rsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_data_budget(&self, stakes: &HashMap<Pubkey, u64>) {
|
||||
let mut w_outbound_budget = self.outbound_budget.write().unwrap();
|
||||
|
||||
let now = timestamp();
|
||||
fn update_data_budget(&self, num_staked: usize) {
|
||||
const INTERVAL_MS: u64 = 100;
|
||||
// allow 50kBps per staked validator, epoch slots + votes ~= 1.5kB/slot ~= 4kB/s
|
||||
const BYTES_PER_INTERVAL: usize = 5000;
|
||||
const MAX_BUDGET_MULTIPLE: usize = 5; // allow budget build-up to 5x the interval default
|
||||
|
||||
if now - w_outbound_budget.last_timestamp_ms > INTERVAL_MS {
|
||||
let len = std::cmp::max(stakes.len(), 2);
|
||||
w_outbound_budget.bytes += len * BYTES_PER_INTERVAL;
|
||||
w_outbound_budget.bytes = std::cmp::min(
|
||||
w_outbound_budget.bytes,
|
||||
MAX_BUDGET_MULTIPLE * len * BYTES_PER_INTERVAL,
|
||||
);
|
||||
w_outbound_budget.last_timestamp_ms = now;
|
||||
}
|
||||
let num_staked = num_staked.max(2);
|
||||
self.outbound_budget.update(INTERVAL_MS, |bytes| {
|
||||
std::cmp::min(
|
||||
bytes + num_staked * BYTES_PER_INTERVAL,
|
||||
MAX_BUDGET_MULTIPLE * num_staked * BYTES_PER_INTERVAL,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
// Pull requests take an incoming bloom filter of contained entries from a node
|
||||
@@ -1795,12 +1897,18 @@ impl ClusterInfo {
|
||||
recycler: &PacketsRecycler,
|
||||
requests: Vec<PullData>,
|
||||
stakes: &HashMap<Pubkey, u64>,
|
||||
feature_set: Option<&FeatureSet>,
|
||||
) -> Option<Packets> {
|
||||
if matches!(feature_set, Some(feature_set) if
|
||||
feature_set.is_active(&feature_set::pull_request_ping_pong_check::id()))
|
||||
{
|
||||
// TODO: add ping-pong check on pull-request addresses.
|
||||
}
|
||||
// split the requests into addrs and filters
|
||||
let mut caller_and_filters = vec![];
|
||||
let mut addrs = vec![];
|
||||
let mut time = Measure::start("handle_pull_requests");
|
||||
self.update_data_budget(stakes);
|
||||
self.update_data_budget(stakes.len());
|
||||
for pull_data in requests {
|
||||
caller_and_filters.push((pull_data.caller, pull_data.filter));
|
||||
addrs.push(pull_data.from_addr);
|
||||
@@ -1880,17 +1988,13 @@ impl ClusterInfo {
|
||||
let response = pull_responses[stat.to].0[stat.responses_index].clone();
|
||||
let protocol = Protocol::PullResponse(self_id, vec![response]);
|
||||
let new_packet = Packet::from_data(&from_addr, protocol);
|
||||
{
|
||||
let mut w_outbound_budget = self.outbound_budget.write().unwrap();
|
||||
if w_outbound_budget.bytes > new_packet.meta.size {
|
||||
sent.insert(index);
|
||||
w_outbound_budget.bytes -= new_packet.meta.size;
|
||||
total_bytes += new_packet.meta.size;
|
||||
packets.packets.push(new_packet)
|
||||
} else {
|
||||
inc_new_counter_info!("gossip_pull_request-no_budget", 1);
|
||||
break;
|
||||
}
|
||||
if self.outbound_budget.take(new_packet.meta.size) {
|
||||
sent.insert(index);
|
||||
total_bytes += new_packet.meta.size;
|
||||
packets.packets.push(new_packet)
|
||||
} else {
|
||||
inc_new_counter_info!("gossip_pull_request-no_budget", 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
time.stop();
|
||||
@@ -2104,14 +2208,34 @@ impl ClusterInfo {
|
||||
recycler: &PacketsRecycler,
|
||||
response_sender: &PacketSender,
|
||||
stakes: HashMap<Pubkey, u64>,
|
||||
feature_set: Option<&FeatureSet>,
|
||||
epoch_time_ms: u64,
|
||||
) {
|
||||
let sender = response_sender.clone();
|
||||
thread_pool.install(|| {
|
||||
requests.into_par_iter().for_each_with(sender, |s, reqs| {
|
||||
self.handle_packets(&recycler, &stakes, reqs, s, epoch_time_ms)
|
||||
});
|
||||
let mut timer = Measure::start("process_gossip_packets_time");
|
||||
let packets: Vec<_> = thread_pool.install(|| {
|
||||
requests
|
||||
.into_par_iter()
|
||||
.flat_map(|request| request.packets.into_par_iter())
|
||||
.filter_map(|packet| {
|
||||
let protocol: Protocol =
|
||||
limited_deserialize(&packet.data[..packet.meta.size]).ok()?;
|
||||
protocol.sanitize().ok()?;
|
||||
let protocol = protocol.par_verify()?;
|
||||
Some((packet.meta.addr(), protocol))
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
self.handle_packets(
|
||||
recycler,
|
||||
&stakes,
|
||||
packets,
|
||||
response_sender,
|
||||
feature_set,
|
||||
epoch_time_ms,
|
||||
);
|
||||
self.stats
|
||||
.process_gossip_packets_time
|
||||
.add_measure(&mut timer);
|
||||
}
|
||||
|
||||
/// Process messages from the network
|
||||
@@ -2143,13 +2267,25 @@ impl ClusterInfo {
|
||||
}
|
||||
|
||||
let (stakes, epoch_time_ms) = Self::get_stakes_and_epoch_time(bank_forks);
|
||||
|
||||
// Using root_bank instead of working_bank here so that an enbaled
|
||||
// feature does not roll back (if the feature happens to get enabled in
|
||||
// a minority fork).
|
||||
let feature_set = bank_forks.map(|bank_forks| {
|
||||
bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.root_bank()
|
||||
.deref()
|
||||
.feature_set
|
||||
.clone()
|
||||
});
|
||||
self.process_packets(
|
||||
requests,
|
||||
thread_pool,
|
||||
recycler,
|
||||
response_sender,
|
||||
stakes,
|
||||
feature_set.as_deref(),
|
||||
epoch_time_ms,
|
||||
);
|
||||
|
||||
@@ -2210,6 +2346,11 @@ impl ClusterInfo {
|
||||
i64
|
||||
),
|
||||
("purge", self.stats.purge.clear(), i64),
|
||||
(
|
||||
"process_gossip_packets_time",
|
||||
self.stats.process_gossip_packets_time.clear(),
|
||||
i64
|
||||
),
|
||||
(
|
||||
"process_pull_resp",
|
||||
self.stats.process_pull_response.clear(),
|
||||
@@ -2494,7 +2635,7 @@ pub struct Node {
|
||||
|
||||
impl Node {
|
||||
pub fn new_localhost() -> Self {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
Self::new_localhost_with_pubkey(&pubkey)
|
||||
}
|
||||
pub fn new_localhost_with_pubkey(pubkey: &Pubkey) -> Self {
|
||||
@@ -2658,10 +2799,13 @@ mod tests {
|
||||
#[test]
|
||||
fn test_gossip_node() {
|
||||
//check that a gossip nodes always show up as spies
|
||||
let (node, _, _) = ClusterInfo::spy_node(&Pubkey::new_rand(), 0);
|
||||
let (node, _, _) = ClusterInfo::spy_node(&solana_sdk::pubkey::new_rand(), 0);
|
||||
assert!(ClusterInfo::is_spy_node(&node));
|
||||
let (node, _, _) =
|
||||
ClusterInfo::gossip_node(&Pubkey::new_rand(), &"1.1.1.1:1111".parse().unwrap(), 0);
|
||||
let (node, _, _) = ClusterInfo::gossip_node(
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
&"1.1.1.1:1111".parse().unwrap(),
|
||||
0,
|
||||
);
|
||||
assert!(ClusterInfo::is_spy_node(&node));
|
||||
}
|
||||
|
||||
@@ -2671,7 +2815,7 @@ mod tests {
|
||||
let node = Node::new_localhost();
|
||||
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(node.info));
|
||||
|
||||
let entrypoint_pubkey = Pubkey::new_rand();
|
||||
let entrypoint_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let data = test_crds_values(entrypoint_pubkey);
|
||||
let timeouts = HashMap::new();
|
||||
assert_eq!(
|
||||
@@ -2684,7 +2828,7 @@ mod tests {
|
||||
)
|
||||
);
|
||||
|
||||
let entrypoint_pubkey2 = Pubkey::new_rand();
|
||||
let entrypoint_pubkey2 = solana_sdk::pubkey::new_rand();
|
||||
assert_eq!(
|
||||
(1, 0, 0),
|
||||
ClusterInfo::handle_pull_response(&cluster_info, &entrypoint_pubkey2, data, &timeouts)
|
||||
@@ -2699,7 +2843,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_filter_shred_version() {
|
||||
let from = Pubkey::new_rand();
|
||||
let from = solana_sdk::pubkey::new_rand();
|
||||
let my_shred_version = 1;
|
||||
let other_shred_version = 1;
|
||||
|
||||
@@ -2734,7 +2878,7 @@ mod tests {
|
||||
assert_eq!(values.len(), 1);
|
||||
|
||||
let snapshot_hash_data = CrdsValue::new_unsigned(CrdsData::SnapshotHashes(SnapshotHash {
|
||||
from: Pubkey::new_rand(),
|
||||
from: solana_sdk::pubkey::new_rand(),
|
||||
hashes: vec![],
|
||||
wallclock: 0,
|
||||
}));
|
||||
@@ -2755,7 +2899,7 @@ mod tests {
|
||||
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
|
||||
//check that gossip doesn't try to push to invalid addresses
|
||||
let node = Node::new_localhost();
|
||||
let (spy, _, _) = ClusterInfo::spy_node(&Pubkey::new_rand(), 0);
|
||||
let (spy, _, _) = ClusterInfo::spy_node(&solana_sdk::pubkey::new_rand(), 0);
|
||||
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(node.info));
|
||||
cluster_info.insert_info(spy);
|
||||
cluster_info
|
||||
@@ -2775,16 +2919,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_cluster_info_new() {
|
||||
let d = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
|
||||
let d = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(d.clone());
|
||||
assert_eq!(d.id, cluster_info.id());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_info_test() {
|
||||
let d = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
|
||||
let d = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(d);
|
||||
let d = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
|
||||
let d = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
|
||||
let label = CrdsValueLabel::ContactInfo(d.id);
|
||||
cluster_info.insert_info(d);
|
||||
assert!(cluster_info
|
||||
@@ -2798,7 +2942,7 @@ mod tests {
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_update_contact_info() {
|
||||
let d = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
|
||||
let d = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(d);
|
||||
let entry_label = CrdsValueLabel::ContactInfo(cluster_info.id());
|
||||
assert!(cluster_info
|
||||
@@ -2827,7 +2971,7 @@ mod tests {
|
||||
|
||||
// Inserting Contactinfo with different pubkey should panic,
|
||||
// and update should fail
|
||||
cluster_info.update_contact_info(|ci| ci.id = Pubkey::new_rand())
|
||||
cluster_info.update_contact_info(|ci| ci.id = solana_sdk::pubkey::new_rand())
|
||||
}
|
||||
|
||||
fn assert_in_range(x: u16, range: (u16, u16)) {
|
||||
@@ -2862,7 +3006,7 @@ mod tests {
|
||||
fn new_with_external_ip_test_random() {
|
||||
let ip = Ipv4Addr::from(0);
|
||||
let node = Node::new_with_external_ip(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
&socketaddr!(ip, 0),
|
||||
VALIDATOR_PORT_RANGE,
|
||||
IpAddr::V4(ip),
|
||||
@@ -2879,8 +3023,12 @@ mod tests {
|
||||
|
||||
let ip = IpAddr::V4(Ipv4Addr::from(0));
|
||||
let port = bind_in_range(ip, port_range).expect("Failed to bind").0;
|
||||
let node =
|
||||
Node::new_with_external_ip(&Pubkey::new_rand(), &socketaddr!(0, port), port_range, ip);
|
||||
let node = Node::new_with_external_ip(
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
&socketaddr!(0, port),
|
||||
port_range,
|
||||
ip,
|
||||
);
|
||||
|
||||
check_node_sockets(&node, ip, port_range);
|
||||
|
||||
@@ -2909,7 +3057,7 @@ mod tests {
|
||||
.gossip
|
||||
.write()
|
||||
.unwrap()
|
||||
.new_push_messages(timestamp());
|
||||
.new_push_messages(cluster_info.drain_push_queue(), timestamp());
|
||||
// there should be some pushes ready
|
||||
assert_eq!(push_messages.is_empty(), false);
|
||||
push_messages
|
||||
@@ -3092,6 +3240,7 @@ mod tests {
|
||||
let tx = test_tx();
|
||||
let index = 1;
|
||||
cluster_info.push_vote(index, tx.clone());
|
||||
cluster_info.flush_push_queue();
|
||||
|
||||
// -1 to make sure that the clock is strictly lower then when insert occurred
|
||||
let (labels, votes, max_ts) = cluster_info.get_votes(now - 1);
|
||||
@@ -3121,6 +3270,7 @@ mod tests {
|
||||
assert!(slots.is_empty());
|
||||
assert!(since.is_none());
|
||||
cluster_info.push_epoch_slots(&[0]);
|
||||
cluster_info.flush_push_queue();
|
||||
|
||||
let (slots, since) = cluster_info.get_epoch_slots_since(Some(std::u64::MAX));
|
||||
assert!(slots.is_empty());
|
||||
@@ -3143,7 +3293,7 @@ mod tests {
|
||||
ContactInfo::new_localhost(&node_keypair.pubkey(), timestamp()),
|
||||
node_keypair,
|
||||
);
|
||||
let entrypoint_pubkey = Pubkey::new_rand();
|
||||
let entrypoint_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let entrypoint = ContactInfo::new_localhost(&entrypoint_pubkey, timestamp());
|
||||
cluster_info.set_entrypoint(entrypoint.clone());
|
||||
let pulls = cluster_info.new_pull_requests(&thread_pool, None, &HashMap::new());
|
||||
@@ -3302,14 +3452,14 @@ mod tests {
|
||||
ContactInfo::new_localhost(&node_keypair.pubkey(), timestamp()),
|
||||
node_keypair,
|
||||
);
|
||||
let entrypoint_pubkey = Pubkey::new_rand();
|
||||
let entrypoint_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let mut entrypoint = ContactInfo::new_localhost(&entrypoint_pubkey, timestamp());
|
||||
entrypoint.gossip = socketaddr!("127.0.0.2:1234");
|
||||
cluster_info.set_entrypoint(entrypoint.clone());
|
||||
|
||||
let mut stakes = HashMap::new();
|
||||
|
||||
let other_node_pubkey = Pubkey::new_rand();
|
||||
let other_node_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let other_node = ContactInfo::new_localhost(&other_node_pubkey, timestamp());
|
||||
assert_ne!(other_node.gossip, entrypoint.gossip);
|
||||
cluster_info.insert_info(other_node.clone());
|
||||
@@ -3352,7 +3502,7 @@ mod tests {
|
||||
for i in 0..10 {
|
||||
// make these invalid for the upcoming repair request
|
||||
let peer_lowest = if i >= 5 { 10 } else { 0 };
|
||||
let other_node_pubkey = Pubkey::new_rand();
|
||||
let other_node_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let other_node = ContactInfo::new_localhost(&other_node_pubkey, timestamp());
|
||||
cluster_info.insert_info(other_node.clone());
|
||||
let value = CrdsValue::new_unsigned(CrdsData::LowestSlot(
|
||||
@@ -3449,7 +3599,9 @@ mod tests {
|
||||
range.push(last + rand::thread_rng().gen_range(1, 32));
|
||||
}
|
||||
cluster_info.push_epoch_slots(&range[..16000]);
|
||||
cluster_info.flush_push_queue();
|
||||
cluster_info.push_epoch_slots(&range[16000..]);
|
||||
cluster_info.flush_push_queue();
|
||||
let (slots, since) = cluster_info.get_epoch_slots_since(None);
|
||||
let slots: Vec<_> = slots.iter().flat_map(|x| x.to_slots(0)).collect();
|
||||
assert_eq!(slots, range);
|
||||
@@ -3501,7 +3653,7 @@ mod tests {
|
||||
|
||||
// Simulate getting entrypoint ContactInfo from gossip
|
||||
let mut gossiped_entrypoint_info =
|
||||
ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
|
||||
ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
|
||||
gossiped_entrypoint_info.gossip = entrypoint_gossip_addr;
|
||||
gossiped_entrypoint_info.shred_version = 1;
|
||||
cluster_info.insert_info(gossiped_entrypoint_info.clone());
|
||||
|
@@ -898,7 +898,7 @@ mod tests {
|
||||
let (vote_tracker, bank, _, _) = setup();
|
||||
|
||||
// Check outdated slots are purged with new root
|
||||
let new_voter = Arc::new(Pubkey::new_rand());
|
||||
let new_voter = Arc::new(solana_sdk::pubkey::new_rand());
|
||||
// Make separate copy so the original doesn't count toward
|
||||
// the ref count, which would prevent cleanup
|
||||
let new_voter_ = Arc::new(*new_voter);
|
||||
@@ -1681,7 +1681,7 @@ mod tests {
|
||||
fn run_test_verify_votes_1_pass(hash: Option<Hash>) {
|
||||
let vote_tx = test_vote_tx(hash);
|
||||
let votes = vec![vote_tx];
|
||||
let labels = vec![CrdsValueLabel::Vote(0, Pubkey::new_rand())];
|
||||
let labels = vec![CrdsValueLabel::Vote(0, solana_sdk::pubkey::new_rand())];
|
||||
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels);
|
||||
assert_eq!(vote_txs.len(), 1);
|
||||
verify_packets_len(&packets, 1);
|
||||
@@ -1698,7 +1698,7 @@ mod tests {
|
||||
let mut bad_vote = vote_tx.clone();
|
||||
bad_vote.signatures[0] = Signature::default();
|
||||
let votes = vec![vote_tx.clone(), bad_vote, vote_tx];
|
||||
let label = CrdsValueLabel::Vote(0, Pubkey::new_rand());
|
||||
let label = CrdsValueLabel::Vote(0, solana_sdk::pubkey::new_rand());
|
||||
let labels: Vec<_> = (0..votes.len()).map(|_| label.clone()).collect();
|
||||
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels);
|
||||
assert_eq!(vote_txs.len(), 2);
|
||||
|
@@ -237,8 +237,8 @@ mod tests {
|
||||
let mut c1 = ContactInfo::default();
|
||||
let mut c2 = ContactInfo::default();
|
||||
let mut map = HashMap::new();
|
||||
let k1 = Pubkey::new_rand();
|
||||
let k2 = Pubkey::new_rand();
|
||||
let k1 = solana_sdk::pubkey::new_rand();
|
||||
let k2 = solana_sdk::pubkey::new_rand();
|
||||
map.insert(Arc::new(k1), std::u64::MAX / 2);
|
||||
map.insert(Arc::new(k2), 0);
|
||||
cs.cluster_slots
|
||||
@@ -259,8 +259,8 @@ mod tests {
|
||||
let mut c1 = ContactInfo::default();
|
||||
let mut c2 = ContactInfo::default();
|
||||
let mut map = HashMap::new();
|
||||
let k1 = Pubkey::new_rand();
|
||||
let k2 = Pubkey::new_rand();
|
||||
let k1 = solana_sdk::pubkey::new_rand();
|
||||
let k2 = solana_sdk::pubkey::new_rand();
|
||||
map.insert(Arc::new(k2), 0);
|
||||
cs.cluster_slots
|
||||
.write()
|
||||
@@ -290,7 +290,7 @@ mod tests {
|
||||
let cs = ClusterSlots::default();
|
||||
let mut contact_infos = vec![ContactInfo::default(); 2];
|
||||
for ci in contact_infos.iter_mut() {
|
||||
ci.id = Pubkey::new_rand();
|
||||
ci.id = solana_sdk::pubkey::new_rand();
|
||||
}
|
||||
let slot = 9;
|
||||
|
||||
@@ -359,7 +359,7 @@ mod tests {
|
||||
let mut epoch_slot = EpochSlots::default();
|
||||
epoch_slot.fill(&[1], 0);
|
||||
cs.update_internal(0, (vec![epoch_slot], None));
|
||||
let self_id = Pubkey::new_rand();
|
||||
let self_id = solana_sdk::pubkey::new_rand();
|
||||
assert_eq!(
|
||||
cs.generate_repairs_for_missing_slots(&self_id, 0),
|
||||
vec![RepairType::HighestShred(1, 0)]
|
||||
|
@@ -181,6 +181,7 @@ mod test {
|
||||
let node_info = Node::new_localhost_with_pubkey(&Pubkey::default());
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(node_info.info);
|
||||
ClusterSlotsService::update_lowest_slot(&Pubkey::default(), 5, &cluster_info);
|
||||
cluster_info.flush_push_queue();
|
||||
let lowest = cluster_info
|
||||
.get_lowest_slot_for_node(&Pubkey::default(), None, |lowest_slot, _| {
|
||||
lowest_slot.clone()
|
||||
|
@@ -375,19 +375,22 @@ mod tests {
|
||||
|
||||
let rooted_stake_amount = 40;
|
||||
|
||||
let sk1 = Pubkey::new_rand();
|
||||
let pk1 = Pubkey::new_rand();
|
||||
let mut vote_account1 = vote_state::create_account(&pk1, &Pubkey::new_rand(), 0, 100);
|
||||
let sk1 = solana_sdk::pubkey::new_rand();
|
||||
let pk1 = solana_sdk::pubkey::new_rand();
|
||||
let mut vote_account1 =
|
||||
vote_state::create_account(&pk1, &solana_sdk::pubkey::new_rand(), 0, 100);
|
||||
let stake_account1 =
|
||||
stake_state::create_account(&sk1, &pk1, &vote_account1, &genesis_config.rent, 100);
|
||||
let sk2 = Pubkey::new_rand();
|
||||
let pk2 = Pubkey::new_rand();
|
||||
let mut vote_account2 = vote_state::create_account(&pk2, &Pubkey::new_rand(), 0, 50);
|
||||
let sk2 = solana_sdk::pubkey::new_rand();
|
||||
let pk2 = solana_sdk::pubkey::new_rand();
|
||||
let mut vote_account2 =
|
||||
vote_state::create_account(&pk2, &solana_sdk::pubkey::new_rand(), 0, 50);
|
||||
let stake_account2 =
|
||||
stake_state::create_account(&sk2, &pk2, &vote_account2, &genesis_config.rent, 50);
|
||||
let sk3 = Pubkey::new_rand();
|
||||
let pk3 = Pubkey::new_rand();
|
||||
let mut vote_account3 = vote_state::create_account(&pk3, &Pubkey::new_rand(), 0, 1);
|
||||
let sk3 = solana_sdk::pubkey::new_rand();
|
||||
let pk3 = solana_sdk::pubkey::new_rand();
|
||||
let mut vote_account3 =
|
||||
vote_state::create_account(&pk3, &solana_sdk::pubkey::new_rand(), 0, 1);
|
||||
let stake_account3 = stake_state::create_account(
|
||||
&sk3,
|
||||
&pk3,
|
||||
@@ -395,9 +398,10 @@ mod tests {
|
||||
&genesis_config.rent,
|
||||
rooted_stake_amount,
|
||||
);
|
||||
let sk4 = Pubkey::new_rand();
|
||||
let pk4 = Pubkey::new_rand();
|
||||
let mut vote_account4 = vote_state::create_account(&pk4, &Pubkey::new_rand(), 0, 1);
|
||||
let sk4 = solana_sdk::pubkey::new_rand();
|
||||
let pk4 = solana_sdk::pubkey::new_rand();
|
||||
let mut vote_account4 =
|
||||
vote_state::create_account(&pk4, &solana_sdk::pubkey::new_rand(), 0, 1);
|
||||
let stake_account4 = stake_state::create_account(
|
||||
&sk4,
|
||||
&pk4,
|
||||
|
@@ -30,11 +30,11 @@ use std::{
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
#[derive(PartialEq, Clone, Debug, AbiExample)]
|
||||
pub enum SwitchForkDecision {
|
||||
SwitchProof(Hash),
|
||||
NoSwitch,
|
||||
FailedSwitchThreshold,
|
||||
SameFork,
|
||||
FailedSwitchThreshold(u64, u64),
|
||||
}
|
||||
|
||||
impl SwitchForkDecision {
|
||||
@@ -45,8 +45,11 @@ impl SwitchForkDecision {
|
||||
authorized_voter_pubkey: &Pubkey,
|
||||
) -> Option<Instruction> {
|
||||
match self {
|
||||
SwitchForkDecision::FailedSwitchThreshold => None,
|
||||
SwitchForkDecision::NoSwitch => Some(vote_instruction::vote(
|
||||
SwitchForkDecision::FailedSwitchThreshold(_, total_stake) => {
|
||||
assert_ne!(*total_stake, 0);
|
||||
None
|
||||
}
|
||||
SwitchForkDecision::SameFork => Some(vote_instruction::vote(
|
||||
vote_account_pubkey,
|
||||
authorized_voter_pubkey,
|
||||
vote,
|
||||
@@ -61,6 +64,10 @@ impl SwitchForkDecision {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_vote(&self) -> bool {
|
||||
!matches!(self, SwitchForkDecision::FailedSwitchThreshold(_, _))
|
||||
}
|
||||
}
|
||||
|
||||
pub const VOTE_THRESHOLD_DEPTH: usize = 8;
|
||||
@@ -100,7 +107,11 @@ pub struct Tower {
|
||||
// (This is a special field for slashing-free validator restart with edge cases).
|
||||
// This could be emptied after some time; but left intact indefinitely for easier
|
||||
// implementation
|
||||
// Further, stray slot can be stale or not. `Stale` here means whether given
|
||||
// bank_forks (=~ ledger) lacks the slot or not.
|
||||
stray_restored_slot: Option<Slot>,
|
||||
#[serde(skip)]
|
||||
pub last_switch_threshold_check: Option<(Slot, SwitchForkDecision)>,
|
||||
}
|
||||
|
||||
impl Default for Tower {
|
||||
@@ -115,6 +126,7 @@ impl Default for Tower {
|
||||
path: PathBuf::default(),
|
||||
tmp_path: PathBuf::default(),
|
||||
stray_restored_slot: Option::default(),
|
||||
last_switch_threshold_check: Option::default(),
|
||||
};
|
||||
// VoteState::root_slot is ensured to be Some in Tower
|
||||
tower.lockouts.root_slot = Some(Slot::default());
|
||||
@@ -377,17 +389,14 @@ impl Tower {
|
||||
pub fn record_bank_vote(&mut self, vote: Vote) -> Option<Slot> {
|
||||
let slot = vote.last_voted_slot().unwrap_or(0);
|
||||
trace!("{} record_vote for {}", self.node_pubkey, slot);
|
||||
let root_slot = self.lockouts.root_slot;
|
||||
let old_root = self.root();
|
||||
self.lockouts.process_vote_unchecked(&vote);
|
||||
self.last_vote = vote;
|
||||
let new_root = self.root();
|
||||
|
||||
datapoint_info!(
|
||||
"tower-vote",
|
||||
("latest", slot, i64),
|
||||
("root", self.lockouts.root_slot.unwrap_or(0), i64)
|
||||
);
|
||||
if root_slot != self.lockouts.root_slot {
|
||||
Some(self.lockouts.root_slot.unwrap())
|
||||
datapoint_info!("tower-vote", ("latest", slot, i64), ("root", new_root, i64));
|
||||
if old_root != new_root {
|
||||
Some(new_root)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -431,13 +440,13 @@ impl Tower {
|
||||
|
||||
// root may be forcibly set by arbitrary replay root slot, for example from a root
|
||||
// after replaying a snapshot.
|
||||
// Also, tower.root() couldn't be None; do_initialize_lockouts() ensures that.
|
||||
// Also, tower.root() couldn't be None; initialize_lockouts() ensures that.
|
||||
// Conceptually, every tower must have been constructed from a concrete starting point,
|
||||
// which establishes the origin of trust (i.e. root) whether booting from genesis (slot 0) or
|
||||
// snapshot (slot N). In other words, there should be no possibility a Tower doesn't have
|
||||
// root, unlike young vote accounts.
|
||||
pub fn root(&self) -> Option<Slot> {
|
||||
self.lockouts.root_slot
|
||||
pub fn root(&self) -> Slot {
|
||||
self.lockouts.root_slot.unwrap()
|
||||
}
|
||||
|
||||
// a slot is recent if it's newer than the last vote we have
|
||||
@@ -493,7 +502,7 @@ impl Tower {
|
||||
false
|
||||
}
|
||||
|
||||
pub(crate) fn check_switch_threshold(
|
||||
fn make_check_switch_threshold_decision(
|
||||
&self,
|
||||
switch_slot: u64,
|
||||
ancestors: &HashMap<Slot, HashSet<u64>>,
|
||||
@@ -504,13 +513,13 @@ impl Tower {
|
||||
) -> SwitchForkDecision {
|
||||
self.last_voted_slot()
|
||||
.map(|last_voted_slot| {
|
||||
let root = self.lockouts.root_slot.unwrap_or(0);
|
||||
let root = self.root();
|
||||
let empty_ancestors = HashSet::default();
|
||||
|
||||
let last_vote_ancestors =
|
||||
ancestors.get(&last_voted_slot).unwrap_or_else(|| {
|
||||
if !self.is_stray_last_vote() {
|
||||
// Unless last vote is stray, ancestors.get(last_voted_slot) must
|
||||
// Unless last vote is stray and stale, ancestors.get(last_voted_slot) must
|
||||
// return Some(_), justifying to panic! here.
|
||||
// Also, adjust_lockouts_after_replay() correctly makes last_voted_slot None,
|
||||
// if all saved votes are ancestors of replayed_root_slot. So this code shouldn't be
|
||||
@@ -520,9 +529,34 @@ impl Tower {
|
||||
// all of them.
|
||||
panic!("no ancestors found with slot: {}", last_voted_slot);
|
||||
} else {
|
||||
// bank_forks doesn't have corresponding data for the stray restored last vote,
|
||||
// meaning some inconsistency between saved tower and ledger.
|
||||
// (newer snapshot, or only a saved tower is moved over to new setup?)
|
||||
// This condition (stale stray last vote) shouldn't occur under normal validator
|
||||
// operation, indicating something unusual happened.
|
||||
// Possible causes include: OS/HW crash, validator process crash, only saved tower
|
||||
// is moved over to a new setup, etc...
|
||||
|
||||
// However, returning empty ancestors as a fallback here shouldn't result in
|
||||
// slashing by itself (Note that we couldn't fully preclude any kind of slashing if
|
||||
// the failure was OS or HW level).
|
||||
|
||||
// Firstly, lockout is ensured elsewhere.
|
||||
|
||||
// Also, there is no risk of optimistic conf. violation. Although empty ancestors
|
||||
// could result in incorrect (= more than actual) locked_out_stake and
|
||||
// false-positive SwitchProof later in this function, there should be no such a
|
||||
// heavier fork candidate, first of all, if the last vote (or any of its
|
||||
// unavailable ancestors) were already optimistically confirmed.
|
||||
// The only exception is that other validator is already violating it...
|
||||
if self.is_first_switch_check() && switch_slot < last_voted_slot {
|
||||
// `switch < last` is needed not to warn! this message just because of using
|
||||
// newer snapshots on validator restart
|
||||
let message = format!(
|
||||
"bank_forks doesn't have corresponding data for the stray restored \
|
||||
last vote({}), meaning some inconsistency between saved tower and ledger.",
|
||||
last_voted_slot
|
||||
);
|
||||
warn!("{}", message);
|
||||
datapoint_warn!("tower_warn", ("warn", message, String));
|
||||
}
|
||||
&empty_ancestors
|
||||
}
|
||||
});
|
||||
@@ -532,12 +566,16 @@ impl Tower {
|
||||
if switch_slot == last_voted_slot || switch_slot_ancestors.contains(&last_voted_slot) {
|
||||
// If the `switch_slot is a descendant of the last vote,
|
||||
// no switching proof is necessary
|
||||
return SwitchForkDecision::NoSwitch;
|
||||
return SwitchForkDecision::SameFork;
|
||||
}
|
||||
|
||||
// Should never consider switching to an ancestor
|
||||
// of your last vote
|
||||
assert!(!last_vote_ancestors.contains(&switch_slot));
|
||||
assert!(
|
||||
!last_vote_ancestors.contains(&switch_slot),
|
||||
"Should never consider switching to slot ({}), which is ancestors({:?}) of last vote: {}",
|
||||
switch_slot,
|
||||
last_vote_ancestors,
|
||||
last_voted_slot
|
||||
);
|
||||
|
||||
// By this point, we know the `switch_slot` is on a different fork
|
||||
// (is neither an ancestor nor descendant of `last_vote`), so a
|
||||
@@ -598,7 +636,7 @@ impl Tower {
|
||||
}
|
||||
|
||||
// Only count lockouts on slots that are:
|
||||
// 1) Not ancestors of `last_vote`
|
||||
// 1) Not ancestors of `last_vote`, meaning being on different fork
|
||||
// 2) Not from before the current root as we can't determine if
|
||||
// anything before the root was an ancestor of `last_vote` or not
|
||||
if !last_vote_ancestors.contains(lockout_interval_start)
|
||||
@@ -622,10 +660,43 @@ impl Tower {
|
||||
if (locked_out_stake as f64 / total_stake as f64) > SWITCH_FORK_THRESHOLD {
|
||||
SwitchForkDecision::SwitchProof(switch_proof)
|
||||
} else {
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(locked_out_stake, total_stake)
|
||||
}
|
||||
})
|
||||
.unwrap_or(SwitchForkDecision::NoSwitch)
|
||||
.unwrap_or(SwitchForkDecision::SameFork)
|
||||
}
|
||||
|
||||
pub(crate) fn check_switch_threshold(
|
||||
&mut self,
|
||||
switch_slot: u64,
|
||||
ancestors: &HashMap<Slot, HashSet<u64>>,
|
||||
descendants: &HashMap<Slot, HashSet<u64>>,
|
||||
progress: &ProgressMap,
|
||||
total_stake: u64,
|
||||
epoch_vote_accounts: &HashMap<Pubkey, (u64, Account)>,
|
||||
) -> SwitchForkDecision {
|
||||
let decision = self.make_check_switch_threshold_decision(
|
||||
switch_slot,
|
||||
ancestors,
|
||||
descendants,
|
||||
progress,
|
||||
total_stake,
|
||||
epoch_vote_accounts,
|
||||
);
|
||||
let new_check = Some((switch_slot, decision.clone()));
|
||||
if new_check != self.last_switch_threshold_check {
|
||||
trace!(
|
||||
"new switch threshold check: slot {}: {:?}",
|
||||
switch_slot,
|
||||
decision,
|
||||
);
|
||||
self.last_switch_threshold_check = new_check;
|
||||
}
|
||||
decision
|
||||
}
|
||||
|
||||
fn is_first_switch_check(&self) -> bool {
|
||||
self.last_switch_threshold_check.is_none()
|
||||
}
|
||||
|
||||
pub fn check_vote_stake_threshold(
|
||||
@@ -760,20 +831,21 @@ impl Tower {
|
||||
// The tower root can be older/newer if the validator booted from a newer/older snapshot, so
|
||||
// tower lockouts may need adjustment
|
||||
pub fn adjust_lockouts_after_replay(
|
||||
self,
|
||||
mut self,
|
||||
replayed_root: Slot,
|
||||
slot_history: &SlotHistory,
|
||||
) -> Result<Self> {
|
||||
info!(
|
||||
"adjusting lockouts (after replay up to {}): {:?}",
|
||||
replayed_root,
|
||||
self.voted_slots()
|
||||
);
|
||||
|
||||
// sanity assertions for roots
|
||||
let tower_root = self.root();
|
||||
info!(
|
||||
"adjusting lockouts (after replay up to {}): {:?} tower root: {} replayed root: {}",
|
||||
replayed_root,
|
||||
self.voted_slots(),
|
||||
tower_root,
|
||||
replayed_root,
|
||||
);
|
||||
assert_eq!(slot_history.check(replayed_root), Check::Found);
|
||||
assert!(self.root().is_some());
|
||||
let tower_root = self.root().unwrap();
|
||||
|
||||
// reconcile_blockstore_roots_with_tower() should already have aligned these.
|
||||
assert!(
|
||||
tower_root <= replayed_root,
|
||||
@@ -791,30 +863,24 @@ impl Tower {
|
||||
)
|
||||
);
|
||||
|
||||
// return immediately if votes are empty...
|
||||
if self.lockouts.votes.is_empty() {
|
||||
return Ok(self);
|
||||
if let Some(last_voted_slot) = self.last_voted_slot() {
|
||||
if slot_history.check(last_voted_slot) == Check::TooOld {
|
||||
// We could try hard to anchor with other older votes, but opt to simplify the
|
||||
// following logic
|
||||
return Err(TowerError::TooOldTower(
|
||||
last_voted_slot,
|
||||
slot_history.oldest(),
|
||||
));
|
||||
}
|
||||
self.adjust_lockouts_with_slot_history(slot_history)?;
|
||||
self.initialize_root(replayed_root);
|
||||
}
|
||||
|
||||
let last_voted_slot = self.last_voted_slot().unwrap();
|
||||
if slot_history.check(last_voted_slot) == Check::TooOld {
|
||||
// We could try hard to anchor with other older votes, but opt to simplify the
|
||||
// following logic
|
||||
return Err(TowerError::TooOldTower(
|
||||
last_voted_slot,
|
||||
slot_history.oldest(),
|
||||
));
|
||||
}
|
||||
|
||||
self.do_adjust_lockouts_after_replay(tower_root, replayed_root, slot_history)
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn do_adjust_lockouts_after_replay(
|
||||
mut self,
|
||||
tower_root: Slot,
|
||||
replayed_root: Slot,
|
||||
slot_history: &SlotHistory,
|
||||
) -> Result<Self> {
|
||||
fn adjust_lockouts_with_slot_history(&mut self, slot_history: &SlotHistory) -> Result<()> {
|
||||
let tower_root = self.root();
|
||||
// retained slots will be consisted only from divergent slots
|
||||
let mut retain_flags_for_each_vote_in_reverse: Vec<_> =
|
||||
Vec::with_capacity(self.lockouts.votes.len());
|
||||
@@ -862,7 +928,12 @@ impl Tower {
|
||||
if !voting_from_genesis {
|
||||
// Unless we're voting since genesis, slots_in_tower must always be older than last checked_slot
|
||||
// including all vote slot and the root slot.
|
||||
assert!(*slot_in_tower < checked_slot)
|
||||
assert!(
|
||||
*slot_in_tower < checked_slot,
|
||||
"slot_in_tower({}) < checked_slot({})",
|
||||
*slot_in_tower,
|
||||
checked_slot
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -890,15 +961,10 @@ impl Tower {
|
||||
retain_flags_for_each_vote_in_reverse.into_iter().rev();
|
||||
|
||||
let original_votes_len = self.lockouts.votes.len();
|
||||
self.do_initialize_lockouts(replayed_root, move |_| {
|
||||
retain_flags_for_each_vote.next().unwrap()
|
||||
});
|
||||
self.initialize_lockouts(move |_| retain_flags_for_each_vote.next().unwrap());
|
||||
|
||||
if self.lockouts.votes.is_empty() {
|
||||
info!(
|
||||
"All restored votes were behind replayed_root({}); resetting root_slot and last_vote in tower!",
|
||||
replayed_root
|
||||
);
|
||||
info!("All restored votes were behind; resetting root_slot and last_vote in tower!");
|
||||
// we might not have banks for those votes so just reset.
|
||||
// That's because the votes may well past replayed_root
|
||||
self.last_vote = Vote::default();
|
||||
@@ -917,7 +983,7 @@ impl Tower {
|
||||
self.stray_restored_slot = Some(self.last_vote.last_voted_slot().unwrap());
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn initialize_lockouts_from_bank(
|
||||
@@ -930,18 +996,19 @@ impl Tower {
|
||||
let vote_state = VoteState::deserialize(&vote_account.data)
|
||||
.expect("vote_account isn't a VoteState?");
|
||||
self.lockouts = vote_state;
|
||||
self.do_initialize_lockouts(root, |v| v.slot > root);
|
||||
self.initialize_root(root);
|
||||
self.initialize_lockouts(|v| v.slot > root);
|
||||
trace!(
|
||||
"{} lockouts initialized to {:?}",
|
||||
"Lockouts in tower for {} is initialized using bank {}",
|
||||
self.node_pubkey,
|
||||
self.lockouts
|
||||
bank.slot(),
|
||||
);
|
||||
assert_eq!(
|
||||
self.lockouts.node_pubkey, self.node_pubkey,
|
||||
"vote account's node_pubkey doesn't match",
|
||||
);
|
||||
} else {
|
||||
self.do_initialize_lockouts(root, |_| true);
|
||||
self.initialize_root(root);
|
||||
info!(
|
||||
"vote account({}) not found in bank (slot={})",
|
||||
vote_account_pubkey,
|
||||
@@ -950,13 +1017,16 @@ impl Tower {
|
||||
}
|
||||
}
|
||||
|
||||
fn do_initialize_lockouts<F: FnMut(&Lockout) -> bool>(&mut self, root: Slot, should_retain: F) {
|
||||
// Updating root is needed to correctly restore from newly-saved tower for the next
|
||||
// boot
|
||||
self.lockouts.root_slot = Some(root);
|
||||
fn initialize_lockouts<F: FnMut(&Lockout) -> bool>(&mut self, should_retain: F) {
|
||||
self.lockouts.votes.retain(should_retain);
|
||||
}
|
||||
|
||||
// Updating root is needed to correctly restore from newly-saved tower for the next
|
||||
// boot
|
||||
fn initialize_root(&mut self, root: Slot) {
|
||||
self.lockouts.root_slot = Some(root);
|
||||
}
|
||||
|
||||
pub fn get_filename(path: &Path, node_pubkey: &Pubkey) -> PathBuf {
|
||||
path.join(format!("tower-{}", node_pubkey))
|
||||
.with_extension("bin")
|
||||
@@ -986,6 +1056,7 @@ impl Tower {
|
||||
bincode::serialize_into(&mut file, &saved_tower)?;
|
||||
// file.sync_all() hurts performance; pipeline sync-ing and submitting votes to the cluster!
|
||||
}
|
||||
trace!("persisted votes: {:?}", self.voted_slots());
|
||||
fs::rename(&new_filename, &filename)?;
|
||||
// self.path.parent().sync_all() hurts performance same as the above sync
|
||||
|
||||
@@ -1047,6 +1118,16 @@ pub enum TowerError {
|
||||
FatallyInconsistent(&'static str),
|
||||
}
|
||||
|
||||
impl TowerError {
|
||||
pub fn is_file_missing(&self) -> bool {
|
||||
if let TowerError::IOError(io_err) = &self {
|
||||
io_err.kind() == std::io::ErrorKind::NotFound
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[frozen_abi(digest = "Gaxfwvx5MArn52mKZQgzHmDCyn5YfCuTHvp5Et3rFfpp")]
|
||||
#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq, AbiExample)]
|
||||
pub struct SavedTower {
|
||||
@@ -1076,28 +1157,27 @@ pub fn reconcile_blockstore_roots_with_tower(
|
||||
tower: &Tower,
|
||||
blockstore: &Blockstore,
|
||||
) -> blockstore_db::Result<()> {
|
||||
if let Some(tower_root) = tower.root() {
|
||||
let last_blockstore_root = blockstore.last_root();
|
||||
if last_blockstore_root < tower_root {
|
||||
// Ensure tower_root itself to exist and be marked as rooted in the blockstore
|
||||
// in addition to its ancestors.
|
||||
let new_roots: Vec<_> = AncestorIterator::new_inclusive(tower_root, &blockstore)
|
||||
.take_while(|current| match current.cmp(&last_blockstore_root) {
|
||||
Ordering::Greater => true,
|
||||
Ordering::Equal => false,
|
||||
Ordering::Less => panic!(
|
||||
"couldn't find a last_blockstore_root upwards from: {}!?",
|
||||
tower_root
|
||||
),
|
||||
})
|
||||
.collect();
|
||||
assert!(
|
||||
!new_roots.is_empty(),
|
||||
"at least 1 parent slot must be found"
|
||||
);
|
||||
let tower_root = tower.root();
|
||||
let last_blockstore_root = blockstore.last_root();
|
||||
if last_blockstore_root < tower_root {
|
||||
// Ensure tower_root itself to exist and be marked as rooted in the blockstore
|
||||
// in addition to its ancestors.
|
||||
let new_roots: Vec<_> = AncestorIterator::new_inclusive(tower_root, &blockstore)
|
||||
.take_while(|current| match current.cmp(&last_blockstore_root) {
|
||||
Ordering::Greater => true,
|
||||
Ordering::Equal => false,
|
||||
Ordering::Less => panic!(
|
||||
"couldn't find a last_blockstore_root upwards from: {}!?",
|
||||
tower_root
|
||||
),
|
||||
})
|
||||
.collect();
|
||||
assert!(
|
||||
!new_roots.is_empty(),
|
||||
"at least 1 parent slot must be found"
|
||||
);
|
||||
|
||||
blockstore.set_roots(&new_roots)?
|
||||
}
|
||||
blockstore.set_roots(&new_roots)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1267,7 +1347,7 @@ pub mod test {
|
||||
&ancestors,
|
||||
&descendants,
|
||||
&self.progress,
|
||||
&tower,
|
||||
tower,
|
||||
);
|
||||
|
||||
// Make sure this slot isn't locked out or failing threshold
|
||||
@@ -1456,7 +1536,7 @@ pub mod test {
|
||||
&mut account.data,
|
||||
)
|
||||
.expect("serialize state");
|
||||
stakes.push((Pubkey::new_rand(), (*lamports, account)));
|
||||
stakes.push((solana_sdk::pubkey::new_rand(), (*lamports, account)));
|
||||
}
|
||||
stakes
|
||||
}
|
||||
@@ -1464,11 +1544,11 @@ pub mod test {
|
||||
#[test]
|
||||
fn test_to_vote_instruction() {
|
||||
let vote = Vote::default();
|
||||
let mut decision = SwitchForkDecision::FailedSwitchThreshold;
|
||||
let mut decision = SwitchForkDecision::FailedSwitchThreshold(0, 1);
|
||||
assert!(decision
|
||||
.to_vote_instruction(vote.clone(), &Pubkey::default(), &Pubkey::default())
|
||||
.is_none());
|
||||
decision = SwitchForkDecision::NoSwitch;
|
||||
decision = SwitchForkDecision::SameFork;
|
||||
assert_eq!(
|
||||
decision.to_vote_instruction(vote.clone(), &Pubkey::default(), &Pubkey::default()),
|
||||
Some(vote_instruction::vote(
|
||||
@@ -1571,7 +1651,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::NoSwitch
|
||||
SwitchForkDecision::SameFork
|
||||
);
|
||||
|
||||
// Trying to switch to another fork at 110 should fail
|
||||
@@ -1584,7 +1664,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
|
||||
// Adding another validator lockout on a descendant of last vote should
|
||||
@@ -1599,7 +1679,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
|
||||
// Adding another validator lockout on an ancestor of last vote should
|
||||
@@ -1614,7 +1694,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
|
||||
// Adding another validator lockout on a different fork, but the lockout
|
||||
@@ -1629,7 +1709,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
|
||||
// Adding another validator lockout on a different fork, and the lockout
|
||||
@@ -1646,7 +1726,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
|
||||
// Adding another validator lockout on a different fork, and the lockout
|
||||
@@ -1697,7 +1777,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2365,7 +2445,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::NoSwitch
|
||||
SwitchForkDecision::SameFork
|
||||
);
|
||||
|
||||
// Trying to switch to another fork at 110 should fail
|
||||
@@ -2378,7 +2458,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
|
||||
vote_simulator.simulate_lockout_interval(111, (10, 49), &other_vote_account);
|
||||
@@ -2456,7 +2536,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
|
||||
// Add lockout_interval which should be excluded
|
||||
@@ -2470,7 +2550,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
|
||||
// Add lockout_interval which should not be excluded
|
||||
@@ -2660,13 +2740,13 @@ pub mod test {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(tower.voted_slots(), vec![2, 3]);
|
||||
assert_eq!(tower.root(), Some(replayed_root_slot));
|
||||
assert_eq!(tower.root(), replayed_root_slot);
|
||||
|
||||
tower = tower
|
||||
.adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
|
||||
.unwrap();
|
||||
assert_eq!(tower.voted_slots(), vec![2, 3]);
|
||||
assert_eq!(tower.root(), Some(replayed_root_slot));
|
||||
assert_eq!(tower.root(), replayed_root_slot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2688,7 +2768,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(tower.voted_slots(), vec![2, 3]);
|
||||
assert_eq!(tower.root(), Some(replayed_root_slot));
|
||||
assert_eq!(tower.root(), replayed_root_slot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2712,12 +2792,12 @@ pub mod test {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(tower.voted_slots(), vec![] as Vec<Slot>);
|
||||
assert_eq!(tower.root(), Some(replayed_root_slot));
|
||||
assert_eq!(tower.root(), replayed_root_slot);
|
||||
assert_eq!(tower.stray_restored_slot, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_adjust_lockouts_after_relay_all_rooted_with_too_old() {
|
||||
fn test_adjust_lockouts_after_replay_all_rooted_with_too_old() {
|
||||
use solana_sdk::slot_history::MAX_ENTRIES;
|
||||
|
||||
let mut tower = Tower::new_for_tests(10, 0.9);
|
||||
@@ -2735,7 +2815,7 @@ pub mod test {
|
||||
.adjust_lockouts_after_replay(MAX_ENTRIES, &slot_history)
|
||||
.unwrap();
|
||||
assert_eq!(tower.voted_slots(), vec![] as Vec<Slot>);
|
||||
assert_eq!(tower.root(), Some(MAX_ENTRIES));
|
||||
assert_eq!(tower.root(), MAX_ENTRIES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2758,7 +2838,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(tower.voted_slots(), vec![3, 4]);
|
||||
assert_eq!(tower.root(), Some(replayed_root_slot));
|
||||
assert_eq!(tower.root(), replayed_root_slot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2779,7 +2859,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(tower.voted_slots(), vec![5, 6]);
|
||||
assert_eq!(tower.root(), Some(replayed_root_slot));
|
||||
assert_eq!(tower.root(), replayed_root_slot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2823,7 +2903,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(tower.voted_slots(), vec![3, 4, 5]);
|
||||
assert_eq!(tower.root(), Some(replayed_root_slot));
|
||||
assert_eq!(tower.root(), replayed_root_slot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2839,7 +2919,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(tower.voted_slots(), vec![] as Vec<Slot>);
|
||||
assert_eq!(tower.root(), Some(replayed_root_slot));
|
||||
assert_eq!(tower.root(), replayed_root_slot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2920,4 +3000,54 @@ pub mod test {
|
||||
"The tower is fatally inconsistent with blockstore: not too old once after got too old?"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "slot_in_tower(2) < checked_slot(1)")]
|
||||
fn test_adjust_lockouts_after_replay_reversed_votes() {
|
||||
let mut tower = Tower::new_for_tests(10, 0.9);
|
||||
tower.lockouts.votes.push_back(Lockout::new(2));
|
||||
tower.lockouts.votes.push_back(Lockout::new(1));
|
||||
let vote = Vote::new(vec![1], Hash::default());
|
||||
tower.last_vote = vote;
|
||||
|
||||
let mut slot_history = SlotHistory::default();
|
||||
slot_history.add(0);
|
||||
slot_history.add(2);
|
||||
|
||||
tower
|
||||
.adjust_lockouts_after_replay(2, &slot_history)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "slot_in_tower(3) < checked_slot(3)")]
|
||||
fn test_adjust_lockouts_after_replay_repeated_non_root_votes() {
|
||||
let mut tower = Tower::new_for_tests(10, 0.9);
|
||||
tower.lockouts.votes.push_back(Lockout::new(2));
|
||||
tower.lockouts.votes.push_back(Lockout::new(3));
|
||||
tower.lockouts.votes.push_back(Lockout::new(3));
|
||||
let vote = Vote::new(vec![3], Hash::default());
|
||||
tower.last_vote = vote;
|
||||
|
||||
let mut slot_history = SlotHistory::default();
|
||||
slot_history.add(0);
|
||||
slot_history.add(2);
|
||||
|
||||
tower
|
||||
.adjust_lockouts_after_replay(2, &slot_history)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_adjust_lockouts_after_replay_vote_on_genesis() {
|
||||
let mut tower = Tower::new_for_tests(10, 0.9);
|
||||
tower.lockouts.votes.push_back(Lockout::new(0));
|
||||
let vote = Vote::new(vec![0], Hash::default());
|
||||
tower.last_vote = vote;
|
||||
|
||||
let mut slot_history = SlotHistory::default();
|
||||
slot_history.add(0);
|
||||
|
||||
assert!(tower.adjust_lockouts_after_replay(0, &slot_history).is_ok());
|
||||
}
|
||||
}
|
||||
|
@@ -130,7 +130,7 @@ impl ContactInfo {
|
||||
let addr = socketaddr!("224.0.1.255:1000");
|
||||
assert!(addr.ip().is_multicast());
|
||||
Self {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
gossip: addr,
|
||||
tvu: addr,
|
||||
tvu_forwards: addr,
|
||||
|
@@ -361,7 +361,9 @@ mod test {
|
||||
}
|
||||
|
||||
let mut crds = Crds::default();
|
||||
let pubkeys: Vec<_> = std::iter::repeat_with(Pubkey::new_rand).take(256).collect();
|
||||
let pubkeys: Vec<_> = std::iter::repeat_with(solana_sdk::pubkey::new_rand)
|
||||
.take(256)
|
||||
.collect();
|
||||
let mut rng = thread_rng();
|
||||
let mut num_inserts = 0;
|
||||
for _ in 0..4096 {
|
||||
@@ -484,14 +486,14 @@ mod test {
|
||||
let v1 = VersionedCrdsValue::new(
|
||||
1,
|
||||
CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
))),
|
||||
);
|
||||
let v2 = VersionedCrdsValue::new(
|
||||
1,
|
||||
CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
))),
|
||||
);
|
||||
|
@@ -88,7 +88,20 @@ impl CrdsGossip {
|
||||
prune_map
|
||||
}
|
||||
|
||||
pub fn new_push_messages(&mut self, now: u64) -> (Pubkey, HashMap<Pubkey, Vec<CrdsValue>>) {
|
||||
pub fn process_push_messages(&mut self, pending_push_messages: Vec<(CrdsValue, u64)>) {
|
||||
for (push_message, timestamp) in pending_push_messages {
|
||||
let _ =
|
||||
self.push
|
||||
.process_push_message(&mut self.crds, &self.id, push_message, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_push_messages(
|
||||
&mut self,
|
||||
pending_push_messages: Vec<(CrdsValue, u64)>,
|
||||
now: u64,
|
||||
) -> (Pubkey, HashMap<Pubkey, Vec<CrdsValue>>) {
|
||||
self.process_push_messages(pending_push_messages);
|
||||
let push_messages = self.push.new_push_messages(&self.crds, now);
|
||||
(self.id, push_messages)
|
||||
}
|
||||
|
@@ -626,7 +626,7 @@ mod test {
|
||||
}
|
||||
let mut rng = thread_rng();
|
||||
for _ in 0..100 {
|
||||
let hash = Hash::new_rand(&mut rng);
|
||||
let hash = solana_sdk::hash::new_rand(&mut rng);
|
||||
assert_eq!(CrdsFilter::hash_as_u64(&hash), hash_as_u64_bitops(&hash));
|
||||
}
|
||||
}
|
||||
@@ -638,7 +638,7 @@ mod test {
|
||||
assert_eq!(filter.mask, mask);
|
||||
let mut rng = thread_rng();
|
||||
for _ in 0..10 {
|
||||
let hash = Hash::new_rand(&mut rng);
|
||||
let hash = solana_sdk::hash::new_rand(&mut rng);
|
||||
assert!(filter.test_mask(&hash));
|
||||
}
|
||||
}
|
||||
@@ -649,13 +649,13 @@ mod test {
|
||||
let mut stakes = HashMap::new();
|
||||
let node = CrdsGossipPull::default();
|
||||
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
crds.insert(me.clone(), 0).unwrap();
|
||||
for i in 1..=30 {
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let id = entry.label().pubkey();
|
||||
@@ -682,25 +682,25 @@ mod test {
|
||||
let gossip = socketaddr!("127.0.0.1:1234");
|
||||
|
||||
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
shred_version: 123,
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let spy = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
shred_version: 0,
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
shred_version: 123,
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_456 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
shred_version: 456,
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
@@ -741,12 +741,12 @@ mod test {
|
||||
let gossip = socketaddr!("127.0.0.1:1234");
|
||||
|
||||
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
@@ -767,7 +767,7 @@ mod test {
|
||||
assert!(options.is_empty());
|
||||
|
||||
// Unknown pubkey in gossip_validators -- will pull from nobody
|
||||
gossip_validators.insert(Pubkey::new_rand());
|
||||
gossip_validators.insert(solana_sdk::pubkey::new_rand());
|
||||
let options = node.pull_options(
|
||||
&crds,
|
||||
&me.label().pubkey(),
|
||||
@@ -797,7 +797,7 @@ mod test {
|
||||
let mut rng = thread_rng();
|
||||
let crds_filter_set =
|
||||
CrdsFilterSet::new(/*num_items=*/ 9672788, /*max_bytes=*/ 8196);
|
||||
let hash_values: Vec<_> = std::iter::repeat_with(|| Hash::new_rand(&mut rng))
|
||||
let hash_values: Vec<_> = std::iter::repeat_with(|| solana_sdk::hash::new_rand(&mut rng))
|
||||
.take(1024)
|
||||
.collect();
|
||||
for hash_value in &hash_values {
|
||||
@@ -849,7 +849,7 @@ mod test {
|
||||
for _ in 0..10_000 {
|
||||
crds_gossip_pull
|
||||
.purged_values
|
||||
.push_back((Hash::new_rand(&mut rng), rng.gen()));
|
||||
.push_back((solana_sdk::hash::new_rand(&mut rng), rng.gen()));
|
||||
}
|
||||
let mut num_inserts = 0;
|
||||
for _ in 0..20_000 {
|
||||
@@ -898,7 +898,7 @@ mod test {
|
||||
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
|
||||
let mut crds = Crds::default();
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let id = entry.label().pubkey();
|
||||
@@ -933,7 +933,7 @@ mod test {
|
||||
);
|
||||
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
crds.insert(new.clone(), 0).unwrap();
|
||||
@@ -957,19 +957,19 @@ mod test {
|
||||
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
|
||||
let mut crds = Crds::default();
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let node_pubkey = entry.label().pubkey();
|
||||
let mut node = CrdsGossipPull::default();
|
||||
crds.insert(entry.clone(), 0).unwrap();
|
||||
let old = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
crds.insert(old.clone(), 0).unwrap();
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
crds.insert(new.clone(), 0).unwrap();
|
||||
@@ -1000,14 +1000,14 @@ mod test {
|
||||
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
|
||||
let mut node_crds = Crds::default();
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let node_pubkey = entry.label().pubkey();
|
||||
let node = CrdsGossipPull::default();
|
||||
node_crds.insert(entry, 0).unwrap();
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
node_crds.insert(new, 0).unwrap();
|
||||
@@ -1031,7 +1031,7 @@ mod test {
|
||||
assert_eq!(rsp[0].len(), 0);
|
||||
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS,
|
||||
)));
|
||||
dest_crds
|
||||
@@ -1047,7 +1047,7 @@ mod test {
|
||||
filters.push(filters[0].clone());
|
||||
//should return new value since caller is new
|
||||
filters[1].0 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS + 1,
|
||||
)));
|
||||
|
||||
@@ -1063,14 +1063,14 @@ mod test {
|
||||
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
|
||||
let mut node_crds = Crds::default();
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let node_pubkey = entry.label().pubkey();
|
||||
let node = CrdsGossipPull::default();
|
||||
node_crds.insert(entry, 0).unwrap();
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
node_crds.insert(new, 0).unwrap();
|
||||
@@ -1113,7 +1113,7 @@ mod test {
|
||||
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
|
||||
let mut node_crds = Crds::default();
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
1,
|
||||
)));
|
||||
let node_pubkey = entry.label().pubkey();
|
||||
@@ -1121,14 +1121,14 @@ mod test {
|
||||
node_crds.insert(entry, 0).unwrap();
|
||||
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
1,
|
||||
)));
|
||||
node_crds.insert(new, 0).unwrap();
|
||||
|
||||
let mut dest = CrdsGossipPull::default();
|
||||
let mut dest_crds = Crds::default();
|
||||
let new_id = Pubkey::new_rand();
|
||||
let new_id = solana_sdk::pubkey::new_rand();
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&new_id, 1,
|
||||
)));
|
||||
@@ -1210,7 +1210,7 @@ mod test {
|
||||
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
|
||||
let mut node_crds = Crds::default();
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let node_label = entry.label();
|
||||
@@ -1218,7 +1218,7 @@ mod test {
|
||||
let mut node = CrdsGossipPull::default();
|
||||
node_crds.insert(entry, 0).unwrap();
|
||||
let old = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
node_crds.insert(old.clone(), 0).unwrap();
|
||||
@@ -1330,7 +1330,7 @@ mod test {
|
||||
let mut node_crds = Crds::default();
|
||||
let mut node = CrdsGossipPull::default();
|
||||
|
||||
let peer_pubkey = Pubkey::new_rand();
|
||||
let peer_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let peer_entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(
|
||||
ContactInfo::new_localhost(&peer_pubkey, 0),
|
||||
));
|
||||
|
@@ -438,15 +438,15 @@ mod test {
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let mut stakes = HashMap::new();
|
||||
|
||||
let self_id = Pubkey::new_rand();
|
||||
let origin = Pubkey::new_rand();
|
||||
let self_id = solana_sdk::pubkey::new_rand();
|
||||
let origin = solana_sdk::pubkey::new_rand();
|
||||
stakes.insert(self_id, 100);
|
||||
stakes.insert(origin, 100);
|
||||
|
||||
let value = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&origin, 0,
|
||||
)));
|
||||
let low_staked_peers = (0..10).map(|_| Pubkey::new_rand());
|
||||
let low_staked_peers = (0..10).map(|_| solana_sdk::pubkey::new_rand());
|
||||
let mut low_staked_set = HashSet::new();
|
||||
low_staked_peers.for_each(|p| {
|
||||
let _ = push.process_push_message(&mut crds, &p, value.clone(), 0);
|
||||
@@ -460,7 +460,7 @@ mod test {
|
||||
"should not prune if min threshold has not been reached"
|
||||
);
|
||||
|
||||
let high_staked_peer = Pubkey::new_rand();
|
||||
let high_staked_peer = solana_sdk::pubkey::new_rand();
|
||||
let high_stake = CrdsGossipPush::prune_stake_threshold(100, 100) + 10;
|
||||
stakes.insert(high_staked_peer, high_stake);
|
||||
let _ = push.process_push_message(&mut crds, &high_staked_peer, value, 0);
|
||||
@@ -483,7 +483,7 @@ mod test {
|
||||
let mut crds = Crds::default();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let value = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let label = value.label();
|
||||
@@ -504,7 +504,7 @@ mod test {
|
||||
fn test_process_push_old_version() {
|
||||
let mut crds = Crds::default();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
|
||||
ci.wallclock = 1;
|
||||
let value = CrdsValue::new_unsigned(CrdsData::ContactInfo(ci.clone()));
|
||||
|
||||
@@ -527,7 +527,7 @@ mod test {
|
||||
let mut crds = Crds::default();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let timeout = push.msg_timeout;
|
||||
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
|
||||
|
||||
// push a version to far in the future
|
||||
ci.wallclock = timeout + 1;
|
||||
@@ -549,7 +549,7 @@ mod test {
|
||||
fn test_process_push_update() {
|
||||
let mut crds = Crds::default();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
|
||||
ci.wallclock = 0;
|
||||
let value_old = CrdsValue::new_unsigned(CrdsData::ContactInfo(ci.clone()));
|
||||
|
||||
@@ -584,7 +584,7 @@ mod test {
|
||||
let mut crds = Crds::default();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let value1 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
|
||||
@@ -593,7 +593,7 @@ mod test {
|
||||
|
||||
assert!(push.active_set.get(&value1.label().pubkey()).is_some());
|
||||
let value2 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
assert!(push.active_set.get(&value2.label().pubkey()).is_none());
|
||||
@@ -608,7 +608,7 @@ mod test {
|
||||
|
||||
for _ in 0..push.num_active {
|
||||
let value2 = CrdsValue::new_unsigned(CrdsData::ContactInfo(
|
||||
ContactInfo::new_localhost(&Pubkey::new_rand(), 0),
|
||||
ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0),
|
||||
));
|
||||
assert_eq!(crds.insert(value2.clone(), now), Ok(None));
|
||||
}
|
||||
@@ -624,7 +624,7 @@ mod test {
|
||||
let mut stakes = HashMap::new();
|
||||
for i in 1..=100 {
|
||||
let peer = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
time,
|
||||
)));
|
||||
let id = peer.label().pubkey();
|
||||
@@ -652,25 +652,25 @@ mod test {
|
||||
let gossip = socketaddr!("127.0.0.1:1234");
|
||||
|
||||
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
shred_version: 123,
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let spy = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
shred_version: 0,
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
shred_version: 123,
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_456 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
shred_version: 456,
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
@@ -709,12 +709,12 @@ mod test {
|
||||
let gossip = socketaddr!("127.0.0.1:1234");
|
||||
|
||||
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
gossip,
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
@@ -735,7 +735,7 @@ mod test {
|
||||
assert!(options.is_empty());
|
||||
|
||||
// Unknown pubkey in gossip_validators -- will push to nobody
|
||||
gossip_validators.insert(Pubkey::new_rand());
|
||||
gossip_validators.insert(solana_sdk::pubkey::new_rand());
|
||||
let options = node.push_options(
|
||||
&crds,
|
||||
&me.label().pubkey(),
|
||||
@@ -765,14 +765,14 @@ mod test {
|
||||
let mut crds = Crds::default();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let peer = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
assert_eq!(crds.insert(peer.clone(), now), Ok(None));
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), None, &Pubkey::default(), 0, 1, 1);
|
||||
|
||||
let new_msg = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let mut expected = HashMap::new();
|
||||
@@ -790,17 +790,17 @@ mod test {
|
||||
let mut crds = Crds::default();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let peer_1 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
assert_eq!(crds.insert(peer_1.clone(), now), Ok(None));
|
||||
let peer_2 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
assert_eq!(crds.insert(peer_2.clone(), now), Ok(None));
|
||||
let peer_3 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
now,
|
||||
)));
|
||||
assert_eq!(
|
||||
@@ -823,17 +823,17 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_prune() {
|
||||
let mut crds = Crds::default();
|
||||
let self_id = Pubkey::new_rand();
|
||||
let self_id = solana_sdk::pubkey::new_rand();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let peer = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
assert_eq!(crds.insert(peer.clone(), 0), Ok(None));
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), None, &Pubkey::default(), 0, 1, 1);
|
||||
|
||||
let new_msg = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let expected = HashMap::new();
|
||||
@@ -853,13 +853,13 @@ mod test {
|
||||
let mut crds = Crds::default();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let peer = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
assert_eq!(crds.insert(peer, 0), Ok(None));
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), None, &Pubkey::default(), 0, 1, 1);
|
||||
|
||||
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
|
||||
ci.wallclock = 1;
|
||||
let new_msg = CrdsValue::new_unsigned(CrdsData::ContactInfo(ci));
|
||||
let expected = HashMap::new();
|
||||
@@ -875,7 +875,7 @@ mod test {
|
||||
fn test_purge_old_received_cache() {
|
||||
let mut crds = Crds::default();
|
||||
let mut push = CrdsGossipPush::default();
|
||||
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
|
||||
ci.wallclock = 0;
|
||||
let value = CrdsValue::new_unsigned(CrdsData::ContactInfo(ci));
|
||||
let label = value.label();
|
||||
|
@@ -135,14 +135,15 @@ mod test {
|
||||
use crate::contact_info::ContactInfo;
|
||||
use crate::crds_value::{CrdsData, CrdsValue};
|
||||
use rand::{thread_rng, Rng};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::timing::timestamp;
|
||||
use std::collections::HashSet;
|
||||
use std::ops::Index;
|
||||
|
||||
fn new_test_crds_value() -> VersionedCrdsValue {
|
||||
let data =
|
||||
CrdsData::ContactInfo(ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp()));
|
||||
let data = CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
timestamp(),
|
||||
));
|
||||
VersionedCrdsValue::new(timestamp(), CrdsValue::new_unsigned(data))
|
||||
}
|
||||
|
||||
|
@@ -318,7 +318,7 @@ impl CrdsValue {
|
||||
R: rand::Rng,
|
||||
{
|
||||
let now = rng.gen();
|
||||
let contact_info = ContactInfo::new_localhost(&Pubkey::new_rand(), now);
|
||||
let contact_info = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), now);
|
||||
Self::new_signed(CrdsData::ContactInfo(contact_info), &Keypair::new())
|
||||
}
|
||||
|
||||
|
112
core/src/data_budget.rs
Normal file
112
core/src/data_budget.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DataBudget {
|
||||
// Amount of bytes we have in the budget to send.
|
||||
bytes: AtomicUsize,
|
||||
// Last time that we upped the bytes count, used
|
||||
// to detect when to up the bytes budget again
|
||||
last_timestamp_ms: AtomicU64,
|
||||
}
|
||||
|
||||
impl DataBudget {
|
||||
// If there are enough bytes in the budget, consumes from
|
||||
// the budget and returns true. Otherwise returns false.
|
||||
#[must_use]
|
||||
pub fn take(&self, size: usize) -> bool {
|
||||
let mut budget = self.bytes.load(Ordering::Acquire);
|
||||
loop {
|
||||
if budget < size {
|
||||
return false;
|
||||
}
|
||||
match self.bytes.compare_exchange_weak(
|
||||
budget,
|
||||
budget - size,
|
||||
Ordering::AcqRel,
|
||||
Ordering::Acquire,
|
||||
) {
|
||||
Ok(_) => return true,
|
||||
Err(bytes) => budget = bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Updates timestamp and returns true, if at least given milliseconds
|
||||
// has passed since last update. Otherwise returns false.
|
||||
fn can_update(&self, duration_millis: u64) -> bool {
|
||||
let now = solana_sdk::timing::timestamp();
|
||||
let mut last_timestamp = self.last_timestamp_ms.load(Ordering::Acquire);
|
||||
loop {
|
||||
if now < last_timestamp + duration_millis {
|
||||
return false;
|
||||
}
|
||||
match self.last_timestamp_ms.compare_exchange_weak(
|
||||
last_timestamp,
|
||||
now,
|
||||
Ordering::AcqRel,
|
||||
Ordering::Acquire,
|
||||
) {
|
||||
Ok(_) => return true,
|
||||
Err(ts) => last_timestamp = ts,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the budget if at least given milliseconds has passed since last
|
||||
// update. Updater function maps current value of bytes to the new one.
|
||||
pub fn update<F>(&self, duration_millis: u64, updater: F)
|
||||
where
|
||||
F: Fn(usize) -> usize,
|
||||
{
|
||||
if !self.can_update(duration_millis) {
|
||||
return;
|
||||
}
|
||||
let mut bytes = self.bytes.load(Ordering::Acquire);
|
||||
loop {
|
||||
match self.bytes.compare_exchange_weak(
|
||||
bytes,
|
||||
updater(bytes),
|
||||
Ordering::AcqRel,
|
||||
Ordering::Acquire,
|
||||
) {
|
||||
Ok(_) => break,
|
||||
Err(b) => bytes = b,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Non-atomic clone only for tests and simulations.
|
||||
pub fn clone_non_atomic(&self) -> Self {
|
||||
Self {
|
||||
bytes: AtomicUsize::new(self.bytes.load(Ordering::Acquire)),
|
||||
last_timestamp_ms: AtomicU64::new(self.last_timestamp_ms.load(Ordering::Acquire)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
fn test_data_budget() {
|
||||
let budget = DataBudget::default();
|
||||
assert!(!budget.take(1)); // budget = 0.
|
||||
|
||||
budget.update(1000, |bytes| bytes + 5); // budget updates to 5.
|
||||
assert!(budget.take(1));
|
||||
assert!(budget.take(2));
|
||||
assert!(!budget.take(3)); // budget = 2, out of budget.
|
||||
|
||||
budget.update(30, |_| 10); // no update, budget = 2.
|
||||
assert!(!budget.take(3)); // budget = 2, out of budget.
|
||||
|
||||
std::thread::sleep(Duration::from_millis(50));
|
||||
budget.update(30, |bytes| bytes * 2); // budget updates to 4.
|
||||
|
||||
assert!(budget.take(3));
|
||||
assert!(budget.take(1));
|
||||
assert!(!budget.take(1)); // budget = 0.
|
||||
}
|
||||
}
|
@@ -306,8 +306,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_gossip_services_spy() {
|
||||
let keypair = Keypair::new();
|
||||
let peer0 = Pubkey::new_rand();
|
||||
let peer1 = Pubkey::new_rand();
|
||||
let peer0 = solana_sdk::pubkey::new_rand();
|
||||
let peer1 = solana_sdk::pubkey::new_rand();
|
||||
let contact_info = ContactInfo::new_localhost(&keypair.pubkey(), 0);
|
||||
let peer0_info = ContactInfo::new_localhost(&peer0, 0);
|
||||
let peer1_info = ContactInfo::new_localhost(&peer1, 0);
|
||||
@@ -335,7 +335,7 @@ mod tests {
|
||||
spy_ref.clone(),
|
||||
None,
|
||||
Some(0),
|
||||
Some(Pubkey::new_rand()),
|
||||
Some(solana_sdk::pubkey::new_rand()),
|
||||
None,
|
||||
);
|
||||
assert_eq!(met_criteria, false);
|
||||
@@ -349,7 +349,7 @@ mod tests {
|
||||
spy_ref.clone(),
|
||||
Some(1),
|
||||
Some(0),
|
||||
Some(Pubkey::new_rand()),
|
||||
Some(solana_sdk::pubkey::new_rand()),
|
||||
None,
|
||||
);
|
||||
assert_eq!(met_criteria, false);
|
||||
|
@@ -498,7 +498,7 @@ impl HeaviestSubtreeForkChoice {
|
||||
let heaviest_slot_on_same_voted_fork = self.best_slot(last_voted_slot);
|
||||
if heaviest_slot_on_same_voted_fork.is_none() {
|
||||
if !tower.is_stray_last_vote() {
|
||||
// Unless last vote is stray, self.bast_slot(last_voted_slot) must return
|
||||
// Unless last vote is stray and stale, self.bast_slot(last_voted_slot) must return
|
||||
// Some(_), justifying to panic! here.
|
||||
// Also, adjust_lockouts_after_replay() correctly makes last_voted_slot None,
|
||||
// if all saved votes are ancestors of replayed_root_slot. So this code shouldn't be
|
||||
@@ -507,12 +507,12 @@ impl HeaviestSubtreeForkChoice {
|
||||
// validator has been running, so we must be able to fetch best_slots for all of
|
||||
// them.
|
||||
panic!(
|
||||
"a bank at last_voted_slot({}) is a frozen bank so must have been\
|
||||
"a bank at last_voted_slot({}) is a frozen bank so must have been \
|
||||
added to heaviest_subtree_fork_choice at time of freezing",
|
||||
last_voted_slot,
|
||||
)
|
||||
} else {
|
||||
// fork_infos doesn't have corresponding data for the stray restored last vote,
|
||||
// fork_infos doesn't have corresponding data for the stale stray last vote,
|
||||
// meaning some inconsistency between saved tower and ledger.
|
||||
// (newer snapshot, or only a saved tower is moved over to new setup?)
|
||||
return None;
|
||||
|
@@ -6,14 +6,10 @@
|
||||
//! command-line tools to spin up validators and a Rust library
|
||||
//!
|
||||
|
||||
#[macro_use]
|
||||
extern crate solana_bpf_loader_program;
|
||||
|
||||
pub mod accounts_hash_verifier;
|
||||
pub mod banking_stage;
|
||||
pub mod bigtable_upload_service;
|
||||
pub mod broadcast_stage;
|
||||
mod builtins;
|
||||
pub mod cache_block_time_service;
|
||||
pub mod cluster_info_vote_listener;
|
||||
pub mod commitment_service;
|
||||
@@ -35,6 +31,7 @@ pub mod crds_gossip_pull;
|
||||
pub mod crds_gossip_push;
|
||||
pub mod crds_shards;
|
||||
pub mod crds_value;
|
||||
pub mod data_budget;
|
||||
pub mod epoch_slots;
|
||||
pub mod fetch_stage;
|
||||
pub mod fork_choice;
|
||||
@@ -59,7 +56,6 @@ mod result;
|
||||
pub mod retransmit_stage;
|
||||
pub mod rewards_recorder_service;
|
||||
pub mod rpc;
|
||||
pub mod rpc_error;
|
||||
pub mod rpc_health;
|
||||
pub mod rpc_pubsub;
|
||||
pub mod rpc_pubsub_service;
|
||||
@@ -97,7 +93,7 @@ extern crate serde_json;
|
||||
extern crate solana_metrics;
|
||||
|
||||
#[macro_use]
|
||||
extern crate solana_sdk_macro_frozen_abi;
|
||||
extern crate solana_frozen_abi_macro;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
|
@@ -79,6 +79,26 @@ solana_sdk::pubkeys!(
|
||||
"GumSE5HsMV5HCwBTv2D2D81yy9x17aDkvobkqAfTRgmo",
|
||||
"AzVV9ZZDxTgW4wWfJmsG6ytaHpQGSe1yz76Nyy84VbQF",
|
||||
"8CUUMKYNGxdgYio5CLHRHyzMEhhVRMcqefgE6dLqnVRK",
|
||||
"CQDYc4ET2mbFhVpgj41gXahL6Exn5ZoPcGAzSHuYxwmE",
|
||||
"5PLJZLJiRR9vf7d1JCCg7UuWjtyN9nkab9uok6TqSyuP",
|
||||
"7xJ9CLtEAcEShw9kW2gSoZkRWL566Dg12cvgzANJwbTr",
|
||||
"BuCEvc9ze8UoAQwwsQLy8d447C8sA4zeVtVpc6m5wQeS",
|
||||
"8ndGYFjav6NDXvzYcxs449Aub3AxYv4vYpk89zRDwgj7",
|
||||
"8W58E8JVJjH1jCy5CeHJQgvwFXTyAVyesuXRZGbcSUGG",
|
||||
"GNiz4Mq886bTNDT3pijGsu2gbw6it7sqrwncro45USeB",
|
||||
"GhsotwFMH6XUrRLJCxcx62h7748N2Uq8mf87hUGkmPhg",
|
||||
"Fgyh8EeYGZtbW8sS33YmNQnzx54WXPrJ5KWNPkCfWPot",
|
||||
"8UVjvYyoqP6sqcctTso3xpCdCfgTMiv3VRh7vraC2eJk",
|
||||
"BhvLngiqqKeZ8rpxch2uGjeCiC88zzewoWPRuoxpp1aS",
|
||||
"63DtkW7zuARcd185EmHAkfF44bDcC2SiTSEj2spLP3iA",
|
||||
"GvpCiTgq9dmEeojCDBivoLoZqc4AkbUDACpqPMwYLWKh",
|
||||
"7Y8smnoUrYKGGuDq2uaFKVxJYhojgg7DVixHyAtGTYEV",
|
||||
"DUS1KxwUhUyDKB4A81E8vdnTe3hSahd92Abtn9CXsEcj",
|
||||
"F9MWFw8cnYVwsRq8Am1PGfFL3cQUZV37mbGoxZftzLjN",
|
||||
"8vqrX3H2BYLaXVintse3gorPEM4TgTwTFZNN1Fm9TdYs",
|
||||
"CUageMFi49kzoDqtdU8NvQ4Bq3sbtJygjKDAXJ45nmAi",
|
||||
"5smrYwb1Hr2T8XMnvsqccTgXxuqQs14iuE8RbHFYf2Cf",
|
||||
"xQadXQiUTCCFhfHjvQx1hyJK6KVWr1w2fD6DT3cdwj7",
|
||||
]
|
||||
);
|
||||
|
||||
@@ -115,7 +135,7 @@ mod tests {
|
||||
let num_genesis_accounts = 10;
|
||||
for _ in 0..num_genesis_accounts {
|
||||
accounts.insert(
|
||||
Pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
Account::new(balance, 0, &Pubkey::default()),
|
||||
);
|
||||
}
|
||||
@@ -127,7 +147,7 @@ mod tests {
|
||||
|
||||
let num_stake_accounts = 3;
|
||||
for _ in 0..num_stake_accounts {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let meta = Meta {
|
||||
authorized: Authorized::auto(&pubkey),
|
||||
lockup: Lockup {
|
||||
|
@@ -401,7 +401,7 @@ mod test {
|
||||
fn test_add_vote_pubkey() {
|
||||
let mut stats = PropagatedStats::default();
|
||||
let mut all_pubkeys = PubkeyReferences::default();
|
||||
let mut vote_pubkey = Pubkey::new_rand();
|
||||
let mut vote_pubkey = solana_sdk::pubkey::new_rand();
|
||||
all_pubkeys.get_or_insert(&vote_pubkey);
|
||||
|
||||
// Add a vote pubkey, the number of references in all_pubkeys
|
||||
@@ -420,7 +420,7 @@ mod test {
|
||||
assert_eq!(stats.propagated_validators_stake, 1);
|
||||
|
||||
// Adding another pubkey should succeed
|
||||
vote_pubkey = Pubkey::new_rand();
|
||||
vote_pubkey = solana_sdk::pubkey::new_rand();
|
||||
stats.add_vote_pubkey(&vote_pubkey, &mut all_pubkeys, 2);
|
||||
assert!(stats.propagated_validators.contains(&vote_pubkey));
|
||||
assert_eq!(stats.propagated_validators_stake, 3);
|
||||
@@ -434,7 +434,7 @@ mod test {
|
||||
fn test_add_node_pubkey_internal() {
|
||||
let num_vote_accounts = 10;
|
||||
let staked_vote_accounts = 5;
|
||||
let vote_account_pubkeys: Vec<_> = std::iter::repeat_with(Pubkey::new_rand)
|
||||
let vote_account_pubkeys: Vec<_> = std::iter::repeat_with(solana_sdk::pubkey::new_rand)
|
||||
.take(num_vote_accounts)
|
||||
.collect();
|
||||
let epoch_vote_accounts: HashMap<_, _> = vote_account_pubkeys
|
||||
@@ -445,7 +445,7 @@ mod test {
|
||||
|
||||
let mut stats = PropagatedStats::default();
|
||||
let mut all_pubkeys = PubkeyReferences::default();
|
||||
let mut node_pubkey = Pubkey::new_rand();
|
||||
let mut node_pubkey = solana_sdk::pubkey::new_rand();
|
||||
all_pubkeys.get_or_insert(&node_pubkey);
|
||||
|
||||
// Add a vote pubkey, the number of references in all_pubkeys
|
||||
@@ -481,7 +481,7 @@ mod test {
|
||||
|
||||
// Adding another pubkey with same vote accounts should succeed, but stake
|
||||
// shouldn't increase
|
||||
node_pubkey = Pubkey::new_rand();
|
||||
node_pubkey = solana_sdk::pubkey::new_rand();
|
||||
stats.add_node_pubkey_internal(
|
||||
&node_pubkey,
|
||||
&mut all_pubkeys,
|
||||
@@ -500,8 +500,8 @@ mod test {
|
||||
|
||||
// Adding another pubkey with different vote accounts should succeed
|
||||
// and increase stake
|
||||
node_pubkey = Pubkey::new_rand();
|
||||
let vote_account_pubkeys: Vec<_> = std::iter::repeat_with(Pubkey::new_rand)
|
||||
node_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let vote_account_pubkeys: Vec<_> = std::iter::repeat_with(solana_sdk::pubkey::new_rand)
|
||||
.take(num_vote_accounts)
|
||||
.collect();
|
||||
let epoch_vote_accounts: HashMap<_, _> = vote_account_pubkeys
|
||||
|
@@ -291,7 +291,6 @@ impl ReplayStage {
|
||||
&bank_forks,
|
||||
&leader_schedule_cache,
|
||||
&subscriptions,
|
||||
rewards_recorder_sender.clone(),
|
||||
&mut progress,
|
||||
&mut all_pubkeys,
|
||||
);
|
||||
@@ -313,6 +312,7 @@ impl ReplayStage {
|
||||
&mut heaviest_subtree_fork_choice,
|
||||
&replay_vote_sender,
|
||||
&bank_notification_sender,
|
||||
&rewards_recorder_sender,
|
||||
);
|
||||
replay_active_banks_time.stop();
|
||||
Self::report_memory(&allocated, "replay_active_banks", start);
|
||||
@@ -408,7 +408,7 @@ impl ReplayStage {
|
||||
&ancestors,
|
||||
&descendants,
|
||||
&progress,
|
||||
&tower,
|
||||
&mut tower,
|
||||
);
|
||||
select_vote_and_reset_forks_time.stop();
|
||||
|
||||
@@ -554,7 +554,6 @@ impl ReplayStage {
|
||||
&poh_recorder,
|
||||
&leader_schedule_cache,
|
||||
&subscriptions,
|
||||
rewards_recorder_sender.clone(),
|
||||
&progress,
|
||||
&retransmit_slots_sender,
|
||||
&mut skipped_slots_info,
|
||||
@@ -854,7 +853,6 @@ impl ReplayStage {
|
||||
poh_recorder: &Arc<Mutex<PohRecorder>>,
|
||||
leader_schedule_cache: &Arc<LeaderScheduleCache>,
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
rewards_recorder_sender: Option<RewardsRecorderSender>,
|
||||
progress_map: &ProgressMap,
|
||||
retransmit_slots_sender: &RetransmitSlotsSender,
|
||||
skipped_slots_info: &mut SkippedSlotsInfo,
|
||||
@@ -953,7 +951,6 @@ impl ReplayStage {
|
||||
poh_slot,
|
||||
root_slot,
|
||||
my_pubkey,
|
||||
&rewards_recorder_sender,
|
||||
subscriptions,
|
||||
);
|
||||
|
||||
@@ -1265,6 +1262,7 @@ impl ReplayStage {
|
||||
heaviest_subtree_fork_choice: &mut HeaviestSubtreeForkChoice,
|
||||
replay_vote_sender: &ReplayVoteSender,
|
||||
bank_notification_sender: &Option<BankNotificationSender>,
|
||||
rewards_recorder_sender: &Option<RewardsRecorderSender>,
|
||||
) -> bool {
|
||||
let mut did_complete_bank = false;
|
||||
let mut tx_count = 0;
|
||||
@@ -1340,6 +1338,8 @@ impl ReplayStage {
|
||||
.send(BankNotification::Frozen(bank.clone()))
|
||||
.unwrap_or_else(|err| warn!("bank_notification_sender failed: {:?}", err));
|
||||
}
|
||||
|
||||
Self::record_rewards(&bank, &rewards_recorder_sender);
|
||||
} else {
|
||||
trace!(
|
||||
"bank {} not completed tick_height: {}, max_tick_height: {}",
|
||||
@@ -1525,7 +1525,7 @@ impl ReplayStage {
|
||||
ancestors: &HashMap<u64, HashSet<u64>>,
|
||||
descendants: &HashMap<u64, HashSet<u64>>,
|
||||
progress: &ProgressMap,
|
||||
tower: &Tower,
|
||||
tower: &mut Tower,
|
||||
) -> SelectVoteAndResetForkResult {
|
||||
// Try to vote on the actual heaviest fork. If the heaviest bank is
|
||||
// locked out or fails the threshold check, the validator will:
|
||||
@@ -1552,7 +1552,7 @@ impl ReplayStage {
|
||||
.epoch_vote_accounts(heaviest_bank.epoch())
|
||||
.expect("Bank epoch vote accounts must contain entry for the bank's own epoch"),
|
||||
);
|
||||
if switch_fork_decision == SwitchForkDecision::FailedSwitchThreshold {
|
||||
if let SwitchForkDecision::FailedSwitchThreshold(_, _) = switch_fork_decision {
|
||||
// If we can't switch, then reset to the the next votable
|
||||
// bank on the same fork as our last vote, but don't vote
|
||||
info!(
|
||||
@@ -1601,7 +1601,7 @@ impl ReplayStage {
|
||||
if !is_locked_out
|
||||
&& vote_threshold
|
||||
&& propagation_confirmed
|
||||
&& switch_fork_decision != SwitchForkDecision::FailedSwitchThreshold
|
||||
&& switch_fork_decision.can_vote()
|
||||
{
|
||||
info!("voting: {} {}", bank.slot(), fork_weight);
|
||||
SelectVoteAndResetForkResult {
|
||||
@@ -1817,7 +1817,6 @@ impl ReplayStage {
|
||||
bank_forks: &RwLock<BankForks>,
|
||||
leader_schedule_cache: &Arc<LeaderScheduleCache>,
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
rewards_recorder_sender: Option<RewardsRecorderSender>,
|
||||
progress: &mut ProgressMap,
|
||||
all_pubkeys: &mut PubkeyReferences,
|
||||
) {
|
||||
@@ -1863,7 +1862,6 @@ impl ReplayStage {
|
||||
child_slot,
|
||||
forks.root(),
|
||||
&leader,
|
||||
&rewards_recorder_sender,
|
||||
subscriptions,
|
||||
);
|
||||
let empty: Vec<&Pubkey> = vec![];
|
||||
@@ -1891,21 +1889,18 @@ impl ReplayStage {
|
||||
slot: u64,
|
||||
root_slot: u64,
|
||||
leader: &Pubkey,
|
||||
rewards_recorder_sender: &Option<RewardsRecorderSender>,
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
) -> Bank {
|
||||
subscriptions.notify_slot(slot, parent.slot(), root_slot);
|
||||
|
||||
let child_bank = Bank::new_from_parent(parent, leader, slot);
|
||||
Self::record_rewards(&child_bank, &rewards_recorder_sender);
|
||||
child_bank
|
||||
Bank::new_from_parent(parent, leader, slot)
|
||||
}
|
||||
|
||||
fn record_rewards(bank: &Bank, rewards_recorder_sender: &Option<RewardsRecorderSender>) {
|
||||
if let Some(rewards_recorder_sender) = rewards_recorder_sender {
|
||||
if let Some(ref rewards) = bank.rewards {
|
||||
let rewards = bank.rewards.read().unwrap();
|
||||
if !rewards.is_empty() {
|
||||
rewards_recorder_sender
|
||||
.send((bank.slot(), rewards.iter().copied().collect()))
|
||||
.send((bank.slot(), rewards.clone()))
|
||||
.unwrap_or_else(|err| warn!("rewards_recorder_sender failed: {:?}", err));
|
||||
}
|
||||
}
|
||||
@@ -2155,7 +2150,6 @@ pub(crate) mod tests {
|
||||
&bank_forks,
|
||||
&leader_schedule_cache,
|
||||
&rpc_subscriptions,
|
||||
None,
|
||||
&mut progress,
|
||||
&mut PubkeyReferences::default(),
|
||||
);
|
||||
@@ -2179,7 +2173,6 @@ pub(crate) mod tests {
|
||||
&bank_forks,
|
||||
&leader_schedule_cache,
|
||||
&rpc_subscriptions,
|
||||
None,
|
||||
&mut progress,
|
||||
&mut PubkeyReferences::default(),
|
||||
);
|
||||
@@ -2561,7 +2554,7 @@ pub(crate) mod tests {
|
||||
bank.store_account(&pubkey, &leader_vote_account);
|
||||
}
|
||||
|
||||
let leader_pubkey = Pubkey::new_rand();
|
||||
let leader_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let leader_lamports = 3;
|
||||
let genesis_config_info =
|
||||
create_genesis_config_with_leader(50, &leader_pubkey, leader_lamports);
|
||||
@@ -2603,7 +2596,11 @@ pub(crate) mod tests {
|
||||
.is_none());
|
||||
|
||||
let bank1 = Bank::new_from_parent(&arc_bank0, &Pubkey::default(), arc_bank0.slot() + 1);
|
||||
let _res = bank1.transfer(10, &genesis_config_info.mint_keypair, &Pubkey::new_rand());
|
||||
let _res = bank1.transfer(
|
||||
10,
|
||||
&genesis_config_info.mint_keypair,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
);
|
||||
for _ in 0..genesis_config.ticks_per_slot {
|
||||
bank1.register_tick(&Hash::default());
|
||||
}
|
||||
@@ -2619,7 +2616,11 @@ pub(crate) mod tests {
|
||||
);
|
||||
|
||||
let bank2 = Bank::new_from_parent(&arc_bank1, &Pubkey::default(), arc_bank1.slot() + 1);
|
||||
let _res = bank2.transfer(10, &genesis_config_info.mint_keypair, &Pubkey::new_rand());
|
||||
let _res = bank2.transfer(
|
||||
10,
|
||||
&genesis_config_info.mint_keypair,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
);
|
||||
for _ in 0..genesis_config.ticks_per_slot {
|
||||
bank2.register_tick(&Hash::default());
|
||||
}
|
||||
|
@@ -504,7 +504,6 @@ mod tests {
|
||||
use solana_ledger::genesis_utils::{create_genesis_config, GenesisConfigInfo};
|
||||
use solana_net_utils::find_available_port_in_range;
|
||||
use solana_perf::packet::{Meta, Packet, Packets};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
|
||||
#[test]
|
||||
@@ -521,7 +520,7 @@ mod tests {
|
||||
let leader_schedule_cache = Arc::new(cached_leader_schedule);
|
||||
let bank_forks = Arc::new(RwLock::new(bank_forks));
|
||||
|
||||
let mut me = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
let mut me = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
|
||||
let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
|
||||
let port = find_available_port_in_range(ip_addr, (8000, 10000)).unwrap();
|
||||
let me_retransmit = UdpSocket::bind(format!("127.0.0.1:{}", port)).unwrap();
|
||||
@@ -533,7 +532,7 @@ mod tests {
|
||||
.local_addr()
|
||||
.unwrap();
|
||||
|
||||
let other = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
let other = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(other);
|
||||
cluster_info.insert_info(me);
|
||||
|
||||
|
@@ -54,6 +54,7 @@ impl RewardsRecorderService {
|
||||
pubkey: pubkey.to_string(),
|
||||
lamports: reward_info.lamports,
|
||||
post_balance: reward_info.post_balance,
|
||||
reward_type: Some(reward_info.reward_type),
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
141
core/src/rpc.rs
141
core/src/rpc.rs
@@ -5,7 +5,6 @@ use crate::{
|
||||
contact_info::ContactInfo,
|
||||
non_circulating_supply::calculate_non_circulating_supply,
|
||||
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||
rpc_error::RpcCustomError,
|
||||
rpc_health::*,
|
||||
send_transaction_service::{SendTransactionService, TransactionInfo},
|
||||
validator::ValidatorExit,
|
||||
@@ -23,6 +22,7 @@ use solana_account_decoder::{
|
||||
};
|
||||
use solana_client::{
|
||||
rpc_config::*,
|
||||
rpc_custom_error::RpcCustomError,
|
||||
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
|
||||
rpc_request::{
|
||||
TokenAccountsFilter, DELINQUENT_VALIDATOR_SLOT_DISTANCE, MAX_GET_CONFIRMED_BLOCKS_RANGE,
|
||||
@@ -35,6 +35,7 @@ use solana_client::{
|
||||
};
|
||||
use solana_faucet::faucet::request_airdrop_transaction;
|
||||
use solana_ledger::{blockstore::Blockstore, blockstore_db::BlockstoreError, get_tmp_ledger_path};
|
||||
use solana_metrics::inc_new_counter_info;
|
||||
use solana_perf::packet::PACKET_DATA_SIZE;
|
||||
use solana_runtime::{
|
||||
accounts::AccountAddressFilter,
|
||||
@@ -548,9 +549,6 @@ impl JsonRpcRequestProcessor {
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let epoch_vote_account = epoch_vote_accounts
|
||||
.iter()
|
||||
.any(|(epoch_vote_pubkey, _)| epoch_vote_pubkey == pubkey);
|
||||
RpcVoteAccountInfo {
|
||||
vote_pubkey: (pubkey).to_string(),
|
||||
node_pubkey: vote_state.node_pubkey.to_string(),
|
||||
@@ -558,7 +556,7 @@ impl JsonRpcRequestProcessor {
|
||||
commission: vote_state.commission,
|
||||
root_slot: vote_state.root_slot.unwrap_or(0),
|
||||
epoch_credits: vote_state.epoch_credits().clone(),
|
||||
epoch_vote_account,
|
||||
epoch_vote_account: epoch_vote_accounts.contains_key(pubkey),
|
||||
last_vote,
|
||||
}
|
||||
})
|
||||
@@ -2609,6 +2607,7 @@ fn deserialize_transaction(
|
||||
) -> Result<(Vec<u8>, Transaction)> {
|
||||
let wire_transaction = match encoding {
|
||||
UiTransactionEncoding::Base58 => {
|
||||
inc_new_counter_info!("rpc-base58_encoded_tx", 1);
|
||||
if encoded_transaction.len() > WORST_CASE_BASE58_TX {
|
||||
return Err(Error::invalid_params(format!(
|
||||
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
|
||||
@@ -2622,6 +2621,7 @@ fn deserialize_transaction(
|
||||
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?
|
||||
}
|
||||
UiTransactionEncoding::Base64 => {
|
||||
inc_new_counter_info!("rpc-base64_encoded_tx", 1);
|
||||
if encoded_transaction.len() > WORST_CASE_BASE64_TX {
|
||||
return Err(Error::invalid_params(format!(
|
||||
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
|
||||
@@ -2904,7 +2904,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_request_processor_new() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let genesis = create_genesis_config(100);
|
||||
let bank = Arc::new(Bank::new(&genesis.genesis_config));
|
||||
bank.transfer(20, &genesis.mint_keypair, &bob_pubkey)
|
||||
@@ -2964,7 +2964,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_cluster_nodes() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -2991,7 +2991,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_recent_performance_samples() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getRecentPerformanceSamples"}"#;
|
||||
@@ -3020,7 +3020,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_recent_performance_samples_invalid_limit() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req =
|
||||
@@ -3046,7 +3046,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_slot_leader() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -3066,7 +3066,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_tx_count() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let genesis = create_genesis_config(10);
|
||||
let bank = Arc::new(Bank::new(&genesis.genesis_config));
|
||||
// Add 4 transactions
|
||||
@@ -3096,7 +3096,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_minimum_ledger_slot() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"minimumLedgerSlot"}"#;
|
||||
@@ -3111,7 +3111,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_total_supply() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getTotalSupply"}"#;
|
||||
@@ -3136,7 +3136,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_supply() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getSupply"}"#;
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
@@ -3161,7 +3161,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_largest_accounts() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io, meta, alice, ..
|
||||
} = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
@@ -3220,7 +3220,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_minimum_balance_for_rent_exemption() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let data_len = 50;
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
@@ -3252,7 +3252,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_inflation() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getInflationGovernor"}"#;
|
||||
@@ -3299,7 +3299,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_epoch_schedule() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getEpochSchedule"}"#;
|
||||
@@ -3321,7 +3321,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_leader_schedule() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
for req in [
|
||||
@@ -3377,7 +3377,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_account_info() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = format!(
|
||||
@@ -3405,7 +3405,7 @@ pub mod tests {
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(expected, result);
|
||||
|
||||
let address = Pubkey::new_rand();
|
||||
let address = solana_sdk::pubkey::new_rand();
|
||||
let data = vec![1, 2, 3, 4, 5];
|
||||
let mut account = Account::new(42, 5, &Pubkey::default());
|
||||
account.data = data.clone();
|
||||
@@ -3459,7 +3459,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_multiple_accounts() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let address = Pubkey::new(&[9; 32]);
|
||||
@@ -3586,7 +3586,7 @@ pub mod tests {
|
||||
..
|
||||
} = start_rpc_handler_with_tx(&bob.pubkey());
|
||||
|
||||
let new_program_id = Pubkey::new_rand();
|
||||
let new_program_id = solana_sdk::pubkey::new_rand();
|
||||
let tx = system_transaction::assign(&bob, blockhash, &new_program_id);
|
||||
bank.process_transaction(&tx).unwrap();
|
||||
let req = format!(
|
||||
@@ -3633,7 +3633,7 @@ pub mod tests {
|
||||
bank.process_transaction(&tx).unwrap();
|
||||
|
||||
let nonce_keypair1 = Keypair::new();
|
||||
let authority = Pubkey::new_rand();
|
||||
let authority = solana_sdk::pubkey::new_rand();
|
||||
let instruction = system_instruction::create_nonce_account(
|
||||
&alice.pubkey(),
|
||||
&nonce_keypair1.pubkey(),
|
||||
@@ -3776,7 +3776,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_simulate_transaction() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -3877,7 +3877,7 @@ pub mod tests {
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_rpc_simulate_transaction_panic_on_unfrozen_bank() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -3903,7 +3903,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_confirm_tx() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -3935,7 +3935,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_signature_status() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -4005,7 +4005,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_signature_statuses() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -4061,7 +4061,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_recent_blockhash() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -4092,7 +4092,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_fees() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -4124,7 +4124,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_fee_calculator_for_blockhash() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
|
||||
@@ -4172,7 +4172,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_fee_rate_governor() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getFeeRateGovernor"}"#;
|
||||
@@ -4201,7 +4201,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_fail_request_airdrop() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
// Expect internal error because no faucet is available
|
||||
@@ -4271,8 +4271,12 @@ pub mod tests {
|
||||
);
|
||||
SendTransactionService::new(tpu_address, &bank_forks, None, receiver);
|
||||
|
||||
let mut bad_transaction =
|
||||
system_transaction::transfer(&mint_keypair, &Pubkey::new_rand(), 42, Hash::default());
|
||||
let mut bad_transaction = system_transaction::transfer(
|
||||
&mint_keypair,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
42,
|
||||
Hash::default(),
|
||||
);
|
||||
|
||||
// sendTransaction will fail because the blockhash is invalid
|
||||
let req = format!(
|
||||
@@ -4302,8 +4306,12 @@ pub mod tests {
|
||||
r#"{"jsonrpc":"2.0","error":{"code":-32002,"message":"Transaction simulation failed: Transaction failed to sanitize accounts offsets correctly","data":{"err":"SanitizeFailure","logs":[]}},"id":1}"#.to_string(),
|
||||
)
|
||||
);
|
||||
let mut bad_transaction =
|
||||
system_transaction::transfer(&mint_keypair, &Pubkey::new_rand(), 42, recent_blockhash);
|
||||
let mut bad_transaction = system_transaction::transfer(
|
||||
&mint_keypair,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
42,
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
// sendTransaction will fail due to poor node health
|
||||
health.stub_set_health_status(Some(RpcHealthStatus::Behind));
|
||||
@@ -4386,7 +4394,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_verify_pubkey() {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
assert_eq!(verify_pubkey(pubkey.to_string()).unwrap(), pubkey);
|
||||
let bad_pubkey = "a1b2c3d4";
|
||||
assert_eq!(
|
||||
@@ -4397,7 +4405,12 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_verify_signature() {
|
||||
let tx = system_transaction::transfer(&Keypair::new(), &Pubkey::new_rand(), 20, hash(&[0]));
|
||||
let tx = system_transaction::transfer(
|
||||
&Keypair::new(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
20,
|
||||
hash(&[0]),
|
||||
);
|
||||
assert_eq!(
|
||||
verify_signature(&tx.signatures[0].to_string()).unwrap(),
|
||||
tx.signatures[0]
|
||||
@@ -4489,7 +4502,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_identity() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getIdentity"}"#;
|
||||
@@ -4510,7 +4523,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_version() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getVersion"}"#;
|
||||
@@ -4597,7 +4610,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_block_commitment() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -4651,7 +4664,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_confirmed_block() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
@@ -4749,7 +4762,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_confirmed_blocks() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let roots = vec![0, 1, 3, 4, 8];
|
||||
let RpcHandler {
|
||||
io,
|
||||
@@ -4826,7 +4839,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_confirmed_blocks_with_limit() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let roots = vec![0, 1, 3, 4, 8];
|
||||
let RpcHandler {
|
||||
io,
|
||||
@@ -4889,7 +4902,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_block_time() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let base_timestamp = 1_576_183_541;
|
||||
let RpcHandler {
|
||||
io,
|
||||
@@ -4976,7 +4989,7 @@ pub mod tests {
|
||||
leader_vote_keypair,
|
||||
block_commitment_cache,
|
||||
..
|
||||
} = start_rpc_handler_with_tx(&Pubkey::new_rand());
|
||||
} = start_rpc_handler_with_tx(&solana_sdk::pubkey::new_rand());
|
||||
|
||||
assert_eq!(bank.vote_accounts().len(), 1);
|
||||
|
||||
@@ -5192,7 +5205,8 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_token_rpcs() {
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand());
|
||||
let RpcHandler { io, meta, bank, .. } =
|
||||
start_rpc_handler_with_tx(&solana_sdk::pubkey::new_rand());
|
||||
|
||||
let mut account_data = vec![0; TokenAccount::get_packed_len()];
|
||||
let mint = SplTokenPubkey::new(&[2; 32]);
|
||||
@@ -5215,7 +5229,7 @@ pub mod tests {
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
let token_account_pubkey = Pubkey::new_rand();
|
||||
let token_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
bank.store_account(&token_account_pubkey, &token_account);
|
||||
|
||||
// Add the mint
|
||||
@@ -5253,7 +5267,7 @@ pub mod tests {
|
||||
// Test non-existent token account
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenAccountBalance","params":["{}"]}}"#,
|
||||
Pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
@@ -5278,7 +5292,7 @@ pub mod tests {
|
||||
// Test non-existent mint address
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenSupply","params":["{}"]}}"#,
|
||||
Pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
@@ -5286,7 +5300,7 @@ pub mod tests {
|
||||
assert!(result.get("error").is_some());
|
||||
|
||||
// Add another token account with the same owner, delegate, and mint
|
||||
let other_token_account_pubkey = Pubkey::new_rand();
|
||||
let other_token_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
bank.store_account(&other_token_account_pubkey, &token_account);
|
||||
|
||||
// Add another token account with the same owner and delegate but different mint
|
||||
@@ -5309,7 +5323,7 @@ pub mod tests {
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
let token_with_different_mint_pubkey = Pubkey::new_rand();
|
||||
let token_with_different_mint_pubkey = solana_sdk::pubkey::new_rand();
|
||||
bank.store_account(&token_with_different_mint_pubkey, &token_account);
|
||||
|
||||
// Test getTokenAccountsByOwner with Token program id returns all accounts, regardless of Mint address
|
||||
@@ -5390,7 +5404,7 @@ pub mod tests {
|
||||
"params":["{}", {{"programId": "{}"}}]
|
||||
}}"#,
|
||||
owner,
|
||||
Pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
@@ -5404,7 +5418,7 @@ pub mod tests {
|
||||
"params":["{}", {{"mint": "{}"}}]
|
||||
}}"#,
|
||||
owner,
|
||||
Pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
@@ -5419,7 +5433,7 @@ pub mod tests {
|
||||
"method":"getTokenAccountsByOwner",
|
||||
"params":["{}", {{"programId": "{}"}}]
|
||||
}}"#,
|
||||
Pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
spl_token_id_v2_0(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
@@ -5473,7 +5487,7 @@ pub mod tests {
|
||||
"params":["{}", {{"programId": "{}"}}]
|
||||
}}"#,
|
||||
delegate,
|
||||
Pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
@@ -5487,7 +5501,7 @@ pub mod tests {
|
||||
"params":["{}", {{"mint": "{}"}}]
|
||||
}}"#,
|
||||
delegate,
|
||||
Pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
@@ -5502,7 +5516,7 @@ pub mod tests {
|
||||
"method":"getTokenAccountsByDelegate",
|
||||
"params":["{}", {{"programId": "{}"}}]
|
||||
}}"#,
|
||||
Pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
spl_token_id_v2_0(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
@@ -5550,7 +5564,7 @@ pub mod tests {
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
let token_with_smaller_balance = Pubkey::new_rand();
|
||||
let token_with_smaller_balance = solana_sdk::pubkey::new_rand();
|
||||
bank.store_account(&token_with_smaller_balance, &token_account);
|
||||
|
||||
// Test largest token accounts
|
||||
@@ -5588,7 +5602,8 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_token_parsing() {
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand());
|
||||
let RpcHandler { io, meta, bank, .. } =
|
||||
start_rpc_handler_with_tx(&solana_sdk::pubkey::new_rand());
|
||||
|
||||
let mut account_data = vec![0; TokenAccount::get_packed_len()];
|
||||
let mint = SplTokenPubkey::new(&[2; 32]);
|
||||
@@ -5611,7 +5626,7 @@ pub mod tests {
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
let token_account_pubkey = Pubkey::new_rand();
|
||||
let token_account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
bank.store_account(&token_account_pubkey, &token_account);
|
||||
|
||||
// Add the mint
|
||||
|
@@ -505,7 +505,7 @@ mod tests {
|
||||
mint_keypair: alice,
|
||||
..
|
||||
} = create_genesis_config(10_000);
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let blockhash = bank.last_blockhash();
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
||||
@@ -551,7 +551,7 @@ mod tests {
|
||||
..
|
||||
} = create_genesis_config(10_000);
|
||||
|
||||
let new_stake_authority = Pubkey::new_rand();
|
||||
let new_stake_authority = solana_sdk::pubkey::new_rand();
|
||||
let stake_authority = Keypair::new();
|
||||
let from = Keypair::new();
|
||||
let stake_account = Keypair::new();
|
||||
@@ -748,7 +748,7 @@ mod tests {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_account_unsubscribe() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let session = create_session();
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config))));
|
||||
|
@@ -550,7 +550,11 @@ mod tests {
|
||||
let cluster_info = Arc::new(ClusterInfo::default());
|
||||
let health_check_slot_distance = 123;
|
||||
let override_health_check = Arc::new(AtomicBool::new(false));
|
||||
let trusted_validators = vec![Pubkey::new_rand(), Pubkey::new_rand(), Pubkey::new_rand()];
|
||||
let trusted_validators = vec![
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
];
|
||||
|
||||
let health = Arc::new(RpcHealth::new(
|
||||
cluster_info.clone(),
|
||||
@@ -566,6 +570,7 @@ mod tests {
|
||||
|
||||
// No account hashes for any trusted validators == "behind"
|
||||
cluster_info.push_accounts_hashes(vec![(1000, Hash::default()), (900, Hash::default())]);
|
||||
cluster_info.flush_push_queue();
|
||||
assert_eq!(rm.health_check(), "behind");
|
||||
override_health_check.store(true, Ordering::Relaxed);
|
||||
assert_eq!(rm.health_check(), "ok");
|
||||
|
@@ -1249,8 +1249,11 @@ pub(crate) mod tests {
|
||||
.process_transaction(&past_bank_tx)
|
||||
.unwrap();
|
||||
|
||||
let next_bank =
|
||||
Bank::new_from_parent(&bank_forks.banks[&0].clone(), &Pubkey::new_rand(), 1);
|
||||
let next_bank = Bank::new_from_parent(
|
||||
&bank_forks.banks[&0].clone(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
1,
|
||||
);
|
||||
bank_forks.insert(next_bank);
|
||||
|
||||
bank_forks
|
||||
|
@@ -396,7 +396,7 @@ impl ServeRepair {
|
||||
cache.insert(slot, (repair_peers, weights));
|
||||
}
|
||||
let (repair_peers, weights) = cache.get(&slot).unwrap();
|
||||
let n = weighted_best(&weights, Pubkey::new_rand().to_bytes());
|
||||
let n = weighted_best(&weights, solana_sdk::pubkey::new_rand().to_bytes());
|
||||
let addr = repair_peers[n].serve_repair; // send the request to the peer's serve_repair port
|
||||
let repair_peer_id = repair_peers[n].id;
|
||||
let out = self.map_repair_request(
|
||||
@@ -419,7 +419,7 @@ impl ServeRepair {
|
||||
return Err(ClusterInfoError::NoPeers.into());
|
||||
}
|
||||
let weights = cluster_slots.compute_weights_exclude_noncomplete(slot, &repair_peers);
|
||||
let n = weighted_best(&weights, Pubkey::new_rand().to_bytes());
|
||||
let n = weighted_best(&weights, solana_sdk::pubkey::new_rand().to_bytes());
|
||||
Ok((repair_peers[n].id, repair_peers[n].serve_repair))
|
||||
}
|
||||
|
||||
@@ -678,7 +678,7 @@ mod tests {
|
||||
{
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let me = ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
gossip: socketaddr!("127.0.0.1:1234"),
|
||||
tvu: socketaddr!("127.0.0.1:1235"),
|
||||
tvu_forwards: socketaddr!("127.0.0.1:1236"),
|
||||
@@ -748,7 +748,7 @@ mod tests {
|
||||
#[test]
|
||||
fn window_index_request() {
|
||||
let cluster_slots = ClusterSlots::default();
|
||||
let me = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
|
||||
let me = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
|
||||
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(me));
|
||||
let serve_repair = ServeRepair::new(cluster_info.clone());
|
||||
let rv = serve_repair.repair_request(
|
||||
@@ -762,7 +762,7 @@ mod tests {
|
||||
|
||||
let serve_repair_addr = socketaddr!([127, 0, 0, 1], 1243);
|
||||
let nxt = ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
gossip: socketaddr!([127, 0, 0, 1], 1234),
|
||||
tvu: socketaddr!([127, 0, 0, 1], 1235),
|
||||
tvu_forwards: socketaddr!([127, 0, 0, 1], 1236),
|
||||
@@ -791,7 +791,7 @@ mod tests {
|
||||
|
||||
let serve_repair_addr2 = socketaddr!([127, 0, 0, 2], 1243);
|
||||
let nxt = ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
id: solana_sdk::pubkey::new_rand(),
|
||||
gossip: socketaddr!([127, 0, 0, 1], 1234),
|
||||
tvu: socketaddr!([127, 0, 0, 1], 1235),
|
||||
tvu_forwards: socketaddr!([127, 0, 0, 1], 1236),
|
||||
@@ -967,12 +967,14 @@ mod tests {
|
||||
#[test]
|
||||
fn test_repair_with_repair_validators() {
|
||||
let cluster_slots = ClusterSlots::default();
|
||||
let me = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
|
||||
let me = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
|
||||
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(me.clone()));
|
||||
|
||||
// Insert two peers on the network
|
||||
let contact_info2 = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
|
||||
let contact_info3 = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
|
||||
let contact_info2 =
|
||||
ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
|
||||
let contact_info3 =
|
||||
ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
|
||||
cluster_info.insert_info(contact_info2.clone());
|
||||
cluster_info.insert_info(contact_info3.clone());
|
||||
let serve_repair = ServeRepair::new(cluster_info);
|
||||
@@ -981,7 +983,7 @@ mod tests {
|
||||
// 1) repair validator set doesn't exist in gossip
|
||||
// 2) repair validator set only includes our own id
|
||||
// then no repairs should be generated
|
||||
for pubkey in &[Pubkey::new_rand(), me.id] {
|
||||
for pubkey in &[solana_sdk::pubkey::new_rand(), me.id] {
|
||||
let trusted_validators = Some(vec![*pubkey].into_iter().collect());
|
||||
assert!(serve_repair.repair_peers(&trusted_validators, 1).is_empty());
|
||||
assert!(serve_repair
|
||||
|
@@ -66,7 +66,7 @@ impl TestValidator {
|
||||
mint_lamports,
|
||||
&contact_info.id,
|
||||
&Keypair::new(),
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
42,
|
||||
bootstrap_validator_lamports,
|
||||
solana_sdk::genesis_config::ClusterType::Development,
|
||||
|
@@ -56,6 +56,7 @@ impl TransactionStatusService {
|
||||
statuses,
|
||||
balances,
|
||||
inner_instructions,
|
||||
transaction_logs,
|
||||
} = write_transaction_status_receiver.recv_timeout(Duration::from_secs(1))?;
|
||||
|
||||
let slot = bank.slot();
|
||||
@@ -65,12 +66,14 @@ impl TransactionStatusService {
|
||||
pre_balances,
|
||||
post_balances,
|
||||
inner_instructions,
|
||||
log_messages,
|
||||
) in izip!(
|
||||
OrderedIterator::new(&transactions, iteration_order.as_deref()),
|
||||
statuses,
|
||||
balances.pre_balances,
|
||||
balances.post_balances,
|
||||
inner_instructions
|
||||
inner_instructions,
|
||||
transaction_logs
|
||||
) {
|
||||
if Bank::can_commit(&status) && !transaction.signatures.is_empty() {
|
||||
let fee_calculator = match hash_age_kind {
|
||||
@@ -96,6 +99,8 @@ impl TransactionStatusService {
|
||||
.collect()
|
||||
});
|
||||
|
||||
let log_messages = Some(log_messages);
|
||||
|
||||
blockstore
|
||||
.write_transaction_status(
|
||||
slot,
|
||||
@@ -108,6 +113,7 @@ impl TransactionStatusService {
|
||||
pre_balances,
|
||||
post_balances,
|
||||
inner_instructions,
|
||||
log_messages,
|
||||
},
|
||||
)
|
||||
.expect("Expect database write to succeed");
|
||||
|
@@ -2,12 +2,11 @@
|
||||
|
||||
use crate::{
|
||||
broadcast_stage::BroadcastStageType,
|
||||
builtins,
|
||||
cache_block_time_service::{CacheBlockTimeSender, CacheBlockTimeService},
|
||||
cluster_info::{ClusterInfo, Node},
|
||||
cluster_info_vote_listener::VoteTracker,
|
||||
completed_data_sets_service::CompletedDataSetsService,
|
||||
consensus::{reconcile_blockstore_roots_with_tower, Tower, TowerError},
|
||||
consensus::{reconcile_blockstore_roots_with_tower, Tower},
|
||||
contact_info::ContactInfo,
|
||||
gossip_service::GossipService,
|
||||
optimistically_confirmed_bank_tracker::{
|
||||
@@ -369,19 +368,6 @@ impl Validator {
|
||||
leader_schedule_cache.slot_leader_at(bank.slot(), Some(&bank))
|
||||
);
|
||||
|
||||
if config.dev_halt_at_slot.is_some() {
|
||||
// Simulate a confirmed root to avoid RPC errors with CommitmentConfig::max() and
|
||||
// to ensure RPC endpoints like getConfirmedBlock, which require a confirmed root, work
|
||||
block_commitment_cache
|
||||
.write()
|
||||
.unwrap()
|
||||
.set_highest_confirmed_root(bank_forks.read().unwrap().root());
|
||||
|
||||
// Park with the RPC service running, ready for inspection!
|
||||
warn!("Validator halted");
|
||||
std::thread::park();
|
||||
}
|
||||
|
||||
let poh_config = Arc::new(genesis_config.poh_config.clone());
|
||||
let (mut poh_recorder, entry_receiver) = PohRecorder::new_with_clear_signal(
|
||||
bank.tick_height(),
|
||||
@@ -411,11 +397,10 @@ impl Validator {
|
||||
if let Some((rpc_addr, rpc_pubsub_addr, rpc_banks_addr)) = config.rpc_addrs {
|
||||
if ContactInfo::is_valid_address(&node.info.rpc) {
|
||||
assert!(ContactInfo::is_valid_address(&node.info.rpc_pubsub));
|
||||
assert_eq!(rpc_addr.port(), node.info.rpc.port());
|
||||
assert_eq!(rpc_pubsub_addr.port(), node.info.rpc_pubsub.port());
|
||||
assert_eq!(rpc_banks_addr.port(), node.info.rpc_banks.port());
|
||||
assert!(ContactInfo::is_valid_address(&node.info.rpc_banks));
|
||||
} else {
|
||||
assert!(!ContactInfo::is_valid_address(&node.info.rpc_pubsub));
|
||||
assert!(!ContactInfo::is_valid_address(&node.info.rpc_banks));
|
||||
}
|
||||
let tpu_address = cluster_info.my_contact_info().tpu;
|
||||
let (bank_notification_sender, bank_notification_receiver) = unbounded();
|
||||
@@ -465,6 +450,19 @@ impl Validator {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
if config.dev_halt_at_slot.is_some() {
|
||||
// Simulate a confirmed root to avoid RPC errors with CommitmentConfig::max() and
|
||||
// to ensure RPC endpoints like getConfirmedBlock, which require a confirmed root, work
|
||||
block_commitment_cache
|
||||
.write()
|
||||
.unwrap()
|
||||
.set_highest_confirmed_root(bank_forks.read().unwrap().root());
|
||||
|
||||
// Park with the RPC service running, ready for inspection!
|
||||
warn!("Validator halted");
|
||||
std::thread::park();
|
||||
}
|
||||
|
||||
let ip_echo_server = solana_net_utils::ip_echo_server(node.sockets.ip_echo.unwrap());
|
||||
|
||||
let gossip_service = GossipService::new(
|
||||
@@ -731,12 +729,7 @@ fn post_process_restored_tower(
|
||||
.unwrap_or_else(|err| {
|
||||
let voting_has_been_active =
|
||||
active_vote_account_exists_in_bank(&bank_forks.working_bank(), &vote_account);
|
||||
let saved_tower_is_missing = if let TowerError::IOError(io_err) = &err {
|
||||
io_err.kind() == std::io::ErrorKind::NotFound
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if !saved_tower_is_missing {
|
||||
if !err.is_file_missing() {
|
||||
datapoint_error!(
|
||||
"tower_error",
|
||||
(
|
||||
@@ -750,11 +743,11 @@ fn post_process_restored_tower(
|
||||
error!("Requested mandatory tower restore failed: {}", err);
|
||||
error!(
|
||||
"And there is an existing vote_account containing actual votes. \
|
||||
Aborting due to possible conflicting duplicate votes"
|
||||
Aborting due to possible conflicting duplicate votes",
|
||||
);
|
||||
process::exit(1);
|
||||
}
|
||||
if saved_tower_is_missing && !voting_has_been_active {
|
||||
if err.is_file_missing() && !voting_has_been_active {
|
||||
// Currently, don't protect against spoofed snapshots with no tower at all
|
||||
info!(
|
||||
"Ignoring expected failed tower restore because this is the initial \
|
||||
@@ -839,7 +832,6 @@ fn new_banks_from_ledger(
|
||||
new_hard_forks: config.new_hard_forks.clone(),
|
||||
frozen_accounts: config.frozen_accounts.clone(),
|
||||
debug_keys: config.debug_keys.clone(),
|
||||
additional_builtins: Some(builtins::get(genesis_config.cluster_type)),
|
||||
..blockstore_processor::ProcessOptions::default()
|
||||
};
|
||||
|
||||
@@ -941,8 +933,8 @@ fn backup_and_clear_blockstore(ledger_path: &Path, start_slot: Slot, shred_versi
|
||||
|
||||
let end_slot = last_slot.unwrap();
|
||||
info!("Purging slots {} to {}", start_slot, end_slot);
|
||||
blockstore.purge_slots(start_slot, end_slot, PurgeType::Exact);
|
||||
blockstore.purge_from_next_slots(start_slot, end_slot);
|
||||
blockstore.purge_slots(start_slot, end_slot, PurgeType::Exact);
|
||||
info!("Purging done, compacting db..");
|
||||
if let Err(e) = blockstore.compact_storage(start_slot, end_slot) {
|
||||
warn!(
|
||||
|
@@ -59,11 +59,10 @@ mod tests {
|
||||
use crate::result::Error;
|
||||
use crossbeam_channel::{unbounded, RecvTimeoutError};
|
||||
use solana_perf::packet::{Meta, Packet};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
#[test]
|
||||
fn test_get_latest_votes() {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let label1 = CrdsValueLabel::Vote(0 as u8, pubkey);
|
||||
let label2 = CrdsValueLabel::Vote(1 as u8, pubkey);
|
||||
let mut verified_vote_packets = VerifiedVotePackets(HashMap::new());
|
||||
@@ -107,7 +106,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_get_and_process_vote_packets() {
|
||||
let (s, r) = unbounded();
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
let label1 = CrdsValueLabel::Vote(0 as u8, pubkey);
|
||||
let label2 = CrdsValueLabel::Vote(1 as u8, pubkey);
|
||||
let mut update_version = 0;
|
||||
|
@@ -52,7 +52,7 @@ mod test {
|
||||
let total_epoch_stake = 10;
|
||||
let mut vote_stake_tracker = VoteStakeTracker::default();
|
||||
for i in 0..10 {
|
||||
let pubkey = Arc::new(Pubkey::new_rand());
|
||||
let pubkey = Arc::new(solana_sdk::pubkey::new_rand());
|
||||
let (is_confirmed, is_new) =
|
||||
vote_stake_tracker.add_vote_pubkey(pubkey.clone(), 1, total_epoch_stake);
|
||||
let stake = vote_stake_tracker.stake();
|
||||
|
@@ -594,7 +594,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_should_retransmit_and_persist() {
|
||||
let me_id = Pubkey::new_rand();
|
||||
let me_id = solana_sdk::pubkey::new_rand();
|
||||
let leader_keypair = Arc::new(Keypair::new());
|
||||
let leader_pubkey = leader_keypair.pubkey();
|
||||
let bank = Arc::new(Bank::new(
|
||||
|
@@ -12,8 +12,7 @@ use solana_runtime::{
|
||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||
};
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig, pubkey::Pubkey, rpc_port, signature::Signer,
|
||||
system_transaction,
|
||||
commitment_config::CommitmentConfig, rpc_port, signature::Signer, system_transaction,
|
||||
};
|
||||
use std::{
|
||||
fs::remove_dir_all,
|
||||
@@ -38,7 +37,7 @@ fn test_rpc_client() {
|
||||
ledger_path,
|
||||
..
|
||||
} = TestValidator::run();
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let client = RpcClient::new_socket(leader_data.rpc);
|
||||
|
||||
|
@@ -72,7 +72,7 @@ fn run_simulation(stakes: &[u64], fanout: usize) {
|
||||
let timeout = 60 * 5;
|
||||
|
||||
// describe the leader
|
||||
let leader_info = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
let leader_info = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(leader_info.clone());
|
||||
|
||||
// setup staked nodes
|
||||
@@ -95,7 +95,7 @@ fn run_simulation(stakes: &[u64], fanout: usize) {
|
||||
chunk.iter().for_each(|i| {
|
||||
//distribute neighbors across threads to maximize parallel compute
|
||||
let batch_ix = *i as usize % batches.len();
|
||||
let node = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
let node = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
|
||||
staked_nodes.insert(node.id, stakes[*i - 1]);
|
||||
cluster_info.insert_info(node.clone());
|
||||
let (s, r) = channel();
|
||||
|
@@ -77,13 +77,13 @@ fn stakes(network: &Network) -> HashMap<Pubkey, u64> {
|
||||
|
||||
fn star_network_create(num: usize) -> Network {
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let mut network: HashMap<_, _> = (1..num)
|
||||
.map(|_| {
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let id = new.label().pubkey();
|
||||
@@ -104,7 +104,7 @@ fn star_network_create(num: usize) -> Network {
|
||||
|
||||
fn rstar_network_create(num: usize) -> Network {
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let mut origin = CrdsGossip::default();
|
||||
@@ -114,7 +114,7 @@ fn rstar_network_create(num: usize) -> Network {
|
||||
let mut network: HashMap<_, _> = (1..num)
|
||||
.map(|_| {
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let id = new.label().pubkey();
|
||||
@@ -133,7 +133,7 @@ fn ring_network_create(num: usize) -> Network {
|
||||
let mut network: HashMap<_, _> = (0..num)
|
||||
.map(|_| {
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let id = new.label().pubkey();
|
||||
@@ -171,7 +171,7 @@ fn connected_staked_network_create(stakes: &[u64]) -> Network {
|
||||
let mut network: HashMap<_, _> = (0..num)
|
||||
.map(|n| {
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let id = new.label().pubkey();
|
||||
@@ -293,9 +293,10 @@ fn network_run_push(network: &mut Network, start: usize, end: usize) -> (usize,
|
||||
let requests: Vec<_> = network_values
|
||||
.par_iter()
|
||||
.map(|node| {
|
||||
let timeouts = node.lock().unwrap().make_timeouts_test();
|
||||
node.lock().unwrap().purge(now, &timeouts);
|
||||
node.lock().unwrap().new_push_messages(now)
|
||||
let mut node_lock = node.lock().unwrap();
|
||||
let timeouts = node_lock.make_timeouts_test();
|
||||
node_lock.purge(now, &timeouts);
|
||||
node_lock.new_push_messages(vec![], now)
|
||||
})
|
||||
.collect();
|
||||
let transfered: Vec<_> = requests
|
||||
|
@@ -15,8 +15,8 @@ use solana_client::{
|
||||
use solana_core::contact_info::ContactInfo;
|
||||
use solana_core::{rpc_pubsub::gen_client::Client as PubsubClient, test_validator::TestValidator};
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig, hash::Hash, pubkey::Pubkey, signature::Signer,
|
||||
system_transaction, transaction::Transaction,
|
||||
commitment_config::CommitmentConfig, hash::Hash, signature::Signer, system_transaction,
|
||||
transaction::Transaction,
|
||||
};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
@@ -63,7 +63,7 @@ fn test_rpc_send_tx() {
|
||||
ledger_path,
|
||||
..
|
||||
} = TestValidator::run();
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let req = json_req!("getRecentBlockhash", json!([]));
|
||||
let json = post_rpc(req, &leader_data);
|
||||
@@ -128,7 +128,7 @@ fn test_rpc_invalid_requests() {
|
||||
ledger_path,
|
||||
..
|
||||
} = TestValidator::run();
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
||||
// test invalid get_balance request
|
||||
let req = json_req!("getBalance", json!(["invalid9999"]));
|
||||
@@ -173,7 +173,9 @@ fn test_rpc_subscriptions() {
|
||||
|
||||
// Create transaction signatures to subscribe to
|
||||
let transactions: Vec<Transaction> = (0..1000)
|
||||
.map(|_| system_transaction::transfer(&alice, &Pubkey::new_rand(), 1, genesis_hash))
|
||||
.map(|_| {
|
||||
system_transaction::transfer(&alice, &solana_sdk::pubkey::new_rand(), 1, genesis_hash)
|
||||
})
|
||||
.collect();
|
||||
let mut signature_set: HashSet<String> = transactions
|
||||
.iter()
|
||||
|
@@ -156,7 +156,7 @@ mod tests {
|
||||
.get(&deserialized_bank.slot())
|
||||
.unwrap()
|
||||
.clone();
|
||||
bank.compare_bank(&deserialized_bank);
|
||||
assert_eq!(*bank, deserialized_bank);
|
||||
|
||||
let slot_snapshot_paths = snapshot_utils::get_snapshot_paths(&snapshot_path);
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-crate-features"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
description = "Solana Crate Features"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,12 +14,11 @@ bytes = { version = "0.4.12", features = ["either"] }
|
||||
cc = { version = "1.0.45", features = ["jobserver", "num_cpus", "parallel"]}
|
||||
curve25519-dalek = { version = "2" }
|
||||
either= { version = "1.5.2" }
|
||||
failure = { version = "0.1.5" }
|
||||
lazy_static = { version = "1.4.0", features = ["spin", "spin_no_std"] }
|
||||
libc = { version = "0.2.62", features = ["extra_traits"] }
|
||||
rand_chacha = { version = "0.2.2" }
|
||||
regex-syntax = { version = "0.6.12" }
|
||||
reqwest = { version = "0.10.1", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
reqwest = { version = "0.10.8", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
serde = { version = "1.0.100", features = ["rc"] }
|
||||
ed25519-dalek = { version = "=1.0.0-pre.4", features = ["serde"] }
|
||||
syn_0_15 = { package = "syn", version = "0.15.42", features = ["extra-traits", "fold", "full"] }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user