Compare commits
58 Commits
document-r
...
v0.23.1
Author | SHA1 | Date | |
---|---|---|---|
293bb63ed8 | |||
8f8fb720af | |||
19f414d843 | |||
eaca1c3170 | |||
9fc75925f9 | |||
b5098ac87c | |||
e23aec9728 | |||
57d490c84f | |||
aa8c9f6a98 | |||
57772dc73d | |||
21706108e8 | |||
50d0caf00f | |||
2739332306 | |||
c85c4699aa | |||
81add4d6bf | |||
8e31eeb696 | |||
e1ce8b37ff | |||
3f831c05f5 | |||
f0d7ce6bb6 | |||
6ba95b2545 | |||
6818e68542 | |||
43659d7deb | |||
f24d8e7d2d | |||
e10fe5e125 | |||
0f8c9ab1c4 | |||
8a9a9cb991 | |||
44208ffa67 | |||
5df0478fa3 | |||
d52567933e | |||
a32cdb9f4d | |||
eacd8d986c | |||
1d32603b49 | |||
8c6f7ee5a4 | |||
be482eed3f | |||
6e1c53cb0f | |||
af92f205cf | |||
87047b08c8 | |||
e282161872 | |||
01b1e287ed | |||
d7fd1fa467 | |||
bfa34cd494 | |||
915835e224 | |||
659332e7ac | |||
272986c6ac | |||
4d8ab45c56 | |||
932ae86d47 | |||
756e6334b0 | |||
4e6eca9748 | |||
d9e37eb30c | |||
04d1b35926 | |||
d13d609050 | |||
20426cf251 | |||
4a220d7c8e | |||
436eab41ca | |||
c8472d0a96 | |||
1a7db9c17e | |||
b468d9f17c | |||
41cf1d7d23 |
666
Cargo.lock
generated
666
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@ members = [
|
|||||||
"chacha",
|
"chacha",
|
||||||
"chacha-cuda",
|
"chacha-cuda",
|
||||||
"chacha-sys",
|
"chacha-sys",
|
||||||
|
"cli-config",
|
||||||
"client",
|
"client",
|
||||||
"core",
|
"core",
|
||||||
"faucet",
|
"faucet",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-archiver-lib"
|
name = "solana-archiver-lib"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Archiver Library"
|
description = "Solana Archiver Library"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -15,22 +15,22 @@ ed25519-dalek = "=1.0.0-pre.1"
|
|||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
rand = "0.6.5"
|
rand = "0.6.5"
|
||||||
rand_chacha = "0.1.1"
|
rand_chacha = "0.1.1"
|
||||||
solana-client = { path = "../client", version = "0.23.0" }
|
solana-client = { path = "../client", version = "0.23.1" }
|
||||||
solana-storage-program = { path = "../programs/storage", version = "0.23.0" }
|
solana-storage-program = { path = "../programs/storage", version = "0.23.1" }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
|
solana-net-utils = { path = "../net-utils", version = "0.23.1" }
|
||||||
solana-chacha = { path = "../chacha", version = "0.23.0" }
|
solana-chacha = { path = "../chacha", version = "0.23.1" }
|
||||||
solana-chacha-sys = { path = "../chacha-sys", version = "0.23.0" }
|
solana-chacha-sys = { path = "../chacha-sys", version = "0.23.1" }
|
||||||
solana-ledger = { path = "../ledger", version = "0.23.0" }
|
solana-ledger = { path = "../ledger", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-perf = { path = "../perf", version = "0.23.0" }
|
solana-perf = { path = "../perf", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-core = { path = "../core", version = "0.23.0" }
|
solana-core = { path = "../core", version = "0.23.1" }
|
||||||
solana-archiver-utils = { path = "../archiver-utils", version = "0.23.0" }
|
solana-archiver-utils = { path = "../archiver-utils", version = "0.23.1" }
|
||||||
solana-metrics = { path = "../metrics", version = "0.23.0" }
|
solana-metrics = { path = "../metrics", version = "0.23.1" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4.0"
|
hex = "0.4.0"
|
||||||
|
@ -522,6 +522,8 @@ impl Archiver {
|
|||||||
let mut contact_info = node_info.clone();
|
let mut contact_info = node_info.clone();
|
||||||
contact_info.tvu = "0.0.0.0:0".parse().unwrap();
|
contact_info.tvu = "0.0.0.0:0".parse().unwrap();
|
||||||
contact_info.wallclock = timestamp();
|
contact_info.wallclock = timestamp();
|
||||||
|
// copy over the adopted shred_version from the entrypoint
|
||||||
|
contact_info.shred_version = cluster_info.read().unwrap().my_data().shred_version;
|
||||||
{
|
{
|
||||||
let mut cluster_info_w = cluster_info.write().unwrap();
|
let mut cluster_info_w = cluster_info.write().unwrap();
|
||||||
cluster_info_w.insert_self(contact_info);
|
cluster_info_w.insert_self(contact_info);
|
||||||
@ -701,7 +703,7 @@ impl Archiver {
|
|||||||
) -> Result<u64> {
|
) -> Result<u64> {
|
||||||
let rpc_peers = {
|
let rpc_peers = {
|
||||||
let cluster_info = cluster_info.read().unwrap();
|
let cluster_info = cluster_info.read().unwrap();
|
||||||
cluster_info.rpc_peers()
|
cluster_info.all_rpc_peers()
|
||||||
};
|
};
|
||||||
debug!("rpc peers: {:?}", rpc_peers);
|
debug!("rpc peers: {:?}", rpc_peers);
|
||||||
if !rpc_peers.is_empty() {
|
if !rpc_peers.is_empty() {
|
||||||
@ -757,7 +759,7 @@ impl Archiver {
|
|||||||
loop {
|
loop {
|
||||||
let rpc_peers = {
|
let rpc_peers = {
|
||||||
let cluster_info = cluster_info.read().unwrap();
|
let cluster_info = cluster_info.read().unwrap();
|
||||||
cluster_info.rpc_peers()
|
cluster_info.all_rpc_peers()
|
||||||
};
|
};
|
||||||
debug!("rpc peers: {:?}", rpc_peers);
|
debug!("rpc peers: {:?}", rpc_peers);
|
||||||
if !rpc_peers.is_empty() {
|
if !rpc_peers.is_empty() {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-archiver-utils"
|
name = "solana-archiver-utils"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Archiver Utils"
|
description = "Solana Archiver Utils"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,12 +12,12 @@ edition = "2018"
|
|||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
rand = "0.6.5"
|
rand = "0.6.5"
|
||||||
rand_chacha = "0.1.1"
|
rand_chacha = "0.1.1"
|
||||||
solana-chacha = { path = "../chacha", version = "0.23.0" }
|
solana-chacha = { path = "../chacha", version = "0.23.1" }
|
||||||
solana-chacha-sys = { path = "../chacha-sys", version = "0.23.0" }
|
solana-chacha-sys = { path = "../chacha-sys", version = "0.23.1" }
|
||||||
solana-ledger = { path = "../ledger", version = "0.23.0" }
|
solana-ledger = { path = "../ledger", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-perf = { path = "../perf", version = "0.23.0" }
|
solana-perf = { path = "../perf", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4.0"
|
hex = "0.4.0"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-archiver"
|
name = "solana-archiver"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -10,11 +10,11 @@ homepage = "https://solana.com/"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
console = "0.9.1"
|
console = "0.9.1"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-core = { path = "../core", version = "0.23.0" }
|
solana-core = { path = "../core", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-metrics = { path = "../metrics", version = "0.23.0" }
|
solana-metrics = { path = "../metrics", version = "0.23.1" }
|
||||||
solana-archiver-lib = { path = "../archiver-lib", version = "0.23.0" }
|
solana-archiver-lib = { path = "../archiver-lib", version = "0.23.1" }
|
||||||
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
|
solana-net-utils = { path = "../net-utils", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-banking-bench"
|
name = "solana-banking-bench"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -10,11 +10,11 @@ homepage = "https://solana.com/"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.6"
|
log = "0.4.6"
|
||||||
rayon = "1.2.0"
|
rayon = "1.2.0"
|
||||||
solana-core = { path = "../core", version = "0.23.0" }
|
solana-core = { path = "../core", version = "0.23.1" }
|
||||||
solana-ledger = { path = "../ledger", version = "0.23.0" }
|
solana-ledger = { path = "../ledger", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../runtime", version = "0.23.0" }
|
solana-runtime = { path = "../runtime", version = "0.23.1" }
|
||||||
solana-measure = { path = "../measure", version = "0.23.0" }
|
solana-measure = { path = "../measure", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
rand = "0.6.5"
|
rand = "0.6.5"
|
||||||
crossbeam-channel = "0.3"
|
crossbeam-channel = "0.3"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-bench-exchange"
|
name = "solana-bench-exchange"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -23,19 +23,19 @@ serde = "1.0.104"
|
|||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
serde_yaml = "0.8.11"
|
serde_yaml = "0.8.11"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-core = { path = "../core", version = "0.23.0" }
|
solana-core = { path = "../core", version = "0.23.1" }
|
||||||
solana-genesis = { path = "../genesis", version = "0.23.0" }
|
solana-genesis = { path = "../genesis", version = "0.23.1" }
|
||||||
solana-client = { path = "../client", version = "0.23.0" }
|
solana-client = { path = "../client", version = "0.23.1" }
|
||||||
solana-faucet = { path = "../faucet", version = "0.23.0" }
|
solana-faucet = { path = "../faucet", version = "0.23.1" }
|
||||||
solana-exchange-program = { path = "../programs/exchange", version = "0.23.0" }
|
solana-exchange-program = { path = "../programs/exchange", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-metrics = { path = "../metrics", version = "0.23.0" }
|
solana-metrics = { path = "../metrics", version = "0.23.1" }
|
||||||
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
|
solana-net-utils = { path = "../net-utils", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../runtime", version = "0.23.0" }
|
solana-runtime = { path = "../runtime", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
untrusted = "0.7.0"
|
untrusted = "0.7.0"
|
||||||
ws = "0.9.1"
|
ws = "0.9.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
solana-local-cluster = { path = "../local-cluster", version = "0.23.0" }
|
solana-local-cluster = { path = "../local-cluster", version = "0.23.1" }
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-bench-streamer"
|
name = "solana-bench-streamer"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-core = { path = "../core", version = "0.23.0" }
|
solana-core = { path = "../core", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
|
solana-net-utils = { path = "../net-utils", version = "0.23.1" }
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-bench-tps"
|
name = "solana-bench-tps"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -16,24 +16,24 @@ serde = "1.0.104"
|
|||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
serde_yaml = "0.8.11"
|
serde_yaml = "0.8.11"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-core = { path = "../core", version = "0.23.0" }
|
solana-core = { path = "../core", version = "0.23.1" }
|
||||||
solana-genesis = { path = "../genesis", version = "0.23.0" }
|
solana-genesis = { path = "../genesis", version = "0.23.1" }
|
||||||
solana-client = { path = "../client", version = "0.23.0" }
|
solana-client = { path = "../client", version = "0.23.1" }
|
||||||
solana-faucet = { path = "../faucet", version = "0.23.0" }
|
solana-faucet = { path = "../faucet", version = "0.23.1" }
|
||||||
solana-librapay = { path = "../programs/librapay", version = "0.23.0", optional = true }
|
solana-librapay = { path = "../programs/librapay", version = "0.23.1", optional = true }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-metrics = { path = "../metrics", version = "0.23.0" }
|
solana-metrics = { path = "../metrics", version = "0.23.1" }
|
||||||
solana-measure = { path = "../measure", version = "0.23.0" }
|
solana-measure = { path = "../measure", version = "0.23.1" }
|
||||||
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
|
solana-net-utils = { path = "../net-utils", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../runtime", version = "0.23.0" }
|
solana-runtime = { path = "../runtime", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-move-loader-program = { path = "../programs/move_loader", version = "0.23.0", optional = true }
|
solana-move-loader-program = { path = "../programs/move_loader", version = "0.23.1", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serial_test = "0.3.2"
|
serial_test = "0.3.2"
|
||||||
serial_test_derive = "0.3.1"
|
serial_test_derive = "0.3.1"
|
||||||
solana-local-cluster = { path = "../local-cluster", version = "0.23.0" }
|
solana-local-cluster = { path = "../local-cluster", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
move = ["solana-librapay", "solana-move-loader-program"]
|
move = ["solana-librapay", "solana-move-loader-program"]
|
||||||
|
@ -827,7 +827,7 @@ The result field will be a JSON object with the following fields:
|
|||||||
// Request
|
// Request
|
||||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getVersion"}' http://localhost:8899
|
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getVersion"}' http://localhost:8899
|
||||||
// Result
|
// Result
|
||||||
{"jsonrpc":"2.0","result":{"solana-core": "0.23.0"},"id":1}
|
{"jsonrpc":"2.0","result":{"solana-core": "0.23.1"},"id":1}
|
||||||
```
|
```
|
||||||
|
|
||||||
### getVoteAccounts
|
### getVoteAccounts
|
||||||
|
@ -177,7 +177,7 @@ $ solana send-timestamp <PUBKEY> <PROCESS_ID> --date 2018-12-24T23:59:00
|
|||||||
## Usage
|
## Usage
|
||||||
### solana-cli
|
### solana-cli
|
||||||
```text
|
```text
|
||||||
solana-cli 0.23.0 [channel=unknown commit=unknown]
|
solana-cli 0.23.1 [channel=unknown commit=unknown]
|
||||||
Blockchain, Rebuilt for Scale
|
Blockchain, Rebuilt for Scale
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
@ -212,7 +212,7 @@ SUBCOMMANDS:
|
|||||||
cluster-version Get the version of the cluster entrypoint
|
cluster-version Get the version of the cluster entrypoint
|
||||||
config Solana command-line tool configuration settings
|
config Solana command-line tool configuration settings
|
||||||
confirm Confirm transaction by signature
|
confirm Confirm transaction by signature
|
||||||
create-address-with-seed Generate a dervied account address with a seed
|
create-address-with-seed Generate a derived account address with a seed
|
||||||
create-archiver-storage-account Create an archiver storage account
|
create-archiver-storage-account Create an archiver storage account
|
||||||
create-nonce-account Create a nonce account
|
create-nonce-account Create a nonce account
|
||||||
create-stake-account Create a stake account
|
create-stake-account Create a stake account
|
||||||
@ -618,7 +618,7 @@ ARGS:
|
|||||||
#### solana-create-address-with-seed
|
#### solana-create-address-with-seed
|
||||||
```text
|
```text
|
||||||
solana-create-address-with-seed
|
solana-create-address-with-seed
|
||||||
Generate a dervied account address with a seed
|
Generate a derived account address with a seed
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
solana create-address-with-seed [FLAGS] [OPTIONS] <SEED_STRING> <PROGRAM_ID>
|
solana create-address-with-seed [FLAGS] [OPTIONS] <SEED_STRING> <PROGRAM_ID>
|
||||||
|
@ -94,12 +94,13 @@ The Stakes and the RewardsPool are accounts that are owned by the same `Stake` p
|
|||||||
|
|
||||||
### StakeInstruction::DelegateStake
|
### StakeInstruction::DelegateStake
|
||||||
|
|
||||||
The Stake account is moved from Ininitialized to StakeState::Stake form. This is how stakers choose their initial delegate validator node and activate their stake account lamports. The transaction must be signed by the stake's `authorized_staker`. If the stake account is already StakeState::Stake \(i.e. already activated\), the stake is re-delegated. Stakes may be re-delegated at any time, and updated stakes are reflected immediately, but only one re-delegation is permitted per epoch.
|
The Stake account is moved from Initialized to StakeState::Stake form, or from a deactivated (i.e. fully cooled-down) StakeState::Stake to activated StakeState::Stake. This is how stakers choose the vote account and validator node to which their stake account lamports are delegated. The transaction must be signed by the stake's `authorized_staker`.
|
||||||
|
|
||||||
* `account[0]` - RW - The StakeState::Stake instance. `StakeState::Stake::credits_observed` is initialized to `VoteState::credits`, `StakeState::Stake::voter_pubkey` is initialized to `account[1]`. If this is the initial delegation of stake, `StakeState::Stake::stake` is initialized to the account's balance in lamports, `StakeState::Stake::activated` is initialized to the current Bank epoch, and `StakeState::Stake::deactivated` is initialized to std::u64::MAX
|
* `account[0]` - RW - The StakeState::Stake instance. `StakeState::Stake::credits_observed` is initialized to `VoteState::credits`, `StakeState::Stake::voter_pubkey` is initialized to `account[1]`. If this is the initial delegation of stake, `StakeState::Stake::stake` is initialized to the account's balance in lamports, `StakeState::Stake::activated` is initialized to the current Bank epoch, and `StakeState::Stake::deactivated` is initialized to std::u64::MAX
|
||||||
* `account[1]` - R - The VoteState instance.
|
* `account[1]` - R - The VoteState instance.
|
||||||
* `account[2]` - R - sysvar::clock account, carries information about current Bank epoch
|
* `account[2]` - R - sysvar::clock account, carries information about current Bank epoch
|
||||||
* `account[3]` - R - stake::Config accoount, carries warmup, cooldown, and slashing configuration
|
* `account[3]` - R - sysvar::stakehistory account, carries information about stake history
|
||||||
|
* `account[4]` - R - stake::Config accoount, carries warmup, cooldown, and slashing configuration
|
||||||
|
|
||||||
### StakeInstruction::Authorize\(Pubkey, StakeAuthorize\)
|
### StakeInstruction::Authorize\(Pubkey, StakeAuthorize\)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-chacha-cuda"
|
name = "solana-chacha-cuda"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Chacha Cuda APIs"
|
description = "Solana Chacha Cuda APIs"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -10,12 +10,12 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
solana-archiver-utils = { path = "../archiver-utils", version = "0.23.0" }
|
solana-archiver-utils = { path = "../archiver-utils", version = "0.23.1" }
|
||||||
solana-chacha = { path = "../chacha", version = "0.23.0" }
|
solana-chacha = { path = "../chacha", version = "0.23.1" }
|
||||||
solana-ledger = { path = "../ledger", version = "0.23.0" }
|
solana-ledger = { path = "../ledger", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-perf = { path = "../perf", version = "0.23.0" }
|
solana-perf = { path = "../perf", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex-literal = "0.2.1"
|
hex-literal = "0.2.1"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-chacha-sys"
|
name = "solana-chacha-sys"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana chacha-sys"
|
description = "Solana chacha-sys"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-chacha"
|
name = "solana-chacha"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Chacha APIs"
|
description = "Solana Chacha APIs"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,11 +12,11 @@ edition = "2018"
|
|||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
rand = "0.6.5"
|
rand = "0.6.5"
|
||||||
rand_chacha = "0.1.1"
|
rand_chacha = "0.1.1"
|
||||||
solana-chacha-sys = { path = "../chacha-sys", version = "0.23.0" }
|
solana-chacha-sys = { path = "../chacha-sys", version = "0.23.1" }
|
||||||
solana-ledger = { path = "../ledger", version = "0.23.0" }
|
solana-ledger = { path = "../ledger", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-perf = { path = "../perf", version = "0.23.0" }
|
solana-perf = { path = "../perf", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex-literal = "0.2.1"
|
hex-literal = "0.2.1"
|
||||||
|
@ -378,7 +378,7 @@ deploy() {
|
|||||||
(
|
(
|
||||||
set -x
|
set -x
|
||||||
ci/testnet-deploy.sh -p testnet-solana-com -C gce -z us-west1-b \
|
ci/testnet-deploy.sh -p testnet-solana-com -C gce -z us-west1-b \
|
||||||
-t "$CHANNEL_OR_TAG" -n 1 -c 0 -u -P \
|
-t "$CHANNEL_OR_TAG" -n 0 -c 0 -u -P \
|
||||||
-a testnet-solana-com --letsencrypt testnet.solana.com \
|
-a testnet-solana-com --letsencrypt testnet.solana.com \
|
||||||
--limit-ledger-size \
|
--limit-ledger-size \
|
||||||
${skipCreate:+-e} \
|
${skipCreate:+-e} \
|
||||||
@ -455,6 +455,10 @@ deploy() {
|
|||||||
TDS_CLIENT_COUNT="1"
|
TDS_CLIENT_COUNT="1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n $TDS_SLOTS_PER_EPOCH ]]; then
|
||||||
|
maybeSlotsPerEpoch=(--slots-per-epoch "$TDS_SLOTS_PER_EPOCH")
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -z $ENABLE_GPU ]]; then
|
if [[ -z $ENABLE_GPU ]]; then
|
||||||
maybeGpu=(-G "--machine-type n1-standard-16 --accelerator count=2,type=nvidia-tesla-v100")
|
maybeGpu=(-G "--machine-type n1-standard-16 --accelerator count=2,type=nvidia-tesla-v100")
|
||||||
elif [[ $ENABLE_GPU == skip ]]; then
|
elif [[ $ENABLE_GPU == skip ]]; then
|
||||||
@ -540,7 +544,7 @@ deploy() {
|
|||||||
${maybeInternalNodesLamports} \
|
${maybeInternalNodesLamports} \
|
||||||
${maybeExternalAccountsFile} \
|
${maybeExternalAccountsFile} \
|
||||||
--target-lamports-per-signature 0 \
|
--target-lamports-per-signature 0 \
|
||||||
--slots-per-epoch 4096 \
|
"${maybeSlotsPerEpoch[@]}" \
|
||||||
${maybeAdditionalDisk}
|
${maybeAdditionalDisk}
|
||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-clap-utils"
|
name = "solana-clap-utils"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana utilities for the clap"
|
description = "Solana utilities for the clap"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,7 +12,7 @@ edition = "2018"
|
|||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
rpassword = "4.0"
|
rpassword = "4.0"
|
||||||
semver = "0.9.0"
|
semver = "0.9.0"
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
tiny-bip39 = "0.7.0"
|
tiny-bip39 = "0.7.0"
|
||||||
url = "2.1.0"
|
url = "2.1.0"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
16
cli-config/Cargo.toml
Normal file
16
cli-config/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
name = "solana-cli-config"
|
||||||
|
description = "Blockchain, Rebuilt for Scale"
|
||||||
|
version = "0.23.1"
|
||||||
|
repository = "https://github.com/solana-labs/solana"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
homepage = "https://solana.com/"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dirs = "2.0.2"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
serde = "1.0.104"
|
||||||
|
serde_derive = "1.0.103"
|
||||||
|
serde_yaml = "0.8.11"
|
@ -1,8 +1,10 @@
|
|||||||
// Wallet settings that can be configured for long-term use
|
// Wallet settings that can be configured for long-term use
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::fs::{create_dir_all, File};
|
use std::{
|
||||||
use std::io::{self, Write};
|
fs::{create_dir_all, File},
|
||||||
use std::path::Path;
|
io::{self, Write},
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref CONFIG_FILE: Option<String> = {
|
pub static ref CONFIG_FILE: Option<String> = {
|
4
cli-config/src/lib.rs
Normal file
4
cli-config/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
|
|
||||||
|
pub mod config;
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-cli"
|
name = "solana-cli"
|
||||||
description = "Blockchain, Rebuilt for Scale"
|
description = "Blockchain, Rebuilt for Scale"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -17,7 +17,6 @@ criterion-stats = "0.3.0"
|
|||||||
ctrlc = { version = "3.1.3", features = ["termination"] }
|
ctrlc = { version = "3.1.3", features = ["termination"] }
|
||||||
console = "0.9.1"
|
console = "0.9.1"
|
||||||
dirs = "2.0.2"
|
dirs = "2.0.2"
|
||||||
lazy_static = "1.4.0"
|
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
indicatif = "0.13.0"
|
indicatif = "0.13.0"
|
||||||
humantime = "2.0.0"
|
humantime = "2.0.0"
|
||||||
@ -28,24 +27,25 @@ serde = "1.0.104"
|
|||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
serde_yaml = "0.8.11"
|
serde_yaml = "0.8.11"
|
||||||
solana-budget-program = { path = "../programs/budget", version = "0.23.0" }
|
solana-budget-program = { path = "../programs/budget", version = "0.23.1" }
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-client = { path = "../client", version = "0.23.0" }
|
solana-cli-config = { path = "../cli-config", version = "0.23.1" }
|
||||||
solana-config-program = { path = "../programs/config", version = "0.23.0" }
|
solana-client = { path = "../client", version = "0.23.1" }
|
||||||
solana-faucet = { path = "../faucet", version = "0.23.0" }
|
solana-config-program = { path = "../programs/config", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-faucet = { path = "../faucet", version = "0.23.1" }
|
||||||
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../runtime", version = "0.23.0" }
|
solana-net-utils = { path = "../net-utils", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-runtime = { path = "../runtime", version = "0.23.1" }
|
||||||
solana-stake-program = { path = "../programs/stake", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-storage-program = { path = "../programs/storage", version = "0.23.0" }
|
solana-stake-program = { path = "../programs/stake", version = "0.23.1" }
|
||||||
solana-vote-program = { path = "../programs/vote", version = "0.23.0" }
|
solana-storage-program = { path = "../programs/storage", version = "0.23.1" }
|
||||||
solana-vote-signer = { path = "../vote-signer", version = "0.23.0" }
|
solana-vote-program = { path = "../programs/vote", version = "0.23.1" }
|
||||||
|
solana-vote-signer = { path = "../vote-signer", version = "0.23.1" }
|
||||||
url = "2.1.1"
|
url = "2.1.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
solana-core = { path = "../core", version = "0.23.0" }
|
solana-core = { path = "../core", version = "0.23.1" }
|
||||||
solana-budget-program = { path = "../programs/budget", version = "0.23.0" }
|
solana-budget-program = { path = "../programs/budget", version = "0.23.1" }
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
130
cli/src/cli.rs
130
cli/src/cli.rs
@ -2,6 +2,7 @@ use crate::{
|
|||||||
cluster_query::*,
|
cluster_query::*,
|
||||||
display::{println_name_value, println_signers},
|
display::{println_name_value, println_signers},
|
||||||
nonce::{self, *},
|
nonce::{self, *},
|
||||||
|
offline::*,
|
||||||
stake::*,
|
stake::*,
|
||||||
storage::*,
|
storage::*,
|
||||||
validator_info::*,
|
validator_info::*,
|
||||||
@ -31,7 +32,7 @@ use solana_sdk::{
|
|||||||
message::Message,
|
message::Message,
|
||||||
native_token::lamports_to_sol,
|
native_token::lamports_to_sol,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{Keypair, KeypairUtil, Signature},
|
signature::{keypair_from_seed, Keypair, KeypairUtil, Signature},
|
||||||
system_instruction::{create_address_with_seed, SystemError, MAX_ADDRESS_SEED_LEN},
|
system_instruction::{create_address_with_seed, SystemError, MAX_ADDRESS_SEED_LEN},
|
||||||
system_transaction,
|
system_transaction,
|
||||||
transaction::{Transaction, TransactionError},
|
transaction::{Transaction, TransactionError},
|
||||||
@ -85,7 +86,8 @@ impl SigningAuthority {
|
|||||||
matches: &ArgMatches<'_>,
|
matches: &ArgMatches<'_>,
|
||||||
name: &str,
|
name: &str,
|
||||||
signers: Option<&[(Pubkey, Signature)]>,
|
signers: Option<&[(Pubkey, Signature)]>,
|
||||||
) -> Result<Self, CliError> {
|
) -> Result<Option<Self>, CliError> {
|
||||||
|
if matches.is_present(name) {
|
||||||
keypair_of(matches, name)
|
keypair_of(matches, name)
|
||||||
.map(|keypair| keypair.into())
|
.map(|keypair| keypair.into())
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
@ -100,6 +102,10 @@ impl SigningAuthority {
|
|||||||
.map(|pubkey| pubkey.into())
|
.map(|pubkey| pubkey.into())
|
||||||
})
|
})
|
||||||
.ok_or_else(|| CliError::BadParameter("Invalid authority".to_string()))
|
.ok_or_else(|| CliError::BadParameter("Invalid authority".to_string()))
|
||||||
|
.map(Some)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keypair(&self) -> &Keypair {
|
pub fn keypair(&self) -> &Keypair {
|
||||||
@ -125,7 +131,7 @@ impl From<Keypair> for SigningAuthority {
|
|||||||
|
|
||||||
impl From<Pubkey> for SigningAuthority {
|
impl From<Pubkey> for SigningAuthority {
|
||||||
fn from(pubkey: Pubkey) -> Self {
|
fn from(pubkey: Pubkey) -> Self {
|
||||||
SigningAuthority::Offline(pubkey, Keypair::new())
|
SigningAuthority::Offline(pubkey, keypair_from_seed(pubkey.as_ref()).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +166,7 @@ pub struct PayCommand {
|
|||||||
pub cancelable: bool,
|
pub cancelable: bool,
|
||||||
pub sign_only: bool,
|
pub sign_only: bool,
|
||||||
pub signers: Option<Vec<(Pubkey, Signature)>>,
|
pub signers: Option<Vec<(Pubkey, Signature)>>,
|
||||||
pub blockhash: Option<Hash>,
|
pub blockhash_query: BlockhashQuery,
|
||||||
pub nonce_account: Option<Pubkey>,
|
pub nonce_account: Option<Pubkey>,
|
||||||
pub nonce_authority: Option<SigningAuthority>,
|
pub nonce_authority: Option<SigningAuthority>,
|
||||||
}
|
}
|
||||||
@ -192,6 +198,7 @@ pub enum CliCommand {
|
|||||||
GetTransactionCount {
|
GetTransactionCount {
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
},
|
},
|
||||||
|
LeaderSchedule,
|
||||||
Ping {
|
Ping {
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
interval: Duration,
|
interval: Duration,
|
||||||
@ -254,7 +261,7 @@ pub enum CliCommand {
|
|||||||
stake_authority: Option<SigningAuthority>,
|
stake_authority: Option<SigningAuthority>,
|
||||||
sign_only: bool,
|
sign_only: bool,
|
||||||
signers: Option<Vec<(Pubkey, Signature)>>,
|
signers: Option<Vec<(Pubkey, Signature)>>,
|
||||||
blockhash: Option<Hash>,
|
blockhash_query: BlockhashQuery,
|
||||||
nonce_account: Option<Pubkey>,
|
nonce_account: Option<Pubkey>,
|
||||||
nonce_authority: Option<SigningAuthority>,
|
nonce_authority: Option<SigningAuthority>,
|
||||||
},
|
},
|
||||||
@ -265,7 +272,7 @@ pub enum CliCommand {
|
|||||||
force: bool,
|
force: bool,
|
||||||
sign_only: bool,
|
sign_only: bool,
|
||||||
signers: Option<Vec<(Pubkey, Signature)>>,
|
signers: Option<Vec<(Pubkey, Signature)>>,
|
||||||
blockhash: Option<Hash>,
|
blockhash_query: BlockhashQuery,
|
||||||
nonce_account: Option<Pubkey>,
|
nonce_account: Option<Pubkey>,
|
||||||
nonce_authority: Option<SigningAuthority>,
|
nonce_authority: Option<SigningAuthority>,
|
||||||
},
|
},
|
||||||
@ -283,7 +290,7 @@ pub enum CliCommand {
|
|||||||
authority: Option<SigningAuthority>,
|
authority: Option<SigningAuthority>,
|
||||||
sign_only: bool,
|
sign_only: bool,
|
||||||
signers: Option<Vec<(Pubkey, Signature)>>,
|
signers: Option<Vec<(Pubkey, Signature)>>,
|
||||||
blockhash: Option<Hash>,
|
blockhash_query: BlockhashQuery,
|
||||||
nonce_account: Option<Pubkey>,
|
nonce_account: Option<Pubkey>,
|
||||||
nonce_authority: Option<SigningAuthority>,
|
nonce_authority: Option<SigningAuthority>,
|
||||||
},
|
},
|
||||||
@ -455,6 +462,10 @@ pub fn parse_command(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Box<dyn
|
|||||||
}),
|
}),
|
||||||
("slot", Some(matches)) => parse_get_slot(matches),
|
("slot", Some(matches)) => parse_get_slot(matches),
|
||||||
("transaction-count", Some(matches)) => parse_get_transaction_count(matches),
|
("transaction-count", Some(matches)) => parse_get_transaction_count(matches),
|
||||||
|
("leader-schedule", Some(_matches)) => Ok(CliCommandInfo {
|
||||||
|
command: CliCommand::LeaderSchedule,
|
||||||
|
require_keypair: false,
|
||||||
|
}),
|
||||||
("ping", Some(matches)) => parse_cluster_ping(matches),
|
("ping", Some(matches)) => parse_cluster_ping(matches),
|
||||||
("block-production", Some(matches)) => parse_show_block_production(matches),
|
("block-production", Some(matches)) => parse_show_block_production(matches),
|
||||||
("gossip", Some(_matches)) => Ok(CliCommandInfo {
|
("gossip", Some(_matches)) => Ok(CliCommandInfo {
|
||||||
@ -488,8 +499,8 @@ pub fn parse_command(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Box<dyn
|
|||||||
("stake-authorize-withdrawer", Some(matches)) => {
|
("stake-authorize-withdrawer", Some(matches)) => {
|
||||||
parse_stake_authorize(matches, StakeAuthorize::Withdrawer)
|
parse_stake_authorize(matches, StakeAuthorize::Withdrawer)
|
||||||
}
|
}
|
||||||
("show-stake-account", Some(matches)) => parse_show_stake_account(matches),
|
("stake-account", Some(matches)) => parse_show_stake_account(matches),
|
||||||
("show-stake-history", Some(matches)) => parse_show_stake_history(matches),
|
("stake-history", Some(matches)) => parse_show_stake_history(matches),
|
||||||
// Storage Commands
|
// Storage Commands
|
||||||
("create-archiver-storage-account", Some(matches)) => {
|
("create-archiver-storage-account", Some(matches)) => {
|
||||||
parse_storage_create_archiver_account(matches)
|
parse_storage_create_archiver_account(matches)
|
||||||
@ -599,19 +610,15 @@ pub fn parse_command(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Box<dyn
|
|||||||
let timestamp_pubkey = value_of(&matches, "timestamp_pubkey");
|
let timestamp_pubkey = value_of(&matches, "timestamp_pubkey");
|
||||||
let witnesses = values_of(&matches, "witness");
|
let witnesses = values_of(&matches, "witness");
|
||||||
let cancelable = matches.is_present("cancelable");
|
let cancelable = matches.is_present("cancelable");
|
||||||
let sign_only = matches.is_present("sign_only");
|
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
|
||||||
let signers = pubkeys_sigs_of(&matches, "signer");
|
let signers = pubkeys_sigs_of(&matches, SIGNER_ARG.name);
|
||||||
let blockhash = value_of(&matches, "blockhash");
|
let blockhash_query = BlockhashQuery::new_from_matches(&matches);
|
||||||
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
|
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
|
||||||
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
|
let nonce_authority = SigningAuthority::new_from_matches(
|
||||||
Some(SigningAuthority::new_from_matches(
|
|
||||||
&matches,
|
&matches,
|
||||||
NONCE_AUTHORITY_ARG.name,
|
NONCE_AUTHORITY_ARG.name,
|
||||||
signers.as_deref(),
|
signers.as_deref(),
|
||||||
)?)
|
)?;
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::Pay(PayCommand {
|
command: CliCommand::Pay(PayCommand {
|
||||||
@ -623,7 +630,7 @@ pub fn parse_command(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Box<dyn
|
|||||||
cancelable,
|
cancelable,
|
||||||
sign_only,
|
sign_only,
|
||||||
signers,
|
signers,
|
||||||
blockhash,
|
blockhash_query,
|
||||||
nonce_account,
|
nonce_account,
|
||||||
nonce_authority,
|
nonce_authority,
|
||||||
}),
|
}),
|
||||||
@ -1002,7 +1009,7 @@ fn process_pay(
|
|||||||
cancelable: bool,
|
cancelable: bool,
|
||||||
sign_only: bool,
|
sign_only: bool,
|
||||||
signers: &Option<Vec<(Pubkey, Signature)>>,
|
signers: &Option<Vec<(Pubkey, Signature)>>,
|
||||||
blockhash: Option<Hash>,
|
blockhash_query: &BlockhashQuery,
|
||||||
nonce_account: Option<Pubkey>,
|
nonce_account: Option<Pubkey>,
|
||||||
nonce_authority: Option<&SigningAuthority>,
|
nonce_authority: Option<&SigningAuthority>,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
@ -1011,8 +1018,7 @@ fn process_pay(
|
|||||||
(to, "to".to_string()),
|
(to, "to".to_string()),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (blockhash, fee_calculator) =
|
let (blockhash, fee_calculator) = blockhash_query.get_blockhash_fee_calculator(rpc_client)?;
|
||||||
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
|
|
||||||
|
|
||||||
let cancelable = if cancelable {
|
let cancelable = if cancelable {
|
||||||
Some(config.keypair.pubkey())
|
Some(config.keypair.pubkey())
|
||||||
@ -1260,6 +1266,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
CliCommand::GetTransactionCount { commitment_config } => {
|
CliCommand::GetTransactionCount { commitment_config } => {
|
||||||
process_get_transaction_count(&rpc_client, commitment_config)
|
process_get_transaction_count(&rpc_client, commitment_config)
|
||||||
}
|
}
|
||||||
|
CliCommand::LeaderSchedule => process_leader_schedule(&rpc_client),
|
||||||
CliCommand::Ping {
|
CliCommand::Ping {
|
||||||
lamports,
|
lamports,
|
||||||
interval,
|
interval,
|
||||||
@ -1381,7 +1388,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
ref stake_authority,
|
ref stake_authority,
|
||||||
sign_only,
|
sign_only,
|
||||||
ref signers,
|
ref signers,
|
||||||
blockhash,
|
blockhash_query,
|
||||||
nonce_account,
|
nonce_account,
|
||||||
ref nonce_authority,
|
ref nonce_authority,
|
||||||
} => process_deactivate_stake_account(
|
} => process_deactivate_stake_account(
|
||||||
@ -1391,7 +1398,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
stake_authority.as_ref(),
|
stake_authority.as_ref(),
|
||||||
*sign_only,
|
*sign_only,
|
||||||
signers,
|
signers,
|
||||||
*blockhash,
|
blockhash_query,
|
||||||
*nonce_account,
|
*nonce_account,
|
||||||
nonce_authority.as_ref(),
|
nonce_authority.as_ref(),
|
||||||
),
|
),
|
||||||
@ -1402,7 +1409,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
force,
|
force,
|
||||||
sign_only,
|
sign_only,
|
||||||
ref signers,
|
ref signers,
|
||||||
blockhash,
|
blockhash_query,
|
||||||
nonce_account,
|
nonce_account,
|
||||||
ref nonce_authority,
|
ref nonce_authority,
|
||||||
} => process_delegate_stake(
|
} => process_delegate_stake(
|
||||||
@ -1414,7 +1421,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
*force,
|
*force,
|
||||||
*sign_only,
|
*sign_only,
|
||||||
signers,
|
signers,
|
||||||
*blockhash,
|
blockhash_query,
|
||||||
*nonce_account,
|
*nonce_account,
|
||||||
nonce_authority.as_ref(),
|
nonce_authority.as_ref(),
|
||||||
),
|
),
|
||||||
@ -1437,7 +1444,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
ref authority,
|
ref authority,
|
||||||
sign_only,
|
sign_only,
|
||||||
ref signers,
|
ref signers,
|
||||||
blockhash,
|
blockhash_query,
|
||||||
nonce_account,
|
nonce_account,
|
||||||
ref nonce_authority,
|
ref nonce_authority,
|
||||||
} => process_stake_authorize(
|
} => process_stake_authorize(
|
||||||
@ -1449,7 +1456,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
authority.as_ref(),
|
authority.as_ref(),
|
||||||
*sign_only,
|
*sign_only,
|
||||||
signers,
|
signers,
|
||||||
*blockhash,
|
blockhash_query,
|
||||||
*nonce_account,
|
*nonce_account,
|
||||||
nonce_authority.as_ref(),
|
nonce_authority.as_ref(),
|
||||||
),
|
),
|
||||||
@ -1621,7 +1628,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
cancelable,
|
cancelable,
|
||||||
sign_only,
|
sign_only,
|
||||||
ref signers,
|
ref signers,
|
||||||
blockhash,
|
blockhash_query,
|
||||||
nonce_account,
|
nonce_account,
|
||||||
ref nonce_authority,
|
ref nonce_authority,
|
||||||
}) => process_pay(
|
}) => process_pay(
|
||||||
@ -1635,7 +1642,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
*cancelable,
|
*cancelable,
|
||||||
*sign_only,
|
*sign_only,
|
||||||
signers,
|
signers,
|
||||||
*blockhash,
|
blockhash_query,
|
||||||
*nonce_account,
|
*nonce_account,
|
||||||
nonce_authority.as_ref(),
|
nonce_authority.as_ref(),
|
||||||
),
|
),
|
||||||
@ -1871,7 +1878,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
|||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("create-address-with-seed")
|
SubCommand::with_name("create-address-with-seed")
|
||||||
.about("Generate a dervied account address with a seed")
|
.about("Generate a derived account address with a seed")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("seed")
|
Arg::with_name("seed")
|
||||||
.index(1)
|
.index(1)
|
||||||
@ -1973,31 +1980,9 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
|||||||
.long("cancelable")
|
.long("cancelable")
|
||||||
.takes_value(false),
|
.takes_value(false),
|
||||||
)
|
)
|
||||||
.arg(
|
.offline_args()
|
||||||
Arg::with_name("sign_only")
|
|
||||||
.long("sign-only")
|
|
||||||
.takes_value(false)
|
|
||||||
.help("Sign the transaction offline"),
|
|
||||||
)
|
|
||||||
.arg(nonce_arg())
|
.arg(nonce_arg())
|
||||||
.arg(nonce_authority_arg())
|
.arg(nonce_authority_arg()),
|
||||||
.arg(
|
|
||||||
Arg::with_name("signer")
|
|
||||||
.long("signer")
|
|
||||||
.value_name("PUBKEY=BASE58_SIG")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_pubkey_sig)
|
|
||||||
.multiple(true)
|
|
||||||
.help("Provide a public-key/signature pair for the transaction"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("blockhash")
|
|
||||||
.long("blockhash")
|
|
||||||
.value_name("BLOCKHASH")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_hash)
|
|
||||||
.help("Use the supplied blockhash"),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("send-signature")
|
SubCommand::with_name("send-signature")
|
||||||
@ -2092,6 +2077,7 @@ mod tests {
|
|||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
nonce_state::{Meta as NonceMeta, NonceState},
|
nonce_state::{Meta as NonceMeta, NonceState},
|
||||||
|
pubkey::Pubkey,
|
||||||
signature::{read_keypair_file, write_keypair_file},
|
signature::{read_keypair_file, write_keypair_file},
|
||||||
system_program,
|
system_program,
|
||||||
transaction::TransactionError,
|
transaction::TransactionError,
|
||||||
@ -2112,6 +2098,13 @@ mod tests {
|
|||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_signing_authority_dummy_keypairs() {
|
||||||
|
let signing_authority: SigningAuthority = Pubkey::new(&[1u8; 32]).into();
|
||||||
|
assert_eq!(signing_authority, Pubkey::new(&[1u8; 32]).into());
|
||||||
|
assert_ne!(signing_authority, Pubkey::new(&[2u8; 32]).into());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cli_parse_command() {
|
fn test_cli_parse_command() {
|
||||||
let test_commands = app("test", "desc", "version");
|
let test_commands = app("test", "desc", "version");
|
||||||
@ -2375,12 +2368,16 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Test Pay Subcommand w/ sign-only
|
// Test Pay Subcommand w/ sign-only
|
||||||
|
let blockhash = Hash::default();
|
||||||
|
let blockhash_string = format!("{}", blockhash);
|
||||||
let test_pay = test_commands.clone().get_matches_from(vec![
|
let test_pay = test_commands.clone().get_matches_from(vec![
|
||||||
"test",
|
"test",
|
||||||
"pay",
|
"pay",
|
||||||
&pubkey_string,
|
&pubkey_string,
|
||||||
"50",
|
"50",
|
||||||
"lamports",
|
"lamports",
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--sign-only",
|
"--sign-only",
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -2389,6 +2386,7 @@ mod tests {
|
|||||||
command: CliCommand::Pay(PayCommand {
|
command: CliCommand::Pay(PayCommand {
|
||||||
lamports: 50,
|
lamports: 50,
|
||||||
to: pubkey,
|
to: pubkey,
|
||||||
|
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
sign_only: true,
|
sign_only: true,
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
}),
|
}),
|
||||||
@ -2406,6 +2404,8 @@ mod tests {
|
|||||||
&pubkey_string,
|
&pubkey_string,
|
||||||
"50",
|
"50",
|
||||||
"lamports",
|
"lamports",
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--signer",
|
"--signer",
|
||||||
&signer1,
|
&signer1,
|
||||||
]);
|
]);
|
||||||
@ -2415,6 +2415,7 @@ mod tests {
|
|||||||
command: CliCommand::Pay(PayCommand {
|
command: CliCommand::Pay(PayCommand {
|
||||||
lamports: 50,
|
lamports: 50,
|
||||||
to: pubkey,
|
to: pubkey,
|
||||||
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
signers: Some(vec![(key1, sig1)]),
|
signers: Some(vec![(key1, sig1)]),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
}),
|
}),
|
||||||
@ -2432,6 +2433,8 @@ mod tests {
|
|||||||
&pubkey_string,
|
&pubkey_string,
|
||||||
"50",
|
"50",
|
||||||
"lamports",
|
"lamports",
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--signer",
|
"--signer",
|
||||||
&signer1,
|
&signer1,
|
||||||
"--signer",
|
"--signer",
|
||||||
@ -2443,6 +2446,7 @@ mod tests {
|
|||||||
command: CliCommand::Pay(PayCommand {
|
command: CliCommand::Pay(PayCommand {
|
||||||
lamports: 50,
|
lamports: 50,
|
||||||
to: pubkey,
|
to: pubkey,
|
||||||
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
}),
|
}),
|
||||||
@ -2451,8 +2455,6 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Test Pay Subcommand w/ Blockhash
|
// Test Pay Subcommand w/ Blockhash
|
||||||
let blockhash = Hash::default();
|
|
||||||
let blockhash_string = format!("{}", blockhash);
|
|
||||||
let test_pay = test_commands.clone().get_matches_from(vec![
|
let test_pay = test_commands.clone().get_matches_from(vec![
|
||||||
"test",
|
"test",
|
||||||
"pay",
|
"pay",
|
||||||
@ -2468,7 +2470,7 @@ mod tests {
|
|||||||
command: CliCommand::Pay(PayCommand {
|
command: CliCommand::Pay(PayCommand {
|
||||||
lamports: 50,
|
lamports: 50,
|
||||||
to: pubkey,
|
to: pubkey,
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
}),
|
}),
|
||||||
require_keypair: true
|
require_keypair: true
|
||||||
@ -2495,7 +2497,7 @@ mod tests {
|
|||||||
command: CliCommand::Pay(PayCommand {
|
command: CliCommand::Pay(PayCommand {
|
||||||
lamports: 50,
|
lamports: 50,
|
||||||
to: pubkey,
|
to: pubkey,
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: Some(pubkey),
|
nonce_account: Some(pubkey),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
}),
|
}),
|
||||||
@ -2526,7 +2528,7 @@ mod tests {
|
|||||||
command: CliCommand::Pay(PayCommand {
|
command: CliCommand::Pay(PayCommand {
|
||||||
lamports: 50,
|
lamports: 50,
|
||||||
to: pubkey,
|
to: pubkey,
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: Some(pubkey),
|
nonce_account: Some(pubkey),
|
||||||
nonce_authority: Some(keypair.into()),
|
nonce_authority: Some(keypair.into()),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
@ -2562,7 +2564,7 @@ mod tests {
|
|||||||
command: CliCommand::Pay(PayCommand {
|
command: CliCommand::Pay(PayCommand {
|
||||||
lamports: 50,
|
lamports: 50,
|
||||||
to: pubkey,
|
to: pubkey,
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: Some(pubkey),
|
nonce_account: Some(pubkey),
|
||||||
nonce_authority: Some(authority_pubkey.into()),
|
nonce_authority: Some(authority_pubkey.into()),
|
||||||
signers: Some(vec![(authority_pubkey, sig)]),
|
signers: Some(vec![(authority_pubkey, sig)]),
|
||||||
@ -2766,7 +2768,7 @@ mod tests {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -2852,7 +2854,7 @@ mod tests {
|
|||||||
lamports: 10,
|
lamports: 10,
|
||||||
to: bob_pubkey,
|
to: bob_pubkey,
|
||||||
nonce_account: Some(bob_pubkey),
|
nonce_account: Some(bob_pubkey),
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
});
|
});
|
||||||
let signature = process_command(&config);
|
let signature = process_command(&config);
|
||||||
@ -2879,7 +2881,7 @@ mod tests {
|
|||||||
config.command = CliCommand::Pay(PayCommand {
|
config.command = CliCommand::Pay(PayCommand {
|
||||||
lamports: 10,
|
lamports: 10,
|
||||||
to: bob_pubkey,
|
to: bob_pubkey,
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: Some(bob_pubkey),
|
nonce_account: Some(bob_pubkey),
|
||||||
nonce_authority: Some(bob_keypair.into()),
|
nonce_authority: Some(bob_keypair.into()),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
|
@ -67,6 +67,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
.help("Slot number of the block to query")
|
.help("Slot number of the block to query")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.subcommand(SubCommand::with_name("leader-schedule").about("Display leader schedule"))
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("epoch-info")
|
SubCommand::with_name("epoch-info")
|
||||||
.about("Get information about the current epoch")
|
.about("Get information about the current epoch")
|
||||||
@ -406,6 +407,41 @@ pub fn process_fees(rpc_client: &RpcClient) -> ProcessResult {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn process_leader_schedule(rpc_client: &RpcClient) -> ProcessResult {
|
||||||
|
let epoch_info = rpc_client.get_epoch_info()?;
|
||||||
|
let first_slot_in_epoch = epoch_info.absolute_slot - epoch_info.slot_index;
|
||||||
|
|
||||||
|
let leader_schedule = rpc_client.get_leader_schedule(Some(first_slot_in_epoch))?;
|
||||||
|
if leader_schedule.is_none() {
|
||||||
|
return Err(format!(
|
||||||
|
"Unable to fetch leader schedule for slot {}",
|
||||||
|
first_slot_in_epoch
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
let leader_schedule = leader_schedule.unwrap();
|
||||||
|
|
||||||
|
let mut leader_per_slot_index = Vec::new();
|
||||||
|
for (pubkey, leader_slots) in leader_schedule.iter() {
|
||||||
|
for slot_index in leader_slots.iter() {
|
||||||
|
if *slot_index >= leader_per_slot_index.len() {
|
||||||
|
leader_per_slot_index.resize(*slot_index + 1, "?");
|
||||||
|
}
|
||||||
|
leader_per_slot_index[*slot_index] = pubkey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (slot_index, leader) in leader_per_slot_index.iter().enumerate() {
|
||||||
|
println!(
|
||||||
|
" {:<15} {:<44}",
|
||||||
|
first_slot_in_epoch + slot_index as u64,
|
||||||
|
leader
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok("".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_get_block_time(rpc_client: &RpcClient, slot: Slot) -> ProcessResult {
|
pub fn process_get_block_time(rpc_client: &RpcClient, slot: Slot) -> ProcessResult {
|
||||||
let timestamp = rpc_client.get_block_time(slot)?;
|
let timestamp = rpc_client.get_block_time(slot)?;
|
||||||
Ok(timestamp.to_string())
|
Ok(timestamp.to_string())
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
|
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
pub mod cluster_query;
|
pub mod cluster_query;
|
||||||
pub mod config;
|
|
||||||
pub mod display;
|
pub mod display;
|
||||||
pub mod nonce;
|
pub mod nonce;
|
||||||
|
pub mod offline;
|
||||||
pub mod stake;
|
pub mod stake;
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
pub mod validator_info;
|
pub mod validator_info;
|
||||||
|
@ -10,9 +10,9 @@ use solana_clap_utils::{
|
|||||||
};
|
};
|
||||||
use solana_cli::{
|
use solana_cli::{
|
||||||
cli::{app, parse_command, process_command, CliCommandInfo, CliConfig, CliError},
|
cli::{app, parse_command, process_command, CliCommandInfo, CliConfig, CliError},
|
||||||
config::{self, Config},
|
|
||||||
display::{println_name_value, println_name_value_or},
|
display::{println_name_value, println_name_value_or},
|
||||||
};
|
};
|
||||||
|
use solana_cli_config::config::{Config, CONFIG_FILE};
|
||||||
use solana_sdk::signature::read_keypair_file;
|
use solana_sdk::signature::read_keypair_file;
|
||||||
|
|
||||||
use std::error;
|
use std::error;
|
||||||
@ -162,7 +162,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.global(true)
|
.global(true)
|
||||||
.help("Configuration file to use");
|
.help("Configuration file to use");
|
||||||
if let Some(ref config_file) = *config::CONFIG_FILE {
|
if let Some(ref config_file) = *CONFIG_FILE {
|
||||||
arg.default_value(&config_file)
|
arg.default_value(&config_file)
|
||||||
} else {
|
} else {
|
||||||
arg
|
arg
|
||||||
|
@ -3,6 +3,7 @@ use crate::cli::{
|
|||||||
log_instruction_custom_error, required_lamports_from, CliCommand, CliCommandInfo, CliConfig,
|
log_instruction_custom_error, required_lamports_from, CliCommand, CliCommandInfo, CliConfig,
|
||||||
CliError, ProcessResult, SigningAuthority,
|
CliError, ProcessResult, SigningAuthority,
|
||||||
};
|
};
|
||||||
|
use crate::offline::BLOCKHASH_ARG;
|
||||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||||
use solana_clap_utils::{input_parsers::*, input_validators::*, ArgConstant};
|
use solana_clap_utils::{input_parsers::*, input_validators::*, ArgConstant};
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
@ -55,7 +56,7 @@ pub fn nonce_arg<'a, 'b>() -> Arg<'a, 'b> {
|
|||||||
.long(NONCE_ARG.long)
|
.long(NONCE_ARG.long)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.value_name("PUBKEY")
|
.value_name("PUBKEY")
|
||||||
.requires("blockhash")
|
.requires(BLOCKHASH_ARG.name)
|
||||||
.validator(is_pubkey)
|
.validator(is_pubkey)
|
||||||
.help(NONCE_ARG.help)
|
.help(NONCE_ARG.help)
|
||||||
}
|
}
|
||||||
@ -233,15 +234,8 @@ impl NonceSubCommands for App<'_, '_> {
|
|||||||
pub fn parse_authorize_nonce_account(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
pub fn parse_authorize_nonce_account(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||||
let nonce_account = pubkey_of(matches, "nonce_account_keypair").unwrap();
|
let nonce_account = pubkey_of(matches, "nonce_account_keypair").unwrap();
|
||||||
let new_authority = pubkey_of(matches, "new_authority").unwrap();
|
let new_authority = pubkey_of(matches, "new_authority").unwrap();
|
||||||
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
|
let nonce_authority =
|
||||||
Some(SigningAuthority::new_from_matches(
|
SigningAuthority::new_from_matches(&matches, NONCE_AUTHORITY_ARG.name, None)?;
|
||||||
&matches,
|
|
||||||
NONCE_AUTHORITY_ARG.name,
|
|
||||||
None,
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::AuthorizeNonceAccount {
|
command: CliCommand::AuthorizeNonceAccount {
|
||||||
@ -281,15 +275,8 @@ pub fn parse_get_nonce(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliEr
|
|||||||
|
|
||||||
pub fn parse_new_nonce(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
pub fn parse_new_nonce(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||||
let nonce_account = pubkey_of(matches, "nonce_account_keypair").unwrap();
|
let nonce_account = pubkey_of(matches, "nonce_account_keypair").unwrap();
|
||||||
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
|
let nonce_authority =
|
||||||
Some(SigningAuthority::new_from_matches(
|
SigningAuthority::new_from_matches(&matches, NONCE_AUTHORITY_ARG.name, None)?;
|
||||||
&matches,
|
|
||||||
NONCE_AUTHORITY_ARG.name,
|
|
||||||
None,
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::NewNonce {
|
command: CliCommand::NewNonce {
|
||||||
@ -319,15 +306,8 @@ pub fn parse_withdraw_from_nonce_account(
|
|||||||
let nonce_account = pubkey_of(matches, "nonce_account_keypair").unwrap();
|
let nonce_account = pubkey_of(matches, "nonce_account_keypair").unwrap();
|
||||||
let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap();
|
let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap();
|
||||||
let lamports = required_lamports_from(matches, "amount", "unit")?;
|
let lamports = required_lamports_from(matches, "amount", "unit")?;
|
||||||
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
|
let nonce_authority =
|
||||||
Some(SigningAuthority::new_from_matches(
|
SigningAuthority::new_from_matches(&matches, NONCE_AUTHORITY_ARG.name, None)?;
|
||||||
&matches,
|
|
||||||
NONCE_AUTHORITY_ARG.name,
|
|
||||||
None,
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::WithdrawFromNonceAccount {
|
command: CliCommand::WithdrawFromNonceAccount {
|
||||||
|
252
cli/src/offline.rs
Normal file
252
cli/src/offline.rs
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
use clap::{App, Arg, ArgMatches};
|
||||||
|
use solana_clap_utils::{
|
||||||
|
input_parsers::value_of,
|
||||||
|
input_validators::{is_hash, is_pubkey_sig},
|
||||||
|
ArgConstant,
|
||||||
|
};
|
||||||
|
use solana_client::rpc_client::RpcClient;
|
||||||
|
use solana_sdk::{fee_calculator::FeeCalculator, hash::Hash};
|
||||||
|
|
||||||
|
pub const BLOCKHASH_ARG: ArgConstant<'static> = ArgConstant {
|
||||||
|
name: "blockhash",
|
||||||
|
long: "blockhash",
|
||||||
|
help: "Use the supplied blockhash",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SIGN_ONLY_ARG: ArgConstant<'static> = ArgConstant {
|
||||||
|
name: "sign_only",
|
||||||
|
long: "sign-only",
|
||||||
|
help: "Sign the transaction offline",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SIGNER_ARG: ArgConstant<'static> = ArgConstant {
|
||||||
|
name: "signer",
|
||||||
|
long: "signer",
|
||||||
|
help: "Provid a public-key/signature pair for the transaction",
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum BlockhashQuery {
|
||||||
|
None(Hash, FeeCalculator),
|
||||||
|
FeeCalculator(Hash),
|
||||||
|
All,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockhashQuery {
|
||||||
|
pub fn new(blockhash: Option<Hash>, sign_only: bool) -> Self {
|
||||||
|
match blockhash {
|
||||||
|
Some(hash) if sign_only => Self::None(hash, FeeCalculator::default()),
|
||||||
|
Some(hash) if !sign_only => Self::FeeCalculator(hash),
|
||||||
|
None if !sign_only => Self::All,
|
||||||
|
_ => panic!("Cannot resolve blockhash"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_from_matches(matches: &ArgMatches<'_>) -> Self {
|
||||||
|
let blockhash = value_of(matches, BLOCKHASH_ARG.name);
|
||||||
|
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
|
||||||
|
BlockhashQuery::new(blockhash, sign_only)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_blockhash_fee_calculator(
|
||||||
|
&self,
|
||||||
|
rpc_client: &RpcClient,
|
||||||
|
) -> Result<(Hash, FeeCalculator), Box<dyn std::error::Error>> {
|
||||||
|
let (hash, fee_calc) = match self {
|
||||||
|
BlockhashQuery::None(hash, fee_calc) => (Some(hash), Some(fee_calc)),
|
||||||
|
BlockhashQuery::FeeCalculator(hash) => (Some(hash), None),
|
||||||
|
BlockhashQuery::All => (None, None),
|
||||||
|
};
|
||||||
|
if None == fee_calc {
|
||||||
|
let (cluster_hash, fee_calc) = rpc_client.get_recent_blockhash()?;
|
||||||
|
Ok((*hash.unwrap_or(&cluster_hash), fee_calc))
|
||||||
|
} else {
|
||||||
|
Ok((*hash.unwrap(), fee_calc.unwrap().clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for BlockhashQuery {
|
||||||
|
fn default() -> Self {
|
||||||
|
BlockhashQuery::All
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blockhash_arg<'a, 'b>() -> Arg<'a, 'b> {
|
||||||
|
Arg::with_name(BLOCKHASH_ARG.name)
|
||||||
|
.long(BLOCKHASH_ARG.long)
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("BLOCKHASH")
|
||||||
|
.validator(is_hash)
|
||||||
|
.help(BLOCKHASH_ARG.help)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sign_only_arg<'a, 'b>() -> Arg<'a, 'b> {
|
||||||
|
Arg::with_name(SIGN_ONLY_ARG.name)
|
||||||
|
.long(SIGN_ONLY_ARG.long)
|
||||||
|
.takes_value(false)
|
||||||
|
.requires(BLOCKHASH_ARG.name)
|
||||||
|
.help(SIGN_ONLY_ARG.help)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signer_arg<'a, 'b>() -> Arg<'a, 'b> {
|
||||||
|
Arg::with_name(SIGNER_ARG.name)
|
||||||
|
.long(SIGNER_ARG.long)
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("BASE58_PUBKEY=BASE58_SIG")
|
||||||
|
.validator(is_pubkey_sig)
|
||||||
|
.requires(BLOCKHASH_ARG.name)
|
||||||
|
.multiple(true)
|
||||||
|
.help(SIGNER_ARG.help)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait OfflineArgs {
|
||||||
|
fn offline_args(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OfflineArgs for App<'_, '_> {
|
||||||
|
fn offline_args(self) -> Self {
|
||||||
|
self.arg(blockhash_arg())
|
||||||
|
.arg(sign_only_arg())
|
||||||
|
.arg(signer_arg())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use clap::App;
|
||||||
|
use serde_json::{self, json, Value};
|
||||||
|
use solana_client::{
|
||||||
|
rpc_request::RpcRequest,
|
||||||
|
rpc_response::{Response, RpcResponseContext},
|
||||||
|
};
|
||||||
|
use solana_sdk::{fee_calculator::FeeCalculator, hash::hash};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_blockhashspec_new_ok() {
|
||||||
|
let blockhash = hash(&[1u8]);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
BlockhashQuery::new(Some(blockhash), true),
|
||||||
|
BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
BlockhashQuery::new(Some(blockhash), false),
|
||||||
|
BlockhashQuery::FeeCalculator(blockhash),
|
||||||
|
);
|
||||||
|
assert_eq!(BlockhashQuery::new(None, false), BlockhashQuery::All,);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_blockhashspec_new_fail() {
|
||||||
|
BlockhashQuery::new(None, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_blockhashspec_new_from_matches_ok() {
|
||||||
|
let test_commands = App::new("blockhashspec_test").offline_args();
|
||||||
|
let blockhash = hash(&[1u8]);
|
||||||
|
let blockhash_string = blockhash.to_string();
|
||||||
|
|
||||||
|
let matches = test_commands.clone().get_matches_from(vec![
|
||||||
|
"blockhashspec_test",
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
|
"--sign-only",
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
BlockhashQuery::new_from_matches(&matches),
|
||||||
|
BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let matches = test_commands.clone().get_matches_from(vec![
|
||||||
|
"blockhashspec_test",
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
BlockhashQuery::new_from_matches(&matches),
|
||||||
|
BlockhashQuery::FeeCalculator(blockhash),
|
||||||
|
);
|
||||||
|
|
||||||
|
let matches = test_commands
|
||||||
|
.clone()
|
||||||
|
.get_matches_from(vec!["blockhashspec_test"]);
|
||||||
|
assert_eq!(
|
||||||
|
BlockhashQuery::new_from_matches(&matches),
|
||||||
|
BlockhashQuery::All,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_blockhashspec_new_from_matches_fail() {
|
||||||
|
let test_commands = App::new("blockhashspec_test")
|
||||||
|
.arg(blockhash_arg())
|
||||||
|
// We can really only hit this case unless the arg requirements
|
||||||
|
// are broken, so unset the requires() to recreate that condition
|
||||||
|
.arg(sign_only_arg().requires(""));
|
||||||
|
|
||||||
|
let matches = test_commands
|
||||||
|
.clone()
|
||||||
|
.get_matches_from(vec!["blockhashspec_test", "--sign-only"]);
|
||||||
|
BlockhashQuery::new_from_matches(&matches);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_blockhashspec_get_blockhash_fee_calc() {
|
||||||
|
let test_blockhash = hash(&[0u8]);
|
||||||
|
let rpc_blockhash = hash(&[1u8]);
|
||||||
|
let rpc_fee_calc = FeeCalculator::new(42, 42);
|
||||||
|
let get_recent_blockhash_response = json!(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: json!((
|
||||||
|
Value::String(rpc_blockhash.to_string()),
|
||||||
|
serde_json::to_value(rpc_fee_calc.clone()).unwrap()
|
||||||
|
)),
|
||||||
|
});
|
||||||
|
let mut mocks = HashMap::new();
|
||||||
|
mocks.insert(
|
||||||
|
RpcRequest::GetRecentBlockhash,
|
||||||
|
get_recent_blockhash_response.clone(),
|
||||||
|
);
|
||||||
|
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
||||||
|
assert_eq!(
|
||||||
|
BlockhashQuery::All
|
||||||
|
.get_blockhash_fee_calculator(&rpc_client)
|
||||||
|
.unwrap(),
|
||||||
|
(rpc_blockhash, rpc_fee_calc.clone()),
|
||||||
|
);
|
||||||
|
let mut mocks = HashMap::new();
|
||||||
|
mocks.insert(
|
||||||
|
RpcRequest::GetRecentBlockhash,
|
||||||
|
get_recent_blockhash_response.clone(),
|
||||||
|
);
|
||||||
|
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
||||||
|
assert_eq!(
|
||||||
|
BlockhashQuery::FeeCalculator(test_blockhash)
|
||||||
|
.get_blockhash_fee_calculator(&rpc_client)
|
||||||
|
.unwrap(),
|
||||||
|
(test_blockhash, rpc_fee_calc.clone()),
|
||||||
|
);
|
||||||
|
let mut mocks = HashMap::new();
|
||||||
|
mocks.insert(
|
||||||
|
RpcRequest::GetRecentBlockhash,
|
||||||
|
get_recent_blockhash_response.clone(),
|
||||||
|
);
|
||||||
|
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
|
||||||
|
assert_eq!(
|
||||||
|
BlockhashQuery::None(test_blockhash, FeeCalculator::default())
|
||||||
|
.get_blockhash_fee_calculator(&rpc_client)
|
||||||
|
.unwrap(),
|
||||||
|
(test_blockhash, FeeCalculator::default()),
|
||||||
|
);
|
||||||
|
let rpc_client = RpcClient::new_mock("fails".to_string());
|
||||||
|
assert!(BlockhashQuery::All
|
||||||
|
.get_blockhash_fee_calculator(&rpc_client)
|
||||||
|
.is_err());
|
||||||
|
}
|
||||||
|
}
|
289
cli/src/stake.rs
289
cli/src/stake.rs
@ -1,11 +1,12 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
cli::{
|
cli::{
|
||||||
build_balance_message, check_account_for_fee, check_unique_pubkeys,
|
build_balance_message, check_account_for_fee, check_unique_pubkeys,
|
||||||
get_blockhash_fee_calculator, log_instruction_custom_error, nonce_authority_arg,
|
log_instruction_custom_error, nonce_authority_arg, replace_signatures,
|
||||||
replace_signatures, required_lamports_from, return_signers, CliCommand, CliCommandInfo,
|
required_lamports_from, return_signers, CliCommand, CliCommandInfo, CliConfig, CliError,
|
||||||
CliConfig, CliError, ProcessResult, SigningAuthority,
|
ProcessResult, SigningAuthority,
|
||||||
},
|
},
|
||||||
nonce::{check_nonce_account, nonce_arg, NONCE_ARG, NONCE_AUTHORITY_ARG},
|
nonce::{check_nonce_account, nonce_arg, NONCE_ARG, NONCE_AUTHORITY_ARG},
|
||||||
|
offline::*,
|
||||||
};
|
};
|
||||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||||
use console::style;
|
use console::style;
|
||||||
@ -14,7 +15,6 @@ use solana_client::rpc_client::RpcClient;
|
|||||||
use solana_sdk::signature::{Keypair, Signature};
|
use solana_sdk::signature::{Keypair, Signature};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
hash::Hash,
|
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::KeypairUtil,
|
signature::KeypairUtil,
|
||||||
system_instruction::{create_address_with_seed, SystemError},
|
system_instruction::{create_address_with_seed, SystemError},
|
||||||
@ -172,29 +172,7 @@ impl StakeSubCommands for App<'_, '_> {
|
|||||||
.help("The vote account to which the stake will be delegated")
|
.help("The vote account to which the stake will be delegated")
|
||||||
)
|
)
|
||||||
.arg(stake_authority_arg())
|
.arg(stake_authority_arg())
|
||||||
.arg(
|
.offline_args()
|
||||||
Arg::with_name("sign_only")
|
|
||||||
.long("sign-only")
|
|
||||||
.takes_value(false)
|
|
||||||
.help("Sign the transaction offline"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("signer")
|
|
||||||
.long("signer")
|
|
||||||
.value_name("PUBKEY=BASE58_SIG")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_pubkey_sig)
|
|
||||||
.multiple(true)
|
|
||||||
.help("Provide a public-key/signature pair for the transaction"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("blockhash")
|
|
||||||
.long("blockhash")
|
|
||||||
.value_name("BLOCKHASH")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_hash)
|
|
||||||
.help("Use the supplied blockhash"),
|
|
||||||
)
|
|
||||||
.arg(nonce_arg())
|
.arg(nonce_arg())
|
||||||
.arg(nonce_authority_arg())
|
.arg(nonce_authority_arg())
|
||||||
)
|
)
|
||||||
@ -220,29 +198,7 @@ impl StakeSubCommands for App<'_, '_> {
|
|||||||
.help("New authorized staker")
|
.help("New authorized staker")
|
||||||
)
|
)
|
||||||
.arg(stake_authority_arg())
|
.arg(stake_authority_arg())
|
||||||
.arg(
|
.offline_args()
|
||||||
Arg::with_name("sign_only")
|
|
||||||
.long("sign-only")
|
|
||||||
.takes_value(false)
|
|
||||||
.help("Sign the transaction offline"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("signer")
|
|
||||||
.long("signer")
|
|
||||||
.value_name("PUBKEY=BASE58_SIG")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_pubkey_sig)
|
|
||||||
.multiple(true)
|
|
||||||
.help("Provide a public-key/signature pair for the transaction"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("blockhash")
|
|
||||||
.long("blockhash")
|
|
||||||
.value_name("BLOCKHASH")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_hash)
|
|
||||||
.help("Use the supplied blockhash"),
|
|
||||||
)
|
|
||||||
.arg(nonce_arg())
|
.arg(nonce_arg())
|
||||||
.arg(nonce_authority_arg())
|
.arg(nonce_authority_arg())
|
||||||
)
|
)
|
||||||
@ -268,29 +224,7 @@ impl StakeSubCommands for App<'_, '_> {
|
|||||||
.help("New authorized withdrawer")
|
.help("New authorized withdrawer")
|
||||||
)
|
)
|
||||||
.arg(withdraw_authority_arg())
|
.arg(withdraw_authority_arg())
|
||||||
.arg(
|
.offline_args()
|
||||||
Arg::with_name("sign_only")
|
|
||||||
.long("sign-only")
|
|
||||||
.takes_value(false)
|
|
||||||
.help("Sign the transaction offline"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("signer")
|
|
||||||
.long("signer")
|
|
||||||
.value_name("PUBKEY=BASE58_SIG")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_pubkey_sig)
|
|
||||||
.multiple(true)
|
|
||||||
.help("Provide a public-key/signature pair for the transaction"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("blockhash")
|
|
||||||
.long("blockhash")
|
|
||||||
.value_name("BLOCKHASH")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_hash)
|
|
||||||
.help("Use the supplied blockhash"),
|
|
||||||
)
|
|
||||||
.arg(nonce_arg())
|
.arg(nonce_arg())
|
||||||
.arg(nonce_authority_arg())
|
.arg(nonce_authority_arg())
|
||||||
)
|
)
|
||||||
@ -306,29 +240,7 @@ impl StakeSubCommands for App<'_, '_> {
|
|||||||
.help("Stake account to be deactivated.")
|
.help("Stake account to be deactivated.")
|
||||||
)
|
)
|
||||||
.arg(stake_authority_arg())
|
.arg(stake_authority_arg())
|
||||||
.arg(
|
.offline_args()
|
||||||
Arg::with_name("sign_only")
|
|
||||||
.long("sign-only")
|
|
||||||
.takes_value(false)
|
|
||||||
.help("Sign the transaction offline"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("signer")
|
|
||||||
.long("signer")
|
|
||||||
.value_name("PUBKEY=BASE58_SIG")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_pubkey_sig)
|
|
||||||
.multiple(true)
|
|
||||||
.help("Provide a public-key/signature pair for the transaction"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("blockhash")
|
|
||||||
.long("blockhash")
|
|
||||||
.value_name("BLOCKHASH")
|
|
||||||
.takes_value(true)
|
|
||||||
.validator(is_hash)
|
|
||||||
.help("Use the supplied blockhash"),
|
|
||||||
)
|
|
||||||
.arg(nonce_arg())
|
.arg(nonce_arg())
|
||||||
.arg(nonce_authority_arg())
|
.arg(nonce_authority_arg())
|
||||||
)
|
)
|
||||||
@ -373,7 +285,7 @@ impl StakeSubCommands for App<'_, '_> {
|
|||||||
.arg(withdraw_authority_arg())
|
.arg(withdraw_authority_arg())
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("show-stake-account")
|
SubCommand::with_name("stake-account")
|
||||||
.about("Show the contents of a stake account")
|
.about("Show the contents of a stake account")
|
||||||
.alias("show-stake-account")
|
.alias("show-stake-account")
|
||||||
.arg(
|
.arg(
|
||||||
@ -437,29 +349,15 @@ pub fn parse_stake_delegate_stake(matches: &ArgMatches<'_>) -> Result<CliCommand
|
|||||||
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
|
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
|
||||||
let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap();
|
let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap();
|
||||||
let force = matches.is_present("force");
|
let force = matches.is_present("force");
|
||||||
let sign_only = matches.is_present("sign_only");
|
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
|
||||||
let signers = pubkeys_sigs_of(&matches, "signer");
|
let signers = pubkeys_sigs_of(&matches, SIGNER_ARG.name);
|
||||||
let blockhash = value_of(matches, "blockhash");
|
let blockhash_query = BlockhashQuery::new_from_matches(matches);
|
||||||
let require_keypair = signers.is_none();
|
let require_keypair = signers.is_none();
|
||||||
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
|
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
|
||||||
let stake_authority = if matches.is_present(STAKE_AUTHORITY_ARG.name) {
|
let stake_authority =
|
||||||
Some(SigningAuthority::new_from_matches(
|
SigningAuthority::new_from_matches(&matches, STAKE_AUTHORITY_ARG.name, signers.as_deref())?;
|
||||||
&matches,
|
let nonce_authority =
|
||||||
STAKE_AUTHORITY_ARG.name,
|
SigningAuthority::new_from_matches(&matches, NONCE_AUTHORITY_ARG.name, signers.as_deref())?;
|
||||||
signers.as_deref(),
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
|
|
||||||
Some(SigningAuthority::new_from_matches(
|
|
||||||
&matches,
|
|
||||||
NONCE_AUTHORITY_ARG.name,
|
|
||||||
signers.as_deref(),
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::DelegateStake {
|
command: CliCommand::DelegateStake {
|
||||||
@ -469,7 +367,7 @@ pub fn parse_stake_delegate_stake(matches: &ArgMatches<'_>) -> Result<CliCommand
|
|||||||
force,
|
force,
|
||||||
sign_only,
|
sign_only,
|
||||||
signers,
|
signers,
|
||||||
blockhash,
|
blockhash_query,
|
||||||
nonce_account,
|
nonce_account,
|
||||||
nonce_authority,
|
nonce_authority,
|
||||||
},
|
},
|
||||||
@ -487,28 +385,14 @@ pub fn parse_stake_authorize(
|
|||||||
StakeAuthorize::Staker => STAKE_AUTHORITY_ARG.name,
|
StakeAuthorize::Staker => STAKE_AUTHORITY_ARG.name,
|
||||||
StakeAuthorize::Withdrawer => WITHDRAW_AUTHORITY_ARG.name,
|
StakeAuthorize::Withdrawer => WITHDRAW_AUTHORITY_ARG.name,
|
||||||
};
|
};
|
||||||
let sign_only = matches.is_present("sign_only");
|
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
|
||||||
let signers = pubkeys_sigs_of(&matches, "signer");
|
let signers = pubkeys_sigs_of(&matches, SIGNER_ARG.name);
|
||||||
let authority = if matches.is_present(authority_flag) {
|
let authority =
|
||||||
Some(SigningAuthority::new_from_matches(
|
SigningAuthority::new_from_matches(&matches, authority_flag, signers.as_deref())?;
|
||||||
&matches,
|
let blockhash_query = BlockhashQuery::new_from_matches(matches);
|
||||||
authority_flag,
|
|
||||||
signers.as_deref(),
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let blockhash = value_of(matches, "blockhash");
|
|
||||||
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
|
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
|
||||||
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
|
let nonce_authority =
|
||||||
Some(SigningAuthority::new_from_matches(
|
SigningAuthority::new_from_matches(&matches, NONCE_AUTHORITY_ARG.name, signers.as_deref())?;
|
||||||
&matches,
|
|
||||||
NONCE_AUTHORITY_ARG.name,
|
|
||||||
signers.as_deref(),
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::StakeAuthorize {
|
command: CliCommand::StakeAuthorize {
|
||||||
@ -518,7 +402,7 @@ pub fn parse_stake_authorize(
|
|||||||
authority,
|
authority,
|
||||||
sign_only,
|
sign_only,
|
||||||
signers,
|
signers,
|
||||||
blockhash,
|
blockhash_query,
|
||||||
nonce_account,
|
nonce_account,
|
||||||
nonce_authority,
|
nonce_authority,
|
||||||
},
|
},
|
||||||
@ -528,29 +412,15 @@ pub fn parse_stake_authorize(
|
|||||||
|
|
||||||
pub fn parse_stake_deactivate_stake(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
pub fn parse_stake_deactivate_stake(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||||
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
|
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
|
||||||
let sign_only = matches.is_present("sign_only");
|
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
|
||||||
let signers = pubkeys_sigs_of(&matches, "signer");
|
let signers = pubkeys_sigs_of(&matches, SIGNER_ARG.name);
|
||||||
let blockhash = value_of(matches, "blockhash");
|
let blockhash_query = BlockhashQuery::new_from_matches(matches);
|
||||||
let require_keypair = signers.is_none();
|
let require_keypair = signers.is_none();
|
||||||
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
|
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
|
||||||
let stake_authority = if matches.is_present(STAKE_AUTHORITY_ARG.name) {
|
let stake_authority =
|
||||||
Some(SigningAuthority::new_from_matches(
|
SigningAuthority::new_from_matches(&matches, STAKE_AUTHORITY_ARG.name, signers.as_deref())?;
|
||||||
&matches,
|
let nonce_authority =
|
||||||
STAKE_AUTHORITY_ARG.name,
|
SigningAuthority::new_from_matches(&matches, NONCE_AUTHORITY_ARG.name, signers.as_deref())?;
|
||||||
signers.as_deref(),
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
|
|
||||||
Some(SigningAuthority::new_from_matches(
|
|
||||||
&matches,
|
|
||||||
NONCE_AUTHORITY_ARG.name,
|
|
||||||
signers.as_deref(),
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::DeactivateStake {
|
command: CliCommand::DeactivateStake {
|
||||||
@ -558,7 +428,7 @@ pub fn parse_stake_deactivate_stake(matches: &ArgMatches<'_>) -> Result<CliComma
|
|||||||
stake_authority,
|
stake_authority,
|
||||||
sign_only,
|
sign_only,
|
||||||
signers,
|
signers,
|
||||||
blockhash,
|
blockhash_query,
|
||||||
nonce_account,
|
nonce_account,
|
||||||
nonce_authority,
|
nonce_authority,
|
||||||
},
|
},
|
||||||
@ -570,15 +440,8 @@ pub fn parse_stake_withdraw_stake(matches: &ArgMatches<'_>) -> Result<CliCommand
|
|||||||
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
|
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
|
||||||
let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap();
|
let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap();
|
||||||
let lamports = required_lamports_from(matches, "amount", "unit")?;
|
let lamports = required_lamports_from(matches, "amount", "unit")?;
|
||||||
let withdraw_authority = if matches.is_present(WITHDRAW_AUTHORITY_ARG.name) {
|
let withdraw_authority =
|
||||||
Some(SigningAuthority::new_from_matches(
|
SigningAuthority::new_from_matches(&matches, WITHDRAW_AUTHORITY_ARG.name, None)?;
|
||||||
&matches,
|
|
||||||
WITHDRAW_AUTHORITY_ARG.name,
|
|
||||||
None,
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::WithdrawStake {
|
command: CliCommand::WithdrawStake {
|
||||||
@ -713,7 +576,7 @@ pub fn process_stake_authorize(
|
|||||||
authority: Option<&SigningAuthority>,
|
authority: Option<&SigningAuthority>,
|
||||||
sign_only: bool,
|
sign_only: bool,
|
||||||
signers: &Option<Vec<(Pubkey, Signature)>>,
|
signers: &Option<Vec<(Pubkey, Signature)>>,
|
||||||
blockhash: Option<Hash>,
|
blockhash_query: &BlockhashQuery,
|
||||||
nonce_account: Option<Pubkey>,
|
nonce_account: Option<Pubkey>,
|
||||||
nonce_authority: Option<&SigningAuthority>,
|
nonce_authority: Option<&SigningAuthority>,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
@ -723,7 +586,7 @@ pub fn process_stake_authorize(
|
|||||||
)?;
|
)?;
|
||||||
let authority = authority.map(|a| a.keypair()).unwrap_or(&config.keypair);
|
let authority = authority.map(|a| a.keypair()).unwrap_or(&config.keypair);
|
||||||
let (recent_blockhash, fee_calculator) =
|
let (recent_blockhash, fee_calculator) =
|
||||||
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
|
blockhash_query.get_blockhash_fee_calculator(rpc_client)?;
|
||||||
let ixs = vec![stake_instruction::authorize(
|
let ixs = vec![stake_instruction::authorize(
|
||||||
stake_account_pubkey, // stake account to update
|
stake_account_pubkey, // stake account to update
|
||||||
&authority.pubkey(), // currently authorized
|
&authority.pubkey(), // currently authorized
|
||||||
@ -779,12 +642,12 @@ pub fn process_deactivate_stake_account(
|
|||||||
stake_authority: Option<&SigningAuthority>,
|
stake_authority: Option<&SigningAuthority>,
|
||||||
sign_only: bool,
|
sign_only: bool,
|
||||||
signers: &Option<Vec<(Pubkey, Signature)>>,
|
signers: &Option<Vec<(Pubkey, Signature)>>,
|
||||||
blockhash: Option<Hash>,
|
blockhash_query: &BlockhashQuery,
|
||||||
nonce_account: Option<Pubkey>,
|
nonce_account: Option<Pubkey>,
|
||||||
nonce_authority: Option<&SigningAuthority>,
|
nonce_authority: Option<&SigningAuthority>,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
let (recent_blockhash, fee_calculator) =
|
let (recent_blockhash, fee_calculator) =
|
||||||
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
|
blockhash_query.get_blockhash_fee_calculator(rpc_client)?;
|
||||||
let stake_authority = stake_authority
|
let stake_authority = stake_authority
|
||||||
.map(|a| a.keypair())
|
.map(|a| a.keypair())
|
||||||
.unwrap_or(&config.keypair);
|
.unwrap_or(&config.keypair);
|
||||||
@ -872,7 +735,7 @@ pub fn process_withdraw_stake(
|
|||||||
pub fn print_stake_state(stake_lamports: u64, stake_state: &StakeState, use_lamports_unit: bool) {
|
pub fn print_stake_state(stake_lamports: u64, stake_state: &StakeState, use_lamports_unit: bool) {
|
||||||
fn show_authorized(authorized: &Authorized) {
|
fn show_authorized(authorized: &Authorized) {
|
||||||
println!("authorized staker: {}", authorized.staker);
|
println!("authorized staker: {}", authorized.staker);
|
||||||
println!("authorized withdrawer: {}", authorized.staker);
|
println!("authorized withdrawer: {}", authorized.withdrawer);
|
||||||
}
|
}
|
||||||
fn show_lockup(lockup: &Lockup) {
|
fn show_lockup(lockup: &Lockup) {
|
||||||
println!("lockup epoch: {}", lockup.epoch);
|
println!("lockup epoch: {}", lockup.epoch);
|
||||||
@ -1000,7 +863,7 @@ pub fn process_delegate_stake(
|
|||||||
force: bool,
|
force: bool,
|
||||||
sign_only: bool,
|
sign_only: bool,
|
||||||
signers: &Option<Vec<(Pubkey, Signature)>>,
|
signers: &Option<Vec<(Pubkey, Signature)>>,
|
||||||
blockhash: Option<Hash>,
|
blockhash_query: &BlockhashQuery,
|
||||||
nonce_account: Option<Pubkey>,
|
nonce_account: Option<Pubkey>,
|
||||||
nonce_authority: Option<&SigningAuthority>,
|
nonce_authority: Option<&SigningAuthority>,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
@ -1053,7 +916,7 @@ pub fn process_delegate_stake(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) =
|
let (recent_blockhash, fee_calculator) =
|
||||||
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
|
blockhash_query.get_blockhash_fee_calculator(rpc_client)?;
|
||||||
|
|
||||||
let ixs = vec![stake_instruction::delegate_stake(
|
let ixs = vec![stake_instruction::delegate_stake(
|
||||||
stake_account_pubkey,
|
stake_account_pubkey,
|
||||||
@ -1105,7 +968,11 @@ pub fn process_delegate_stake(
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::cli::{app, parse_command};
|
use crate::cli::{app, parse_command};
|
||||||
use solana_sdk::signature::{read_keypair_file, write_keypair};
|
use solana_sdk::{
|
||||||
|
fee_calculator::FeeCalculator,
|
||||||
|
hash::Hash,
|
||||||
|
signature::{read_keypair_file, write_keypair},
|
||||||
|
};
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
fn make_tmp_file() -> (String, NamedTempFile) {
|
fn make_tmp_file() -> (String, NamedTempFile) {
|
||||||
@ -1143,7 +1010,7 @@ mod tests {
|
|||||||
authority: None,
|
authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1169,7 +1036,7 @@ mod tests {
|
|||||||
authority: Some(read_keypair_file(&authority_keypair_file).unwrap().into()),
|
authority: Some(read_keypair_file(&authority_keypair_file).unwrap().into()),
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1177,11 +1044,15 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
// Test Authorize Subcommand w/ sign-only
|
// Test Authorize Subcommand w/ sign-only
|
||||||
|
let blockhash = Hash::default();
|
||||||
|
let blockhash_string = format!("{}", blockhash);
|
||||||
let test_authorize = test_commands.clone().get_matches_from(vec![
|
let test_authorize = test_commands.clone().get_matches_from(vec![
|
||||||
"test",
|
"test",
|
||||||
&subcommand,
|
&subcommand,
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--sign-only",
|
"--sign-only",
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -1194,7 +1065,7 @@ mod tests {
|
|||||||
authority: None,
|
authority: None,
|
||||||
sign_only: true,
|
sign_only: true,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1210,6 +1081,8 @@ mod tests {
|
|||||||
&subcommand,
|
&subcommand,
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--signer",
|
"--signer",
|
||||||
&signer,
|
&signer,
|
||||||
]);
|
]);
|
||||||
@ -1223,7 +1096,7 @@ mod tests {
|
|||||||
authority: None,
|
authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(vec![(keypair.pubkey(), sig)]),
|
signers: Some(vec![(keypair.pubkey(), sig)]),
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1239,6 +1112,8 @@ mod tests {
|
|||||||
&subcommand,
|
&subcommand,
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--signer",
|
"--signer",
|
||||||
&signer,
|
&signer,
|
||||||
"--signer",
|
"--signer",
|
||||||
@ -1254,7 +1129,7 @@ mod tests {
|
|||||||
authority: None,
|
authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(vec![(keypair.pubkey(), sig), (keypair2.pubkey(), sig2),]),
|
signers: Some(vec![(keypair.pubkey(), sig), (keypair2.pubkey(), sig2),]),
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1262,8 +1137,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
// Test Authorize Subcommand w/ blockhash
|
// Test Authorize Subcommand w/ blockhash
|
||||||
let blockhash = Hash::default();
|
|
||||||
let blockhash_string = format!("{}", blockhash);
|
|
||||||
let test_authorize = test_commands.clone().get_matches_from(vec![
|
let test_authorize = test_commands.clone().get_matches_from(vec![
|
||||||
"test",
|
"test",
|
||||||
&subcommand,
|
&subcommand,
|
||||||
@ -1282,7 +1155,7 @@ mod tests {
|
|||||||
authority: None,
|
authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1317,7 +1190,7 @@ mod tests {
|
|||||||
authority: None,
|
authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: Some(nonce_account_pubkey),
|
nonce_account: Some(nonce_account_pubkey),
|
||||||
nonce_authority: Some(nonce_authority_keypair.into()),
|
nonce_authority: Some(nonce_authority_keypair.into()),
|
||||||
},
|
},
|
||||||
@ -1437,7 +1310,7 @@ mod tests {
|
|||||||
force: false,
|
force: false,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1470,7 +1343,7 @@ mod tests {
|
|||||||
force: false,
|
force: false,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1496,7 +1369,7 @@ mod tests {
|
|||||||
force: true,
|
force: true,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1525,7 +1398,7 @@ mod tests {
|
|||||||
force: false,
|
force: false,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1538,6 +1411,8 @@ mod tests {
|
|||||||
"delegate-stake",
|
"delegate-stake",
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
&vote_account_string,
|
&vote_account_string,
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--sign-only",
|
"--sign-only",
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -1550,7 +1425,7 @@ mod tests {
|
|||||||
force: false,
|
force: false,
|
||||||
sign_only: true,
|
sign_only: true,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1567,6 +1442,8 @@ mod tests {
|
|||||||
"delegate-stake",
|
"delegate-stake",
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
&vote_account_string,
|
&vote_account_string,
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--signer",
|
"--signer",
|
||||||
&signer1,
|
&signer1,
|
||||||
]);
|
]);
|
||||||
@ -1580,7 +1457,7 @@ mod tests {
|
|||||||
force: false,
|
force: false,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(vec![(key1, sig1)]),
|
signers: Some(vec![(key1, sig1)]),
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1597,6 +1474,8 @@ mod tests {
|
|||||||
"delegate-stake",
|
"delegate-stake",
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
&vote_account_string,
|
&vote_account_string,
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--signer",
|
"--signer",
|
||||||
&signer1,
|
&signer1,
|
||||||
"--signer",
|
"--signer",
|
||||||
@ -1612,7 +1491,7 @@ mod tests {
|
|||||||
force: false,
|
force: false,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1686,7 +1565,7 @@ mod tests {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1714,7 +1593,7 @@ mod tests {
|
|||||||
),
|
),
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1740,7 +1619,7 @@ mod tests {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1752,6 +1631,8 @@ mod tests {
|
|||||||
"test",
|
"test",
|
||||||
"deactivate-stake",
|
"deactivate-stake",
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--sign-only",
|
"--sign-only",
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -1762,7 +1643,7 @@ mod tests {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: true,
|
sign_only: true,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1778,6 +1659,8 @@ mod tests {
|
|||||||
"test",
|
"test",
|
||||||
"deactivate-stake",
|
"deactivate-stake",
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--signer",
|
"--signer",
|
||||||
&signer1,
|
&signer1,
|
||||||
]);
|
]);
|
||||||
@ -1789,7 +1672,7 @@ mod tests {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(vec![(key1, sig1)]),
|
signers: Some(vec![(key1, sig1)]),
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
@ -1805,6 +1688,8 @@ mod tests {
|
|||||||
"test",
|
"test",
|
||||||
"deactivate-stake",
|
"deactivate-stake",
|
||||||
&stake_account_string,
|
&stake_account_string,
|
||||||
|
"--blockhash",
|
||||||
|
&blockhash_string,
|
||||||
"--signer",
|
"--signer",
|
||||||
&signer1,
|
&signer1,
|
||||||
"--signer",
|
"--signer",
|
||||||
@ -1818,7 +1703,7 @@ mod tests {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
},
|
},
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use solana_cli::cli::{
|
use solana_cli::{
|
||||||
process_command, request_and_confirm_airdrop, CliCommand, CliConfig, PayCommand,
|
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig, PayCommand},
|
||||||
|
offline::BlockhashQuery,
|
||||||
};
|
};
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_faucet::faucet::run_local_faucet;
|
use solana_faucet::faucet::run_local_faucet;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
|
fee_calculator::FeeCalculator,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
nonce_state::NonceState,
|
nonce_state::NonceState,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
@ -289,9 +291,11 @@ fn test_offline_pay_tx() {
|
|||||||
check_balance(50, &rpc_client, &config_offline.keypair.pubkey());
|
check_balance(50, &rpc_client, &config_offline.keypair.pubkey());
|
||||||
check_balance(50, &rpc_client, &config_online.keypair.pubkey());
|
check_balance(50, &rpc_client, &config_online.keypair.pubkey());
|
||||||
|
|
||||||
|
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
||||||
config_offline.command = CliCommand::Pay(PayCommand {
|
config_offline.command = CliCommand::Pay(PayCommand {
|
||||||
lamports: 10,
|
lamports: 10,
|
||||||
to: bob_pubkey,
|
to: bob_pubkey,
|
||||||
|
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
sign_only: true,
|
sign_only: true,
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
});
|
});
|
||||||
@ -318,7 +322,7 @@ fn test_offline_pay_tx() {
|
|||||||
lamports: 10,
|
lamports: 10,
|
||||||
to: bob_pubkey,
|
to: bob_pubkey,
|
||||||
signers: Some(signers),
|
signers: Some(signers),
|
||||||
blockhash: Some(blockhash_str.parse::<Hash>().unwrap()),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash_str.parse::<Hash>().unwrap()),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
});
|
});
|
||||||
process_command(&config_online).unwrap();
|
process_command(&config_online).unwrap();
|
||||||
@ -389,7 +393,7 @@ fn test_nonced_pay_tx() {
|
|||||||
config.command = CliCommand::Pay(PayCommand {
|
config.command = CliCommand::Pay(PayCommand {
|
||||||
lamports: 10,
|
lamports: 10,
|
||||||
to: bob_pubkey,
|
to: bob_pubkey,
|
||||||
blockhash: Some(nonce_hash),
|
blockhash_query: BlockhashQuery::FeeCalculator(nonce_hash),
|
||||||
nonce_account: Some(nonce_account.pubkey()),
|
nonce_account: Some(nonce_account.pubkey()),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use solana_cli::cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig};
|
use solana_cli::{
|
||||||
|
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
|
||||||
|
offline::BlockhashQuery,
|
||||||
|
};
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_faucet::faucet::run_local_faucet;
|
use solana_faucet::faucet::run_local_faucet;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
|
fee_calculator::FeeCalculator,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
nonce_state::NonceState,
|
nonce_state::NonceState,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
@ -132,7 +136,7 @@ fn test_seed_stake_delegation_and_deactivation() {
|
|||||||
force: true,
|
force: true,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -144,7 +148,7 @@ fn test_seed_stake_delegation_and_deactivation() {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -220,7 +224,7 @@ fn test_stake_delegation_and_deactivation() {
|
|||||||
force: true,
|
force: true,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -232,7 +236,7 @@ fn test_stake_delegation_and_deactivation() {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -305,6 +309,7 @@ fn test_offline_stake_delegation_and_deactivation() {
|
|||||||
process_command(&config_validator).unwrap();
|
process_command(&config_validator).unwrap();
|
||||||
|
|
||||||
// Delegate stake offline
|
// Delegate stake offline
|
||||||
|
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
||||||
config_validator.command = CliCommand::DelegateStake {
|
config_validator.command = CliCommand::DelegateStake {
|
||||||
stake_account_pubkey: config_stake.keypair.pubkey(),
|
stake_account_pubkey: config_stake.keypair.pubkey(),
|
||||||
vote_account_pubkey: config_vote.keypair.pubkey(),
|
vote_account_pubkey: config_vote.keypair.pubkey(),
|
||||||
@ -312,7 +317,7 @@ fn test_offline_stake_delegation_and_deactivation() {
|
|||||||
force: true,
|
force: true,
|
||||||
sign_only: true,
|
sign_only: true,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -327,19 +332,20 @@ fn test_offline_stake_delegation_and_deactivation() {
|
|||||||
force: true,
|
force: true,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(signers),
|
signers: Some(signers),
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
process_command(&config_payer).unwrap();
|
process_command(&config_payer).unwrap();
|
||||||
|
|
||||||
// Deactivate stake offline
|
// Deactivate stake offline
|
||||||
|
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
||||||
config_validator.command = CliCommand::DeactivateStake {
|
config_validator.command = CliCommand::DeactivateStake {
|
||||||
stake_account_pubkey: config_stake.keypair.pubkey(),
|
stake_account_pubkey: config_stake.keypair.pubkey(),
|
||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: true,
|
sign_only: true,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -352,7 +358,7 @@ fn test_offline_stake_delegation_and_deactivation() {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(signers),
|
signers: Some(signers),
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -439,7 +445,7 @@ fn test_nonced_stake_delegation_and_deactivation() {
|
|||||||
force: true,
|
force: true,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: Some(nonce_hash),
|
blockhash_query: BlockhashQuery::None(nonce_hash, FeeCalculator::default()),
|
||||||
nonce_account: Some(nonce_account.pubkey()),
|
nonce_account: Some(nonce_account.pubkey()),
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -460,7 +466,7 @@ fn test_nonced_stake_delegation_and_deactivation() {
|
|||||||
stake_authority: None,
|
stake_authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: Some(nonce_hash),
|
blockhash_query: BlockhashQuery::FeeCalculator(nonce_hash),
|
||||||
nonce_account: Some(nonce_account.pubkey()),
|
nonce_account: Some(nonce_account.pubkey()),
|
||||||
nonce_authority: Some(config_keypair.into()),
|
nonce_authority: Some(config_keypair.into()),
|
||||||
};
|
};
|
||||||
@ -514,7 +520,7 @@ fn test_stake_authorize() {
|
|||||||
authority: None,
|
authority: None,
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -539,7 +545,7 @@ fn test_stake_authorize() {
|
|||||||
authority: Some(read_keypair_file(&online_authority_file).unwrap().into()),
|
authority: Some(read_keypair_file(&online_authority_file).unwrap().into()),
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::default(),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -557,6 +563,7 @@ fn test_stake_authorize() {
|
|||||||
let nonced_authority_pubkey = nonced_authority.pubkey();
|
let nonced_authority_pubkey = nonced_authority.pubkey();
|
||||||
let (nonced_authority_file, mut tmp_file) = make_tmp_file();
|
let (nonced_authority_file, mut tmp_file) = make_tmp_file();
|
||||||
write_keypair(&nonced_authority, tmp_file.as_file_mut()).unwrap();
|
write_keypair(&nonced_authority, tmp_file.as_file_mut()).unwrap();
|
||||||
|
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
|
||||||
config.command = CliCommand::StakeAuthorize {
|
config.command = CliCommand::StakeAuthorize {
|
||||||
stake_account_pubkey,
|
stake_account_pubkey,
|
||||||
new_authorized_pubkey: nonced_authority_pubkey,
|
new_authorized_pubkey: nonced_authority_pubkey,
|
||||||
@ -564,7 +571,7 @@ fn test_stake_authorize() {
|
|||||||
authority: Some(read_keypair_file(&offline_authority_file).unwrap().into()),
|
authority: Some(read_keypair_file(&offline_authority_file).unwrap().into()),
|
||||||
sign_only: true,
|
sign_only: true,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None,
|
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -577,7 +584,7 @@ fn test_stake_authorize() {
|
|||||||
authority: Some(offline_authority_pubkey.into()),
|
authority: Some(offline_authority_pubkey.into()),
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(signers),
|
signers: Some(signers),
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: None,
|
nonce_account: None,
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -625,7 +632,7 @@ fn test_stake_authorize() {
|
|||||||
authority: Some(read_keypair_file(&nonced_authority_file).unwrap().into()),
|
authority: Some(read_keypair_file(&nonced_authority_file).unwrap().into()),
|
||||||
sign_only: true,
|
sign_only: true,
|
||||||
signers: None,
|
signers: None,
|
||||||
blockhash: Some(nonce_hash),
|
blockhash_query: BlockhashQuery::None(nonce_hash, FeeCalculator::default()),
|
||||||
nonce_account: Some(nonce_account.pubkey()),
|
nonce_account: Some(nonce_account.pubkey()),
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
@ -639,7 +646,7 @@ fn test_stake_authorize() {
|
|||||||
authority: Some(nonced_authority_pubkey.into()),
|
authority: Some(nonced_authority_pubkey.into()),
|
||||||
sign_only: false,
|
sign_only: false,
|
||||||
signers: Some(signers),
|
signers: Some(signers),
|
||||||
blockhash: Some(blockhash),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
nonce_account: Some(nonce_account.pubkey()),
|
nonce_account: Some(nonce_account.pubkey()),
|
||||||
nonce_authority: None,
|
nonce_authority: None,
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-client"
|
name = "solana-client"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Client"
|
description = "Solana Client"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -19,11 +19,11 @@ reqwest = { version = "0.10.1", default-features = false, features = ["blocking"
|
|||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
|
solana-net-utils = { path = "../net-utils", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_matches = "1.3.0"
|
assert_matches = "1.3.0"
|
||||||
jsonrpc-core = "14.0.5"
|
jsonrpc-core = "14.0.5"
|
||||||
jsonrpc-http-server = "14.0.5"
|
jsonrpc-http-server = "14.0.5"
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
|
@ -177,7 +177,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetVoteAccounts parse failure: {}", err),
|
format!("GetVoteAccounts parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetClusterNodes parse failure: {}", err),
|
format!("GetClusterNodes parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -215,7 +215,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetConfirmedBlock parse failure: {}", err),
|
format!("GetConfirmedBlock parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -242,7 +242,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetConfirmedBlocks parse failure: {}", err),
|
format!("GetConfirmedBlocks parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -293,7 +293,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetEpochInfo parse failure: {}", err),
|
format!("GetEpochInfo parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -324,7 +324,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetLeaderSchedule failure: {}", err),
|
format!("GetLeaderSchedule failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -343,7 +343,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetEpochSchedule parse failure: {}", err),
|
format!("GetEpochSchedule parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -381,7 +381,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetVersion parse failure: {}", err),
|
format!("GetVersion parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -400,7 +400,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("MinimumLedgerSlot parse failure: {}", err),
|
format!("MinimumLedgerSlot parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -612,7 +612,7 @@ impl RpcClient {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("AccountNotFound: pubkey={}: {}", pubkey, err),
|
format!("AccountNotFound: pubkey={}: {:?}", pubkey, err),
|
||||||
)
|
)
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
@ -698,7 +698,7 @@ impl RpcClient {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("AccountNotFound: pubkey={}: {}", pubkey, err),
|
format!("AccountNotFound: pubkey={}: {:?}", pubkey, err),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -749,7 +749,7 @@ impl RpcClient {
|
|||||||
serde_json::from_value(response).map_err(|err| {
|
serde_json::from_value(response).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetTransactionCount parse failure: {}", err),
|
format!("GetTransactionCount parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,7 @@ pub struct RpcClientRequest {
|
|||||||
|
|
||||||
impl RpcClientRequest {
|
impl RpcClientRequest {
|
||||||
pub fn new(url: String) -> Self {
|
pub fn new(url: String) -> Self {
|
||||||
Self {
|
Self::new_with_timeout(url, Duration::from_secs(20))
|
||||||
client: reqwest::blocking::Client::new(),
|
|
||||||
url,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_timeout(url: String, timeout: Duration) -> Self {
|
pub fn new_with_timeout(url: String, timeout: Duration) -> Self {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-core"
|
name = "solana-core"
|
||||||
description = "Blockchain, Rebuilt for Scale"
|
description = "Blockchain, Rebuilt for Scale"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
documentation = "https://docs.rs/solana"
|
documentation = "https://docs.rs/solana"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
readme = "../README.md"
|
readme = "../README.md"
|
||||||
@ -40,26 +40,26 @@ rayon = "1.2.0"
|
|||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
solana-budget-program = { path = "../programs/budget", version = "0.23.0" }
|
solana-budget-program = { path = "../programs/budget", version = "0.23.1" }
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-client = { path = "../client", version = "0.23.0" }
|
solana-client = { path = "../client", version = "0.23.1" }
|
||||||
solana-faucet = { path = "../faucet", version = "0.23.0" }
|
solana-faucet = { path = "../faucet", version = "0.23.1" }
|
||||||
ed25519-dalek = "=1.0.0-pre.1"
|
ed25519-dalek = "=1.0.0-pre.1"
|
||||||
solana-ledger = { path = "../ledger", version = "0.23.0" }
|
solana-ledger = { path = "../ledger", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-merkle-tree = { path = "../merkle-tree", version = "0.23.0" }
|
solana-merkle-tree = { path = "../merkle-tree", version = "0.23.1" }
|
||||||
solana-metrics = { path = "../metrics", version = "0.23.0" }
|
solana-metrics = { path = "../metrics", version = "0.23.1" }
|
||||||
solana-measure = { path = "../measure", version = "0.23.0" }
|
solana-measure = { path = "../measure", version = "0.23.1" }
|
||||||
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
|
solana-net-utils = { path = "../net-utils", version = "0.23.1" }
|
||||||
solana-chacha-cuda = { path = "../chacha-cuda", version = "0.23.0" }
|
solana-chacha-cuda = { path = "../chacha-cuda", version = "0.23.1" }
|
||||||
solana-perf = { path = "../perf", version = "0.23.0" }
|
solana-perf = { path = "../perf", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../runtime", version = "0.23.0" }
|
solana-runtime = { path = "../runtime", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-stake-program = { path = "../programs/stake", version = "0.23.0" }
|
solana-stake-program = { path = "../programs/stake", version = "0.23.1" }
|
||||||
solana-storage-program = { path = "../programs/storage", version = "0.23.0" }
|
solana-storage-program = { path = "../programs/storage", version = "0.23.1" }
|
||||||
solana-vote-program = { path = "../programs/vote", version = "0.23.0" }
|
solana-vote-program = { path = "../programs/vote", version = "0.23.1" }
|
||||||
solana-vote-signer = { path = "../vote-signer", version = "0.23.0" }
|
solana-vote-signer = { path = "../vote-signer", version = "0.23.1" }
|
||||||
solana-sys-tuner = { path = "../sys-tuner", version = "0.23.0" }
|
solana-sys-tuner = { path = "../sys-tuner", version = "0.23.1" }
|
||||||
symlink = "0.1.0"
|
symlink = "0.1.0"
|
||||||
sys-info = "0.5.8"
|
sys-info = "0.5.8"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
@ -69,7 +69,7 @@ tokio-codec = "0.1"
|
|||||||
tokio-fs = "0.1"
|
tokio-fs = "0.1"
|
||||||
tokio-io = "0.1"
|
tokio-io = "0.1"
|
||||||
untrusted = "0.7.0"
|
untrusted = "0.7.0"
|
||||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.23.0" }
|
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.23.1" }
|
||||||
reed-solomon-erasure = { package = "solana-reed-solomon-erasure", version = "4.0.1-3", features = ["simd-accel"] }
|
reed-solomon-erasure = { package = "solana-reed-solomon-erasure", version = "4.0.1-3", features = ["simd-accel"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -58,8 +58,11 @@ impl BlockstreamService {
|
|||||||
let timeout = Duration::new(1, 0);
|
let timeout = Duration::new(1, 0);
|
||||||
let (slot, slot_leader) = slot_full_receiver.recv_timeout(timeout)?;
|
let (slot, slot_leader) = slot_full_receiver.recv_timeout(timeout)?;
|
||||||
|
|
||||||
let entries = blockstore.get_slot_entries(slot, 0, None).unwrap();
|
// Slot might not exist due to LedgerCleanupService, check first
|
||||||
let blockstore_meta = blockstore.meta(slot).unwrap().unwrap();
|
let blockstore_meta = blockstore.meta(slot).unwrap();
|
||||||
|
if let Some(blockstore_meta) = blockstore_meta {
|
||||||
|
// Return error to main loop. Thread won't exit, will just log the error
|
||||||
|
let entries = blockstore.get_slot_entries(slot, 0, None)?;
|
||||||
let _parent_slot = if slot == 0 {
|
let _parent_slot = if slot == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -85,6 +88,7 @@ impl BlockstreamService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ impl ClusterInfo {
|
|||||||
|
|
||||||
let ip_addr = node.gossip.ip();
|
let ip_addr = node.gossip.ip();
|
||||||
format!(
|
format!(
|
||||||
"{:15} {:2}| {:5} | {:44} | {:5}| {:5}| {:5} | {:5}| {:5} | {:5}| {:5} | {:5}| {:5}| v{}\n",
|
"{:15} {:2}| {:5} | {:44} | {:5}| {:5}| {:5} | {:5}| {:5} | {:5}| {:5} | {:5}| {:5}| {}\n",
|
||||||
if ContactInfo::is_valid_address(&node.gossip) {
|
if ContactInfo::is_valid_address(&node.gossip) {
|
||||||
ip_addr.to_string()
|
ip_addr.to_string()
|
||||||
} else {
|
} else {
|
||||||
@ -405,7 +405,8 @@ impl ClusterInfo {
|
|||||||
.map(|x| x.value.contact_info().unwrap())
|
.map(|x| x.value.contact_info().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rpc_peers(&self) -> Vec<ContactInfo> {
|
/// all validators that have a valid rpc port regardless of `shred_version`.
|
||||||
|
pub fn all_rpc_peers(&self) -> Vec<ContactInfo> {
|
||||||
let me = self.my_data();
|
let me = self.my_data();
|
||||||
self.gossip
|
self.gossip
|
||||||
.crds
|
.crds
|
||||||
@ -440,13 +441,15 @@ impl ClusterInfo {
|
|||||||
.values()
|
.values()
|
||||||
.filter_map(|x| x.value.contact_info())
|
.filter_map(|x| x.value.contact_info())
|
||||||
.filter(|x| x.id != me)
|
.filter(|x| x.id != me)
|
||||||
|
/* shred_version not considered for gossip peers (ie, spy nodes do not set
|
||||||
|
shred_version) */
|
||||||
.filter(|x| ContactInfo::is_valid_address(&x.gossip))
|
.filter(|x| ContactInfo::is_valid_address(&x.gossip))
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// all validators that have a valid tvu port.
|
/// all validators that have a valid tvu port regardless of `shred_version`.
|
||||||
pub fn tvu_peers(&self) -> Vec<ContactInfo> {
|
pub fn all_tvu_peers(&self) -> Vec<ContactInfo> {
|
||||||
let me = self.my_data();
|
let me = self.my_data();
|
||||||
self.gossip
|
self.gossip
|
||||||
.crds
|
.crds
|
||||||
@ -460,7 +463,37 @@ impl ClusterInfo {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// all peers that have a valid storage addr
|
/// all validators that have a valid tvu port and are on the same `shred_version`.
|
||||||
|
pub fn tvu_peers(&self) -> Vec<ContactInfo> {
|
||||||
|
let me = self.my_data();
|
||||||
|
self.gossip
|
||||||
|
.crds
|
||||||
|
.table
|
||||||
|
.values()
|
||||||
|
.filter_map(|x| x.value.contact_info())
|
||||||
|
.filter(|x| ContactInfo::is_valid_address(&x.tvu))
|
||||||
|
.filter(|x| !ClusterInfo::is_archiver(x))
|
||||||
|
.filter(|x| x.id != me.id)
|
||||||
|
.filter(|x| x.shred_version == me.shred_version)
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// all peers that have a valid storage addr regardless of `shred_version`.
|
||||||
|
pub fn all_storage_peers(&self) -> Vec<ContactInfo> {
|
||||||
|
let me = self.my_data();
|
||||||
|
self.gossip
|
||||||
|
.crds
|
||||||
|
.table
|
||||||
|
.values()
|
||||||
|
.filter_map(|x| x.value.contact_info())
|
||||||
|
.filter(|x| ContactInfo::is_valid_address(&x.storage_addr))
|
||||||
|
.filter(|x| x.id != me.id)
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// all peers that have a valid storage addr and are on the same `shred_version`.
|
||||||
pub fn storage_peers(&self) -> Vec<ContactInfo> {
|
pub fn storage_peers(&self) -> Vec<ContactInfo> {
|
||||||
let me = self.my_data();
|
let me = self.my_data();
|
||||||
self.gossip
|
self.gossip
|
||||||
@ -470,6 +503,7 @@ impl ClusterInfo {
|
|||||||
.filter_map(|x| x.value.contact_info())
|
.filter_map(|x| x.value.contact_info())
|
||||||
.filter(|x| ContactInfo::is_valid_address(&x.storage_addr))
|
.filter(|x| ContactInfo::is_valid_address(&x.storage_addr))
|
||||||
.filter(|x| x.id != me.id)
|
.filter(|x| x.id != me.id)
|
||||||
|
.filter(|x| x.shred_version == me.shred_version)
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@ -483,6 +517,7 @@ impl ClusterInfo {
|
|||||||
.values()
|
.values()
|
||||||
.filter_map(|x| x.value.contact_info())
|
.filter_map(|x| x.value.contact_info())
|
||||||
.filter(|x| x.id != me.id)
|
.filter(|x| x.id != me.id)
|
||||||
|
.filter(|x| x.shred_version == me.shred_version)
|
||||||
.filter(|x| ContactInfo::is_valid_address(&x.tvu))
|
.filter(|x| ContactInfo::is_valid_address(&x.tvu))
|
||||||
.filter(|x| ContactInfo::is_valid_address(&x.tvu_forwards))
|
.filter(|x| ContactInfo::is_valid_address(&x.tvu_forwards))
|
||||||
.cloned()
|
.cloned()
|
||||||
@ -495,6 +530,7 @@ impl ClusterInfo {
|
|||||||
ClusterInfo::tvu_peers(self)
|
ClusterInfo::tvu_peers(self)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|x| x.id != me.id)
|
.filter(|x| x.id != me.id)
|
||||||
|
.filter(|x| x.shred_version == me.shred_version)
|
||||||
.filter(|x| ContactInfo::is_valid_address(&x.gossip))
|
.filter(|x| ContactInfo::is_valid_address(&x.gossip))
|
||||||
.filter(|x| {
|
.filter(|x| {
|
||||||
self.get_epoch_state_for_node(&x.id, None)
|
self.get_epoch_state_for_node(&x.id, None)
|
||||||
@ -1057,6 +1093,7 @@ impl ClusterInfo {
|
|||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
let mut last_push = timestamp();
|
let mut last_push = timestamp();
|
||||||
let mut last_contact_info_trace = timestamp();
|
let mut last_contact_info_trace = timestamp();
|
||||||
|
let mut adopt_shred_version = obj.read().unwrap().my_data().shred_version == 0;
|
||||||
let recycler = PacketsRecycler::default();
|
let recycler = PacketsRecycler::default();
|
||||||
loop {
|
loop {
|
||||||
let start = timestamp();
|
let start = timestamp();
|
||||||
@ -1094,9 +1131,32 @@ impl ClusterInfo {
|
|||||||
let table_size = obj.read().unwrap().gossip.crds.table.len();
|
let table_size = obj.read().unwrap().gossip.crds.table.len();
|
||||||
datapoint_debug!(
|
datapoint_debug!(
|
||||||
"cluster_info-purge",
|
"cluster_info-purge",
|
||||||
("tabel_size", table_size as i64, i64),
|
("table_size", table_size as i64, i64),
|
||||||
("purge_stake_timeout", timeout as i64, i64)
|
("purge_stake_timeout", timeout as i64, i64)
|
||||||
);
|
);
|
||||||
|
// Adopt the entrypoint's `shred_version` if ours is unset
|
||||||
|
if adopt_shred_version {
|
||||||
|
// If gossip was given an entrypoint, lookup its id
|
||||||
|
let entrypoint_id = obj.read().unwrap().entrypoint.as_ref().map(|e| e.id);
|
||||||
|
if let Some(entrypoint_id) = entrypoint_id {
|
||||||
|
// If a pull from the entrypoint was successful, it should exist in the crds table
|
||||||
|
let entrypoint = obj.read().unwrap().lookup(&entrypoint_id).cloned();
|
||||||
|
if let Some(entrypoint) = entrypoint {
|
||||||
|
let mut self_info = obj.read().unwrap().my_data();
|
||||||
|
if entrypoint.shred_version == 0 {
|
||||||
|
info!("Unable to adopt entrypoint's shred version");
|
||||||
|
} else {
|
||||||
|
info!(
|
||||||
|
"Setting shred version to {:?} from entrypoint {:?}",
|
||||||
|
entrypoint.shred_version, entrypoint.id
|
||||||
|
);
|
||||||
|
self_info.shred_version = entrypoint.shred_version;
|
||||||
|
obj.write().unwrap().insert_self(self_info);
|
||||||
|
adopt_shred_version = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
//TODO: possibly tune this parameter
|
//TODO: possibly tune this parameter
|
||||||
//we saw a deadlock passing an obj.read().unwrap().timeout into sleep
|
//we saw a deadlock passing an obj.read().unwrap().timeout into sleep
|
||||||
if start - last_push > CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS / 2 {
|
if start - last_push > CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS / 2 {
|
||||||
@ -2663,6 +2723,14 @@ mod tests {
|
|||||||
cluster_info.insert_info(contact_info);
|
cluster_info.insert_info(contact_info);
|
||||||
stakes.insert(id3, 10);
|
stakes.insert(id3, 10);
|
||||||
|
|
||||||
|
// normal but with different shred version
|
||||||
|
let id4 = Pubkey::new(&[4u8; 32]);
|
||||||
|
let mut contact_info = ContactInfo::new_localhost(&id4, timestamp());
|
||||||
|
contact_info.shred_version = 1;
|
||||||
|
assert_ne!(contact_info.shred_version, d.shred_version);
|
||||||
|
cluster_info.insert_info(contact_info.clone());
|
||||||
|
stakes.insert(id4, 10);
|
||||||
|
|
||||||
let stakes = Arc::new(stakes);
|
let stakes = Arc::new(stakes);
|
||||||
let (peers, peers_and_stakes) = cluster_info.sorted_tvu_peers_and_stakes(Some(stakes));
|
let (peers, peers_and_stakes) = cluster_info.sorted_tvu_peers_and_stakes(Some(stakes));
|
||||||
assert_eq!(peers.len(), 2);
|
assert_eq!(peers.len(), 2);
|
||||||
|
@ -135,7 +135,7 @@ impl ClusterInfoRepairListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let lowest_slot = blockstore.lowest_slot();
|
let lowest_slot = blockstore.lowest_slot();
|
||||||
let peers = cluster_info.read().unwrap().gossip_peers();
|
let peers = cluster_info.read().unwrap().tvu_peers();
|
||||||
let mut peers_needing_repairs: HashMap<Pubkey, EpochSlots> = HashMap::new();
|
let mut peers_needing_repairs: HashMap<Pubkey, EpochSlots> = HashMap::new();
|
||||||
|
|
||||||
// Iterate through all the known nodes in the network, looking for ones that
|
// Iterate through all the known nodes in the network, looking for ones that
|
||||||
|
@ -321,13 +321,27 @@ impl Tower {
|
|||||||
if let Some(fork_stake) = stake_lockouts.get(&vote.slot) {
|
if let Some(fork_stake) = stake_lockouts.get(&vote.slot) {
|
||||||
let lockout = fork_stake.stake as f64 / total_staked as f64;
|
let lockout = fork_stake.stake as f64 / total_staked as f64;
|
||||||
trace!(
|
trace!(
|
||||||
"fork_stake {} {} {} {}",
|
"fork_stake slot: {} lockout: {} fork_stake: {} total_stake: {}",
|
||||||
slot,
|
slot,
|
||||||
lockout,
|
lockout,
|
||||||
fork_stake.stake,
|
fork_stake.stake,
|
||||||
total_staked
|
total_staked
|
||||||
);
|
);
|
||||||
lockout > self.threshold_size
|
for (new_lockout, original_lockout) in
|
||||||
|
lockouts.votes.iter().zip(self.lockouts.votes.iter())
|
||||||
|
{
|
||||||
|
if new_lockout.slot == original_lockout.slot {
|
||||||
|
if new_lockout.confirmation_count <= self.threshold_depth as u32 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if new_lockout.confirmation_count != original_lockout.confirmation_count {
|
||||||
|
return lockout > self.threshold_size;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -742,6 +756,34 @@ mod test {
|
|||||||
assert!(!tower.check_vote_stake_threshold(1, &stakes, 2));
|
assert!(!tower.check_vote_stake_threshold(1, &stakes, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_check_vote_threshold_lockouts_not_updated() {
|
||||||
|
solana_logger::setup();
|
||||||
|
let mut tower = Tower::new_for_tests(1, 0.67);
|
||||||
|
let stakes = vec![
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
StakeLockout {
|
||||||
|
stake: 1,
|
||||||
|
lockout: 8,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
StakeLockout {
|
||||||
|
stake: 2,
|
||||||
|
lockout: 8,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
tower.record_vote(0, Hash::default());
|
||||||
|
tower.record_vote(1, Hash::default());
|
||||||
|
tower.record_vote(2, Hash::default());
|
||||||
|
assert!(tower.check_vote_stake_threshold(6, &stakes, 2));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lockout_is_updated_for_entire_branch() {
|
fn test_lockout_is_updated_for_entire_branch() {
|
||||||
let mut stake_lockouts = HashMap::new();
|
let mut stake_lockouts = HashMap::new();
|
||||||
|
@ -299,8 +299,8 @@ mod tests {
|
|||||||
assert_eq!(ci.gossip.port(), 11);
|
assert_eq!(ci.gossip.port(), 11);
|
||||||
assert_eq!(ci.tvu.port(), 12);
|
assert_eq!(ci.tvu.port(), 12);
|
||||||
assert_eq!(ci.tpu_forwards.port(), 13);
|
assert_eq!(ci.tpu_forwards.port(), 13);
|
||||||
assert_eq!(ci.rpc.port(), 8899);
|
assert_eq!(ci.rpc.port(), rpc_port::DEFAULT_RPC_PORT);
|
||||||
assert_eq!(ci.rpc_pubsub.port(), 8900);
|
assert_eq!(ci.rpc_pubsub.port(), rpc_port::DEFAULT_RPC_PUBSUB_PORT);
|
||||||
assert!(ci.storage_addr.ip().is_unspecified());
|
assert!(ci.storage_addr.ip().is_unspecified());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
@ -315,8 +315,14 @@ mod tests {
|
|||||||
assert_eq!(d1.tvu, socketaddr!("127.0.0.1:1236"));
|
assert_eq!(d1.tvu, socketaddr!("127.0.0.1:1236"));
|
||||||
assert_eq!(d1.tpu_forwards, socketaddr!("127.0.0.1:1237"));
|
assert_eq!(d1.tpu_forwards, socketaddr!("127.0.0.1:1237"));
|
||||||
assert_eq!(d1.tpu, socketaddr!("127.0.0.1:1234"));
|
assert_eq!(d1.tpu, socketaddr!("127.0.0.1:1234"));
|
||||||
assert_eq!(d1.rpc, socketaddr!("127.0.0.1:8899"));
|
assert_eq!(
|
||||||
assert_eq!(d1.rpc_pubsub, socketaddr!("127.0.0.1:8900"));
|
d1.rpc,
|
||||||
|
socketaddr!(format!("127.0.0.1:{}", rpc_port::DEFAULT_RPC_PORT))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
d1.rpc_pubsub,
|
||||||
|
socketaddr!(format!("127.0.0.1:{}", rpc_port::DEFAULT_RPC_PUBSUB_PORT))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -197,10 +197,10 @@ fn spy(
|
|||||||
tvu_peers = spy_ref
|
tvu_peers = spy_ref
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.tvu_peers()
|
.all_tvu_peers()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
archivers = spy_ref.read().unwrap().storage_peers();
|
archivers = spy_ref.read().unwrap().all_storage_peers();
|
||||||
if let Some(num) = num_nodes {
|
if let Some(num) = num_nodes {
|
||||||
if tvu_peers.len() + archivers.len() >= num {
|
if tvu_peers.len() + archivers.len() >= num {
|
||||||
if let Some(gossip_addr) = find_node_by_gossip_addr {
|
if let Some(gossip_addr) = find_node_by_gossip_addr {
|
||||||
|
@ -68,9 +68,13 @@ impl LedgerCleanupService {
|
|||||||
let disk_utilization_pre = blockstore.storage_size();
|
let disk_utilization_pre = blockstore.storage_size();
|
||||||
|
|
||||||
let root = new_root_receiver.recv_timeout(Duration::from_secs(1))?;
|
let root = new_root_receiver.recv_timeout(Duration::from_secs(1))?;
|
||||||
|
|
||||||
|
// Notify blockstore of impending purge
|
||||||
if root > *next_purge_batch {
|
if root > *next_purge_batch {
|
||||||
//cleanup
|
//cleanup
|
||||||
blockstore.purge_slots(0, Some(root - max_ledger_slots));
|
let lowest_slot = root - max_ledger_slots;
|
||||||
|
*blockstore.lowest_cleanup_slot.write().unwrap() = lowest_slot;
|
||||||
|
blockstore.purge_slots(0, Some(lowest_slot));
|
||||||
*next_purge_batch += DEFAULT_PURGE_BATCH_SIZE;
|
*next_purge_batch += DEFAULT_PURGE_BATCH_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@ pub mod gossip_service;
|
|||||||
pub mod ledger_cleanup_service;
|
pub mod ledger_cleanup_service;
|
||||||
pub mod local_vote_signer_service;
|
pub mod local_vote_signer_service;
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
pub mod partition_cfg;
|
|
||||||
pub mod poh_recorder;
|
pub mod poh_recorder;
|
||||||
pub mod poh_service;
|
pub mod poh_service;
|
||||||
pub mod recvmmsg;
|
pub mod recvmmsg;
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
use solana_ledger::leader_schedule_cache::LeaderScheduleCache;
|
|
||||||
use solana_ledger::shred::Shred;
|
|
||||||
use solana_runtime::bank::Bank;
|
|
||||||
use solana_sdk::pubkey::Pubkey;
|
|
||||||
use solana_sdk::timing::timestamp;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::RwLock;
|
|
||||||
|
|
||||||
///Configure a partition in the retransmit stage
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Partition {
|
|
||||||
pub num_partitions: usize,
|
|
||||||
pub my_partition: usize,
|
|
||||||
pub start_ts: u64,
|
|
||||||
pub end_ts: u64,
|
|
||||||
leaders: Arc<RwLock<Vec<Pubkey>>>,
|
|
||||||
}
|
|
||||||
impl Default for Partition {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
num_partitions: 0,
|
|
||||||
my_partition: 0,
|
|
||||||
start_ts: 0,
|
|
||||||
end_ts: 0,
|
|
||||||
leaders: Arc::new(RwLock::new(vec![])),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
|
||||||
pub struct PartitionCfg {
|
|
||||||
partitions: Vec<Partition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartitionCfg {
|
|
||||||
pub fn new(partitions: Vec<Partition>) -> Self {
|
|
||||||
Self { partitions }
|
|
||||||
}
|
|
||||||
pub fn is_connected(
|
|
||||||
&self,
|
|
||||||
bank: &Option<Arc<Bank>>,
|
|
||||||
leader_schedule_cache: &Arc<LeaderScheduleCache>,
|
|
||||||
shred: &Shred,
|
|
||||||
) -> bool {
|
|
||||||
if bank.is_none() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let bank = bank.as_ref().unwrap().clone();
|
|
||||||
let slot_leader_pubkey = leader_schedule_cache.slot_leader_at(shred.slot(), Some(&bank));
|
|
||||||
let slot_leader_pubkey = slot_leader_pubkey.unwrap_or_default();
|
|
||||||
let time = timestamp();
|
|
||||||
for p in &self.partitions {
|
|
||||||
let is_time = (p.start_ts <= time) && (time < p.end_ts);
|
|
||||||
if !is_time {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
trace!("PARTITION_TEST partition time! {}", p.my_partition);
|
|
||||||
if p.num_partitions == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if p.leaders.read().unwrap().is_empty() {
|
|
||||||
let mut leader_vec = p.leaders.write().unwrap();
|
|
||||||
let mut leaders: Vec<Pubkey> = bank.vote_accounts().keys().cloned().collect();
|
|
||||||
leaders.sort();
|
|
||||||
*leader_vec = leaders;
|
|
||||||
warn!("PARTITION_TEST partition enabled {}", p.my_partition);
|
|
||||||
}
|
|
||||||
let is_connected: bool = {
|
|
||||||
let leaders = p.leaders.read().unwrap();
|
|
||||||
let start = p.my_partition * leaders.len() / p.num_partitions;
|
|
||||||
let partition_size = leaders.len() / p.num_partitions;
|
|
||||||
let end = start + partition_size;
|
|
||||||
let end = if leaders.len() - end < partition_size {
|
|
||||||
leaders.len()
|
|
||||||
} else {
|
|
||||||
end
|
|
||||||
};
|
|
||||||
let my_leaders: HashSet<_> = leaders[start..end].iter().collect();
|
|
||||||
my_leaders.contains(&slot_leader_pubkey)
|
|
||||||
};
|
|
||||||
if is_connected {
|
|
||||||
trace!("PARTITION_TEST connected {}", p.my_partition);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
trace!("PARTITION_TEST not connected {}", p.my_partition);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
trace!("PARTITION_TEST connected");
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
@ -527,6 +527,9 @@ impl ReplayStage {
|
|||||||
let tx_count = tx_count_after - tx_count_before;
|
let tx_count = tx_count_after - tx_count_before;
|
||||||
|
|
||||||
confirm_result.map_err(|err| {
|
confirm_result.map_err(|err| {
|
||||||
|
// LedgerCleanupService should not be cleaning up anything
|
||||||
|
// that comes after the root, so we should not see any
|
||||||
|
// errors related to the slot being purged
|
||||||
let slot = bank.slot();
|
let slot = bank.slot();
|
||||||
warn!("Fatal replay error in slot: {}, err: {:?}", slot, err);
|
warn!("Fatal replay error in slot: {}, err: {:?}", slot, err);
|
||||||
datapoint_error!(
|
datapoint_error!(
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
cluster_info::{compute_retransmit_peers, ClusterInfo, DATA_PLANE_FANOUT},
|
cluster_info::{compute_retransmit_peers, ClusterInfo, DATA_PLANE_FANOUT},
|
||||||
packet::Packets,
|
packet::Packets,
|
||||||
partition_cfg::PartitionCfg,
|
|
||||||
repair_service::RepairStrategy,
|
repair_service::RepairStrategy,
|
||||||
result::{Error, Result},
|
result::{Error, Result},
|
||||||
streamer::PacketReceiver,
|
streamer::PacketReceiver,
|
||||||
@ -22,7 +21,7 @@ use solana_sdk::epoch_schedule::EpochSchedule;
|
|||||||
use std::{
|
use std::{
|
||||||
cmp,
|
cmp,
|
||||||
net::UdpSocket,
|
net::UdpSocket,
|
||||||
sync::atomic::AtomicBool,
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
sync::mpsc::channel,
|
sync::mpsc::channel,
|
||||||
sync::mpsc::RecvTimeoutError,
|
sync::mpsc::RecvTimeoutError,
|
||||||
sync::Mutex,
|
sync::Mutex,
|
||||||
@ -213,7 +212,7 @@ impl RetransmitStage {
|
|||||||
exit: &Arc<AtomicBool>,
|
exit: &Arc<AtomicBool>,
|
||||||
completed_slots_receiver: CompletedSlotsReceiver,
|
completed_slots_receiver: CompletedSlotsReceiver,
|
||||||
epoch_schedule: EpochSchedule,
|
epoch_schedule: EpochSchedule,
|
||||||
cfg: Option<PartitionCfg>,
|
cfg: Option<Arc<AtomicBool>>,
|
||||||
shred_version: u16,
|
shred_version: u16,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (retransmit_sender, retransmit_receiver) = channel();
|
let (retransmit_sender, retransmit_receiver) = channel();
|
||||||
@ -245,7 +244,7 @@ impl RetransmitStage {
|
|||||||
move |id, shred, working_bank, last_root| {
|
move |id, shred, working_bank, last_root| {
|
||||||
let is_connected = cfg
|
let is_connected = cfg
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|x| x.is_connected(&working_bank, &leader_schedule_cache, shred))
|
.map(|x| x.load(Ordering::Relaxed))
|
||||||
.unwrap_or(true);
|
.unwrap_or(true);
|
||||||
let rv = should_retransmit_and_persist(
|
let rv = should_retransmit_and_persist(
|
||||||
shred,
|
shred,
|
||||||
|
@ -45,21 +45,12 @@ fn new_response<T>(bank: &Bank, value: T) -> RpcResponse<T> {
|
|||||||
Ok(Response { context, value })
|
Ok(Response { context, value })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct JsonRpcConfig {
|
pub struct JsonRpcConfig {
|
||||||
pub enable_validator_exit: bool, // Enable the 'validatorExit' command
|
pub enable_validator_exit: bool, // Enable the 'validatorExit' command
|
||||||
pub faucet_addr: Option<SocketAddr>,
|
pub faucet_addr: Option<SocketAddr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for JsonRpcConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
enable_validator_exit: false,
|
|
||||||
faucet_addr: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct JsonRpcRequestProcessor {
|
pub struct JsonRpcRequestProcessor {
|
||||||
bank_forks: Arc<RwLock<BankForks>>,
|
bank_forks: Arc<RwLock<BankForks>>,
|
||||||
@ -383,7 +374,11 @@ impl JsonRpcRequestProcessor {
|
|||||||
let stakes = HashMap::new();
|
let stakes = HashMap::new();
|
||||||
let stakes = bank.epoch_vote_accounts(epoch).unwrap_or(&stakes);
|
let stakes = bank.epoch_vote_accounts(epoch).unwrap_or(&stakes);
|
||||||
|
|
||||||
Ok(self.blockstore.get_block_time(slot, slot_duration, stakes))
|
Ok(self
|
||||||
|
.blockstore
|
||||||
|
.get_block_time(slot, slot_duration, stakes)
|
||||||
|
.ok()
|
||||||
|
.unwrap_or(None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,11 +719,14 @@ impl RpcSol for RpcSolImpl {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let shred_version = cluster_info.my_data().shred_version;
|
||||||
Ok(cluster_info
|
Ok(cluster_info
|
||||||
.all_peers()
|
.all_peers()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(contact_info, _)| {
|
.filter_map(|(contact_info, _)| {
|
||||||
if ContactInfo::is_valid_address(&contact_info.gossip) {
|
if shred_version == contact_info.shred_version
|
||||||
|
&& ContactInfo::is_valid_address(&contact_info.gossip)
|
||||||
|
{
|
||||||
Some(RpcContactInfo {
|
Some(RpcContactInfo {
|
||||||
pubkey: contact_info.id.to_string(),
|
pubkey: contact_info.id.to_string(),
|
||||||
gossip: Some(contact_info.gossip),
|
gossip: Some(contact_info.gossip),
|
||||||
@ -1117,6 +1115,7 @@ pub mod tests {
|
|||||||
fee_calculator::DEFAULT_BURN_PERCENT,
|
fee_calculator::DEFAULT_BURN_PERCENT,
|
||||||
hash::{hash, Hash},
|
hash::{hash, Hash},
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
|
rpc_port,
|
||||||
signature::{Keypair, KeypairUtil},
|
signature::{Keypair, KeypairUtil},
|
||||||
system_transaction,
|
system_transaction,
|
||||||
transaction::TransactionError,
|
transaction::TransactionError,
|
||||||
@ -1355,8 +1354,9 @@ pub mod tests {
|
|||||||
.expect("actual response deserialization");
|
.expect("actual response deserialization");
|
||||||
|
|
||||||
let expected = format!(
|
let expected = format!(
|
||||||
r#"{{"jsonrpc":"2.0","result":[{{"pubkey": "{}", "gossip": "127.0.0.1:1235", "tpu": "127.0.0.1:1234", "rpc": "127.0.0.1:8899"}}],"id":1}}"#,
|
r#"{{"jsonrpc":"2.0","result":[{{"pubkey": "{}", "gossip": "127.0.0.1:1235", "tpu": "127.0.0.1:1234", "rpc": "127.0.0.1:{}"}}],"id":1}}"#,
|
||||||
leader_pubkey,
|
leader_pubkey,
|
||||||
|
rpc_port::DEFAULT_RPC_PORT
|
||||||
);
|
);
|
||||||
|
|
||||||
let expected: Response =
|
let expected: Response =
|
||||||
|
@ -131,6 +131,7 @@ impl JsonRpcService {
|
|||||||
.cors(DomainsValidation::AllowOnly(vec![
|
.cors(DomainsValidation::AllowOnly(vec![
|
||||||
AccessControlAllowOrigin::Any,
|
AccessControlAllowOrigin::Any,
|
||||||
]))
|
]))
|
||||||
|
.cors_max_age(86400)
|
||||||
.request_middleware(RpcRequestMiddleware::new(ledger_path))
|
.request_middleware(RpcRequestMiddleware::new(ledger_path))
|
||||||
.start_http(&rpc_addr);
|
.start_http(&rpc_addr);
|
||||||
if let Err(e) = server {
|
if let Err(e) = server {
|
||||||
|
@ -6,7 +6,6 @@ use crate::{
|
|||||||
cluster_info::ClusterInfo,
|
cluster_info::ClusterInfo,
|
||||||
commitment::BlockCommitmentCache,
|
commitment::BlockCommitmentCache,
|
||||||
ledger_cleanup_service::LedgerCleanupService,
|
ledger_cleanup_service::LedgerCleanupService,
|
||||||
partition_cfg::PartitionCfg,
|
|
||||||
poh_recorder::PohRecorder,
|
poh_recorder::PohRecorder,
|
||||||
replay_stage::{ReplayStage, ReplayStageConfig},
|
replay_stage::{ReplayStage, ReplayStageConfig},
|
||||||
retransmit_stage::RetransmitStage,
|
retransmit_stage::RetransmitStage,
|
||||||
@ -84,7 +83,7 @@ impl Tvu {
|
|||||||
completed_slots_receiver: CompletedSlotsReceiver,
|
completed_slots_receiver: CompletedSlotsReceiver,
|
||||||
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
||||||
sigverify_disabled: bool,
|
sigverify_disabled: bool,
|
||||||
cfg: Option<PartitionCfg>,
|
cfg: Option<Arc<AtomicBool>>,
|
||||||
shred_version: u16,
|
shred_version: u16,
|
||||||
transaction_status_sender: Option<TransactionStatusSender>,
|
transaction_status_sender: Option<TransactionStatusSender>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -6,7 +6,6 @@ use crate::{
|
|||||||
commitment::BlockCommitmentCache,
|
commitment::BlockCommitmentCache,
|
||||||
contact_info::ContactInfo,
|
contact_info::ContactInfo,
|
||||||
gossip_service::{discover_cluster, GossipService},
|
gossip_service::{discover_cluster, GossipService},
|
||||||
partition_cfg::PartitionCfg,
|
|
||||||
poh_recorder::PohRecorder,
|
poh_recorder::PohRecorder,
|
||||||
poh_service::PohService,
|
poh_service::PohService,
|
||||||
rpc::JsonRpcConfig,
|
rpc::JsonRpcConfig,
|
||||||
@ -57,16 +56,18 @@ pub struct ValidatorConfig {
|
|||||||
pub dev_sigverify_disabled: bool,
|
pub dev_sigverify_disabled: bool,
|
||||||
pub dev_halt_at_slot: Option<Slot>,
|
pub dev_halt_at_slot: Option<Slot>,
|
||||||
pub expected_genesis_hash: Option<Hash>,
|
pub expected_genesis_hash: Option<Hash>,
|
||||||
|
pub expected_shred_version: Option<u16>,
|
||||||
pub voting_disabled: bool,
|
pub voting_disabled: bool,
|
||||||
pub transaction_status_service_disabled: bool,
|
pub transaction_status_service_disabled: bool,
|
||||||
pub blockstream_unix_socket: Option<PathBuf>,
|
pub blockstream_unix_socket: Option<PathBuf>,
|
||||||
pub storage_slots_per_turn: u64,
|
pub storage_slots_per_turn: u64,
|
||||||
pub account_paths: Vec<PathBuf>,
|
pub account_paths: Vec<PathBuf>,
|
||||||
pub rpc_config: JsonRpcConfig,
|
pub rpc_config: JsonRpcConfig,
|
||||||
|
pub rpc_ports: Option<(u16, u16)>, // (API, PubSub)
|
||||||
pub snapshot_config: Option<SnapshotConfig>,
|
pub snapshot_config: Option<SnapshotConfig>,
|
||||||
pub max_ledger_slots: Option<u64>,
|
pub max_ledger_slots: Option<u64>,
|
||||||
pub broadcast_stage_type: BroadcastStageType,
|
pub broadcast_stage_type: BroadcastStageType,
|
||||||
pub partition_cfg: Option<PartitionCfg>,
|
pub enable_partition: Option<Arc<AtomicBool>>,
|
||||||
pub fixed_leader_schedule: Option<FixedSchedule>,
|
pub fixed_leader_schedule: Option<FixedSchedule>,
|
||||||
pub wait_for_supermajority: bool,
|
pub wait_for_supermajority: bool,
|
||||||
pub new_hard_forks: Option<Vec<Slot>>,
|
pub new_hard_forks: Option<Vec<Slot>>,
|
||||||
@ -78,6 +79,7 @@ impl Default for ValidatorConfig {
|
|||||||
dev_sigverify_disabled: false,
|
dev_sigverify_disabled: false,
|
||||||
dev_halt_at_slot: None,
|
dev_halt_at_slot: None,
|
||||||
expected_genesis_hash: None,
|
expected_genesis_hash: None,
|
||||||
|
expected_shred_version: None,
|
||||||
voting_disabled: false,
|
voting_disabled: false,
|
||||||
transaction_status_service_disabled: false,
|
transaction_status_service_disabled: false,
|
||||||
blockstream_unix_socket: None,
|
blockstream_unix_socket: None,
|
||||||
@ -85,9 +87,10 @@ impl Default for ValidatorConfig {
|
|||||||
max_ledger_slots: None,
|
max_ledger_slots: None,
|
||||||
account_paths: Vec::new(),
|
account_paths: Vec::new(),
|
||||||
rpc_config: JsonRpcConfig::default(),
|
rpc_config: JsonRpcConfig::default(),
|
||||||
|
rpc_ports: None,
|
||||||
snapshot_config: None,
|
snapshot_config: None,
|
||||||
broadcast_stage_type: BroadcastStageType::Standard,
|
broadcast_stage_type: BroadcastStageType::Standard,
|
||||||
partition_cfg: None,
|
enable_partition: None,
|
||||||
fixed_leader_schedule: None,
|
fixed_leader_schedule: None,
|
||||||
wait_for_supermajority: false,
|
wait_for_supermajority: false,
|
||||||
new_hard_forks: None,
|
new_hard_forks: None,
|
||||||
@ -115,8 +118,7 @@ impl ValidatorExit {
|
|||||||
pub struct Validator {
|
pub struct Validator {
|
||||||
pub id: Pubkey,
|
pub id: Pubkey,
|
||||||
validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
|
validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
|
||||||
rpc_service: Option<JsonRpcService>,
|
rpc_service: Option<(JsonRpcService, PubSubService)>,
|
||||||
rpc_pubsub_service: Option<PubSubService>,
|
|
||||||
transaction_status_service: Option<TransactionStatusService>,
|
transaction_status_service: Option<TransactionStatusService>,
|
||||||
gossip_service: GossipService,
|
gossip_service: GossipService,
|
||||||
poh_recorder: Arc<Mutex<PohRecorder>>,
|
poh_recorder: Arc<Mutex<PohRecorder>>,
|
||||||
@ -172,6 +174,15 @@ impl Validator {
|
|||||||
let exit = Arc::new(AtomicBool::new(false));
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
let bank_info = &bank_forks_info[0];
|
let bank_info = &bank_forks_info[0];
|
||||||
let bank = bank_forks[bank_info.bank_slot].clone();
|
let bank = bank_forks[bank_info.bank_slot].clone();
|
||||||
|
|
||||||
|
info!("Starting validator from slot {}", bank.slot());
|
||||||
|
{
|
||||||
|
let hard_forks: Vec<_> = bank.hard_forks().read().unwrap().iter().copied().collect();
|
||||||
|
if !hard_forks.is_empty() {
|
||||||
|
info!("Hard forks: {:?}", hard_forks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let bank_forks = Arc::new(RwLock::new(bank_forks));
|
let bank_forks = Arc::new(RwLock::new(bank_forks));
|
||||||
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
|
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
|
||||||
|
|
||||||
@ -185,6 +196,16 @@ impl Validator {
|
|||||||
compute_shred_version(&genesis_hash, &bank.hard_forks().read().unwrap());
|
compute_shred_version(&genesis_hash, &bank.hard_forks().read().unwrap());
|
||||||
Self::print_node_info(&node);
|
Self::print_node_info(&node);
|
||||||
|
|
||||||
|
if let Some(expected_shred_version) = config.expected_shred_version {
|
||||||
|
if expected_shred_version != node.info.shred_version {
|
||||||
|
error!(
|
||||||
|
"shred version mismatch: expected {}",
|
||||||
|
expected_shred_version
|
||||||
|
);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let cluster_info = Arc::new(RwLock::new(ClusterInfo::new(
|
let cluster_info = Arc::new(RwLock::new(ClusterInfo::new(
|
||||||
node.info.clone(),
|
node.info.clone(),
|
||||||
keypair.clone(),
|
keypair.clone(),
|
||||||
@ -198,11 +219,19 @@ impl Validator {
|
|||||||
|
|
||||||
let blockstore = Arc::new(blockstore);
|
let blockstore = Arc::new(blockstore);
|
||||||
|
|
||||||
let rpc_service = if node.info.rpc.port() == 0 {
|
let subscriptions = Arc::new(RpcSubscriptions::new(&exit));
|
||||||
None
|
|
||||||
|
let rpc_service = config.rpc_ports.map(|(rpc_port, rpc_pubsub_port)| {
|
||||||
|
if ContactInfo::is_valid_address(&node.info.rpc) {
|
||||||
|
assert!(ContactInfo::is_valid_address(&node.info.rpc_pubsub));
|
||||||
|
assert_eq!(rpc_port, node.info.rpc.port());
|
||||||
|
assert_eq!(rpc_pubsub_port, node.info.rpc_pubsub.port());
|
||||||
} else {
|
} else {
|
||||||
Some(JsonRpcService::new(
|
assert!(!ContactInfo::is_valid_address(&node.info.rpc_pubsub));
|
||||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), node.info.rpc.port()),
|
}
|
||||||
|
(
|
||||||
|
JsonRpcService::new(
|
||||||
|
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), rpc_port),
|
||||||
config.rpc_config.clone(),
|
config.rpc_config.clone(),
|
||||||
bank_forks.clone(),
|
bank_forks.clone(),
|
||||||
block_commitment_cache.clone(),
|
block_commitment_cache.clone(),
|
||||||
@ -212,22 +241,14 @@ impl Validator {
|
|||||||
ledger_path,
|
ledger_path,
|
||||||
storage_state.clone(),
|
storage_state.clone(),
|
||||||
validator_exit.clone(),
|
validator_exit.clone(),
|
||||||
))
|
|
||||||
};
|
|
||||||
|
|
||||||
let subscriptions = Arc::new(RpcSubscriptions::new(&exit));
|
|
||||||
let rpc_pubsub_service = if node.info.rpc_pubsub.port() == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(PubSubService::new(
|
|
||||||
&subscriptions,
|
|
||||||
SocketAddr::new(
|
|
||||||
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
|
|
||||||
node.info.rpc_pubsub.port(),
|
|
||||||
),
|
),
|
||||||
|
PubSubService::new(
|
||||||
|
&subscriptions,
|
||||||
|
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), rpc_pubsub_port),
|
||||||
&exit,
|
&exit,
|
||||||
))
|
),
|
||||||
};
|
)
|
||||||
|
});
|
||||||
|
|
||||||
let (transaction_status_sender, transaction_status_service) =
|
let (transaction_status_sender, transaction_status_service) =
|
||||||
if rpc_service.is_some() && !config.transaction_status_service_disabled {
|
if rpc_service.is_some() && !config.transaction_status_service_disabled {
|
||||||
@ -296,23 +317,28 @@ impl Validator {
|
|||||||
.set_entrypoint(entrypoint_info.clone());
|
.set_entrypoint(entrypoint_info.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.wait_for_supermajority {
|
wait_for_supermajority(config, &bank, &cluster_info);
|
||||||
info!(
|
|
||||||
"Waiting for more than 75% of activated stake at slot {} to be in gossip...",
|
let voting_keypair = if config.voting_disabled {
|
||||||
bank.slot()
|
None
|
||||||
|
} else {
|
||||||
|
Some(voting_keypair.clone())
|
||||||
|
};
|
||||||
|
|
||||||
|
let poh_service = PohService::new(poh_recorder.clone(), &poh_config, &exit);
|
||||||
|
assert_eq!(
|
||||||
|
blockstore.new_shreds_signals.len(),
|
||||||
|
1,
|
||||||
|
"New shred signal for the TVU should be the same as the clear bank signal."
|
||||||
);
|
);
|
||||||
loop {
|
|
||||||
let gossip_stake_percent = get_stake_percent_in_gossip(&bank, &cluster_info);
|
|
||||||
|
|
||||||
info!("{}% of activated stake in gossip", gossip_stake_percent,);
|
let tvu = Tvu::new(
|
||||||
if gossip_stake_percent > 75 {
|
vote_account,
|
||||||
break;
|
voting_keypair,
|
||||||
}
|
storage_keypair,
|
||||||
sleep(Duration::new(1, 0));
|
&bank_forks,
|
||||||
}
|
&cluster_info,
|
||||||
}
|
Sockets {
|
||||||
|
|
||||||
let sockets = Sockets {
|
|
||||||
repair: node
|
repair: node
|
||||||
.sockets
|
.sockets
|
||||||
.repair
|
.repair
|
||||||
@ -336,28 +362,7 @@ impl Validator {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.try_clone().expect("Failed to clone TVU forwards Sockets"))
|
.map(|s| s.try_clone().expect("Failed to clone TVU forwards Sockets"))
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
},
|
||||||
|
|
||||||
let voting_keypair = if config.voting_disabled {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(voting_keypair.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
let poh_service = PohService::new(poh_recorder.clone(), &poh_config, &exit);
|
|
||||||
assert_eq!(
|
|
||||||
blockstore.new_shreds_signals.len(),
|
|
||||||
1,
|
|
||||||
"New shred signal for the TVU should be the same as the clear bank signal."
|
|
||||||
);
|
|
||||||
|
|
||||||
let tvu = Tvu::new(
|
|
||||||
vote_account,
|
|
||||||
voting_keypair,
|
|
||||||
storage_keypair,
|
|
||||||
&bank_forks,
|
|
||||||
&cluster_info,
|
|
||||||
sockets,
|
|
||||||
blockstore.clone(),
|
blockstore.clone(),
|
||||||
&storage_state,
|
&storage_state,
|
||||||
config.blockstream_unix_socket.as_ref(),
|
config.blockstream_unix_socket.as_ref(),
|
||||||
@ -370,7 +375,7 @@ impl Validator {
|
|||||||
completed_slots_receiver,
|
completed_slots_receiver,
|
||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
config.dev_sigverify_disabled,
|
config.dev_sigverify_disabled,
|
||||||
config.partition_cfg.clone(),
|
config.enable_partition.clone(),
|
||||||
node.info.shred_version,
|
node.info.shred_version,
|
||||||
transaction_status_sender.clone(),
|
transaction_status_sender.clone(),
|
||||||
);
|
);
|
||||||
@ -399,7 +404,6 @@ impl Validator {
|
|||||||
id,
|
id,
|
||||||
gossip_service,
|
gossip_service,
|
||||||
rpc_service,
|
rpc_service,
|
||||||
rpc_pubsub_service,
|
|
||||||
transaction_status_service,
|
transaction_status_service,
|
||||||
tpu,
|
tpu,
|
||||||
tvu,
|
tvu,
|
||||||
@ -450,10 +454,8 @@ impl Validator {
|
|||||||
pub fn join(self) -> Result<()> {
|
pub fn join(self) -> Result<()> {
|
||||||
self.poh_service.join()?;
|
self.poh_service.join()?;
|
||||||
drop(self.poh_recorder);
|
drop(self.poh_recorder);
|
||||||
if let Some(rpc_service) = self.rpc_service {
|
if let Some((rpc_service, rpc_pubsub_service)) = self.rpc_service {
|
||||||
rpc_service.join()?;
|
rpc_service.join()?;
|
||||||
}
|
|
||||||
if let Some(rpc_pubsub_service) = self.rpc_pubsub_service {
|
|
||||||
rpc_pubsub_service.join()?;
|
rpc_pubsub_service.join()?;
|
||||||
}
|
}
|
||||||
if let Some(transaction_status_service) = self.transaction_status_service {
|
if let Some(transaction_status_service) = self.transaction_status_service {
|
||||||
@ -475,7 +477,7 @@ fn compute_shred_version(genesis_hash: &Hash, hard_forks: &HardForks) -> u16 {
|
|||||||
let mut hash = *genesis_hash;
|
let mut hash = *genesis_hash;
|
||||||
for (slot, count) in hard_forks.iter() {
|
for (slot, count) in hard_forks.iter() {
|
||||||
let mut buf = [0u8; 16];
|
let mut buf = [0u8; 16];
|
||||||
LittleEndian::write_u64(&mut buf[..7], *slot);
|
LittleEndian::write_u64(&mut buf[..8], *slot);
|
||||||
LittleEndian::write_u64(&mut buf[8..], *count as u64);
|
LittleEndian::write_u64(&mut buf[8..], *count as u64);
|
||||||
hash = extend_and_hash(&hash, &buf);
|
hash = extend_and_hash(&hash, &buf);
|
||||||
}
|
}
|
||||||
@ -554,6 +556,30 @@ fn new_banks_from_blockstore(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wait_for_supermajority(
|
||||||
|
config: &ValidatorConfig,
|
||||||
|
bank: &Arc<Bank>,
|
||||||
|
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
||||||
|
) {
|
||||||
|
if !config.wait_for_supermajority {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Waiting for more than 75% of activated stake at slot {} to be in gossip...",
|
||||||
|
bank.slot()
|
||||||
|
);
|
||||||
|
loop {
|
||||||
|
let gossip_stake_percent = get_stake_percent_in_gossip(&bank, &cluster_info);
|
||||||
|
|
||||||
|
info!("{}% of activated stake in gossip", gossip_stake_percent,);
|
||||||
|
if gossip_stake_percent > 75 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sleep(Duration::new(1, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_validator_for_tests() -> (Validator, ContactInfo, Keypair, PathBuf) {
|
pub fn new_validator_for_tests() -> (Validator, ContactInfo, Keypair, PathBuf) {
|
||||||
use crate::genesis_utils::{create_genesis_config_with_leader, GenesisConfigInfo};
|
use crate::genesis_utils::{create_genesis_config_with_leader, GenesisConfigInfo};
|
||||||
|
|
||||||
@ -577,8 +603,11 @@ pub fn new_validator_for_tests() -> (Validator, ContactInfo, Keypair, PathBuf) {
|
|||||||
|
|
||||||
let leader_voting_keypair = Arc::new(voting_keypair);
|
let leader_voting_keypair = Arc::new(voting_keypair);
|
||||||
let storage_keypair = Arc::new(Keypair::new());
|
let storage_keypair = Arc::new(Keypair::new());
|
||||||
let mut config = ValidatorConfig::default();
|
let config = ValidatorConfig {
|
||||||
config.transaction_status_service_disabled = true;
|
transaction_status_service_disabled: true,
|
||||||
|
rpc_ports: Some((node.info.rpc.port(), node.info.rpc_pubsub.port())),
|
||||||
|
..ValidatorConfig::default()
|
||||||
|
};
|
||||||
let node = Validator::new(
|
let node = Validator::new(
|
||||||
node,
|
node,
|
||||||
&node_keypair,
|
&node_keypair,
|
||||||
@ -654,6 +683,16 @@ mod tests {
|
|||||||
use crate::genesis_utils::create_genesis_config_with_leader;
|
use crate::genesis_utils::create_genesis_config_with_leader;
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_compute_shred_version() {
|
||||||
|
let mut hard_forks = HardForks::default();
|
||||||
|
assert_eq!(compute_shred_version(&Hash::default(), &hard_forks), 1);
|
||||||
|
hard_forks.register(1);
|
||||||
|
assert_eq!(compute_shred_version(&Hash::default(), &hard_forks), 55551);
|
||||||
|
hard_forks.register(1);
|
||||||
|
assert_eq!(compute_shred_version(&Hash::default(), &hard_forks), 46353);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn validator_exit() {
|
fn validator_exit() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
@ -669,8 +708,14 @@ mod tests {
|
|||||||
|
|
||||||
let voting_keypair = Arc::new(Keypair::new());
|
let voting_keypair = Arc::new(Keypair::new());
|
||||||
let storage_keypair = Arc::new(Keypair::new());
|
let storage_keypair = Arc::new(Keypair::new());
|
||||||
let mut config = ValidatorConfig::default();
|
let config = ValidatorConfig {
|
||||||
config.transaction_status_service_disabled = true;
|
transaction_status_service_disabled: true,
|
||||||
|
rpc_ports: Some((
|
||||||
|
validator_node.info.rpc.port(),
|
||||||
|
validator_node.info.rpc_pubsub.port(),
|
||||||
|
)),
|
||||||
|
..ValidatorConfig::default()
|
||||||
|
};
|
||||||
let validator = Validator::new(
|
let validator = Validator::new(
|
||||||
validator_node,
|
validator_node,
|
||||||
&Arc::new(validator_keypair),
|
&Arc::new(validator_keypair),
|
||||||
@ -703,8 +748,14 @@ mod tests {
|
|||||||
ledger_paths.push(validator_ledger_path.clone());
|
ledger_paths.push(validator_ledger_path.clone());
|
||||||
let voting_keypair = Arc::new(Keypair::new());
|
let voting_keypair = Arc::new(Keypair::new());
|
||||||
let storage_keypair = Arc::new(Keypair::new());
|
let storage_keypair = Arc::new(Keypair::new());
|
||||||
let mut config = ValidatorConfig::default();
|
let config = ValidatorConfig {
|
||||||
config.transaction_status_service_disabled = true;
|
transaction_status_service_disabled: true,
|
||||||
|
rpc_ports: Some((
|
||||||
|
validator_node.info.rpc.port(),
|
||||||
|
validator_node.info.rpc_pubsub.port(),
|
||||||
|
)),
|
||||||
|
..ValidatorConfig::default()
|
||||||
|
};
|
||||||
Validator::new(
|
Validator::new(
|
||||||
validator_node,
|
validator_node,
|
||||||
&Arc::new(validator_keypair),
|
&Arc::new(validator_keypair),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-crate-features"
|
name = "solana-crate-features"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Crate Features"
|
description = "Solana Crate Features"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-faucet"
|
name = "solana-faucet"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Faucet"
|
description = "Solana Faucet"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -19,10 +19,10 @@ clap = "2.33"
|
|||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-metrics = { path = "../metrics", version = "0.23.0" }
|
solana-metrics = { path = "../metrics", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
tokio = "0.1"
|
tokio = "0.1"
|
||||||
tokio-codec = "0.1"
|
tokio-codec = "0.1"
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-genesis-programs"
|
name = "solana-genesis-programs"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana genesis programs"
|
description = "Solana genesis programs"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -10,16 +10,16 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = { version = "0.4.8" }
|
log = { version = "0.4.8" }
|
||||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "0.23.0" }
|
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "0.23.1" }
|
||||||
solana-budget-program = { path = "../programs/budget", version = "0.23.0" }
|
solana-budget-program = { path = "../programs/budget", version = "0.23.1" }
|
||||||
solana-config-program = { path = "../programs/config", version = "0.23.0" }
|
solana-config-program = { path = "../programs/config", version = "0.23.1" }
|
||||||
solana-exchange-program = { path = "../programs/exchange", version = "0.23.0" }
|
solana-exchange-program = { path = "../programs/exchange", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../runtime", version = "0.23.0" }
|
solana-runtime = { path = "../runtime", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-stake-program = { path = "../programs/stake", version = "0.23.0" }
|
solana-stake-program = { path = "../programs/stake", version = "0.23.1" }
|
||||||
solana-storage-program = { path = "../programs/storage", version = "0.23.0" }
|
solana-storage-program = { path = "../programs/storage", version = "0.23.1" }
|
||||||
solana-vest-program = { path = "../programs/vest", version = "0.23.0" }
|
solana-vest-program = { path = "../programs/vest", version = "0.23.1" }
|
||||||
solana-vote-program = { path = "../programs/vote", version = "0.23.0" }
|
solana-vote-program = { path = "../programs/vote", version = "0.23.1" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["lib"]
|
crate-type = ["lib"]
|
||||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-genesis"
|
name = "solana-genesis"
|
||||||
description = "Blockchain, Rebuilt for Scale"
|
description = "Blockchain, Rebuilt for Scale"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -17,13 +17,13 @@ serde = "1.0.104"
|
|||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
serde_yaml = "0.8.11"
|
serde_yaml = "0.8.11"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-genesis-programs = { path = "../genesis-programs", version = "0.23.0" }
|
solana-genesis-programs = { path = "../genesis-programs", version = "0.23.1" }
|
||||||
solana-ledger = { path = "../ledger", version = "0.23.0" }
|
solana-ledger = { path = "../ledger", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-stake-program = { path = "../programs/stake", version = "0.23.0" }
|
solana-stake-program = { path = "../programs/stake", version = "0.23.1" }
|
||||||
solana-storage-program = { path = "../programs/storage", version = "0.23.0" }
|
solana-storage-program = { path = "../programs/storage", version = "0.23.1" }
|
||||||
solana-vote-program = { path = "../programs/vote", version = "0.23.0" }
|
solana-vote-program = { path = "../programs/vote", version = "0.23.1" }
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@ -55,7 +55,7 @@ pub const BATCH_FOUR_STAKER_INFOS: &[StakerInfo] = &[
|
|||||||
},
|
},
|
||||||
StakerInfo {
|
StakerInfo {
|
||||||
name: "unbecoming silver",
|
name: "unbecoming silver",
|
||||||
staker: "42yapY7Vrs5jqht9TCKZsPoyb4vDFYcPfRkqAP85NSAQ",
|
staker: "4AcoZa1P8fF5XK21RJsiuMRZPEScbbWNc75oakRFHiBz",
|
||||||
lamports: 28_800 * LAMPORTS_PER_SOL,
|
lamports: 28_800 * LAMPORTS_PER_SOL,
|
||||||
},
|
},
|
||||||
StakerInfo {
|
StakerInfo {
|
||||||
@ -220,7 +220,6 @@ pub const VALIDATOR_PUBKEYS: &[&str] = &[
|
|||||||
"7v5DXDvYzkgTdFYXYB12ZLKD6z8QfzR53N9hg6XgEQJE", // Cryptium Labs GmbH
|
"7v5DXDvYzkgTdFYXYB12ZLKD6z8QfzR53N9hg6XgEQJE", // Cryptium Labs GmbH
|
||||||
"8LSwP5qYbmuUfKLGwi8XaKJnai9HyZAJTnBovyWebRfd", //
|
"8LSwP5qYbmuUfKLGwi8XaKJnai9HyZAJTnBovyWebRfd", //
|
||||||
"8UPb8LMWyoJJC9Aeq9QmTzKZKV2ssov739bTJ14M4ws1", //
|
"8UPb8LMWyoJJC9Aeq9QmTzKZKV2ssov739bTJ14M4ws1", //
|
||||||
"8oRw7qpj6XgLGXYCDuNoTMCqoJnDd6A8LTpNyqApSfkA", //
|
|
||||||
"8wFK4fCAuDoAH1fsgou9yKZPqDMFtJUVoDdkZAAMuhyA", // LunaNova Technologies Ltd
|
"8wFK4fCAuDoAH1fsgou9yKZPqDMFtJUVoDdkZAAMuhyA", // LunaNova Technologies Ltd
|
||||||
"94eWgQm2k8BXKEWbJP2eScHZeKopXpqkuoVrCofQWBhW", // Node A-Team
|
"94eWgQm2k8BXKEWbJP2eScHZeKopXpqkuoVrCofQWBhW", // Node A-Team
|
||||||
"9J8WcnXxo3ArgEwktfk9tsrf4Rp8h5uPUgnQbQHLvtkd", // moonli.me
|
"9J8WcnXxo3ArgEwktfk9tsrf4Rp8h5uPUgnQbQHLvtkd", // moonli.me
|
||||||
|
@ -3,19 +3,19 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-gossip"
|
name = "solana-gossip"
|
||||||
description = "Blockchain, Rebuilt for Scale"
|
description = "Blockchain, Rebuilt for Scale"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-core = { path = "../core", version = "0.23.0" }
|
solana-core = { path = "../core", version = "0.23.1" }
|
||||||
solana-client = { path = "../client", version = "0.23.0" }
|
solana-client = { path = "../client", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
|
solana-net-utils = { path = "../net-utils", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-install"
|
name = "solana-install"
|
||||||
description = "The solana cluster software installer"
|
description = "The solana cluster software installer"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -26,11 +26,11 @@ reqwest = { version = "0.10.1", default-features = false, features = ["blocking"
|
|||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_yaml = "0.8.11"
|
serde_yaml = "0.8.11"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-client = { path = "../client", version = "0.23.0" }
|
solana-client = { path = "../client", version = "0.23.1" }
|
||||||
solana-config-program = { path = "../programs/config", version = "0.23.0" }
|
solana-config-program = { path = "../programs/config", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
tar = "0.4.26"
|
tar = "0.4.26"
|
||||||
tempdir = "0.3.7"
|
tempdir = "0.3.7"
|
||||||
url = "2.1.1"
|
url = "2.1.1"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-keygen"
|
name = "solana-keygen"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana key generation utility"
|
description = "Solana key generation utility"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -14,8 +14,9 @@ clap = "2.33"
|
|||||||
dirs = "2.0.2"
|
dirs = "2.0.2"
|
||||||
num_cpus = "1.12.0"
|
num_cpus = "1.12.0"
|
||||||
rpassword = "4.0"
|
rpassword = "4.0"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-cli-config = { path = "../cli-config", version = "0.23.1" }
|
||||||
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
tiny-bip39 = "0.7.0"
|
tiny-bip39 = "0.7.0"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@ -8,6 +8,7 @@ use num_cpus;
|
|||||||
use solana_clap_utils::keypair::{
|
use solana_clap_utils::keypair::{
|
||||||
keypair_from_seed_phrase, prompt_passphrase, ASK_KEYWORD, SKIP_SEED_PHRASE_VALIDATION_ARG,
|
keypair_from_seed_phrase, prompt_passphrase, ASK_KEYWORD, SKIP_SEED_PHRASE_VALIDATION_ARG,
|
||||||
};
|
};
|
||||||
|
use solana_cli_config::config::{Config, CONFIG_FILE};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
pubkey::write_pubkey_file,
|
pubkey::write_pubkey_file,
|
||||||
signature::{
|
signature::{
|
||||||
@ -21,7 +22,7 @@ use std::{
|
|||||||
path::Path,
|
path::Path,
|
||||||
process::exit,
|
process::exit,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicU64, Ordering},
|
atomic::{AtomicBool, AtomicU64, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
},
|
},
|
||||||
thread,
|
thread,
|
||||||
@ -30,6 +31,12 @@ use std::{
|
|||||||
|
|
||||||
const NO_PASSPHRASE: &str = "";
|
const NO_PASSPHRASE: &str = "";
|
||||||
|
|
||||||
|
struct GrindMatch {
|
||||||
|
starts: String,
|
||||||
|
ends: String,
|
||||||
|
count: AtomicU64,
|
||||||
|
}
|
||||||
|
|
||||||
fn check_for_overwrite(outfile: &str, matches: &ArgMatches) {
|
fn check_for_overwrite(outfile: &str, matches: &ArgMatches) {
|
||||||
let force = matches.is_present("force");
|
let force = matches.is_present("force");
|
||||||
if !force && Path::new(outfile).exists() {
|
if !force && Path::new(outfile).exists() {
|
||||||
@ -38,23 +45,28 @@ fn check_for_overwrite(outfile: &str, matches: &ArgMatches) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_keypair_from_matches(matches: &ArgMatches) -> Result<Keypair, Box<dyn error::Error>> {
|
fn get_keypair_from_matches(
|
||||||
|
matches: &ArgMatches,
|
||||||
|
config: Config,
|
||||||
|
) -> Result<Keypair, Box<dyn error::Error>> {
|
||||||
let mut path = dirs::home_dir().expect("home directory");
|
let mut path = dirs::home_dir().expect("home directory");
|
||||||
let infile = if matches.is_present("infile") {
|
let keypair = if matches.is_present("keypair") {
|
||||||
matches.value_of("infile").unwrap()
|
matches.value_of("keypair").unwrap()
|
||||||
|
} else if config.keypair_path != "" {
|
||||||
|
&config.keypair_path
|
||||||
} else {
|
} else {
|
||||||
path.extend(&[".config", "solana", "id.json"]);
|
path.extend(&[".config", "solana", "id.json"]);
|
||||||
path.to_str().unwrap()
|
path.to_str().unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
if infile == "-" {
|
if keypair == "-" {
|
||||||
let mut stdin = std::io::stdin();
|
let mut stdin = std::io::stdin();
|
||||||
read_keypair(&mut stdin)
|
read_keypair(&mut stdin)
|
||||||
} else if infile == ASK_KEYWORD {
|
} else if keypair == ASK_KEYWORD {
|
||||||
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
|
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
|
||||||
keypair_from_seed_phrase("pubkey recovery", skip_validation, false)
|
keypair_from_seed_phrase("pubkey recovery", skip_validation, false)
|
||||||
} else {
|
} else {
|
||||||
read_keypair_file(infile)
|
read_keypair_file(keypair)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,28 +85,152 @@ fn output_keypair(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn grind_validator_starts_with(v: String) -> Result<(), String> {
|
||||||
|
if v.matches(':').count() != 1 || (v.starts_with(':') || v.ends_with(':')) {
|
||||||
|
return Err(String::from("Expected : between PREFIX and COUNT"));
|
||||||
|
}
|
||||||
|
let args: Vec<&str> = v.split(':').collect();
|
||||||
|
bs58::decode(&args[0])
|
||||||
|
.into_vec()
|
||||||
|
.map_err(|err| format!("{}: {:?}", args[0], err))?;
|
||||||
|
let count = args[1].parse::<u64>();
|
||||||
|
if count.is_err() || count.unwrap() == 0 {
|
||||||
|
return Err(String::from("Expected COUNT to be of type u64"));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grind_validator_ends_with(v: String) -> Result<(), String> {
|
||||||
|
if v.matches(':').count() != 1 || (v.starts_with(':') || v.ends_with(':')) {
|
||||||
|
return Err(String::from("Expected : between SUFFIX and COUNT"));
|
||||||
|
}
|
||||||
|
let args: Vec<&str> = v.split(':').collect();
|
||||||
|
bs58::decode(&args[0])
|
||||||
|
.into_vec()
|
||||||
|
.map_err(|err| format!("{}: {:?}", args[0], err))?;
|
||||||
|
let count = args[1].parse::<u64>();
|
||||||
|
if count.is_err() || count.unwrap() == 0 {
|
||||||
|
return Err(String::from("Expected COUNT to be of type u64"));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grind_validator_starts_and_ends_with(v: String) -> Result<(), String> {
|
||||||
|
if v.matches(':').count() != 2 || (v.starts_with(':') || v.ends_with(':')) {
|
||||||
|
return Err(String::from(
|
||||||
|
"Expected : between PREFIX and SUFFIX and COUNT",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let args: Vec<&str> = v.split(':').collect();
|
||||||
|
bs58::decode(&args[0])
|
||||||
|
.into_vec()
|
||||||
|
.map_err(|err| format!("{}: {:?}", args[0], err))?;
|
||||||
|
bs58::decode(&args[1])
|
||||||
|
.into_vec()
|
||||||
|
.map_err(|err| format!("{}: {:?}", args[1], err))?;
|
||||||
|
let count = args[2].parse::<u64>();
|
||||||
|
if count.is_err() || count.unwrap() == 0 {
|
||||||
|
return Err(String::from("Expected COUNT to be a u64"));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grind_print_info(grind_matches: &[GrindMatch]) {
|
||||||
|
println!("Searching with {} threads for:", num_cpus::get());
|
||||||
|
for gm in grind_matches {
|
||||||
|
let mut msg = Vec::<String>::new();
|
||||||
|
if gm.count.load(Ordering::Relaxed) > 1 {
|
||||||
|
msg.push("pubkeys".to_string());
|
||||||
|
msg.push("start".to_string());
|
||||||
|
msg.push("end".to_string());
|
||||||
|
} else {
|
||||||
|
msg.push("pubkey".to_string());
|
||||||
|
msg.push("starts".to_string());
|
||||||
|
msg.push("ends".to_string());
|
||||||
|
}
|
||||||
|
println!(
|
||||||
|
"\t{} {} that {} with '{}' and {} with '{}'",
|
||||||
|
gm.count.load(Ordering::Relaxed),
|
||||||
|
msg[0],
|
||||||
|
msg[1],
|
||||||
|
gm.starts,
|
||||||
|
msg[2],
|
||||||
|
gm.ends
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grind_parse_args(
|
||||||
|
starts_with_args: HashSet<String>,
|
||||||
|
ends_with_args: HashSet<String>,
|
||||||
|
starts_and_ends_with_args: HashSet<String>,
|
||||||
|
) -> Vec<GrindMatch> {
|
||||||
|
let mut grind_matches = Vec::<GrindMatch>::new();
|
||||||
|
for sw in starts_with_args {
|
||||||
|
let args: Vec<&str> = sw.split(':').collect();
|
||||||
|
grind_matches.push(GrindMatch {
|
||||||
|
starts: args[0].to_lowercase(),
|
||||||
|
ends: "".to_string(),
|
||||||
|
count: AtomicU64::new(args[1].parse::<u64>().unwrap()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for ew in ends_with_args {
|
||||||
|
let args: Vec<&str> = ew.split(':').collect();
|
||||||
|
grind_matches.push(GrindMatch {
|
||||||
|
starts: "".to_string(),
|
||||||
|
ends: args[0].to_lowercase(),
|
||||||
|
count: AtomicU64::new(args[1].parse::<u64>().unwrap()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for swew in starts_and_ends_with_args {
|
||||||
|
let args: Vec<&str> = swew.split(':').collect();
|
||||||
|
grind_matches.push(GrindMatch {
|
||||||
|
starts: args[0].to_lowercase(),
|
||||||
|
ends: args[1].to_lowercase(),
|
||||||
|
count: AtomicU64::new(args[2].parse::<u64>().unwrap()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
grind_print_info(&grind_matches);
|
||||||
|
grind_matches
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn error::Error>> {
|
fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
let matches = App::new(crate_name!())
|
let matches = App::new(crate_name!())
|
||||||
.about(crate_description!())
|
.about(crate_description!())
|
||||||
.version(solana_clap_utils::version!())
|
.version(solana_clap_utils::version!())
|
||||||
.setting(AppSettings::SubcommandRequiredElseHelp)
|
.setting(AppSettings::SubcommandRequiredElseHelp)
|
||||||
|
.arg({
|
||||||
|
let arg = Arg::with_name("config_file")
|
||||||
|
.short("C")
|
||||||
|
.long("config")
|
||||||
|
.value_name("PATH")
|
||||||
|
.takes_value(true)
|
||||||
|
.global(true)
|
||||||
|
.help("Configuration file to use");
|
||||||
|
if let Some(ref config_file) = *CONFIG_FILE {
|
||||||
|
arg.default_value(&config_file)
|
||||||
|
} else {
|
||||||
|
arg
|
||||||
|
}
|
||||||
|
})
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("verify")
|
SubCommand::with_name("verify")
|
||||||
.about("Verify a keypair can sign and verify a message.")
|
.about("Verify a keypair can sign and verify a message.")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("infile")
|
Arg::with_name("pubkey")
|
||||||
.index(1)
|
.index(1)
|
||||||
|
.value_name("BASE58_PUBKEY")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(true)
|
||||||
|
.help("Public key"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("keypair")
|
||||||
|
.index(2)
|
||||||
.value_name("PATH")
|
.value_name("PATH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Path to keypair file"),
|
.help("Path to keypair file"),
|
||||||
)
|
)
|
||||||
.arg(
|
|
||||||
Arg::with_name("pubkey")
|
|
||||||
.index(2)
|
|
||||||
.value_name("BASE58_PUBKEY")
|
|
||||||
.takes_value(true)
|
|
||||||
.help("Public key"),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("new")
|
SubCommand::with_name("new")
|
||||||
@ -148,33 +284,37 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("ignore_case")
|
Arg::with_name("ignore_case")
|
||||||
.long("ignore-case")
|
.long("ignore-case")
|
||||||
.help("Perform case insensitive matches"),
|
.help("Performs case insensitive matches"),
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("includes")
|
|
||||||
.long("includes")
|
|
||||||
.value_name("BASE58")
|
|
||||||
.takes_value(true)
|
|
||||||
.multiple(true)
|
|
||||||
.validator(|value| {
|
|
||||||
bs58::decode(&value).into_vec()
|
|
||||||
.map(|_| ())
|
|
||||||
.map_err(|err| format!("{}: {:?}", value, err))
|
|
||||||
})
|
|
||||||
.help("Save keypair if its public key includes this string\n(may be specified multiple times)"),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("starts_with")
|
Arg::with_name("starts_with")
|
||||||
.long("starts-with")
|
.long("starts-with")
|
||||||
.value_name("BASE58 PREFIX")
|
.value_name("PREFIX:COUNT")
|
||||||
|
.number_of_values(1)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.multiple(true)
|
.multiple(true)
|
||||||
.validator(|value| {
|
.validator(grind_validator_starts_with)
|
||||||
bs58::decode(&value).into_vec()
|
.help("Saves specified number of keypairs whos public key starts with the indicated prefix\nExample: --starts-with sol:4\nPREFIX type is Base58\nCOUNT type is u64"),
|
||||||
.map(|_| ())
|
)
|
||||||
.map_err(|err| format!("{}: {:?}", value, err))
|
.arg(
|
||||||
})
|
Arg::with_name("ends_with")
|
||||||
.help("Save keypair if its public key starts with this prefix\n(may be specified multiple times)"),
|
.long("ends-with")
|
||||||
|
.value_name("SUFFIX:COUNT")
|
||||||
|
.number_of_values(1)
|
||||||
|
.takes_value(true)
|
||||||
|
.multiple(true)
|
||||||
|
.validator(grind_validator_ends_with)
|
||||||
|
.help("Saves specified number of keypairs whos public key ends with the indicated suffix\nExample: --ends-with ana:4\nSUFFIX type is Base58\nCOUNT type is u64"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("starts_and_ends_with")
|
||||||
|
.long("starts-and-ends-with")
|
||||||
|
.value_name("PREFIX:SUFFIX:COUNT")
|
||||||
|
.number_of_values(1)
|
||||||
|
.takes_value(true)
|
||||||
|
.multiple(true)
|
||||||
|
.validator(grind_validator_starts_and_ends_with)
|
||||||
|
.help("Saves specified number of keypairs whos public key starts and ends with the indicated perfix and suffix\nExample: --starts-and-ends-with sol:ana:4\nPREFIX and SUFFIX type is Base58\nCOUNT type is u64"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
@ -182,7 +322,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
.about("Display the pubkey from a keypair file")
|
.about("Display the pubkey from a keypair file")
|
||||||
.setting(AppSettings::DisableVersion)
|
.setting(AppSettings::DisableVersion)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("infile")
|
Arg::with_name("keypair")
|
||||||
.index(1)
|
.index(1)
|
||||||
.value_name("PATH")
|
.value_name("PATH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
@ -234,10 +374,15 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
|
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
let config = if let Some(config_file) = matches.value_of("config_file") {
|
||||||
|
Config::load(config_file).unwrap_or_default()
|
||||||
|
} else {
|
||||||
|
Config::default()
|
||||||
|
};
|
||||||
|
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
("pubkey", Some(matches)) => {
|
("pubkey", Some(matches)) => {
|
||||||
let keypair = get_keypair_from_matches(matches)?;
|
let keypair = get_keypair_from_matches(matches, config)?;
|
||||||
|
|
||||||
if matches.is_present("outfile") {
|
if matches.is_present("outfile") {
|
||||||
let outfile = matches.value_of("outfile").unwrap();
|
let outfile = matches.value_of("outfile").unwrap();
|
||||||
@ -311,16 +456,8 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
}
|
}
|
||||||
("grind", Some(matches)) => {
|
("grind", Some(matches)) => {
|
||||||
let ignore_case = matches.is_present("ignore_case");
|
let ignore_case = matches.is_present("ignore_case");
|
||||||
let includes = if matches.is_present("includes") {
|
|
||||||
values_t_or_exit!(matches, "includes", String)
|
|
||||||
.into_iter()
|
|
||||||
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
HashSet::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
let starts_with = if matches.is_present("starts_with") {
|
let starts_with_args = if matches.is_present("starts_with") {
|
||||||
values_t_or_exit!(matches, "starts_with", String)
|
values_t_or_exit!(matches, "starts_with", String)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
||||||
@ -328,68 +465,101 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
} else {
|
} else {
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
};
|
};
|
||||||
|
let ends_with_args = if matches.is_present("ends_with") {
|
||||||
|
values_t_or_exit!(matches, "ends_with", String)
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
HashSet::new()
|
||||||
|
};
|
||||||
|
let starts_and_ends_with_args = if matches.is_present("starts_and_ends_with") {
|
||||||
|
values_t_or_exit!(matches, "starts_and_ends_with", String)
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
HashSet::new()
|
||||||
|
};
|
||||||
|
|
||||||
if includes.is_empty() && starts_with.is_empty() {
|
if starts_with_args.is_empty()
|
||||||
|
&& ends_with_args.is_empty()
|
||||||
|
&& starts_and_ends_with_args.is_empty()
|
||||||
|
{
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Error: No keypair search criteria provided (--includes or --starts-with)"
|
"Error: No keypair search criteria provided (--starts-with or --ends-with or --starts-and-ends-with)"
|
||||||
);
|
);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let grind_matches =
|
||||||
|
grind_parse_args(starts_with_args, ends_with_args, starts_and_ends_with_args);
|
||||||
|
|
||||||
|
let grind_matches_thread_safe = Arc::new(grind_matches);
|
||||||
let attempts = Arc::new(AtomicU64::new(1));
|
let attempts = Arc::new(AtomicU64::new(1));
|
||||||
let found = Arc::new(AtomicU64::new(0));
|
let found = Arc::new(AtomicU64::new(0));
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
let done = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
println!(
|
for _ in 0..num_cpus::get() {
|
||||||
"Searching with {} threads for a pubkey containing {:?} or starting with {:?}",
|
let done = done.clone();
|
||||||
num_cpus::get(),
|
|
||||||
includes,
|
|
||||||
starts_with
|
|
||||||
);
|
|
||||||
|
|
||||||
let _threads = (0..num_cpus::get())
|
|
||||||
.map(|_| {
|
|
||||||
let attempts = attempts.clone();
|
let attempts = attempts.clone();
|
||||||
let found = found.clone();
|
let found = found.clone();
|
||||||
let includes = includes.clone();
|
let grind_matches_thread_safe = grind_matches_thread_safe.clone();
|
||||||
let starts_with = starts_with.clone();
|
|
||||||
|
|
||||||
thread::spawn(move || loop {
|
let handle = thread::spawn(move || loop {
|
||||||
|
if done.load(Ordering::Relaxed) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
let attempts = attempts.fetch_add(1, Ordering::Relaxed);
|
let attempts = attempts.fetch_add(1, Ordering::Relaxed);
|
||||||
if attempts % 5_000_000 == 0 {
|
if attempts % 1_000_000 == 0 {
|
||||||
println!(
|
println!(
|
||||||
"Searched {} keypairs in {}s. {} matches found",
|
"Searched {} keypairs in {}s. {} matches found.",
|
||||||
attempts,
|
attempts,
|
||||||
start.elapsed().as_secs(),
|
start.elapsed().as_secs(),
|
||||||
found.load(Ordering::Relaxed),
|
found.load(Ordering::Relaxed),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let mut pubkey = bs58::encode(keypair.pubkey()).into_string();
|
let mut pubkey = bs58::encode(keypair.pubkey()).into_string();
|
||||||
|
|
||||||
if ignore_case {
|
if ignore_case {
|
||||||
pubkey = pubkey.to_lowercase();
|
pubkey = pubkey.to_lowercase();
|
||||||
}
|
}
|
||||||
|
let mut total_matches_found = 0;
|
||||||
if starts_with.iter().any(|s| pubkey.starts_with(s))
|
for i in 0..grind_matches_thread_safe.len() {
|
||||||
|| includes.iter().any(|s| pubkey.contains(s))
|
if grind_matches_thread_safe[i].count.load(Ordering::Relaxed) == 0 {
|
||||||
|
total_matches_found += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!grind_matches_thread_safe[i].starts.is_empty()
|
||||||
|
&& grind_matches_thread_safe[i].ends.is_empty()
|
||||||
|
&& pubkey.starts_with(&grind_matches_thread_safe[i].starts))
|
||||||
|
|| (grind_matches_thread_safe[i].starts.is_empty()
|
||||||
|
&& !grind_matches_thread_safe[i].ends.is_empty()
|
||||||
|
&& pubkey.ends_with(&grind_matches_thread_safe[i].ends))
|
||||||
|
|| (!grind_matches_thread_safe[i].starts.is_empty()
|
||||||
|
&& !grind_matches_thread_safe[i].ends.is_empty()
|
||||||
|
&& pubkey.starts_with(&grind_matches_thread_safe[i].starts)
|
||||||
|
&& pubkey.ends_with(&grind_matches_thread_safe[i].ends))
|
||||||
{
|
{
|
||||||
let found = found.fetch_add(1, Ordering::Relaxed);
|
let _found = found.fetch_add(1, Ordering::Relaxed);
|
||||||
output_keypair(
|
grind_matches_thread_safe[i]
|
||||||
&keypair,
|
.count
|
||||||
&format!("{}.json", keypair.pubkey()),
|
.fetch_sub(1, Ordering::Relaxed);
|
||||||
&format!("{}", found),
|
println!("Wrote keypair to {}", &format!("{}.json", keypair.pubkey()));
|
||||||
)
|
write_keypair_file(&keypair, &format!("{}.json", keypair.pubkey()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if total_matches_found == grind_matches_thread_safe.len() {
|
||||||
|
done.store(true, Ordering::Relaxed);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
})
|
handle.join().unwrap();
|
||||||
.collect::<Vec<_>>();
|
}
|
||||||
thread::park();
|
|
||||||
}
|
}
|
||||||
("verify", Some(matches)) => {
|
("verify", Some(matches)) => {
|
||||||
let keypair = get_keypair_from_matches(matches)?;
|
let keypair = get_keypair_from_matches(matches, config)?;
|
||||||
let test_data = b"test";
|
let test_data = b"test";
|
||||||
let signature = Signature::new(&keypair.sign(test_data).to_bytes());
|
let signature = Signature::new(&keypair.sign(test_data).to_bytes());
|
||||||
let pubkey_bs58 = matches.value_of("pubkey").unwrap();
|
let pubkey_bs58 = matches.value_of("pubkey").unwrap();
|
||||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-ledger-tool"
|
name = "solana-ledger-tool"
|
||||||
description = "Blockchain, Rebuilt for Scale"
|
description = "Blockchain, Rebuilt for Scale"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -16,12 +16,12 @@ serde = "1.0.104"
|
|||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
serde_yaml = "0.8.11"
|
serde_yaml = "0.8.11"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-ledger = { path = "../ledger", version = "0.23.0" }
|
solana-ledger = { path = "../ledger", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../runtime", version = "0.23.0" }
|
solana-runtime = { path = "../runtime", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-vote-program = { path = "../programs/vote", version = "0.23.0" }
|
solana-vote-program = { path = "../programs/vote", version = "0.23.1" }
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-ledger"
|
name = "solana-ledger"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana ledger"
|
description = "Solana ledger"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -29,19 +29,19 @@ reed-solomon-erasure = { package = "solana-reed-solomon-erasure", version = "4.0
|
|||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_bytes = "0.11.3"
|
serde_bytes = "0.11.3"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
solana-client = { path = "../client", version = "0.23.0" }
|
solana-client = { path = "../client", version = "0.23.1" }
|
||||||
solana-genesis-programs = { path = "../genesis-programs", version = "0.23.0" }
|
solana-genesis-programs = { path = "../genesis-programs", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-measure = { path = "../measure", version = "0.23.0" }
|
solana-measure = { path = "../measure", version = "0.23.1" }
|
||||||
solana-merkle-tree = { path = "../merkle-tree", version = "0.23.0" }
|
solana-merkle-tree = { path = "../merkle-tree", version = "0.23.1" }
|
||||||
solana-metrics = { path = "../metrics", version = "0.23.0" }
|
solana-metrics = { path = "../metrics", version = "0.23.1" }
|
||||||
solana-perf = { path = "../perf", version = "0.23.0" }
|
solana-perf = { path = "../perf", version = "0.23.1" }
|
||||||
ed25519-dalek = "1.0.0-pre.1"
|
ed25519-dalek = "1.0.0-pre.1"
|
||||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.23.0" }
|
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../runtime", version = "0.23.0" }
|
solana-runtime = { path = "../runtime", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-stake-program = { path = "../programs/stake", version = "0.23.0" }
|
solana-stake-program = { path = "../programs/stake", version = "0.23.1" }
|
||||||
solana-vote-program = { path = "../programs/vote", version = "0.23.0" }
|
solana-vote-program = { path = "../programs/vote", version = "0.23.1" }
|
||||||
sys-info = "0.5.8"
|
sys-info = "0.5.8"
|
||||||
symlink = "0.1.0"
|
symlink = "0.1.0"
|
||||||
tar = "0.4.26"
|
tar = "0.4.26"
|
||||||
@ -59,7 +59,7 @@ features = ["lz4"]
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_matches = "1.3.0"
|
assert_matches = "1.3.0"
|
||||||
matches = "0.1.6"
|
matches = "0.1.6"
|
||||||
solana-budget-program = { path = "../programs/budget", version = "0.23.0" }
|
solana-budget-program = { path = "../programs/budget", version = "0.23.1" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["lib"]
|
crate-type = ["lib"]
|
||||||
|
@ -90,6 +90,7 @@ pub struct Blockstore {
|
|||||||
insert_shreds_lock: Arc<Mutex<()>>,
|
insert_shreds_lock: Arc<Mutex<()>>,
|
||||||
pub new_shreds_signals: Vec<SyncSender<bool>>,
|
pub new_shreds_signals: Vec<SyncSender<bool>>,
|
||||||
pub completed_slots_senders: Vec<SyncSender<Vec<Slot>>>,
|
pub completed_slots_senders: Vec<SyncSender<Vec<Slot>>>,
|
||||||
|
pub lowest_cleanup_slot: Arc<RwLock<u64>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IndexMetaWorkingSetEntry {
|
pub struct IndexMetaWorkingSetEntry {
|
||||||
@ -207,7 +208,7 @@ impl Blockstore {
|
|||||||
|
|
||||||
measure.stop();
|
measure.stop();
|
||||||
info!("{:?} {}", blockstore_path, measure);
|
info!("{:?} {}", blockstore_path, measure);
|
||||||
Ok(Blockstore {
|
let blockstore = Blockstore {
|
||||||
db,
|
db,
|
||||||
meta_cf,
|
meta_cf,
|
||||||
dead_slots_cf,
|
dead_slots_cf,
|
||||||
@ -222,7 +223,9 @@ impl Blockstore {
|
|||||||
completed_slots_senders: vec![],
|
completed_slots_senders: vec![],
|
||||||
insert_shreds_lock: Arc::new(Mutex::new(())),
|
insert_shreds_lock: Arc::new(Mutex::new(())),
|
||||||
last_root,
|
last_root,
|
||||||
})
|
lowest_cleanup_slot: Arc::new(RwLock::new(0)),
|
||||||
|
};
|
||||||
|
Ok(blockstore)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_with_signal(
|
pub fn open_with_signal(
|
||||||
@ -1059,6 +1062,12 @@ impl Blockstore {
|
|||||||
to_index: u64,
|
to_index: u64,
|
||||||
buffer: &mut [u8],
|
buffer: &mut [u8],
|
||||||
) -> Result<(u64, usize)> {
|
) -> Result<(u64, usize)> {
|
||||||
|
// lowest_cleanup_slot is the last slot that was not cleaned up by
|
||||||
|
// LedgerCleanupService
|
||||||
|
let lowest_cleanup_slot = self.lowest_cleanup_slot.read().unwrap();
|
||||||
|
if *lowest_cleanup_slot > slot {
|
||||||
|
return Err(BlockstoreError::SlotCleanedUp);
|
||||||
|
}
|
||||||
let meta_cf = self.db.column::<cf::SlotMeta>();
|
let meta_cf = self.db.column::<cf::SlotMeta>();
|
||||||
let mut buffer_offset = 0;
|
let mut buffer_offset = 0;
|
||||||
let mut last_index = 0;
|
let mut last_index = 0;
|
||||||
@ -1288,14 +1297,26 @@ impl Blockstore {
|
|||||||
slot: Slot,
|
slot: Slot,
|
||||||
slot_duration: Duration,
|
slot_duration: Duration,
|
||||||
stakes: &HashMap<Pubkey, (u64, Account)>,
|
stakes: &HashMap<Pubkey, (u64, Account)>,
|
||||||
) -> Option<UnixTimestamp> {
|
) -> Result<Option<UnixTimestamp>> {
|
||||||
|
let lowest_cleanup_slot = self.lowest_cleanup_slot.read().unwrap();
|
||||||
|
// lowest_cleanup_slot is the last slot that was not cleaned up by
|
||||||
|
// LedgerCleanupService
|
||||||
|
if *lowest_cleanup_slot > slot {
|
||||||
|
return Err(BlockstoreError::SlotCleanedUp);
|
||||||
|
}
|
||||||
|
|
||||||
let unique_timestamps: HashMap<Pubkey, (Slot, UnixTimestamp)> = self
|
let unique_timestamps: HashMap<Pubkey, (Slot, UnixTimestamp)> = self
|
||||||
.get_timestamp_slots(slot, TIMESTAMP_SLOT_INTERVAL, TIMESTAMP_SLOT_RANGE)
|
.get_timestamp_slots(slot, TIMESTAMP_SLOT_INTERVAL, TIMESTAMP_SLOT_RANGE)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|query_slot| self.get_block_timestamps(query_slot).unwrap_or_default())
|
.flat_map(|query_slot| self.get_block_timestamps(query_slot).unwrap_or_default())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
calculate_stake_weighted_timestamp(unique_timestamps, stakes, slot, slot_duration)
|
Ok(calculate_stake_weighted_timestamp(
|
||||||
|
unique_timestamps,
|
||||||
|
stakes,
|
||||||
|
slot,
|
||||||
|
slot_duration,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_timestamp_slots(
|
fn get_timestamp_slots(
|
||||||
@ -1346,6 +1367,12 @@ impl Blockstore {
|
|||||||
slot: Slot,
|
slot: Slot,
|
||||||
encoding: Option<RpcTransactionEncoding>,
|
encoding: Option<RpcTransactionEncoding>,
|
||||||
) -> Result<RpcConfirmedBlock> {
|
) -> Result<RpcConfirmedBlock> {
|
||||||
|
let lowest_cleanup_slot = self.lowest_cleanup_slot.read().unwrap();
|
||||||
|
// lowest_cleanup_slot is the last slot that was not cleaned up by
|
||||||
|
// LedgerCleanupService
|
||||||
|
if *lowest_cleanup_slot > slot {
|
||||||
|
return Err(BlockstoreError::SlotCleanedUp);
|
||||||
|
}
|
||||||
let encoding = encoding.unwrap_or(RpcTransactionEncoding::Json);
|
let encoding = encoding.unwrap_or(RpcTransactionEncoding::Json);
|
||||||
if self.is_root(slot) {
|
if self.is_root(slot) {
|
||||||
let slot_meta_cf = self.db.column::<cf::SlotMeta>();
|
let slot_meta_cf = self.db.column::<cf::SlotMeta>();
|
||||||
@ -1466,6 +1493,14 @@ impl Blockstore {
|
|||||||
if self.is_dead(slot) {
|
if self.is_dead(slot) {
|
||||||
return Err(BlockstoreError::DeadSlot);
|
return Err(BlockstoreError::DeadSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lowest_cleanup_slot is the last slot that was not cleaned up by
|
||||||
|
// LedgerCleanupService
|
||||||
|
let lowest_cleanup_slot = self.lowest_cleanup_slot.read().unwrap();
|
||||||
|
if *lowest_cleanup_slot > slot {
|
||||||
|
return Err(BlockstoreError::SlotCleanedUp);
|
||||||
|
}
|
||||||
|
|
||||||
let slot_meta_cf = self.db.column::<cf::SlotMeta>();
|
let slot_meta_cf = self.db.column::<cf::SlotMeta>();
|
||||||
let slot_meta = slot_meta_cf.get(slot)?;
|
let slot_meta = slot_meta_cf.get(slot)?;
|
||||||
if slot_meta.is_none() {
|
if slot_meta.is_none() {
|
||||||
@ -4886,10 +4921,11 @@ pub mod tests {
|
|||||||
})
|
})
|
||||||
.sum();
|
.sum();
|
||||||
expected_time /= total_stake;
|
expected_time /= total_stake;
|
||||||
assert_eq!(block_time_slot_3.unwrap() as u64, expected_time);
|
assert_eq!(block_time_slot_3.unwrap().unwrap() as u64, expected_time);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
blockstore
|
blockstore
|
||||||
.get_block_time(8, slot_duration.clone(), &stakes)
|
.get_block_time(8, slot_duration.clone(), &stakes)
|
||||||
|
.unwrap()
|
||||||
.unwrap() as u64,
|
.unwrap() as u64,
|
||||||
expected_time + 2 // At 400ms block duration, 5 slots == 2sec
|
expected_time + 2 // At 400ms block duration, 5 slots == 2sec
|
||||||
);
|
);
|
||||||
|
@ -49,6 +49,7 @@ pub enum BlockstoreError {
|
|||||||
IO(#[from] std::io::Error),
|
IO(#[from] std::io::Error),
|
||||||
Serialize(#[from] Box<bincode::ErrorKind>),
|
Serialize(#[from] Box<bincode::ErrorKind>),
|
||||||
FsExtraError(#[from] fs_extra::error::Error),
|
FsExtraError(#[from] fs_extra::error::Error),
|
||||||
|
SlotCleanedUp,
|
||||||
}
|
}
|
||||||
pub(crate) type Result<T> = std::result::Result<T, BlockstoreError>;
|
pub(crate) type Result<T> = std::result::Result<T, BlockstoreError>;
|
||||||
|
|
||||||
|
@ -396,11 +396,11 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.next_leader_slot(&pubkey, 0, &bank, None),
|
cache.next_leader_slot(&pubkey, 0, &bank, None),
|
||||||
Some((1, 6047999))
|
Some((1, 863999))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.next_leader_slot(&pubkey, 1, &bank, None),
|
cache.next_leader_slot(&pubkey, 1, &bank, None),
|
||||||
Some((2, 6047999))
|
Some((2, 863999))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.next_leader_slot(
|
cache.next_leader_slot(
|
||||||
|
@ -448,7 +448,7 @@ pub fn bank_from_archive<P: AsRef<Path>>(
|
|||||||
} else {
|
} else {
|
||||||
// Once v0.23.x is deployed, this default can be removed and snapshots without a version
|
// Once v0.23.x is deployed, this default can be removed and snapshots without a version
|
||||||
// file can be rejected
|
// file can be rejected
|
||||||
String::from("v0.22.3")
|
String::from("0.22.3")
|
||||||
};
|
};
|
||||||
|
|
||||||
let bank = rebuild_bank_from_snapshots(
|
let bank = rebuild_bank_from_snapshots(
|
||||||
@ -525,11 +525,6 @@ where
|
|||||||
|stream| {
|
|stream| {
|
||||||
let mut bank: Bank = match snapshot_version {
|
let mut bank: Bank = match snapshot_version {
|
||||||
env!("CARGO_PKG_VERSION") => deserialize_from_snapshot(stream.by_ref())?,
|
env!("CARGO_PKG_VERSION") => deserialize_from_snapshot(stream.by_ref())?,
|
||||||
"v0.22.3" => {
|
|
||||||
let bank0223: solana_runtime::bank::LegacyBank0223 =
|
|
||||||
deserialize_from_snapshot(stream.by_ref())?;
|
|
||||||
bank0223.into()
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(get_io_error(&format!(
|
return Err(get_io_error(&format!(
|
||||||
"unsupported snapshot version: {}",
|
"unsupported snapshot version: {}",
|
||||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-local-cluster"
|
name = "solana-local-cluster"
|
||||||
description = "Blockchain, Rebuilt for Scale"
|
description = "Blockchain, Rebuilt for Scale"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -12,24 +12,24 @@ homepage = "https://solana.com/"
|
|||||||
itertools = "0.8.1"
|
itertools = "0.8.1"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
rand = "0.6.5"
|
rand = "0.6.5"
|
||||||
solana-archiver-lib = { path = "../archiver-lib", version = "0.23.0" }
|
solana-archiver-lib = { path = "../archiver-lib", version = "0.23.1" }
|
||||||
solana-config-program = { path = "../programs/config", version = "0.23.0" }
|
solana-config-program = { path = "../programs/config", version = "0.23.1" }
|
||||||
solana-core = { path = "../core", version = "0.23.0" }
|
solana-core = { path = "../core", version = "0.23.1" }
|
||||||
solana-client = { path = "../client", version = "0.23.0" }
|
solana-client = { path = "../client", version = "0.23.1" }
|
||||||
solana-faucet = { path = "../faucet", version = "0.23.0" }
|
solana-faucet = { path = "../faucet", version = "0.23.1" }
|
||||||
solana-exchange-program = { path = "../programs/exchange", version = "0.23.0" }
|
solana-exchange-program = { path = "../programs/exchange", version = "0.23.1" }
|
||||||
solana-genesis-programs = { path = "../genesis-programs", version = "0.23.0" }
|
solana-genesis-programs = { path = "../genesis-programs", version = "0.23.1" }
|
||||||
solana-ledger = { path = "../ledger", version = "0.23.0" }
|
solana-ledger = { path = "../ledger", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../runtime", version = "0.23.0" }
|
solana-runtime = { path = "../runtime", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-stake-program = { path = "../programs/stake", version = "0.23.0" }
|
solana-stake-program = { path = "../programs/stake", version = "0.23.1" }
|
||||||
solana-storage-program = { path = "../programs/storage", version = "0.23.0" }
|
solana-storage-program = { path = "../programs/storage", version = "0.23.1" }
|
||||||
solana-vest-program = { path = "../programs/vest", version = "0.23.0" }
|
solana-vest-program = { path = "../programs/vest", version = "0.23.1" }
|
||||||
solana-vote-program = { path = "../programs/vote", version = "0.23.0" }
|
solana-vote-program = { path = "../programs/vote", version = "0.23.1" }
|
||||||
symlink = "0.1.0"
|
symlink = "0.1.0"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.23.0" }
|
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.23.1" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_matches = "1.3.0"
|
assert_matches = "1.3.0"
|
||||||
|
@ -38,6 +38,7 @@ impl ClusterValidatorInfo {
|
|||||||
pub trait Cluster {
|
pub trait Cluster {
|
||||||
fn get_node_pubkeys(&self) -> Vec<Pubkey>;
|
fn get_node_pubkeys(&self) -> Vec<Pubkey>;
|
||||||
fn get_validator_client(&self, pubkey: &Pubkey) -> Option<ThinClient>;
|
fn get_validator_client(&self, pubkey: &Pubkey) -> Option<ThinClient>;
|
||||||
|
fn get_contact_info(&self, pubkey: &Pubkey) -> Option<&ContactInfo>;
|
||||||
fn exit_node(&mut self, pubkey: &Pubkey) -> ClusterValidatorInfo;
|
fn exit_node(&mut self, pubkey: &Pubkey) -> ClusterValidatorInfo;
|
||||||
fn restart_node(&mut self, pubkey: &Pubkey, cluster_validator_info: ClusterValidatorInfo);
|
fn restart_node(&mut self, pubkey: &Pubkey, cluster_validator_info: ClusterValidatorInfo);
|
||||||
fn exit_restart_node(&mut self, pubkey: &Pubkey, config: ValidatorConfig);
|
fn exit_restart_node(&mut self, pubkey: &Pubkey, config: ValidatorConfig);
|
||||||
|
@ -207,6 +207,10 @@ impl LocalCluster {
|
|||||||
let leader_storage_keypair = Arc::new(storage_keypair);
|
let leader_storage_keypair = Arc::new(storage_keypair);
|
||||||
let leader_voting_keypair = Arc::new(voting_keypair);
|
let leader_voting_keypair = Arc::new(voting_keypair);
|
||||||
let mut leader_config = config.validator_configs[0].clone();
|
let mut leader_config = config.validator_configs[0].clone();
|
||||||
|
leader_config.rpc_ports = Some((
|
||||||
|
leader_node.info.rpc.port(),
|
||||||
|
leader_node.info.rpc_pubsub.port(),
|
||||||
|
));
|
||||||
leader_config.transaction_status_service_disabled = true;
|
leader_config.transaction_status_service_disabled = true;
|
||||||
let leader_server = Validator::new(
|
let leader_server = Validator::new(
|
||||||
leader_node,
|
leader_node,
|
||||||
@ -351,6 +355,10 @@ impl LocalCluster {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut config = validator_config.clone();
|
let mut config = validator_config.clone();
|
||||||
|
config.rpc_ports = Some((
|
||||||
|
validator_node.info.rpc.port(),
|
||||||
|
validator_node.info.rpc_pubsub.port(),
|
||||||
|
));
|
||||||
config.transaction_status_service_disabled = true;
|
config.transaction_status_service_disabled = true;
|
||||||
let voting_keypair = Arc::new(voting_keypair);
|
let voting_keypair = Arc::new(voting_keypair);
|
||||||
let validator_server = Validator::new(
|
let validator_server = Validator::new(
|
||||||
@ -658,6 +666,8 @@ impl Cluster for LocalCluster {
|
|||||||
// Update the stored ContactInfo for this node
|
// Update the stored ContactInfo for this node
|
||||||
let node = Node::new_localhost_with_pubkey(&pubkey);
|
let node = Node::new_localhost_with_pubkey(&pubkey);
|
||||||
cluster_validator_info.info.contact_info = node.info.clone();
|
cluster_validator_info.info.contact_info = node.info.clone();
|
||||||
|
cluster_validator_info.config.rpc_ports =
|
||||||
|
Some((node.info.rpc.port(), node.info.rpc_pubsub.port()));
|
||||||
cluster_validator_info
|
cluster_validator_info
|
||||||
.config
|
.config
|
||||||
.transaction_status_service_disabled = true;
|
.transaction_status_service_disabled = true;
|
||||||
@ -695,6 +705,10 @@ impl Cluster for LocalCluster {
|
|||||||
cluster_validator_info.config = validator_config;
|
cluster_validator_info.config = validator_config;
|
||||||
self.restart_node(pubkey, cluster_validator_info);
|
self.restart_node(pubkey, cluster_validator_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_contact_info(&self, pubkey: &Pubkey) -> Option<&ContactInfo> {
|
||||||
|
self.validators.get(pubkey).map(|v| &v.info.contact_info)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for LocalCluster {
|
impl Drop for LocalCluster {
|
||||||
|
@ -73,12 +73,14 @@ fn run_archiver_startup_basic(num_nodes: usize, num_archivers: usize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn test_archiver_startup_1_node() {
|
fn test_archiver_startup_1_node() {
|
||||||
run_archiver_startup_basic(1, 1);
|
run_archiver_startup_basic(1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn test_archiver_startup_2_nodes() {
|
fn test_archiver_startup_2_nodes() {
|
||||||
run_archiver_startup_basic(2, 1);
|
run_archiver_startup_basic(2, 1);
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
use log::*;
|
use log::*;
|
||||||
use serial_test_derive::serial;
|
use serial_test_derive::serial;
|
||||||
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_client::thin_client::create_client;
|
use solana_client::thin_client::create_client;
|
||||||
use solana_core::{
|
use solana_core::{
|
||||||
broadcast_stage::BroadcastStageType,
|
broadcast_stage::BroadcastStageType, consensus::VOTE_THRESHOLD_DEPTH,
|
||||||
consensus::VOTE_THRESHOLD_DEPTH,
|
gossip_service::discover_cluster, validator::ValidatorConfig,
|
||||||
gossip_service::discover_cluster,
|
|
||||||
partition_cfg::{Partition, PartitionCfg},
|
|
||||||
validator::ValidatorConfig,
|
|
||||||
};
|
};
|
||||||
use solana_ledger::{
|
use solana_ledger::{
|
||||||
bank_forks::SnapshotConfig, blockstore::Blockstore, leader_schedule::FixedSchedule,
|
bank_forks::SnapshotConfig, blockstore::Blockstore, leader_schedule::FixedSchedule,
|
||||||
@ -18,7 +16,6 @@ use solana_local_cluster::{
|
|||||||
cluster_tests,
|
cluster_tests,
|
||||||
local_cluster::{ClusterConfig, LocalCluster},
|
local_cluster::{ClusterConfig, LocalCluster},
|
||||||
};
|
};
|
||||||
use solana_sdk::timing::timestamp;
|
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
client::SyncClient,
|
client::SyncClient,
|
||||||
clock,
|
clock,
|
||||||
@ -28,6 +25,7 @@ use solana_sdk::{
|
|||||||
poh_config::PohConfig,
|
poh_config::PohConfig,
|
||||||
signature::{Keypair, KeypairUtil},
|
signature::{Keypair, KeypairUtil},
|
||||||
};
|
};
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fs, iter,
|
fs, iter,
|
||||||
@ -248,7 +246,7 @@ fn run_cluster_partition(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let validator_pubkeys: Vec<_> = validator_keys.iter().map(|v| v.pubkey()).collect();
|
let validator_pubkeys: Vec<_> = validator_keys.iter().map(|v| v.pubkey()).collect();
|
||||||
let mut config = ClusterConfig {
|
let config = ClusterConfig {
|
||||||
cluster_lamports,
|
cluster_lamports,
|
||||||
node_stakes,
|
node_stakes,
|
||||||
validator_configs: vec![validator_config.clone(); num_nodes],
|
validator_configs: vec![validator_config.clone(); num_nodes],
|
||||||
@ -256,71 +254,65 @@ fn run_cluster_partition(
|
|||||||
..ClusterConfig::default()
|
..ClusterConfig::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let now = timestamp();
|
let enable_partition = Some(Arc::new(AtomicBool::new(true)));
|
||||||
// Partition needs to start after the first few shorter warmup epochs, otherwise
|
|
||||||
// no root will be set before the partition is resolved, the leader schedule will
|
|
||||||
// not be computable, and the cluster wll halt.
|
|
||||||
let partition_epoch_start_offset = cluster_tests::time_until_nth_epoch(
|
|
||||||
partition_start_epoch,
|
|
||||||
config.slots_per_epoch,
|
|
||||||
config.stakers_slot_offset,
|
|
||||||
);
|
|
||||||
// Assume it takes <= 10 seconds for `LocalCluster::new` to boot up.
|
|
||||||
let local_cluster_boot_time = 10_000;
|
|
||||||
let partition_start = now + partition_epoch_start_offset + local_cluster_boot_time;
|
|
||||||
let partition_end = partition_start + leader_schedule_time as u64;
|
|
||||||
let mut validator_index = 0;
|
|
||||||
for (i, partition) in partitions.iter().enumerate() {
|
|
||||||
for _ in partition.iter() {
|
|
||||||
let mut p1 = Partition::default();
|
|
||||||
p1.num_partitions = partitions.len();
|
|
||||||
p1.my_partition = i;
|
|
||||||
p1.start_ts = partition_start;
|
|
||||||
p1.end_ts = partition_end;
|
|
||||||
config.validator_configs[validator_index].partition_cfg =
|
|
||||||
Some(PartitionCfg::new(vec![p1]));
|
|
||||||
validator_index += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info!(
|
info!(
|
||||||
"PARTITION_TEST starting cluster with {:?} partitions",
|
"PARTITION_TEST starting cluster with {:?} partitions slots_per_epoch: {}",
|
||||||
partitions
|
partitions, config.slots_per_epoch,
|
||||||
);
|
);
|
||||||
let now = Instant::now();
|
|
||||||
let mut cluster = LocalCluster::new(&config);
|
let mut cluster = LocalCluster::new(&config);
|
||||||
let elapsed = now.elapsed();
|
|
||||||
assert!(elapsed.as_millis() < local_cluster_boot_time as u128);
|
|
||||||
|
|
||||||
let now = timestamp();
|
let (cluster_nodes, _) = discover_cluster(&cluster.entry_point_info.gossip, num_nodes).unwrap();
|
||||||
let timeout = partition_start as u64 - now as u64;
|
|
||||||
info!(
|
info!("PARTITION_TEST sleeping until partition starting condition",);
|
||||||
"PARTITION_TEST sleeping until partition start timeout {}",
|
loop {
|
||||||
timeout
|
let mut reached_epoch = true;
|
||||||
);
|
for node in &cluster_nodes {
|
||||||
let mut dead_nodes = HashSet::new();
|
let node_client = RpcClient::new_socket(node.rpc);
|
||||||
if timeout > 0 {
|
if let Ok(epoch_info) = node_client.get_epoch_info() {
|
||||||
sleep(Duration::from_millis(timeout as u64));
|
info!("slots_per_epoch: {:?}", epoch_info);
|
||||||
|
if epoch_info.slots_in_epoch <= (1 << VOTE_THRESHOLD_DEPTH) {
|
||||||
|
reached_epoch = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
info!("PARTITION_TEST done sleeping until partition start timeout");
|
} else {
|
||||||
let now = timestamp();
|
reached_epoch = false;
|
||||||
let timeout = partition_end as u64 - now as u64;
|
}
|
||||||
info!(
|
}
|
||||||
"PARTITION_TEST sleeping until partition end timeout {}",
|
|
||||||
timeout
|
if reached_epoch {
|
||||||
);
|
info!("PARTITION_TEST start partition");
|
||||||
|
enable_partition
|
||||||
|
.clone()
|
||||||
|
.unwrap()
|
||||||
|
.store(false, Ordering::Relaxed);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
sleep(Duration::from_millis(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sleep(Duration::from_millis(leader_schedule_time));
|
||||||
|
|
||||||
|
info!("PARTITION_TEST remove partition");
|
||||||
|
enable_partition.unwrap().store(true, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let mut dead_nodes = HashSet::new();
|
||||||
let mut alive_node_contact_infos = vec![];
|
let mut alive_node_contact_infos = vec![];
|
||||||
let should_exits: Vec<_> = partitions
|
let should_exits: Vec<_> = partitions
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|p| p.iter().map(|(_, should_exit)| should_exit))
|
.flat_map(|p| p.iter().map(|(_, should_exit)| should_exit))
|
||||||
.collect();
|
.collect();
|
||||||
assert_eq!(should_exits.len(), validator_pubkeys.len());
|
assert_eq!(should_exits.len(), validator_pubkeys.len());
|
||||||
|
let timeout = 10;
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
// Give partitions time to propagate their blocks from durinig the partition
|
// Give partitions time to propagate their blocks from during the partition
|
||||||
// after the partition resolves
|
// after the partition resolves
|
||||||
let propagation_time = leader_schedule_time;
|
let propagation_time = leader_schedule_time;
|
||||||
info!("PARTITION_TEST resolving partition");
|
info!("PARTITION_TEST resolving partition. sleeping {}ms", timeout);
|
||||||
sleep(Duration::from_millis(timeout));
|
sleep(Duration::from_millis(10_000));
|
||||||
info!("PARTITION_TEST waiting for blocks to propagate after partition");
|
info!(
|
||||||
|
"PARTITION_TEST waiting for blocks to propagate after partition {}ms",
|
||||||
|
propagation_time
|
||||||
|
);
|
||||||
sleep(Duration::from_millis(propagation_time));
|
sleep(Duration::from_millis(propagation_time));
|
||||||
info!("PARTITION_TEST resuming normal operation");
|
info!("PARTITION_TEST resuming normal operation");
|
||||||
for (pubkey, should_exit) in validator_pubkeys.iter().zip(should_exits) {
|
for (pubkey, should_exit) in validator_pubkeys.iter().zip(should_exits) {
|
||||||
@ -353,6 +345,7 @@ fn run_cluster_partition(
|
|||||||
info!("PARTITION_TEST looking for new roots on all nodes");
|
info!("PARTITION_TEST looking for new roots on all nodes");
|
||||||
let mut roots = vec![HashSet::new(); alive_node_contact_infos.len()];
|
let mut roots = vec![HashSet::new(); alive_node_contact_infos.len()];
|
||||||
let mut done = false;
|
let mut done = false;
|
||||||
|
let mut last_print = Instant::now();
|
||||||
while !done {
|
while !done {
|
||||||
for (i, ingress_node) in alive_node_contact_infos.iter().enumerate() {
|
for (i, ingress_node) in alive_node_contact_infos.iter().enumerate() {
|
||||||
let client = create_client(
|
let client = create_client(
|
||||||
@ -362,12 +355,15 @@ fn run_cluster_partition(
|
|||||||
let slot = client.get_slot().unwrap_or(0);
|
let slot = client.get_slot().unwrap_or(0);
|
||||||
roots[i].insert(slot);
|
roots[i].insert(slot);
|
||||||
let min_node = roots.iter().map(|r| r.len()).min().unwrap_or(0);
|
let min_node = roots.iter().map(|r| r.len()).min().unwrap_or(0);
|
||||||
|
if last_print.elapsed().as_secs() > 3 {
|
||||||
info!("PARTITION_TEST min observed roots {}/16", min_node);
|
info!("PARTITION_TEST min observed roots {}/16", min_node);
|
||||||
|
last_print = Instant::now();
|
||||||
|
}
|
||||||
done = min_node >= 16;
|
done = min_node >= 16;
|
||||||
}
|
}
|
||||||
sleep(Duration::from_millis(clock::DEFAULT_MS_PER_SLOT / 2));
|
sleep(Duration::from_millis(clock::DEFAULT_MS_PER_SLOT / 2));
|
||||||
}
|
}
|
||||||
info!("PARTITION_TEST done spending on all node");
|
info!("PARTITION_TEST done waiting for roots");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_attributes)]
|
#[allow(unused_attributes)]
|
||||||
@ -424,6 +420,7 @@ fn test_kill_partition() {
|
|||||||
leader_schedule.push(k.pubkey())
|
leader_schedule.push(k.pubkey())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
info!("leader_schedule: {}", leader_schedule.len());
|
||||||
|
|
||||||
run_cluster_partition(
|
run_cluster_partition(
|
||||||
&partitions,
|
&partitions,
|
||||||
@ -665,8 +662,11 @@ fn test_snapshot_restart_tower() {
|
|||||||
cluster.restart_node(&validator_id, validator_info);
|
cluster.restart_node(&validator_id, validator_info);
|
||||||
|
|
||||||
// Test cluster can still make progress and get confirmations in tower
|
// Test cluster can still make progress and get confirmations in tower
|
||||||
|
// Use the restarted node as the discovery point so that we get updated
|
||||||
|
// validator's ContactInfo
|
||||||
|
let restarted_node_info = cluster.get_contact_info(&validator_id).unwrap();
|
||||||
cluster_tests::spend_and_verify_all_nodes(
|
cluster_tests::spend_and_verify_all_nodes(
|
||||||
&cluster.entry_point_info,
|
&restarted_node_info,
|
||||||
&cluster.funding_keypair,
|
&cluster.funding_keypair,
|
||||||
1,
|
1,
|
||||||
HashSet::new(),
|
HashSet::new(),
|
||||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-log-analyzer"
|
name = "solana-log-analyzer"
|
||||||
description = "The solana cluster network analysis tool"
|
description = "The solana cluster network analysis tool"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -17,8 +17,8 @@ semver = "0.9.0"
|
|||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "solana-log-analyzer"
|
name = "solana-log-analyzer"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-logger"
|
name = "solana-logger"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Logger"
|
description = "Solana Logger"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-measure"
|
name = "solana-measure"
|
||||||
description = "Blockchain, Rebuilt for Scale"
|
description = "Blockchain, Rebuilt for Scale"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
documentation = "https://docs.rs/solana"
|
documentation = "https://docs.rs/solana"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
readme = "../README.md"
|
readme = "../README.md"
|
||||||
@ -12,8 +12,8 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-metrics = { path = "../metrics", version = "0.23.0" }
|
solana-metrics = { path = "../metrics", version = "0.23.1" }
|
||||||
|
|
||||||
[target."cfg(unix)".dependencies]
|
[target."cfg(unix)".dependencies]
|
||||||
jemallocator = "0.3.2"
|
jemallocator = "0.3.2"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-merkle-tree"
|
name = "solana-merkle-tree"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Merkle Tree"
|
description = "Solana Merkle Tree"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -9,7 +9,7 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4.0"
|
hex = "0.4.0"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-metrics"
|
name = "solana-metrics"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Metrics"
|
description = "Solana Metrics"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -13,7 +13,7 @@ env_logger = "0.7.1"
|
|||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
reqwest = { version = "0.10.1", default-features = false, features = ["blocking", "rustls-tls"] }
|
reqwest = { version = "0.10.1", default-features = false, features = ["blocking", "rustls-tls"] }
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
sys-info = "0.5.8"
|
sys-info = "0.5.8"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "solana-net-shaper"
|
name = "solana-net-shaper"
|
||||||
description = "The solana cluster network shaping tool"
|
description = "The solana cluster network shaping tool"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
@ -16,8 +16,8 @@ semver = "0.9.0"
|
|||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
rand = "0.6.5"
|
rand = "0.6.5"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-net-utils"
|
name = "solana-net-utils"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Network Utilities"
|
description = "Solana Network Utilities"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -18,8 +18,8 @@ rand = "0.6.1"
|
|||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
socket2 = "0.3.11"
|
socket2 = "0.3.11"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
|
solana-clap-utils = { path = "../clap-utils", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
tokio = "0.1"
|
tokio = "0.1"
|
||||||
tokio-codec = "0.1"
|
tokio-codec = "0.1"
|
||||||
|
|
||||||
|
@ -868,6 +868,7 @@ EOF
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
config)
|
config)
|
||||||
|
failOnValidatorBootupFailure=false
|
||||||
prepareInstancesAndWriteConfigFile
|
prepareInstancesAndWriteConfigFile
|
||||||
;;
|
;;
|
||||||
info)
|
info)
|
||||||
|
@ -75,7 +75,7 @@ solana-bench-exchange)
|
|||||||
"
|
"
|
||||||
;;
|
;;
|
||||||
idle)
|
idle)
|
||||||
# Add the mint keypair to idle clients for convenience
|
# Add the faucet keypair to idle clients for convenience
|
||||||
net/scripts/rsync-retry.sh -vPrc \
|
net/scripts/rsync-retry.sh -vPrc \
|
||||||
"$entrypointIp":~/solana/config/faucet-keypair.json ~/solana/
|
"$entrypointIp":~/solana/config/faucet-keypair.json ~/solana/
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -221,8 +221,8 @@ EOF
|
|||||||
# shellcheck disable=SC2206 # Do not want to quote $genesisOptions
|
# shellcheck disable=SC2206 # Do not want to quote $genesisOptions
|
||||||
args+=($genesisOptions)
|
args+=($genesisOptions)
|
||||||
|
|
||||||
if [[ -f net/keypairs/mint.json ]]; then
|
if [[ -f net/keypairs/faucet.json ]]; then
|
||||||
export FAUCET_KEYPAIR=net/keypairs/mint.json
|
export FAUCET_KEYPAIR=net/keypairs/faucet.json
|
||||||
fi
|
fi
|
||||||
if [[ -f net/keypairs/bootstrap-validator-identity.json ]]; then
|
if [[ -f net/keypairs/bootstrap-validator-identity.json ]]; then
|
||||||
export BOOTSTRAP_VALIDATOR_IDENTITY_KEYPAIR=net/keypairs/bootstrap-validator-identity.json
|
export BOOTSTRAP_VALIDATOR_IDENTITY_KEYPAIR=net/keypairs/bootstrap-validator-identity.json
|
||||||
@ -303,11 +303,11 @@ EOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
# Add the mint keypair to validators for convenient access from tools
|
# Add the faucet keypair to validators for convenient access from tools
|
||||||
# like bench-tps and add to blocktreamers to run a faucet
|
# like bench-tps and add to blocktreamers to run a faucet
|
||||||
scp "$entrypointIp":~/solana/config/faucet-keypair.json config/
|
scp "$entrypointIp":~/solana/config/faucet-keypair.json config/
|
||||||
if [[ $nodeType = blockstreamer ]]; then
|
if [[ $nodeType = blockstreamer ]]; then
|
||||||
# Run another faucet with the mint keypair on the blockstreamer node.
|
# Run another faucet with the same keypair on the blockstreamer node.
|
||||||
# Typically the blockstreamer node has a static IP/DNS name for hosting
|
# Typically the blockstreamer node has a static IP/DNS name for hosting
|
||||||
# the blockexplorer web app, and is a location that somebody would expect
|
# the blockexplorer web app, and is a location that somebody would expect
|
||||||
# to be able to airdrop from
|
# to be able to airdrop from
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
asteroids|216.24.140.155|10.1.1.26|16|64|NVME|2000|||0|Denver
|
|
||||||
pacman|216.24.140.154|10.1.1.25|16|64|NVME|2000|||0|Denver
|
|
||||||
dumoulin|216.24.140.149|10.1.1.20|16|64|SATA|2000|NVME,NVME,NVME|1000,1000,1000|4|Denver
|
dumoulin|216.24.140.149|10.1.1.20|16|64|SATA|2000|NVME,NVME,NVME|1000,1000,1000|4|Denver
|
||||||
foosball|216.24.140.150|10.1.1.21|16|64|SATA|2000|NVME|1000|2|Denver
|
foosball|216.24.140.150|10.1.1.21|16|64|SATA|2000|NVME|1000|2|Denver
|
||||||
pingpong|216.24.140.151|10.1.1.22|16|64|SATA|2000|NVME|1000|2|Denver
|
pingpong|216.24.140.151|10.1.1.22|16|64|SATA|2000|NVME|1000|2|Denver
|
||||||
|
@ -174,7 +174,7 @@ cloud_CreateInstances() {
|
|||||||
# the stock Ubuntu 18.04 image and programmatically install CUDA after the
|
# the stock Ubuntu 18.04 image and programmatically install CUDA after the
|
||||||
# instance boots
|
# instance boots
|
||||||
#
|
#
|
||||||
imageName="ubuntu-1804-bionic-v20181029-with-cuda-10-and-cuda-9-2"
|
imageName="ubuntu-1804-bionic-v20181029-with-cuda-10-and-cuda-9-2 --image-project principal-lane-200702"
|
||||||
else
|
else
|
||||||
# Upstream Ubuntu 18.04 LTS image
|
# Upstream Ubuntu 18.04 LTS image
|
||||||
imageName="ubuntu-1804-bionic-v20190813a --image-project ubuntu-os-cloud"
|
imageName="ubuntu-1804-bionic-v20190813a --image-project ubuntu-os-cloud"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-perf"
|
name = "solana-perf"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Performance APIs"
|
description = "Solana Performance APIs"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -18,11 +18,11 @@ serde_derive = "1.0.103"
|
|||||||
dlopen_derive = "0.1.4"
|
dlopen_derive = "0.1.4"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
solana-sdk = { path = "../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../sdk", version = "0.23.1" }
|
||||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.23.0" }
|
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.23.1" }
|
||||||
solana-budget-program = { path = "../programs/budget", version = "0.23.0" }
|
solana-budget-program = { path = "../programs/budget", version = "0.23.1" }
|
||||||
solana-logger = { path = "../logger", version = "0.23.0" }
|
solana-logger = { path = "../logger", version = "0.23.1" }
|
||||||
solana-metrics = { path = "../metrics", version = "0.23.0" }
|
solana-metrics = { path = "../metrics", version = "0.23.1" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "solana_perf"
|
name = "solana_perf"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-programs"
|
name = "solana-bpf-programs"
|
||||||
description = "Blockchain, Rebuilt for Scale"
|
description = "Blockchain, Rebuilt for Scale"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
documentation = "https://docs.rs/solana"
|
documentation = "https://docs.rs/solana"
|
||||||
homepage = "https://solana.com/"
|
homepage = "https://solana.com/"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -22,10 +22,10 @@ walkdir = "2"
|
|||||||
bincode = "1.1.4"
|
bincode = "1.1.4"
|
||||||
byteorder = "1.3.2"
|
byteorder = "1.3.2"
|
||||||
elf = "0.0.10"
|
elf = "0.0.10"
|
||||||
solana-bpf-loader-program = { path = "../bpf_loader", version = "0.23.0" }
|
solana-bpf-loader-program = { path = "../bpf_loader", version = "0.23.1" }
|
||||||
solana-logger = { path = "../../logger", version = "0.23.0" }
|
solana-logger = { path = "../../logger", version = "0.23.1" }
|
||||||
solana-runtime = { path = "../../runtime", version = "0.23.0" }
|
solana-runtime = { path = "../../runtime", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../../sdk", version = "0.23.1" }
|
||||||
solana_rbpf = "=0.1.19"
|
solana_rbpf = "=0.1.19"
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-128bit"
|
name = "solana-bpf-rust-128bit"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,11 +12,11 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "0.23.0" }
|
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "0.23.1" }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-128bit-dep"
|
name = "solana-bpf-rust-128bit-dep"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-alloc"
|
name = "solana-bpf-rust-alloc"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-dep-crate"
|
name = "solana-bpf-rust-dep-crate"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -13,10 +13,10 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = { version = "1", default-features = false }
|
byteorder = { version = "1", default-features = false }
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-dup-accounts"
|
name = "solana-bpf-rust-dup-accounts"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-external-spend"
|
name = "solana-bpf-rust-external-spend"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-iter"
|
name = "solana-bpf-rust-iter"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-many-args"
|
name = "solana-bpf-rust-many-args"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,11 +12,11 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "0.23.0" }
|
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "0.23.1" }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-many-args-dep"
|
name = "solana-bpf-rust-many-args-dep"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-noop"
|
name = "solana-bpf-rust-noop"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-panic"
|
name = "solana-bpf-rust-panic"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-param-passing"
|
name = "solana-bpf-rust-param-passing"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,11 +12,11 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "0.23.0" }
|
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "0.23.1" }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-param-passing-dep"
|
name = "solana-bpf-rust-param-passing-dep"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF program written in Rust"
|
description = "Solana BPF program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-rust-sysval"
|
name = "solana-bpf-rust-sysval"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF test program written in Rust"
|
description = "Solana BPF test program written in Rust"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
solana-sdk = { path = "../../../../sdk/", version = "0.23.0", default-features = false }
|
solana-sdk = { path = "../../../../sdk/", version = "0.23.1", default-features = false }
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.0" }
|
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.23.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
program = ["solana-sdk/program"]
|
program = ["solana-sdk/program"]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-bpf-loader-program"
|
name = "solana-bpf-loader-program"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana BPF loader"
|
description = "Solana BPF loader"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -14,8 +14,8 @@ byteorder = "1.3.2"
|
|||||||
libc = "0.2.66"
|
libc = "0.2.66"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
solana-logger = { path = "../../logger", version = "0.23.0" }
|
solana-logger = { path = "../../logger", version = "0.23.1" }
|
||||||
solana-sdk = { path = "../../sdk", version = "0.23.0" }
|
solana-sdk = { path = "../../sdk", version = "0.23.1" }
|
||||||
solana_rbpf = "=0.1.19"
|
solana_rbpf = "=0.1.19"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-btc-spv-program"
|
name = "solana-btc-spv-program"
|
||||||
version = "0.23.0"
|
version = "0.23.1"
|
||||||
description = "Solana Bitcoin spv parsing program"
|
description = "Solana Bitcoin spv parsing program"
|
||||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
repository = "https://github.com/solana-labs/solana"
|
repository = "https://github.com/solana-labs/solana"
|
||||||
@ -16,7 +16,7 @@ num-derive = "0.3"
|
|||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
solana-sdk = { path = "../../sdk", version = "0.23.0"}
|
solana-sdk = { path = "../../sdk", version = "0.23.1"}
|
||||||
hex = "0.3.2"
|
hex = "0.3.2"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user