Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9498f11d46 | ||
|
558324b861 | ||
|
9a5fc3513a | ||
|
b7c6e139e6 | ||
|
a9d2fa6aad | ||
|
056a9952c3 | ||
|
fc21c857a3 | ||
|
614ad64ec1 | ||
|
f72c186004 | ||
|
59a2b05b44 | ||
|
bed6e566ef | ||
|
e85f9fcb73 | ||
|
8cb3953c9a | ||
|
d8e885f425 | ||
|
28fa5149b7 | ||
|
190acd7d15 | ||
|
909316bd53 | ||
|
000b763e95 | ||
|
9d00ff6624 |
130
Cargo.lock
generated
130
Cargo.lock
generated
@@ -292,7 +292,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "btc_spv_bin"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"hex",
|
||||
@@ -3029,7 +3029,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-accounts-bench"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"crossbeam-channel",
|
||||
@@ -3044,7 +3044,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-archiver"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"console 0.10.3",
|
||||
@@ -3059,7 +3059,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-archiver-lib"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"crossbeam-channel",
|
||||
@@ -3089,7 +3089,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-archiver-utils"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"log 0.4.8",
|
||||
@@ -3104,7 +3104,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-banking-bench"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"log 0.4.8",
|
||||
@@ -3122,7 +3122,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-bench-exchange"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"itertools 0.9.0",
|
||||
@@ -3149,7 +3149,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-bench-streamer"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"solana-clap-utils",
|
||||
@@ -3160,7 +3160,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-bench-tps"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"clap",
|
||||
@@ -3186,7 +3186,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-bpf-loader-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"byteorder",
|
||||
@@ -3202,7 +3202,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-btc-spv-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"hex",
|
||||
@@ -3216,7 +3216,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-budget-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"chrono",
|
||||
@@ -3232,7 +3232,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-chacha"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"hex-literal",
|
||||
"log 0.4.8",
|
||||
@@ -3247,7 +3247,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-chacha-cuda"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"hex-literal",
|
||||
"log 0.4.8",
|
||||
@@ -3261,14 +3261,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-chacha-sys"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-clap-utils"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
@@ -3282,7 +3282,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-cli"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"bincode",
|
||||
@@ -3326,7 +3326,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-cli-config"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
"lazy_static",
|
||||
@@ -3338,7 +3338,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-client"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"bincode",
|
||||
@@ -3364,7 +3364,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-config-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"chrono",
|
||||
@@ -3377,7 +3377,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-core"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bs58",
|
||||
@@ -3446,7 +3446,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-crate-features"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes 0.4.12",
|
||||
@@ -3469,7 +3469,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-dos"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"clap",
|
||||
@@ -3484,7 +3484,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-download-utils"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bzip2",
|
||||
"console 0.10.3",
|
||||
@@ -3498,7 +3498,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-exchange-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"log 0.4.8",
|
||||
@@ -3515,7 +3515,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-failure-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"solana-runtime",
|
||||
"solana-sdk",
|
||||
@@ -3523,7 +3523,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-faucet"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"byteorder",
|
||||
@@ -3542,7 +3542,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-genesis"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"base64 0.12.0",
|
||||
"chrono",
|
||||
@@ -3562,7 +3562,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-genesis-programs"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"log 0.4.8",
|
||||
"solana-bpf-loader-program",
|
||||
@@ -3576,7 +3576,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-gossip"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"solana-clap-utils",
|
||||
@@ -3589,7 +3589,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-install"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bincode",
|
||||
@@ -3621,7 +3621,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-keygen"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"clap",
|
||||
@@ -3636,7 +3636,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-ledger"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"bincode",
|
||||
@@ -3683,7 +3683,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-ledger-tool"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"assert_cmd",
|
||||
"bs58",
|
||||
@@ -3705,7 +3705,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-local-cluster"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"itertools 0.9.0",
|
||||
@@ -3735,7 +3735,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-log-analyzer"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"byte-unit",
|
||||
"clap",
|
||||
@@ -3747,7 +3747,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-logger"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"env_logger 0.7.1",
|
||||
"lazy_static",
|
||||
@@ -3756,7 +3756,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-measure"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"jemalloc-ctl",
|
||||
"jemallocator",
|
||||
@@ -3767,7 +3767,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-merkle-tree"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"fast-math",
|
||||
"hex",
|
||||
@@ -3776,7 +3776,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-metrics"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"env_logger 0.7.1",
|
||||
"gethostname",
|
||||
@@ -3791,7 +3791,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-net-shaper"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"rand 0.7.3",
|
||||
@@ -3803,7 +3803,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-net-utils"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bytes 0.4.12",
|
||||
@@ -3822,7 +3822,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-noop-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"log 0.4.8",
|
||||
"solana-logger",
|
||||
@@ -3831,7 +3831,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-ownable"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"num-derive 0.3.0",
|
||||
@@ -3843,7 +3843,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-perf"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"dlopen",
|
||||
@@ -3863,7 +3863,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-rayon-threadlimit"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
@@ -3882,7 +3882,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-remote-wallet"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"base32",
|
||||
"console 0.10.3",
|
||||
@@ -3898,7 +3898,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-runtime"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"bincode",
|
||||
@@ -3936,7 +3936,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-scripts"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"csv",
|
||||
"serde",
|
||||
@@ -3944,7 +3944,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-sdk"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"bincode",
|
||||
@@ -3978,7 +3978,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-sdk-c"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bs58",
|
||||
@@ -3992,7 +3992,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-sdk-macro"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"proc-macro2 1.0.10",
|
||||
@@ -4002,7 +4002,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-stake-accounts"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"solana-clap-utils",
|
||||
@@ -4016,7 +4016,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-stake-monitor"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"console 0.10.3",
|
||||
@@ -4040,7 +4040,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-stake-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"log 0.4.8",
|
||||
@@ -4058,7 +4058,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-storage-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"bincode",
|
||||
@@ -4074,7 +4074,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-streamer"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log 0.4.8",
|
||||
@@ -4089,7 +4089,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-sys-tuner"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"libc",
|
||||
@@ -4104,7 +4104,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-transaction-status"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bs58",
|
||||
@@ -4115,7 +4115,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-upload-perf"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
"solana-metrics",
|
||||
@@ -4123,7 +4123,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-validator"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
@@ -4151,7 +4151,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-vest-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"chrono",
|
||||
@@ -4167,7 +4167,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-vote-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"log 0.4.8",
|
||||
@@ -4182,7 +4182,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-vote-signer"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"jsonrpc-core",
|
||||
@@ -4197,7 +4197,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solana-watchtower"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"humantime 2.0.0",
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-accounts-bench"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -10,10 +10,10 @@ homepage = "https://solana.com/"
|
||||
[dependencies]
|
||||
log = "0.4.6"
|
||||
rayon = "1.3.0"
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-measure = { path = "../measure", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-measure = { path = "../measure", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
rand = "0.7.0"
|
||||
clap = "2.33.0"
|
||||
crossbeam-channel = "0.4"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-archiver-lib"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Archiver Library"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,23 +15,23 @@ ed25519-dalek = "=1.0.0-pre.3"
|
||||
log = "0.4.8"
|
||||
rand = "0.7.0"
|
||||
rand_chacha = "0.2.2"
|
||||
solana-client = { path = "../client", version = "1.1.8" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.8" }
|
||||
solana-client = { path = "../client", version = "1.1.10" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.10" }
|
||||
thiserror = "1.0"
|
||||
serde = "1.0.105"
|
||||
serde_json = "1.0.48"
|
||||
serde_derive = "1.0.103"
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-chacha = { path = "../chacha", version = "1.1.8" }
|
||||
solana-chacha-sys = { path = "../chacha-sys", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-perf = { path = "../perf", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-core = { path = "../core", version = "1.1.8" }
|
||||
solana-streamer = { path = "../streamer", version = "1.1.8" }
|
||||
solana-archiver-utils = { path = "../archiver-utils", version = "1.1.8" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
solana-chacha = { path = "../chacha", version = "1.1.10" }
|
||||
solana-chacha-sys = { path = "../chacha-sys", version = "1.1.10" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-perf = { path = "../perf", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-core = { path = "../core", version = "1.1.10" }
|
||||
solana-streamer = { path = "../streamer", version = "1.1.10" }
|
||||
solana-archiver-utils = { path = "../archiver-utils", version = "1.1.10" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.4.2"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-archiver-utils"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Archiver Utils"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -11,12 +11,12 @@ edition = "2018"
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
rand = "0.7.0"
|
||||
solana-chacha = { path = "../chacha", version = "1.1.8" }
|
||||
solana-chacha-sys = { path = "../chacha-sys", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-perf = { path = "../perf", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-chacha = { path = "../chacha", version = "1.1.10" }
|
||||
solana-chacha-sys = { path = "../chacha-sys", version = "1.1.10" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-perf = { path = "../perf", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.4.2"
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-archiver"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -10,13 +10,13 @@ homepage = "https://solana.com/"
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
console = "0.10.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-core = { path = "../core", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.8" }
|
||||
solana-archiver-lib = { path = "../archiver-lib", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-core = { path = "../core", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.10" }
|
||||
solana-archiver-lib = { path = "../archiver-lib", version = "1.1.10" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-banking-bench"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -10,14 +10,14 @@ homepage = "https://solana.com/"
|
||||
[dependencies]
|
||||
log = "0.4.6"
|
||||
rayon = "1.3.0"
|
||||
solana-core = { path = "../core", version = "1.1.8" }
|
||||
solana-streamer = { path = "../streamer", version = "1.1.8" }
|
||||
solana-perf = { path = "../perf", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-measure = { path = "../measure", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-core = { path = "../core", version = "1.1.10" }
|
||||
solana-streamer = { path = "../streamer", version = "1.1.10" }
|
||||
solana-perf = { path = "../perf", version = "1.1.10" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-measure = { path = "../measure", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
rand = "0.7.0"
|
||||
crossbeam-channel = "0.4"
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-exchange"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -18,20 +18,20 @@ rand = "0.7.0"
|
||||
rayon = "1.3.0"
|
||||
serde_json = "1.0.48"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-core = { path = "../core", version = "1.1.8" }
|
||||
solana-genesis = { path = "../genesis", version = "1.1.8" }
|
||||
solana-client = { path = "../client", version = "1.1.8" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.8" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-core = { path = "../core", version = "1.1.10" }
|
||||
solana-genesis = { path = "../genesis", version = "1.1.10" }
|
||||
solana-client = { path = "../client", version = "1.1.10" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.10" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.10" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.1.8" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.1.10" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,17 +2,17 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-streamer"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-streamer = { path = "../streamer", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-streamer = { path = "../streamer", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-tps"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -14,24 +14,24 @@ log = "0.4.8"
|
||||
rayon = "1.3.0"
|
||||
serde_json = "1.0.48"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-core = { path = "../core", version = "1.1.8" }
|
||||
solana-genesis = { path = "../genesis", version = "1.1.8" }
|
||||
solana-client = { path = "../client", version = "1.1.8" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-core = { path = "../core", version = "1.1.10" }
|
||||
solana-genesis = { path = "../genesis", version = "1.1.10" }
|
||||
solana-client = { path = "../client", version = "1.1.10" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.10" }
|
||||
#solana-librapay = { path = "../programs/librapay", version = "1.1.8", optional = true }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.8" }
|
||||
solana-measure = { path = "../measure", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.10" }
|
||||
solana-measure = { path = "../measure", version = "1.1.10" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
#solana-move-loader-program = { path = "../programs/move_loader", version = "1.1.8", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.4.0"
|
||||
serial_test_derive = "0.4.0"
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.1.8" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.1.10" }
|
||||
|
||||
#[features]
|
||||
#move = ["solana-librapay", "solana-move-loader-program"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-chacha-cuda"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Chacha Cuda APIs"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,12 +10,12 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
solana-archiver-utils = { path = "../archiver-utils", version = "1.1.8" }
|
||||
solana-chacha = { path = "../chacha", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-perf = { path = "../perf", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-archiver-utils = { path = "../archiver-utils", version = "1.1.10" }
|
||||
solana-chacha = { path = "../chacha", version = "1.1.10" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-perf = { path = "../perf", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.2.1"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-chacha-sys"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana chacha-sys"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-chacha"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Chacha APIs"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,11 +12,11 @@ edition = "2018"
|
||||
log = "0.4.8"
|
||||
rand = "0.7.0"
|
||||
rand_chacha = "0.2.2"
|
||||
solana-chacha-sys = { path = "../chacha-sys", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-perf = { path = "../perf", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-chacha-sys = { path = "../chacha-sys", version = "1.1.10" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-perf = { path = "../perf", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.2.1"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-clap-utils"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana utilities for the clap"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -11,8 +11,8 @@ edition = "2018"
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
rpassword = "4.0"
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
thiserror = "1.0.11"
|
||||
tiny-bip39 = "0.7.0"
|
||||
url = "2.1.0"
|
||||
|
@@ -11,7 +11,8 @@ pub fn commitment_arg<'a, 'b>() -> Arg<'a, 'b> {
|
||||
Arg::with_name(COMMITMENT_ARG.name)
|
||||
.long(COMMITMENT_ARG.long)
|
||||
.takes_value(true)
|
||||
.possible_values(&["default", "max", "recent", "root"])
|
||||
.possible_values(&["recent", "root", "max"])
|
||||
.default_value("recent")
|
||||
.value_name("COMMITMENT_LEVEL")
|
||||
.help(COMMITMENT_ARG.help)
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli-config"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -27,28 +27,28 @@ reqwest = { version = "0.10.4", default-features = false, features = ["blocking"
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.48"
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.1.8" }
|
||||
solana-client = { path = "../client", version = "1.1.8" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.1.8" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.8" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.8" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.8" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.8" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.1.8" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.10" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.1.10" }
|
||||
solana-client = { path = "../client", version = "1.1.10" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.1.10" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.10" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.10" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.10" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.10" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.1.10" }
|
||||
thiserror = "1.0.13"
|
||||
url = "2.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-core = { path = "../core", version = "1.1.8" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.8" }
|
||||
solana-core = { path = "../core", version = "1.1.10" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.10" }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
cli_output::{CliAccount, OutputFormat},
|
||||
cli_output::{CliAccount, CliSignOnlyData, CliSignature, OutputFormat},
|
||||
cluster_query::*,
|
||||
display::{println_name_value, println_signers},
|
||||
display::println_name_value,
|
||||
nonce::{self, *},
|
||||
offline::{blockhash_query::BlockhashQuery, *},
|
||||
stake::*,
|
||||
@@ -55,6 +55,7 @@ use solana_transaction_status::{EncodedTransaction, TransactionEncoding};
|
||||
use solana_vote_program::vote_state::VoteAuthorize;
|
||||
use std::{
|
||||
error,
|
||||
fmt::Write as FmtWrite,
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
net::{IpAddr, SocketAddr},
|
||||
@@ -179,6 +180,7 @@ pub enum CliCommand {
|
||||
commitment_config: CommitmentConfig,
|
||||
follow: bool,
|
||||
},
|
||||
ClusterDate,
|
||||
ClusterVersion,
|
||||
CreateAddressWithSeed {
|
||||
from_pubkey: Option<Pubkey>,
|
||||
@@ -187,7 +189,7 @@ pub enum CliCommand {
|
||||
},
|
||||
Fees,
|
||||
GetBlockTime {
|
||||
slot: Slot,
|
||||
slot: Option<Slot>,
|
||||
},
|
||||
GetEpochInfo {
|
||||
commitment_config: CommitmentConfig,
|
||||
@@ -587,6 +589,10 @@ pub fn parse_command(
|
||||
let response = match matches.subcommand() {
|
||||
// Cluster Query Commands
|
||||
("catchup", Some(matches)) => parse_catchup(matches, wallet_manager),
|
||||
("cluster-date", Some(_matches)) => Ok(CliCommandInfo {
|
||||
command: CliCommand::ClusterDate,
|
||||
signers: vec![],
|
||||
}),
|
||||
("cluster-version", Some(_matches)) => Ok(CliCommandInfo {
|
||||
command: CliCommand::ClusterVersion,
|
||||
signers: vec![],
|
||||
@@ -1044,7 +1050,7 @@ pub fn get_blockhash_and_fee_calculator(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn return_signers(tx: &Transaction) -> ProcessResult {
|
||||
pub fn return_signers(tx: &Transaction, config: &CliConfig) -> ProcessResult {
|
||||
let verify_results = tx.verify_with_results();
|
||||
let mut signers = Vec::new();
|
||||
let mut absent = Vec::new();
|
||||
@@ -1063,15 +1069,14 @@ pub fn return_signers(tx: &Transaction) -> ProcessResult {
|
||||
}
|
||||
});
|
||||
|
||||
println_signers(&tx.message.recent_blockhash, &signers, &absent, &bad_sig);
|
||||
let cli_command = CliSignOnlyData {
|
||||
blockhash: tx.message.recent_blockhash.to_string(),
|
||||
signers,
|
||||
absent,
|
||||
bad_sig,
|
||||
};
|
||||
|
||||
Ok(json!({
|
||||
"blockhash": tx.message.recent_blockhash.to_string(),
|
||||
"signers": &signers,
|
||||
"absent": &absent,
|
||||
"badSig": &bad_sig,
|
||||
})
|
||||
.to_string())
|
||||
Ok(config.output_format.formatted_string(&cli_command))
|
||||
}
|
||||
|
||||
pub fn parse_create_address_with_seed(
|
||||
@@ -1159,7 +1164,7 @@ fn process_airdrop(
|
||||
}
|
||||
};
|
||||
|
||||
request_and_confirm_airdrop(&rpc_client, faucet_addr, &pubkey, lamports)?;
|
||||
request_and_confirm_airdrop(&rpc_client, faucet_addr, &pubkey, lamports, &config)?;
|
||||
|
||||
let current_balance = rpc_client
|
||||
.retry_get_balance(&pubkey, 5)?
|
||||
@@ -1260,21 +1265,21 @@ fn process_show_account(
|
||||
use_lamports_unit,
|
||||
};
|
||||
|
||||
config.output_format.formatted_print(&cli_account);
|
||||
let mut account_string = config.output_format.formatted_string(&cli_account);
|
||||
|
||||
if config.output_format == OutputFormat::Display {
|
||||
if let Some(output_file) = output_file {
|
||||
let mut f = File::create(output_file)?;
|
||||
f.write_all(&data)?;
|
||||
println!();
|
||||
println!("Wrote account data to {}", output_file);
|
||||
writeln!(&mut account_string)?;
|
||||
writeln!(&mut account_string, "Wrote account data to {}", output_file)?;
|
||||
} else if !data.is_empty() {
|
||||
use pretty_hex::*;
|
||||
println!("{:?}", data.hex_dump());
|
||||
writeln!(&mut account_string, "{:?}", data.hex_dump())?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok("".to_string())
|
||||
Ok(account_string)
|
||||
}
|
||||
|
||||
fn process_deploy(
|
||||
@@ -1340,8 +1345,9 @@ fn process_deploy(
|
||||
trace!("Creating program account");
|
||||
let result =
|
||||
rpc_client.send_and_confirm_transaction_with_spinner(&mut create_account_tx, &signers);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
.map_err(|_| CliError::DynamicProgramError("Program allocate space failed".to_string()))?;
|
||||
log_instruction_custom_error::<SystemError>(result, &config).map_err(|_| {
|
||||
CliError::DynamicProgramError("Program account allocation failed".to_string())
|
||||
})?;
|
||||
|
||||
trace!("Writing program data");
|
||||
rpc_client.send_and_confirm_transactions(write_transactions, &signers)?;
|
||||
@@ -1400,7 +1406,7 @@ fn process_pay(
|
||||
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&config.signers, blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&config.signers, blockhash)?;
|
||||
if let Some(nonce_account) = &nonce_account {
|
||||
@@ -1415,7 +1421,7 @@ fn process_pay(
|
||||
)?;
|
||||
let result =
|
||||
rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
} else if *witnesses == None {
|
||||
let dt = timestamp.unwrap();
|
||||
@@ -1440,7 +1446,7 @@ fn process_pay(
|
||||
let mut tx = Transaction::new_unsigned(message);
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&[config.signers[0], &contract_state], blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&[config.signers[0], &contract_state], blockhash)?;
|
||||
check_account_for_fee(
|
||||
@@ -1453,10 +1459,9 @@ fn process_pay(
|
||||
&mut tx,
|
||||
&[config.signers[0], &contract_state],
|
||||
);
|
||||
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
||||
|
||||
let signature = log_instruction_custom_error::<BudgetError>(result, &config)?;
|
||||
Ok(json!({
|
||||
"signature": signature_str,
|
||||
"signature": signature,
|
||||
"processId": format!("{}", contract_state.pubkey()),
|
||||
})
|
||||
.to_string())
|
||||
@@ -1486,7 +1491,7 @@ fn process_pay(
|
||||
let mut tx = Transaction::new_unsigned(message);
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&[config.signers[0], &contract_state], blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&[config.signers[0], &contract_state], blockhash)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(
|
||||
@@ -1499,10 +1504,9 @@ fn process_pay(
|
||||
&fee_calculator,
|
||||
&tx.message,
|
||||
)?;
|
||||
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
||||
|
||||
let signature = log_instruction_custom_error::<BudgetError>(result, &config)?;
|
||||
Ok(json!({
|
||||
"signature": signature_str,
|
||||
"signature": signature,
|
||||
"processId": format!("{}", contract_state.pubkey()),
|
||||
})
|
||||
.to_string())
|
||||
@@ -1530,7 +1534,7 @@ fn process_cancel(rpc_client: &RpcClient, config: &CliConfig, pubkey: &Pubkey) -
|
||||
)?;
|
||||
let result =
|
||||
rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &[config.signers[0]]);
|
||||
log_instruction_custom_error::<BudgetError>(result)
|
||||
log_instruction_custom_error::<BudgetError>(result, &config)
|
||||
}
|
||||
|
||||
fn process_time_elapsed(
|
||||
@@ -1554,7 +1558,7 @@ fn process_time_elapsed(
|
||||
)?;
|
||||
let result =
|
||||
rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &[config.signers[0]]);
|
||||
log_instruction_custom_error::<BudgetError>(result)
|
||||
log_instruction_custom_error::<BudgetError>(result, &config)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -1599,7 +1603,7 @@ fn process_transfer(
|
||||
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&config.signers, recent_blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
||||
if let Some(nonce_account) = &nonce_account {
|
||||
@@ -1617,7 +1621,7 @@ fn process_transfer(
|
||||
} else {
|
||||
rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers)
|
||||
};
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1641,7 +1645,7 @@ fn process_witness(
|
||||
)?;
|
||||
let result =
|
||||
rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &[config.signers[0]]);
|
||||
log_instruction_custom_error::<BudgetError>(result)
|
||||
log_instruction_custom_error::<BudgetError>(result, &config)
|
||||
}
|
||||
|
||||
pub fn process_command(config: &CliConfig) -> ProcessResult {
|
||||
@@ -1680,6 +1684,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
||||
*commitment_config,
|
||||
*follow,
|
||||
),
|
||||
CliCommand::ClusterDate => process_cluster_date(&rpc_client, config),
|
||||
CliCommand::ClusterVersion => process_cluster_version(&rpc_client),
|
||||
CliCommand::CreateAddressWithSeed {
|
||||
from_pubkey,
|
||||
@@ -1687,7 +1692,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
||||
program_id,
|
||||
} => process_create_address_with_seed(config, from_pubkey.as_ref(), &seed, &program_id),
|
||||
CliCommand::Fees => process_fees(&rpc_client),
|
||||
CliCommand::GetBlockTime { slot } => process_get_block_time(&rpc_client, *slot),
|
||||
CliCommand::GetBlockTime { slot } => process_get_block_time(&rpc_client, config, *slot),
|
||||
CliCommand::GetGenesisHash => process_get_genesis_hash(&rpc_client),
|
||||
CliCommand::GetEpochInfo { commitment_config } => {
|
||||
process_get_epoch_info(&rpc_client, config, *commitment_config)
|
||||
@@ -2256,6 +2261,7 @@ pub fn request_and_confirm_airdrop(
|
||||
faucet_addr: &SocketAddr,
|
||||
to_pubkey: &Pubkey,
|
||||
lamports: u64,
|
||||
config: &CliConfig,
|
||||
) -> ProcessResult {
|
||||
let (blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||
let keypair = {
|
||||
@@ -2271,10 +2277,13 @@ pub fn request_and_confirm_airdrop(
|
||||
}?;
|
||||
let mut tx = keypair.airdrop_transaction();
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &[&keypair]);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
|
||||
pub fn log_instruction_custom_error<E>(result: ClientResult<Signature>) -> ProcessResult
|
||||
pub fn log_instruction_custom_error<E>(
|
||||
result: ClientResult<Signature>,
|
||||
config: &CliConfig,
|
||||
) -> ProcessResult
|
||||
where
|
||||
E: 'static + std::error::Error + DecodeError<E> + FromPrimitive,
|
||||
{
|
||||
@@ -2291,7 +2300,12 @@ where
|
||||
}
|
||||
Err(err.into())
|
||||
}
|
||||
Ok(sig) => Ok(sig.to_string()),
|
||||
Ok(sig) => {
|
||||
let signature = CliSignature {
|
||||
signature: sig.clone().to_string(),
|
||||
};
|
||||
Ok(config.output_format.formatted_string(&signature))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3833,6 +3847,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
let mut config = CliConfig::default();
|
||||
config.output_format = OutputFormat::JsonCompact;
|
||||
let present: Box<dyn Signer> = Box::new(keypair_from_seed(&[2u8; 32]).unwrap());
|
||||
let absent: Box<dyn Signer> = Box::new(NullSigner::new(&Pubkey::new(&[3u8; 32])));
|
||||
let bad: Box<dyn Signer> = Box::new(BadSigner::new(Pubkey::new(&[4u8; 32])));
|
||||
@@ -3851,7 +3867,7 @@ mod tests {
|
||||
let signers = vec![present.as_ref(), absent.as_ref(), bad.as_ref()];
|
||||
let blockhash = Hash::new(&[7u8; 32]);
|
||||
tx.try_partial_sign(&signers, blockhash).unwrap();
|
||||
let res = return_signers(&tx).unwrap();
|
||||
let res = return_signers(&tx, &config).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&res);
|
||||
assert_eq!(sign_only.blockhash, blockhash);
|
||||
assert_eq!(sign_only.present_signers[0].0, present.pubkey());
|
||||
|
@@ -26,20 +26,14 @@ pub enum OutputFormat {
|
||||
}
|
||||
|
||||
impl OutputFormat {
|
||||
pub fn formatted_print<T>(&self, item: &T)
|
||||
pub fn formatted_string<T>(&self, item: &T) -> String
|
||||
where
|
||||
T: Serialize + fmt::Display,
|
||||
{
|
||||
match self {
|
||||
OutputFormat::Display => {
|
||||
println!("{}", item);
|
||||
}
|
||||
OutputFormat::Json => {
|
||||
println!("{}", serde_json::to_string_pretty(item).unwrap());
|
||||
}
|
||||
OutputFormat::JsonCompact => {
|
||||
println!("{}", serde_json::to_value(item).unwrap());
|
||||
}
|
||||
OutputFormat::Display => format!("{}", item),
|
||||
OutputFormat::Json => serde_json::to_string_pretty(item).unwrap(),
|
||||
OutputFormat::JsonCompact => serde_json::to_value(item).unwrap().to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -839,3 +833,77 @@ impl From<&Lockout> for CliLockout {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliBlockTime {
|
||||
pub slot: Slot,
|
||||
pub timestamp: UnixTimestamp,
|
||||
}
|
||||
|
||||
impl fmt::Display for CliBlockTime {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln_name_value(f, "Block:", &self.slot.to_string())?;
|
||||
writeln_name_value(
|
||||
f,
|
||||
"Date:",
|
||||
&format!(
|
||||
"{} (UnixTimestamp: {})",
|
||||
DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(self.timestamp, 0), Utc)
|
||||
.to_rfc3339_opts(SecondsFormat::Secs, true),
|
||||
self.timestamp
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliSignOnlyData {
|
||||
pub blockhash: String,
|
||||
#[serde(skip_serializing_if = "Vec::is_empty", default)]
|
||||
pub signers: Vec<String>,
|
||||
#[serde(skip_serializing_if = "Vec::is_empty", default)]
|
||||
pub absent: Vec<String>,
|
||||
#[serde(skip_serializing_if = "Vec::is_empty", default)]
|
||||
pub bad_sig: Vec<String>,
|
||||
}
|
||||
|
||||
impl fmt::Display for CliSignOnlyData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f)?;
|
||||
writeln_name_value(f, "Blockhash:", &self.blockhash)?;
|
||||
if !self.signers.is_empty() {
|
||||
writeln!(f, "{}", style("Signers (Pubkey=Signature):").bold())?;
|
||||
for signer in self.signers.iter() {
|
||||
writeln!(f, " {}", signer)?;
|
||||
}
|
||||
}
|
||||
if !self.absent.is_empty() {
|
||||
writeln!(f, "{}", style("Absent Signers (Pubkey):").bold())?;
|
||||
for pubkey in self.absent.iter() {
|
||||
writeln!(f, " {}", pubkey)?;
|
||||
}
|
||||
}
|
||||
if !self.bad_sig.is_empty() {
|
||||
writeln!(f, "{}", style("Bad Signatures (Pubkey):").bold())?;
|
||||
for pubkey in self.bad_sig.iter() {
|
||||
writeln!(f, " {}", pubkey)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct CliSignature {
|
||||
pub signature: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for CliSignature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f)?;
|
||||
writeln_name_value(f, "Signature:", &self.signature)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,8 @@
|
||||
use crate::{
|
||||
cli::{check_account_for_fee, CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult},
|
||||
cli_output::{
|
||||
CliBlockProduction, CliBlockProductionEntry, CliEpochInfo, CliKeyedStakeState,
|
||||
CliSlotStatus, CliStakeVec, CliValidator, CliValidators,
|
||||
},
|
||||
cli_output::*,
|
||||
display::println_name_value,
|
||||
};
|
||||
use chrono::{DateTime, NaiveDateTime, SecondsFormat, Utc};
|
||||
use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand};
|
||||
use console::{style, Emoji};
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
@@ -24,7 +20,7 @@ use solana_client::{
|
||||
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
|
||||
use solana_sdk::{
|
||||
account_utils::StateMut,
|
||||
clock::{self, Slot},
|
||||
clock::{self, Clock, Slot},
|
||||
commitment_config::CommitmentConfig,
|
||||
epoch_schedule::Epoch,
|
||||
hash::Hash,
|
||||
@@ -33,6 +29,7 @@ use solana_sdk::{
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
system_instruction,
|
||||
sysvar::{self, Sysvar},
|
||||
transaction::Transaction,
|
||||
};
|
||||
use std::{
|
||||
@@ -83,6 +80,10 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
||||
)
|
||||
.arg(commitment_arg()),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("cluster-date")
|
||||
.about("Get current cluster date, computed from genesis creation time and network time")
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("cluster-version")
|
||||
.about("Get the version of the cluster entrypoint"),
|
||||
@@ -96,7 +97,6 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
||||
.index(1)
|
||||
.takes_value(true)
|
||||
.value_name("SLOT")
|
||||
.required(true)
|
||||
.help("Slot number of the block to query")
|
||||
)
|
||||
)
|
||||
@@ -168,14 +168,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
||||
.default_value("15")
|
||||
.help("Wait up to timeout seconds for transaction confirmation"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(COMMITMENT_ARG.name)
|
||||
.long(COMMITMENT_ARG.long)
|
||||
.takes_value(true)
|
||||
.possible_values(&["default", "max", "recent", "root"])
|
||||
.value_name("COMMITMENT_LEVEL")
|
||||
.help("Wait until the transaction is confirmed at selected commitment level"),
|
||||
),
|
||||
.arg(commitment_arg()),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("live-slots")
|
||||
@@ -277,8 +270,7 @@ pub fn parse_catchup(
|
||||
) -> Result<CliCommandInfo, CliError> {
|
||||
let node_pubkey = pubkey_of_signer(matches, "node_pubkey", wallet_manager)?.unwrap();
|
||||
let node_json_rpc_url = value_t!(matches, "node_json_rpc_url", String).ok();
|
||||
let commitment_config =
|
||||
commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent);
|
||||
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
|
||||
let follow = matches.is_present("follow");
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::Catchup {
|
||||
@@ -304,8 +296,7 @@ pub fn parse_cluster_ping(
|
||||
None
|
||||
};
|
||||
let timeout = Duration::from_secs(value_t_or_exit!(matches, "timeout", u64));
|
||||
let commitment_config =
|
||||
commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent);
|
||||
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::Ping {
|
||||
lamports,
|
||||
@@ -324,7 +315,7 @@ pub fn parse_cluster_ping(
|
||||
}
|
||||
|
||||
pub fn parse_get_block_time(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let slot = value_t_or_exit!(matches, "slot", u64);
|
||||
let slot = value_of(matches, "slot");
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::GetBlockTime { slot },
|
||||
signers: vec![],
|
||||
@@ -332,8 +323,7 @@ pub fn parse_get_block_time(matches: &ArgMatches<'_>) -> Result<CliCommandInfo,
|
||||
}
|
||||
|
||||
pub fn parse_get_epoch_info(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let commitment_config =
|
||||
commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent);
|
||||
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::GetEpochInfo { commitment_config },
|
||||
signers: vec![],
|
||||
@@ -341,8 +331,7 @@ pub fn parse_get_epoch_info(matches: &ArgMatches<'_>) -> Result<CliCommandInfo,
|
||||
}
|
||||
|
||||
pub fn parse_get_slot(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let commitment_config =
|
||||
commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent);
|
||||
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::GetSlot { commitment_config },
|
||||
signers: vec![],
|
||||
@@ -350,8 +339,7 @@ pub fn parse_get_slot(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliErr
|
||||
}
|
||||
|
||||
pub fn parse_get_epoch(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let commitment_config =
|
||||
commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent);
|
||||
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::GetEpoch { commitment_config },
|
||||
signers: vec![],
|
||||
@@ -359,8 +347,7 @@ pub fn parse_get_epoch(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliEr
|
||||
}
|
||||
|
||||
pub fn parse_total_supply(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let commitment_config =
|
||||
commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent);
|
||||
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::TotalSupply { commitment_config },
|
||||
signers: vec![],
|
||||
@@ -368,8 +355,7 @@ pub fn parse_total_supply(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Cl
|
||||
}
|
||||
|
||||
pub fn parse_get_transaction_count(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let commitment_config =
|
||||
commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent);
|
||||
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::GetTransactionCount { commitment_config },
|
||||
signers: vec![],
|
||||
@@ -395,8 +381,7 @@ pub fn parse_show_stakes(
|
||||
|
||||
pub fn parse_show_validators(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||
let use_lamports_unit = matches.is_present("lamports");
|
||||
let commitment_config =
|
||||
commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent);
|
||||
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
|
||||
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::ShowValidators {
|
||||
@@ -501,14 +486,13 @@ pub fn process_catchup(
|
||||
let slot_distance = rpc_slot as i64 - node_slot as i64;
|
||||
let slots_per_second =
|
||||
(previous_slot_distance - slot_distance) as f64 / f64::from(sleep_interval);
|
||||
let time_remaining = if slots_per_second <= 0.0 {
|
||||
let time_remaining = (slot_distance as f64 / slots_per_second).round();
|
||||
let time_remaining = if !time_remaining.is_normal() || time_remaining <= 0.0 {
|
||||
"".to_string()
|
||||
} else {
|
||||
format!(
|
||||
". Time remaining: {}",
|
||||
humantime::format_duration(Duration::from_secs_f64(
|
||||
(slot_distance as f64 / slots_per_second).round()
|
||||
))
|
||||
humantime::format_duration(Duration::from_secs_f64(time_remaining))
|
||||
)
|
||||
};
|
||||
|
||||
@@ -539,6 +523,23 @@ pub fn process_catchup(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_cluster_date(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
|
||||
let result = rpc_client
|
||||
.get_account_with_commitment(&sysvar::clock::id(), CommitmentConfig::default())?;
|
||||
if let Some(clock_account) = result.value {
|
||||
let clock: Clock = Sysvar::from_account(&clock_account).ok_or_else(|| {
|
||||
CliError::RpcRequestError("Failed to deserialize clock sysvar".to_string())
|
||||
})?;
|
||||
let block_time = CliBlockTime {
|
||||
slot: result.context.slot,
|
||||
timestamp: clock.unix_timestamp,
|
||||
};
|
||||
Ok(config.output_format.formatted_string(&block_time))
|
||||
} else {
|
||||
Err(format!("AccountNotFound: pubkey={}", sysvar::clock::id()).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_cluster_version(rpc_client: &RpcClient) -> ProcessResult {
|
||||
let remote_version = rpc_client.get_version()?;
|
||||
Ok(remote_version.solana_core)
|
||||
@@ -588,15 +589,19 @@ pub fn process_leader_schedule(rpc_client: &RpcClient) -> ProcessResult {
|
||||
Ok("".to_string())
|
||||
}
|
||||
|
||||
pub fn process_get_block_time(rpc_client: &RpcClient, slot: Slot) -> ProcessResult {
|
||||
pub fn process_get_block_time(
|
||||
rpc_client: &RpcClient,
|
||||
config: &CliConfig,
|
||||
slot: Option<Slot>,
|
||||
) -> ProcessResult {
|
||||
let slot = if let Some(slot) = slot {
|
||||
slot
|
||||
} else {
|
||||
rpc_client.get_slot()?
|
||||
};
|
||||
let timestamp = rpc_client.get_block_time(slot)?;
|
||||
let result = format!(
|
||||
"{} (UnixTimestamp: {})",
|
||||
DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc)
|
||||
.to_rfc3339_opts(SecondsFormat::Secs, true),
|
||||
timestamp
|
||||
);
|
||||
Ok(result)
|
||||
let block_time = CliBlockTime { slot, timestamp };
|
||||
Ok(config.output_format.formatted_string(&block_time))
|
||||
}
|
||||
|
||||
pub fn process_get_epoch_info(
|
||||
@@ -607,8 +612,7 @@ pub fn process_get_epoch_info(
|
||||
let epoch_info: CliEpochInfo = rpc_client
|
||||
.get_epoch_info_with_commitment(commitment_config.clone())?
|
||||
.into();
|
||||
config.output_format.formatted_print(&epoch_info);
|
||||
Ok("".to_string())
|
||||
Ok(config.output_format.formatted_string(&epoch_info))
|
||||
}
|
||||
|
||||
pub fn process_get_genesis_hash(rpc_client: &RpcClient) -> ProcessResult {
|
||||
@@ -790,8 +794,7 @@ pub fn process_show_block_production(
|
||||
individual_slot_status,
|
||||
verbose: config.verbose,
|
||||
};
|
||||
config.output_format.formatted_print(&block_production);
|
||||
Ok("".to_string())
|
||||
Ok(config.output_format.formatted_string(&block_production))
|
||||
}
|
||||
|
||||
pub fn process_total_supply(
|
||||
@@ -1120,10 +1123,9 @@ pub fn process_show_stakes(
|
||||
}
|
||||
}
|
||||
}
|
||||
config
|
||||
Ok(config
|
||||
.output_format
|
||||
.formatted_print(&CliStakeVec::new(stake_accounts));
|
||||
Ok("".to_string())
|
||||
.formatted_string(&CliStakeVec::new(stake_accounts)))
|
||||
}
|
||||
|
||||
pub fn process_show_validators(
|
||||
@@ -1167,8 +1169,7 @@ pub fn process_show_validators(
|
||||
delinquent_validators,
|
||||
use_lamports_unit,
|
||||
};
|
||||
config.output_format.formatted_print(&cli_validators);
|
||||
Ok("".to_string())
|
||||
Ok(config.output_format.formatted_string(&cli_validators))
|
||||
}
|
||||
|
||||
pub fn process_transaction_history(
|
||||
@@ -1217,6 +1218,17 @@ mod tests {
|
||||
let (default_keypair_file, mut tmp_file) = make_tmp_file();
|
||||
write_keypair(&default_keypair, tmp_file.as_file_mut()).unwrap();
|
||||
|
||||
let test_cluster_version = test_commands
|
||||
.clone()
|
||||
.get_matches_from(vec!["test", "cluster-date"]);
|
||||
assert_eq!(
|
||||
parse_command(&test_cluster_version, &default_keypair_file, &mut None).unwrap(),
|
||||
CliCommandInfo {
|
||||
command: CliCommand::ClusterDate,
|
||||
signers: vec![],
|
||||
}
|
||||
);
|
||||
|
||||
let test_cluster_version = test_commands
|
||||
.clone()
|
||||
.get_matches_from(vec!["test", "cluster-version"]);
|
||||
@@ -1245,7 +1257,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
parse_command(&test_get_block_time, &default_keypair_file, &mut None).unwrap(),
|
||||
CliCommandInfo {
|
||||
command: CliCommand::GetBlockTime { slot },
|
||||
command: CliCommand::GetBlockTime { slot: Some(slot) },
|
||||
signers: vec![],
|
||||
}
|
||||
);
|
||||
|
@@ -146,7 +146,12 @@ pub fn write_transaction<W: io::Write>(
|
||||
Err(err) => err.to_string(),
|
||||
}
|
||||
)?;
|
||||
writeln!(w, "{} Fee: {}", prefix, transaction_status.fee)?;
|
||||
writeln!(
|
||||
w,
|
||||
"{} Fee: {} SOL",
|
||||
prefix,
|
||||
lamports_to_sol(transaction_status.fee)
|
||||
)?;
|
||||
assert_eq!(
|
||||
transaction_status.pre_balances.len(),
|
||||
transaction_status.post_balances.len()
|
||||
|
@@ -2,8 +2,7 @@ use clap::{crate_description, crate_name, AppSettings, Arg, ArgGroup, ArgMatches
|
||||
use console::style;
|
||||
|
||||
use solana_clap_utils::{
|
||||
input_validators::is_url, keypair::SKIP_SEED_PHRASE_VALIDATION_ARG, offline::SIGN_ONLY_ARG,
|
||||
DisplayError,
|
||||
input_validators::is_url, keypair::SKIP_SEED_PHRASE_VALIDATION_ARG, DisplayError,
|
||||
};
|
||||
use solana_cli::{
|
||||
cli::{app, parse_command, process_command, CliCommandInfo, CliConfig, CliSigners},
|
||||
@@ -262,13 +261,7 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||
let (mut config, signers) = parse_args(&matches, &mut wallet_manager)?;
|
||||
config.signers = signers.iter().map(|s| s.as_ref()).collect();
|
||||
let result = process_command(&config)?;
|
||||
let (_, submatches) = matches.subcommand();
|
||||
let sign_only = submatches
|
||||
.map(|m| m.is_present(SIGN_ONLY_ARG.name))
|
||||
.unwrap_or(false);
|
||||
if !sign_only {
|
||||
println!("{}", result);
|
||||
}
|
||||
println!("{}", result);
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -463,7 +463,7 @@ pub fn process_authorize_nonce_account(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<NonceError>(result)
|
||||
log_instruction_custom_error::<NonceError>(result, &config)
|
||||
}
|
||||
|
||||
pub fn process_create_nonce_account(
|
||||
@@ -540,7 +540,7 @@ pub fn process_create_nonce_account(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
|
||||
pub fn process_get_nonce(rpc_client: &RpcClient, nonce_account_pubkey: &Pubkey) -> ProcessResult {
|
||||
@@ -582,7 +582,7 @@ pub fn process_new_nonce(
|
||||
)?;
|
||||
let result = rpc_client
|
||||
.send_and_confirm_transaction_with_spinner(&mut tx, &[config.signers[0], nonce_authority]);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
|
||||
pub fn process_show_nonce_account(
|
||||
@@ -606,8 +606,7 @@ pub fn process_show_nonce_account(
|
||||
nonce_account.authority = Some(data.authority.to_string());
|
||||
}
|
||||
|
||||
config.output_format.formatted_print(&nonce_account);
|
||||
Ok("".to_string())
|
||||
Ok(config.output_format.formatted_string(&nonce_account))
|
||||
};
|
||||
match state_from_account(&nonce_account)? {
|
||||
State::Uninitialized => print_account(None),
|
||||
@@ -642,7 +641,7 @@ pub fn process_withdraw_from_nonce_account(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<NonceError>(result)
|
||||
log_instruction_custom_error::<NonceError>(result, &config)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@@ -79,32 +79,47 @@ pub fn parse_sign_only_reply_string(reply: &str) -> SignOnly {
|
||||
let object: Value = serde_json::from_str(&reply).unwrap();
|
||||
let blockhash_str = object.get("blockhash").unwrap().as_str().unwrap();
|
||||
let blockhash = blockhash_str.parse::<Hash>().unwrap();
|
||||
let signer_strings = object.get("signers").unwrap().as_array().unwrap();
|
||||
let present_signers = signer_strings
|
||||
.iter()
|
||||
.map(|signer_string| {
|
||||
let mut signer = signer_string.as_str().unwrap().split('=');
|
||||
let key = Pubkey::from_str(signer.next().unwrap()).unwrap();
|
||||
let sig = Signature::from_str(signer.next().unwrap()).unwrap();
|
||||
(key, sig)
|
||||
})
|
||||
.collect();
|
||||
let signer_strings = object.get("absent").unwrap().as_array().unwrap();
|
||||
let absent_signers = signer_strings
|
||||
.iter()
|
||||
.map(|val| {
|
||||
let s = val.as_str().unwrap();
|
||||
Pubkey::from_str(s).unwrap()
|
||||
})
|
||||
.collect();
|
||||
let signer_strings = object.get("badSig").unwrap().as_array().unwrap();
|
||||
let bad_signers = signer_strings
|
||||
.iter()
|
||||
.map(|val| {
|
||||
let s = val.as_str().unwrap();
|
||||
Pubkey::from_str(s).unwrap()
|
||||
})
|
||||
.collect();
|
||||
let mut present_signers: Vec<(Pubkey, Signature)> = Vec::new();
|
||||
let signer_strings = object.get("signers");
|
||||
if let Some(sig_strings) = signer_strings {
|
||||
present_signers = sig_strings
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|signer_string| {
|
||||
let mut signer = signer_string.as_str().unwrap().split('=');
|
||||
let key = Pubkey::from_str(signer.next().unwrap()).unwrap();
|
||||
let sig = Signature::from_str(signer.next().unwrap()).unwrap();
|
||||
(key, sig)
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
let mut absent_signers: Vec<Pubkey> = Vec::new();
|
||||
let signer_strings = object.get("absent");
|
||||
if let Some(sig_strings) = signer_strings {
|
||||
absent_signers = sig_strings
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|val| {
|
||||
let s = val.as_str().unwrap();
|
||||
Pubkey::from_str(s).unwrap()
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
let mut bad_signers: Vec<Pubkey> = Vec::new();
|
||||
let signer_strings = object.get("badSig");
|
||||
if let Some(sig_strings) = signer_strings {
|
||||
bad_signers = sig_strings
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|val| {
|
||||
let s = val.as_str().unwrap();
|
||||
Pubkey::from_str(s).unwrap()
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
SignOnly {
|
||||
blockhash,
|
||||
present_signers,
|
||||
|
@@ -881,7 +881,7 @@ pub fn process_create_stake_account(
|
||||
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&config.signers, recent_blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
||||
if let Some(nonce_account) = &nonce_account {
|
||||
@@ -895,7 +895,7 @@ pub fn process_create_stake_account(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -946,7 +946,7 @@ pub fn process_stake_authorize(
|
||||
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&config.signers, recent_blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
||||
if let Some(nonce_account) = &nonce_account {
|
||||
@@ -960,7 +960,7 @@ pub fn process_stake_authorize(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<StakeError>(result)
|
||||
log_instruction_custom_error::<StakeError>(result, &config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1000,7 +1000,7 @@ pub fn process_deactivate_stake_account(
|
||||
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&config.signers, recent_blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
||||
if let Some(nonce_account) = &nonce_account {
|
||||
@@ -1014,7 +1014,7 @@ pub fn process_deactivate_stake_account(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<StakeError>(result)
|
||||
log_instruction_custom_error::<StakeError>(result, &config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1063,7 +1063,7 @@ pub fn process_withdraw_stake(
|
||||
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&config.signers, recent_blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
||||
if let Some(nonce_account) = &nonce_account {
|
||||
@@ -1077,7 +1077,7 @@ pub fn process_withdraw_stake(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1197,7 +1197,7 @@ pub fn process_split_stake(
|
||||
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&config.signers, recent_blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
||||
if let Some(nonce_account) = &nonce_account {
|
||||
@@ -1211,7 +1211,7 @@ pub fn process_split_stake(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<StakeError>(result)
|
||||
log_instruction_custom_error::<StakeError>(result, &config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1254,7 +1254,7 @@ pub fn process_stake_set_lockup(
|
||||
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&config.signers, recent_blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
||||
if let Some(nonce_account) = &nonce_account {
|
||||
@@ -1268,7 +1268,7 @@ pub fn process_stake_set_lockup(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<StakeError>(result)
|
||||
log_instruction_custom_error::<StakeError>(result, &config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1341,8 +1341,7 @@ pub fn process_show_stake_account(
|
||||
match stake_account.state() {
|
||||
Ok(stake_state) => {
|
||||
let state = build_stake_state(stake_account.lamports, &stake_state, use_lamports_unit);
|
||||
config.output_format.formatted_print(&state);
|
||||
Ok("".to_string())
|
||||
Ok(config.output_format.formatted_string(&state))
|
||||
}
|
||||
Err(err) => Err(CliError::RpcRequestError(format!(
|
||||
"Account data could not be deserialized to stake state: {}",
|
||||
@@ -1370,8 +1369,7 @@ pub fn process_show_stake_history(
|
||||
entries,
|
||||
use_lamports_unit,
|
||||
};
|
||||
config.output_format.formatted_print(&stake_history_output);
|
||||
Ok("".to_string())
|
||||
Ok(config.output_format.formatted_string(&stake_history_output))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -1464,7 +1462,7 @@ pub fn process_delegate_stake(
|
||||
|
||||
if sign_only {
|
||||
tx.try_partial_sign(&config.signers, recent_blockhash)?;
|
||||
return_signers(&tx)
|
||||
return_signers(&tx, &config)
|
||||
} else {
|
||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
||||
if let Some(nonce_account) = &nonce_account {
|
||||
@@ -1478,7 +1476,7 @@ pub fn process_delegate_stake(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<StakeError>(result)
|
||||
log_instruction_custom_error::<StakeError>(result, &config)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -243,7 +243,7 @@ pub fn process_create_storage_account(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
|
||||
pub fn process_claim_storage_reward(
|
||||
|
@@ -410,10 +410,9 @@ pub fn process_get_validator_info(
|
||||
info: validator_info,
|
||||
});
|
||||
}
|
||||
config
|
||||
Ok(config
|
||||
.output_format
|
||||
.formatted_print(&CliValidatorInfoVec::new(validator_info_list));
|
||||
Ok("".to_string())
|
||||
.formatted_string(&CliValidatorInfoVec::new(validator_info_list)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@@ -335,8 +335,7 @@ pub fn parse_vote_get_account_command(
|
||||
let vote_account_pubkey =
|
||||
pubkey_of_signer(matches, "vote_account_pubkey", wallet_manager)?.unwrap();
|
||||
let use_lamports_unit = matches.is_present("lamports");
|
||||
let commitment_config =
|
||||
commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent);
|
||||
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::ShowVoteAccount {
|
||||
pubkey: vote_account_pubkey,
|
||||
@@ -459,7 +458,7 @@ pub fn process_create_vote_account(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<SystemError>(result)
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
|
||||
pub fn process_vote_authorize(
|
||||
@@ -500,7 +499,7 @@ pub fn process_vote_authorize(
|
||||
)?;
|
||||
let result =
|
||||
rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &[config.signers[0]]);
|
||||
log_instruction_custom_error::<VoteError>(result)
|
||||
log_instruction_custom_error::<VoteError>(result, &config)
|
||||
}
|
||||
|
||||
pub fn process_vote_update_validator(
|
||||
@@ -533,7 +532,7 @@ pub fn process_vote_update_validator(
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &config.signers);
|
||||
log_instruction_custom_error::<VoteError>(result)
|
||||
log_instruction_custom_error::<VoteError>(result, &config)
|
||||
}
|
||||
|
||||
fn get_vote_account(
|
||||
@@ -607,8 +606,7 @@ pub fn process_show_vote_account(
|
||||
use_lamports_unit,
|
||||
};
|
||||
|
||||
config.output_format.formatted_print(&vote_account_data);
|
||||
Ok("".to_string())
|
||||
Ok(config.output_format.formatted_string(&vote_account_data))
|
||||
}
|
||||
|
||||
pub fn process_withdraw_from_vote_account(
|
||||
@@ -640,7 +638,7 @@ pub fn process_withdraw_from_vote_account(
|
||||
)?;
|
||||
let result =
|
||||
rpc_client.send_and_confirm_transaction_with_spinner(&mut transaction, &config.signers);
|
||||
log_instruction_custom_error::<VoteError>(result)
|
||||
log_instruction_custom_error::<VoteError>(result, &config)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@@ -1,5 +1,6 @@
|
||||
use solana_cli::{
|
||||
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
|
||||
cli_output::OutputFormat,
|
||||
nonce,
|
||||
offline::{
|
||||
blockhash_query::{self, BlockhashQuery},
|
||||
@@ -119,6 +120,7 @@ fn full_battery_tests(
|
||||
&faucet_addr,
|
||||
&config_payer.signers[0].pubkey(),
|
||||
2000,
|
||||
&config_payer,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(2000, &rpc_client, &config_payer.signers[0].pubkey());
|
||||
@@ -275,6 +277,7 @@ fn test_create_account_with_seed() {
|
||||
let offline_nonce_authority_signer = keypair_from_seed(&[1u8; 32]).unwrap();
|
||||
let online_nonce_creator_signer = keypair_from_seed(&[2u8; 32]).unwrap();
|
||||
let to_address = Pubkey::new(&[3u8; 32]);
|
||||
let config = CliConfig::default();
|
||||
|
||||
// Setup accounts
|
||||
let rpc_client = RpcClient::new_socket(leader_data.rpc);
|
||||
@@ -283,6 +286,7 @@ fn test_create_account_with_seed() {
|
||||
&faucet_addr,
|
||||
&offline_nonce_authority_signer.pubkey(),
|
||||
42,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
request_and_confirm_airdrop(
|
||||
@@ -290,6 +294,7 @@ fn test_create_account_with_seed() {
|
||||
&faucet_addr,
|
||||
&online_nonce_creator_signer.pubkey(),
|
||||
4242,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(42, &rpc_client, &offline_nonce_authority_signer.pubkey());
|
||||
@@ -344,6 +349,7 @@ fn test_create_account_with_seed() {
|
||||
nonce_authority: 0,
|
||||
fee_payer: 0,
|
||||
};
|
||||
authority_config.output_format = OutputFormat::JsonCompact;
|
||||
let sign_only_reply = process_command(&authority_config).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sign_only_reply);
|
||||
let authority_presigner = sign_only.presigner_of(&authority_pubkey).unwrap();
|
||||
|
@@ -2,6 +2,7 @@ use chrono::prelude::*;
|
||||
use serde_json::Value;
|
||||
use solana_cli::{
|
||||
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig, PayCommand},
|
||||
cli_output::OutputFormat,
|
||||
nonce,
|
||||
offline::{
|
||||
blockhash_query::{self, BlockhashQuery},
|
||||
@@ -69,6 +70,7 @@ fn test_cli_timestamp_tx() {
|
||||
&faucet_addr,
|
||||
&config_payer.signers[0].pubkey(),
|
||||
50,
|
||||
&config_witness,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(50, &rpc_client, &config_payer.signers[0].pubkey());
|
||||
@@ -78,6 +80,7 @@ fn test_cli_timestamp_tx() {
|
||||
&faucet_addr,
|
||||
&config_witness.signers[0].pubkey(),
|
||||
1,
|
||||
&config_witness,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -154,6 +157,7 @@ fn test_cli_witness_tx() {
|
||||
&faucet_addr,
|
||||
&config_payer.signers[0].pubkey(),
|
||||
50,
|
||||
&config_witness,
|
||||
)
|
||||
.unwrap();
|
||||
request_and_confirm_airdrop(
|
||||
@@ -161,6 +165,7 @@ fn test_cli_witness_tx() {
|
||||
&faucet_addr,
|
||||
&config_witness.signers[0].pubkey(),
|
||||
1,
|
||||
&config_witness,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -234,6 +239,7 @@ fn test_cli_cancel_tx() {
|
||||
&faucet_addr,
|
||||
&config_payer.signers[0].pubkey(),
|
||||
50,
|
||||
&config_witness,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -307,6 +313,7 @@ fn test_offline_pay_tx() {
|
||||
&faucet_addr,
|
||||
&config_offline.signers[0].pubkey(),
|
||||
50,
|
||||
&config_offline,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -315,6 +322,7 @@ fn test_offline_pay_tx() {
|
||||
&faucet_addr,
|
||||
&config_online.signers[0].pubkey(),
|
||||
50,
|
||||
&config_offline,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(50, &rpc_client, &config_offline.signers[0].pubkey());
|
||||
@@ -328,6 +336,7 @@ fn test_offline_pay_tx() {
|
||||
sign_only: true,
|
||||
..PayCommand::default()
|
||||
});
|
||||
config_offline.output_format = OutputFormat::JsonCompact;
|
||||
let sig_response = process_command(&config_offline).unwrap();
|
||||
|
||||
check_balance(50, &rpc_client, &config_offline.signers[0].pubkey());
|
||||
@@ -388,6 +397,7 @@ fn test_nonced_pay_tx() {
|
||||
&faucet_addr,
|
||||
&config.signers[0].pubkey(),
|
||||
50 + minimum_nonce_balance,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(
|
||||
|
@@ -1,5 +1,6 @@
|
||||
use solana_cli::{
|
||||
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
|
||||
cli_output::OutputFormat,
|
||||
nonce,
|
||||
offline::{
|
||||
blockhash_query::{self, BlockhashQuery},
|
||||
@@ -59,6 +60,7 @@ fn test_stake_delegation_force() {
|
||||
&faucet_addr,
|
||||
&config.signers[0].pubkey(),
|
||||
100_000,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -155,6 +157,7 @@ fn test_seed_stake_delegation_and_deactivation() {
|
||||
&faucet_addr,
|
||||
&config_validator.signers[0].pubkey(),
|
||||
100_000,
|
||||
&config_validator,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
|
||||
@@ -245,6 +248,7 @@ fn test_stake_delegation_and_deactivation() {
|
||||
&faucet_addr,
|
||||
&config_validator.signers[0].pubkey(),
|
||||
100_000,
|
||||
&config_validator,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
|
||||
@@ -341,6 +345,7 @@ fn test_offline_stake_delegation_and_deactivation() {
|
||||
&faucet_addr,
|
||||
&config_validator.signers[0].pubkey(),
|
||||
100_000,
|
||||
&config_offline,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
|
||||
@@ -350,6 +355,7 @@ fn test_offline_stake_delegation_and_deactivation() {
|
||||
&faucet_addr,
|
||||
&config_offline.signers[0].pubkey(),
|
||||
100_000,
|
||||
&config_validator,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &config_offline.signers[0].pubkey());
|
||||
@@ -385,6 +391,7 @@ fn test_offline_stake_delegation_and_deactivation() {
|
||||
nonce_authority: 0,
|
||||
fee_payer: 0,
|
||||
};
|
||||
config_offline.output_format = OutputFormat::JsonCompact;
|
||||
let sig_response = process_command(&config_offline).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sig_response);
|
||||
assert!(sign_only.has_all_signers());
|
||||
@@ -470,6 +477,7 @@ fn test_nonced_stake_delegation_and_deactivation() {
|
||||
&faucet_addr,
|
||||
&config.signers[0].pubkey(),
|
||||
100_000,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -579,6 +587,7 @@ fn test_stake_authorize() {
|
||||
&faucet_addr,
|
||||
&config.signers[0].pubkey(),
|
||||
100_000,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -596,6 +605,7 @@ fn test_stake_authorize() {
|
||||
&faucet_addr,
|
||||
&config_offline.signers[0].pubkey(),
|
||||
100_000,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -703,6 +713,7 @@ fn test_stake_authorize() {
|
||||
nonce_authority: 0,
|
||||
fee_payer: 0,
|
||||
};
|
||||
config_offline.output_format = OutputFormat::JsonCompact;
|
||||
let sign_reply = process_command(&config_offline).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sign_reply);
|
||||
assert!(sign_only.has_all_signers());
|
||||
@@ -841,13 +852,16 @@ fn test_stake_authorize_with_fee_payer() {
|
||||
config_offline.command = CliCommand::ClusterVersion;
|
||||
process_command(&config_offline).unwrap_err();
|
||||
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &default_pubkey, 100_000).unwrap();
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &default_pubkey, 100_000, &config)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &config.signers[0].pubkey());
|
||||
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &payer_pubkey, 100_000).unwrap();
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &payer_pubkey, 100_000, &config)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &payer_pubkey);
|
||||
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000).unwrap();
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000, &config)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &offline_pubkey);
|
||||
|
||||
// Create stake account, identity is authority
|
||||
@@ -901,6 +915,7 @@ fn test_stake_authorize_with_fee_payer() {
|
||||
nonce_authority: 0,
|
||||
fee_payer: 0,
|
||||
};
|
||||
config_offline.output_format = OutputFormat::JsonCompact;
|
||||
let sign_reply = process_command(&config_offline).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sign_reply);
|
||||
assert!(sign_only.has_all_signers());
|
||||
@@ -966,11 +981,13 @@ fn test_stake_split() {
|
||||
&faucet_addr,
|
||||
&config.signers[0].pubkey(),
|
||||
500_000,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(500_000, &rpc_client, &config.signers[0].pubkey());
|
||||
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000).unwrap();
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000, &config)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &offline_pubkey);
|
||||
|
||||
// Create stake account, identity is authority
|
||||
@@ -1038,6 +1055,7 @@ fn test_stake_split() {
|
||||
lamports: 2 * minimum_stake_balance,
|
||||
fee_payer: 0,
|
||||
};
|
||||
config_offline.output_format = OutputFormat::JsonCompact;
|
||||
let sig_response = process_command(&config_offline).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sig_response);
|
||||
assert!(sign_only.has_all_signers());
|
||||
@@ -1114,11 +1132,13 @@ fn test_stake_set_lockup() {
|
||||
&faucet_addr,
|
||||
&config.signers[0].pubkey(),
|
||||
500_000,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(500_000, &rpc_client, &config.signers[0].pubkey());
|
||||
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000).unwrap();
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000, &config)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &offline_pubkey);
|
||||
|
||||
// Create stake account, identity is authority
|
||||
@@ -1292,6 +1312,7 @@ fn test_stake_set_lockup() {
|
||||
nonce_authority: 0,
|
||||
fee_payer: 0,
|
||||
};
|
||||
config_offline.output_format = OutputFormat::JsonCompact;
|
||||
let sig_response = process_command(&config_offline).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sig_response);
|
||||
assert!(sign_only.has_all_signers());
|
||||
@@ -1364,11 +1385,13 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
|
||||
&faucet_addr,
|
||||
&config.signers[0].pubkey(),
|
||||
200_000,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(200_000, &rpc_client, &config.signers[0].pubkey());
|
||||
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000).unwrap();
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000, &config)
|
||||
.unwrap();
|
||||
check_balance(100_000, &rpc_client, &offline_pubkey);
|
||||
|
||||
// Create nonce account
|
||||
@@ -1410,6 +1433,7 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
|
||||
fee_payer: 0,
|
||||
from: 0,
|
||||
};
|
||||
config_offline.output_format = OutputFormat::JsonCompact;
|
||||
let sig_response = process_command(&config_offline).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sig_response);
|
||||
assert!(sign_only.has_all_signers());
|
||||
|
@@ -1,5 +1,6 @@
|
||||
use solana_cli::{
|
||||
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
|
||||
cli_output::OutputFormat,
|
||||
nonce,
|
||||
offline::{
|
||||
blockhash_query::{self, BlockhashQuery},
|
||||
@@ -59,7 +60,8 @@ fn test_transfer() {
|
||||
let sender_pubkey = config.signers[0].pubkey();
|
||||
let recipient_pubkey = Pubkey::new(&[1u8; 32]);
|
||||
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &sender_pubkey, 50_000).unwrap();
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &sender_pubkey, 50_000, &config)
|
||||
.unwrap();
|
||||
check_balance(50_000, &rpc_client, &sender_pubkey);
|
||||
check_balance(0, &rpc_client, &recipient_pubkey);
|
||||
|
||||
@@ -87,7 +89,7 @@ fn test_transfer() {
|
||||
process_command(&offline).unwrap_err();
|
||||
|
||||
let offline_pubkey = offline.signers[0].pubkey();
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 50).unwrap();
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 50, &config).unwrap();
|
||||
check_balance(50, &rpc_client, &offline_pubkey);
|
||||
|
||||
// Offline transfer
|
||||
@@ -103,6 +105,7 @@ fn test_transfer() {
|
||||
nonce_authority: 0,
|
||||
fee_payer: 0,
|
||||
};
|
||||
offline.output_format = OutputFormat::JsonCompact;
|
||||
let sign_only_reply = process_command(&offline).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sign_only_reply);
|
||||
assert!(sign_only.has_all_signers());
|
||||
@@ -247,16 +250,24 @@ fn test_transfer_multisession_signing() {
|
||||
let offline_from_signer = keypair_from_seed(&[2u8; 32]).unwrap();
|
||||
let offline_fee_payer_signer = keypair_from_seed(&[3u8; 32]).unwrap();
|
||||
let from_null_signer = NullSigner::new(&offline_from_signer.pubkey());
|
||||
let config = CliConfig::default();
|
||||
|
||||
// Setup accounts
|
||||
let rpc_client = RpcClient::new_socket(leader_data.rpc);
|
||||
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_from_signer.pubkey(), 43)
|
||||
.unwrap();
|
||||
request_and_confirm_airdrop(
|
||||
&rpc_client,
|
||||
&faucet_addr,
|
||||
&offline_from_signer.pubkey(),
|
||||
43,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
request_and_confirm_airdrop(
|
||||
&rpc_client,
|
||||
&faucet_addr,
|
||||
&offline_fee_payer_signer.pubkey(),
|
||||
3,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
check_balance(43, &rpc_client, &offline_from_signer.pubkey());
|
||||
@@ -283,6 +294,7 @@ fn test_transfer_multisession_signing() {
|
||||
nonce_authority: 0,
|
||||
fee_payer: 0,
|
||||
};
|
||||
fee_payer_config.output_format = OutputFormat::JsonCompact;
|
||||
let sign_only_reply = process_command(&fee_payer_config).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sign_only_reply);
|
||||
assert!(!sign_only.has_all_signers());
|
||||
@@ -308,6 +320,7 @@ fn test_transfer_multisession_signing() {
|
||||
nonce_authority: 0,
|
||||
fee_payer: 0,
|
||||
};
|
||||
from_config.output_format = OutputFormat::JsonCompact;
|
||||
let sign_only_reply = process_command(&from_config).unwrap();
|
||||
let sign_only = parse_sign_only_reply_string(&sign_only_reply);
|
||||
assert!(sign_only.has_all_signers());
|
||||
|
@@ -48,6 +48,7 @@ fn test_vote_authorize_and_withdraw() {
|
||||
&faucet_addr,
|
||||
&config.signers[0].pubkey(),
|
||||
100_000,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-client"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Client"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -19,10 +19,10 @@ reqwest = { version = "0.10.4", default-features = false, features = ["blocking"
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.48"
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.8" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.10" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.10" }
|
||||
thiserror = "1.0"
|
||||
tungstenite = "0.10.1"
|
||||
url = "2.1.1"
|
||||
@@ -31,7 +31,7 @@ url = "2.1.1"
|
||||
assert_matches = "1.3.0"
|
||||
jsonrpc-core = "14.0.5"
|
||||
jsonrpc-http-server = "14.0.6"
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -192,3 +192,10 @@ pub struct RpcStorageTurn {
|
||||
pub blockhash: String,
|
||||
pub slot: Slot,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcAccountBalance {
|
||||
pub address: String,
|
||||
pub lamports: u64,
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-core"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "../README.md"
|
||||
@@ -41,36 +41,36 @@ regex = "1.3.6"
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.48"
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.1.8" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-client = { path = "../client", version = "1.1.8" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.8" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.8" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.1.10" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.10" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-client = { path = "../client", version = "1.1.10" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.10" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.10" }
|
||||
ed25519-dalek = "=1.0.0-pre.3"
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.1.8" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.8" }
|
||||
solana-measure = { path = "../measure", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-chacha-cuda = { path = "../chacha-cuda", version = "1.1.8" }
|
||||
solana-perf = { path = "../perf", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.8" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.8" }
|
||||
solana-streamer = { path = "../streamer", version = "1.1.8" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.8" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.1.8" }
|
||||
solana-sys-tuner = { path = "../sys-tuner", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.1.10" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.10" }
|
||||
solana-measure = { path = "../measure", version = "1.1.10" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
solana-chacha-cuda = { path = "../chacha-cuda", version = "1.1.10" }
|
||||
solana-perf = { path = "../perf", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.10" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.10" }
|
||||
solana-streamer = { path = "../streamer", version = "1.1.10" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.10" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.1.10" }
|
||||
solana-sys-tuner = { path = "../sys-tuner", version = "1.1.10" }
|
||||
tempfile = "3.1.0"
|
||||
thiserror = "1.0"
|
||||
tokio = "0.1"
|
||||
tokio-codec = "0.1"
|
||||
tokio-fs = "0.1"
|
||||
tokio-io = "0.1"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.1.8" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.1.10" }
|
||||
trees = "0.2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -267,7 +267,11 @@ impl ClusterInfo {
|
||||
my_contact_info: RwLock::new(contact_info),
|
||||
id,
|
||||
};
|
||||
me.gossip.write().unwrap().set_self(&id);
|
||||
{
|
||||
let mut gossip = me.gossip.write().unwrap();
|
||||
gossip.set_self(&id);
|
||||
gossip.set_shred_version(me.my_shred_version());
|
||||
}
|
||||
me.insert_self();
|
||||
me.push_self(&HashMap::new());
|
||||
me
|
||||
@@ -361,51 +365,59 @@ impl ClusterInfo {
|
||||
let now = timestamp();
|
||||
let mut spy_nodes = 0;
|
||||
let mut archivers = 0;
|
||||
let mut different_shred_nodes = 0;
|
||||
let my_pubkey = self.id();
|
||||
let my_shred_version = self.my_shred_version();
|
||||
let nodes: Vec<_> = self
|
||||
.all_peers()
|
||||
.into_iter()
|
||||
.map(|(node, last_updated)| {
|
||||
.filter_map(|(node, last_updated)| {
|
||||
if Self::is_spy_node(&node) {
|
||||
spy_nodes += 1;
|
||||
} else if Self::is_archiver(&node) {
|
||||
archivers += 1;
|
||||
}
|
||||
fn addr_to_string(default_ip: &IpAddr, addr: &SocketAddr) -> String {
|
||||
if ContactInfo::is_valid_address(addr) {
|
||||
if &addr.ip() == default_ip {
|
||||
addr.port().to_string()
|
||||
} else {
|
||||
addr.to_string()
|
||||
}
|
||||
} else {
|
||||
"none".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
let ip_addr = node.gossip.ip();
|
||||
format!(
|
||||
"{:15} {:2}| {:5} | {:44} | {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
|
||||
if ContactInfo::is_valid_address(&node.gossip) {
|
||||
ip_addr.to_string()
|
||||
} else {
|
||||
"none".to_string()
|
||||
},
|
||||
if node.id == my_pubkey { "me" } else { "" }.to_string(),
|
||||
now.saturating_sub(last_updated),
|
||||
node.id.to_string(),
|
||||
addr_to_string(&ip_addr, &node.gossip),
|
||||
addr_to_string(&ip_addr, &node.tpu),
|
||||
addr_to_string(&ip_addr, &node.tpu_forwards),
|
||||
addr_to_string(&ip_addr, &node.tvu),
|
||||
addr_to_string(&ip_addr, &node.tvu_forwards),
|
||||
addr_to_string(&ip_addr, &node.repair),
|
||||
addr_to_string(&ip_addr, &node.serve_repair),
|
||||
addr_to_string(&ip_addr, &node.storage_addr),
|
||||
addr_to_string(&ip_addr, &node.rpc),
|
||||
addr_to_string(&ip_addr, &node.rpc_pubsub),
|
||||
node.shred_version,
|
||||
)
|
||||
if my_shred_version != 0 && (node.shred_version != 0 && node.shred_version != my_shred_version) {
|
||||
different_shred_nodes += 1;
|
||||
None
|
||||
} else {
|
||||
fn addr_to_string(default_ip: &IpAddr, addr: &SocketAddr) -> String {
|
||||
if ContactInfo::is_valid_address(addr) {
|
||||
if &addr.ip() == default_ip {
|
||||
addr.port().to_string()
|
||||
} else {
|
||||
addr.to_string()
|
||||
}
|
||||
} else {
|
||||
"none".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
let ip_addr = node.gossip.ip();
|
||||
Some(format!(
|
||||
"{:15} {:2}| {:5} | {:44} | {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
|
||||
if ContactInfo::is_valid_address(&node.gossip) {
|
||||
ip_addr.to_string()
|
||||
} else {
|
||||
"none".to_string()
|
||||
},
|
||||
if node.id == my_pubkey { "me" } else { "" }.to_string(),
|
||||
now.saturating_sub(last_updated),
|
||||
node.id.to_string(),
|
||||
addr_to_string(&ip_addr, &node.gossip),
|
||||
addr_to_string(&ip_addr, &node.tpu),
|
||||
addr_to_string(&ip_addr, &node.tpu_forwards),
|
||||
addr_to_string(&ip_addr, &node.tvu),
|
||||
addr_to_string(&ip_addr, &node.tvu_forwards),
|
||||
addr_to_string(&ip_addr, &node.repair),
|
||||
addr_to_string(&ip_addr, &node.serve_repair),
|
||||
addr_to_string(&ip_addr, &node.storage_addr),
|
||||
addr_to_string(&ip_addr, &node.rpc),
|
||||
addr_to_string(&ip_addr, &node.rpc_pubsub),
|
||||
node.shred_version,
|
||||
))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -415,7 +427,7 @@ impl ClusterInfo {
|
||||
------------------+-------+----------------------------------------------+\
|
||||
------+------+------+------+------+------+------+------+------+------+--------\n\
|
||||
{}\
|
||||
Nodes: {}{}{}",
|
||||
Nodes: {}{}{}{}",
|
||||
nodes.join(""),
|
||||
nodes.len() - spy_nodes - archivers,
|
||||
if archivers > 0 {
|
||||
@@ -427,6 +439,14 @@ impl ClusterInfo {
|
||||
format!("\nSpies: {}", spy_nodes)
|
||||
} else {
|
||||
"".to_string()
|
||||
},
|
||||
if spy_nodes > 0 {
|
||||
format!(
|
||||
"\nNodes with different shred version: {}",
|
||||
different_shred_nodes
|
||||
)
|
||||
} else {
|
||||
"".to_string()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1350,6 +1370,10 @@ impl ClusterInfo {
|
||||
);
|
||||
obj.my_contact_info.write().unwrap().shred_version =
|
||||
entrypoint.shred_version;
|
||||
obj.gossip
|
||||
.write()
|
||||
.unwrap()
|
||||
.set_shred_version(entrypoint.shred_version);
|
||||
obj.insert_self();
|
||||
adopt_shred_version = false;
|
||||
}
|
||||
@@ -1735,7 +1759,10 @@ impl ClusterInfo {
|
||||
requests.push(more_reqs)
|
||||
}
|
||||
if num_requests >= MAX_GOSSIP_TRAFFIC {
|
||||
warn!("Too much gossip traffic, ignoring some messages");
|
||||
warn!(
|
||||
"Too much gossip traffic, ignoring some messages (requests={}, max requests={})",
|
||||
num_requests, MAX_GOSSIP_TRAFFIC
|
||||
);
|
||||
}
|
||||
let epoch_ms;
|
||||
let stakes: HashMap<_, _> = match bank_forks {
|
||||
|
@@ -162,6 +162,24 @@ impl BlockCommitmentCache {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn new_for_tests_with_blockstore_bank(
|
||||
blockstore: Arc<Blockstore>,
|
||||
bank: Arc<Bank>,
|
||||
root: Slot,
|
||||
) -> Self {
|
||||
let mut block_commitment: HashMap<Slot, BlockCommitment> = HashMap::new();
|
||||
block_commitment.insert(0, BlockCommitment::default());
|
||||
Self {
|
||||
block_commitment,
|
||||
blockstore,
|
||||
total_stake: 42,
|
||||
largest_confirmed_root: root,
|
||||
bank,
|
||||
root,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn set_get_largest_confirmed_root(&mut self, root: Slot) {
|
||||
self.largest_confirmed_root = root;
|
||||
|
@@ -20,6 +20,7 @@ pub const CRDS_GOSSIP_DEFAULT_BLOOM_ITEMS: usize = 500;
|
||||
pub struct CrdsGossip {
|
||||
pub crds: Crds,
|
||||
pub id: Pubkey,
|
||||
pub shred_version: u16,
|
||||
pub push: CrdsGossipPush,
|
||||
pub pull: CrdsGossipPull,
|
||||
}
|
||||
@@ -29,6 +30,7 @@ impl Default for CrdsGossip {
|
||||
CrdsGossip {
|
||||
crds: Crds::default(),
|
||||
id: Pubkey::default(),
|
||||
shred_version: 0,
|
||||
push: CrdsGossipPush::default(),
|
||||
pull: CrdsGossipPull::default(),
|
||||
}
|
||||
@@ -39,6 +41,9 @@ impl CrdsGossip {
|
||||
pub fn set_self(&mut self, id: &Pubkey) {
|
||||
self.id = *id;
|
||||
}
|
||||
pub fn set_shred_version(&mut self, shred_version: u16) {
|
||||
self.shred_version = shred_version;
|
||||
}
|
||||
|
||||
/// process a push message to the network
|
||||
pub fn process_push_message(
|
||||
@@ -122,6 +127,7 @@ impl CrdsGossip {
|
||||
&self.crds,
|
||||
stakes,
|
||||
&self.id,
|
||||
self.shred_version,
|
||||
self.pull.pull_request_time.len(),
|
||||
CRDS_GOSSIP_NUM_ACTIVE,
|
||||
)
|
||||
@@ -134,8 +140,14 @@ impl CrdsGossip {
|
||||
stakes: &HashMap<Pubkey, u64>,
|
||||
bloom_size: usize,
|
||||
) -> Result<(Pubkey, Vec<CrdsFilter>, CrdsValue), CrdsGossipError> {
|
||||
self.pull
|
||||
.new_pull_request(&self.crds, &self.id, now, stakes, bloom_size)
|
||||
self.pull.new_pull_request(
|
||||
&self.crds,
|
||||
&self.id,
|
||||
self.shred_version,
|
||||
now,
|
||||
stakes,
|
||||
bloom_size,
|
||||
)
|
||||
}
|
||||
|
||||
/// time when a request to `from` was initiated
|
||||
|
@@ -144,11 +144,12 @@ impl CrdsGossipPull {
|
||||
&self,
|
||||
crds: &Crds,
|
||||
self_id: &Pubkey,
|
||||
self_shred_version: u16,
|
||||
now: u64,
|
||||
stakes: &HashMap<Pubkey, u64>,
|
||||
bloom_size: usize,
|
||||
) -> Result<(Pubkey, Vec<CrdsFilter>, CrdsValue), CrdsGossipError> {
|
||||
let options = self.pull_options(crds, &self_id, now, stakes);
|
||||
let options = self.pull_options(crds, &self_id, self_shred_version, now, stakes);
|
||||
if options.is_empty() {
|
||||
return Err(CrdsGossipError::NoPeers);
|
||||
}
|
||||
@@ -165,13 +166,20 @@ impl CrdsGossipPull {
|
||||
&self,
|
||||
crds: &'a Crds,
|
||||
self_id: &Pubkey,
|
||||
self_shred_version: u16,
|
||||
now: u64,
|
||||
stakes: &HashMap<Pubkey, u64>,
|
||||
) -> Vec<(f32, &'a ContactInfo)> {
|
||||
crds.table
|
||||
.values()
|
||||
.filter_map(|v| v.value.contact_info())
|
||||
.filter(|v| v.id != *self_id && ContactInfo::is_valid_address(&v.gossip))
|
||||
.filter(|v| {
|
||||
v.id != *self_id
|
||||
&& ContactInfo::is_valid_address(&v.gossip)
|
||||
&& (self_shred_version == 0
|
||||
|| v.shred_version == 0
|
||||
|| self_shred_version == v.shred_version)
|
||||
})
|
||||
.map(|item| {
|
||||
let max_weight = f32::from(u16::max_value()) - 1.0;
|
||||
let req_time: u64 = *self.pull_request_time.get(&item.id).unwrap_or(&0);
|
||||
@@ -402,7 +410,7 @@ mod test {
|
||||
stakes.insert(id, i * 100);
|
||||
}
|
||||
let now = 1024;
|
||||
let mut options = node.pull_options(&crds, &me.label().pubkey(), now, &stakes);
|
||||
let mut options = node.pull_options(&crds, &me.label().pubkey(), 0, now, &stakes);
|
||||
assert!(!options.is_empty());
|
||||
options.sort_by(|(weight_l, _), (weight_r, _)| weight_r.partial_cmp(weight_l).unwrap());
|
||||
// check that the highest stake holder is also the heaviest weighted.
|
||||
@@ -412,6 +420,66 @@ mod test {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_pulls_from_different_shred_versions() {
|
||||
let mut crds = Crds::default();
|
||||
let stakes = HashMap::new();
|
||||
let node = CrdsGossipPull::default();
|
||||
|
||||
let gossip = socketaddr!("127.0.0.1:1234");
|
||||
|
||||
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
shred_version: 123,
|
||||
gossip: gossip.clone(),
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let spy = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
shred_version: 0,
|
||||
gossip: gossip.clone(),
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
shred_version: 123,
|
||||
gossip: gossip.clone(),
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_456 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
shred_version: 456,
|
||||
gossip: gossip.clone(),
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
|
||||
crds.insert(me.clone(), 0).unwrap();
|
||||
crds.insert(spy.clone(), 0).unwrap();
|
||||
crds.insert(node_123.clone(), 0).unwrap();
|
||||
crds.insert(node_456.clone(), 0).unwrap();
|
||||
|
||||
// shred version 123 should ignore 456 nodes
|
||||
let options = node
|
||||
.pull_options(&crds, &me.label().pubkey(), 123, 0, &stakes)
|
||||
.iter()
|
||||
.map(|(_, c)| c.id)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(options.len(), 2);
|
||||
assert!(options.contains(&spy.pubkey()));
|
||||
assert!(options.contains(&node_123.pubkey()));
|
||||
|
||||
// spy nodes will see all
|
||||
let options = node
|
||||
.pull_options(&crds, &spy.label().pubkey(), 0, 0, &stakes)
|
||||
.iter()
|
||||
.map(|(_, c)| c.id)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(options.len(), 3);
|
||||
assert!(options.contains(&me.pubkey()));
|
||||
assert!(options.contains(&node_123.pubkey()));
|
||||
assert!(options.contains(&node_456.pubkey()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_pull_request() {
|
||||
let mut crds = Crds::default();
|
||||
@@ -422,13 +490,13 @@ mod test {
|
||||
let id = entry.label().pubkey();
|
||||
let node = CrdsGossipPull::default();
|
||||
assert_eq!(
|
||||
node.new_pull_request(&crds, &id, 0, &HashMap::new(), PACKET_DATA_SIZE),
|
||||
node.new_pull_request(&crds, &id, 0, 0, &HashMap::new(), PACKET_DATA_SIZE),
|
||||
Err(CrdsGossipError::NoPeers)
|
||||
);
|
||||
|
||||
crds.insert(entry.clone(), 0).unwrap();
|
||||
assert_eq!(
|
||||
node.new_pull_request(&crds, &id, 0, &HashMap::new(), PACKET_DATA_SIZE),
|
||||
node.new_pull_request(&crds, &id, 0, 0, &HashMap::new(), PACKET_DATA_SIZE),
|
||||
Err(CrdsGossipError::NoPeers)
|
||||
);
|
||||
|
||||
@@ -437,7 +505,7 @@ mod test {
|
||||
0,
|
||||
)));
|
||||
crds.insert(new.clone(), 0).unwrap();
|
||||
let req = node.new_pull_request(&crds, &id, 0, &HashMap::new(), PACKET_DATA_SIZE);
|
||||
let req = node.new_pull_request(&crds, &id, 0, 0, &HashMap::new(), PACKET_DATA_SIZE);
|
||||
let (to, _, self_info) = req.unwrap();
|
||||
assert_eq!(to, new.label().pubkey());
|
||||
assert_eq!(self_info, entry);
|
||||
@@ -472,6 +540,7 @@ mod test {
|
||||
let req = node.new_pull_request(
|
||||
&crds,
|
||||
&node_pubkey,
|
||||
0,
|
||||
u64::max_value(),
|
||||
&HashMap::new(),
|
||||
PACKET_DATA_SIZE,
|
||||
@@ -501,6 +570,7 @@ mod test {
|
||||
&node_crds,
|
||||
&node_pubkey,
|
||||
0,
|
||||
0,
|
||||
&HashMap::new(),
|
||||
PACKET_DATA_SIZE,
|
||||
);
|
||||
@@ -573,6 +643,7 @@ mod test {
|
||||
&node_crds,
|
||||
&node_pubkey,
|
||||
0,
|
||||
0,
|
||||
&HashMap::new(),
|
||||
PACKET_DATA_SIZE,
|
||||
);
|
||||
|
@@ -236,13 +236,14 @@ impl CrdsGossipPush {
|
||||
crds: &Crds,
|
||||
stakes: &HashMap<Pubkey, u64>,
|
||||
self_id: &Pubkey,
|
||||
self_shred_version: u16,
|
||||
network_size: usize,
|
||||
ratio: usize,
|
||||
) {
|
||||
let need = Self::compute_need(self.num_active, self.active_set.len(), ratio);
|
||||
let mut new_items = HashMap::new();
|
||||
|
||||
let options: Vec<_> = self.push_options(crds, &self_id, stakes);
|
||||
let options: Vec<_> = self.push_options(crds, &self_id, self_shred_version, stakes);
|
||||
if options.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -288,13 +289,20 @@ impl CrdsGossipPush {
|
||||
&self,
|
||||
crds: &'a Crds,
|
||||
self_id: &Pubkey,
|
||||
self_shred_version: u16,
|
||||
stakes: &HashMap<Pubkey, u64>,
|
||||
) -> Vec<(f32, &'a ContactInfo)> {
|
||||
crds.table
|
||||
.values()
|
||||
.filter(|v| v.value.contact_info().is_some())
|
||||
.map(|v| (v.value.contact_info().unwrap(), v))
|
||||
.filter(|(info, _)| info.id != *self_id && ContactInfo::is_valid_address(&info.gossip))
|
||||
.filter(|(info, _)| {
|
||||
info.id != *self_id
|
||||
&& ContactInfo::is_valid_address(&info.gossip)
|
||||
&& (self_shred_version == 0
|
||||
|| info.shred_version == 0
|
||||
|| self_shred_version == info.shred_version)
|
||||
})
|
||||
.map(|(info, value)| {
|
||||
let max_weight = f32::from(u16::max_value()) - 1.0;
|
||||
let last_updated: u64 = value.local_timestamp;
|
||||
@@ -510,7 +518,7 @@ mod test {
|
||||
)));
|
||||
|
||||
assert_eq!(crds.insert(value1.clone(), 0), Ok(None));
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 1, 1);
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 0, 1, 1);
|
||||
|
||||
assert!(push.active_set.get(&value1.label().pubkey()).is_some());
|
||||
let value2 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
@@ -520,7 +528,7 @@ mod test {
|
||||
assert!(push.active_set.get(&value2.label().pubkey()).is_none());
|
||||
assert_eq!(crds.insert(value2.clone(), 0), Ok(None));
|
||||
for _ in 0..30 {
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 1, 1);
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 0, 1, 1);
|
||||
if push.active_set.get(&value2.label().pubkey()).is_some() {
|
||||
break;
|
||||
}
|
||||
@@ -533,7 +541,7 @@ mod test {
|
||||
));
|
||||
assert_eq!(crds.insert(value2.clone(), 0), Ok(None));
|
||||
}
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 1, 1);
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 0, 1, 1);
|
||||
assert_eq!(push.active_set.len(), push.num_active);
|
||||
}
|
||||
#[test]
|
||||
@@ -551,7 +559,7 @@ mod test {
|
||||
crds.insert(peer.clone(), time).unwrap();
|
||||
stakes.insert(id, i * 100);
|
||||
}
|
||||
let mut options = push.push_options(&crds, &Pubkey::default(), &stakes);
|
||||
let mut options = push.push_options(&crds, &Pubkey::default(), 0, &stakes);
|
||||
assert!(!options.is_empty());
|
||||
options.sort_by(|(weight_l, _), (weight_r, _)| weight_r.partial_cmp(weight_l).unwrap());
|
||||
// check that the highest stake holder is also the heaviest weighted.
|
||||
@@ -560,6 +568,66 @@ mod test {
|
||||
10_000_u64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_pushes_to_from_different_shred_versions() {
|
||||
let mut crds = Crds::default();
|
||||
let stakes = HashMap::new();
|
||||
let node = CrdsGossipPush::default();
|
||||
|
||||
let gossip = socketaddr!("127.0.0.1:1234");
|
||||
|
||||
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
shred_version: 123,
|
||||
gossip: gossip.clone(),
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let spy = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
shred_version: 0,
|
||||
gossip: gossip.clone(),
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
shred_version: 123,
|
||||
gossip: gossip.clone(),
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
let node_456 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
|
||||
id: Pubkey::new_rand(),
|
||||
shred_version: 456,
|
||||
gossip: gossip.clone(),
|
||||
..ContactInfo::default()
|
||||
}));
|
||||
|
||||
crds.insert(me.clone(), 0).unwrap();
|
||||
crds.insert(spy.clone(), 0).unwrap();
|
||||
crds.insert(node_123.clone(), 0).unwrap();
|
||||
crds.insert(node_456.clone(), 0).unwrap();
|
||||
|
||||
// shred version 123 should ignore 456 nodes
|
||||
let options = node
|
||||
.push_options(&crds, &me.label().pubkey(), 123, &stakes)
|
||||
.iter()
|
||||
.map(|(_, c)| c.id)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(options.len(), 2);
|
||||
assert!(options.contains(&spy.pubkey()));
|
||||
assert!(options.contains(&node_123.pubkey()));
|
||||
|
||||
// spy nodes will see all
|
||||
let options = node
|
||||
.push_options(&crds, &spy.label().pubkey(), 0, &stakes)
|
||||
.iter()
|
||||
.map(|(_, c)| c.id)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(options.len(), 3);
|
||||
assert!(options.contains(&me.pubkey()));
|
||||
assert!(options.contains(&node_123.pubkey()));
|
||||
assert!(options.contains(&node_456.pubkey()));
|
||||
}
|
||||
#[test]
|
||||
fn test_new_push_messages() {
|
||||
let mut crds = Crds::default();
|
||||
@@ -569,7 +637,7 @@ mod test {
|
||||
0,
|
||||
)));
|
||||
assert_eq!(crds.insert(peer.clone(), 0), Ok(None));
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 1, 1);
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 0, 1, 1);
|
||||
|
||||
let new_msg = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
@@ -606,7 +674,7 @@ mod test {
|
||||
push.process_push_message(&mut crds, &Pubkey::default(), peer_3.clone(), 0),
|
||||
Ok(None)
|
||||
);
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 1, 1);
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 0, 1, 1);
|
||||
|
||||
// push 3's contact info to 1 and 2 and 3
|
||||
let new_msg = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
@@ -628,7 +696,7 @@ mod test {
|
||||
0,
|
||||
)));
|
||||
assert_eq!(crds.insert(peer.clone(), 0), Ok(None));
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 1, 1);
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 0, 1, 1);
|
||||
|
||||
let new_msg = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
@@ -651,7 +719,7 @@ mod test {
|
||||
0,
|
||||
)));
|
||||
assert_eq!(crds.insert(peer.clone(), 0), Ok(None));
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 1, 1);
|
||||
push.refresh_push_active_set(&crds, &HashMap::new(), &Pubkey::default(), 0, 1, 1);
|
||||
|
||||
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
|
||||
ci.wallclock = 1;
|
||||
|
@@ -297,10 +297,8 @@ impl ReplayStage {
|
||||
|
||||
// Vote on a fork
|
||||
if let Some(ref vote_bank) = vote_bank {
|
||||
subscriptions.notify_subscribers(
|
||||
block_commitment_cache.read().unwrap().slot(),
|
||||
&bank_forks,
|
||||
);
|
||||
subscriptions
|
||||
.notify_subscribers(block_commitment_cache.read().unwrap().slot());
|
||||
if let Some(votable_leader) =
|
||||
leader_schedule_cache.slot_leader_at(vote_bank.slot(), Some(vote_bank))
|
||||
{
|
||||
@@ -1994,12 +1992,6 @@ pub(crate) mod tests {
|
||||
);
|
||||
let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank0));
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
Arc::new(RwLock::new(BlockCommitmentCache::default_with_blockstore(
|
||||
blockstore.clone(),
|
||||
))),
|
||||
));
|
||||
let mut bank_forks = BankForks::new(0, bank0);
|
||||
|
||||
// Insert a non-root bank so that the propagation logic will update this
|
||||
@@ -2023,7 +2015,14 @@ pub(crate) mod tests {
|
||||
assert!(progress.get_propagated_stats(1).unwrap().is_leader_slot);
|
||||
bank1.freeze();
|
||||
bank_forks.insert(bank1);
|
||||
let bank_forks = RwLock::new(bank_forks);
|
||||
let bank_forks = Arc::new(RwLock::new(bank_forks));
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks.clone(),
|
||||
Arc::new(RwLock::new(BlockCommitmentCache::default_with_blockstore(
|
||||
blockstore.clone(),
|
||||
))),
|
||||
));
|
||||
|
||||
// Insert shreds for slot NUM_CONSECUTIVE_LEADER_SLOTS,
|
||||
// chaining to slot 1
|
||||
|
187
core/src/rpc.rs
187
core/src/rpc.rs
@@ -19,7 +19,7 @@ use solana_client::{
|
||||
use solana_faucet::faucet::request_airdrop_transaction;
|
||||
use solana_ledger::{bank_forks::BankForks, blockstore::Blockstore};
|
||||
use solana_perf::packet::PACKET_DATA_SIZE;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::{accounts::AccountAddressFilter, bank::Bank};
|
||||
use solana_sdk::{
|
||||
clock::{Slot, UnixTimestamp},
|
||||
commitment_config::{CommitmentConfig, CommitmentLevel},
|
||||
@@ -36,8 +36,8 @@ use solana_transaction_status::{
|
||||
};
|
||||
use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY};
|
||||
use std::{
|
||||
cmp::max,
|
||||
collections::HashMap,
|
||||
cmp::{max, min},
|
||||
collections::{HashMap, HashSet},
|
||||
net::{SocketAddr, UdpSocket},
|
||||
str::FromStr,
|
||||
sync::{Arc, RwLock},
|
||||
@@ -46,6 +46,7 @@ use std::{
|
||||
};
|
||||
|
||||
const JSON_RPC_SERVER_ERROR_0: i64 = -32000;
|
||||
const NUM_LARGEST_ACCOUNTS: usize = 20;
|
||||
|
||||
type RpcResponse<T> = Result<Response<T>>;
|
||||
|
||||
@@ -283,6 +284,27 @@ impl JsonRpcRequestProcessor {
|
||||
Ok(self.bank(commitment)?.capitalization())
|
||||
}
|
||||
|
||||
fn get_largest_accounts(
|
||||
&self,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> RpcResponse<Vec<RpcAccountBalance>> {
|
||||
let bank = self.bank(commitment)?;
|
||||
new_response(
|
||||
&bank,
|
||||
bank.get_largest_accounts(
|
||||
NUM_LARGEST_ACCOUNTS,
|
||||
&HashSet::new(),
|
||||
AccountAddressFilter::Exclude,
|
||||
)
|
||||
.into_iter()
|
||||
.map(|(address, lamports)| RpcAccountBalance {
|
||||
address: address.to_string(),
|
||||
lamports,
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_vote_accounts(
|
||||
&self,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
@@ -387,7 +409,14 @@ impl JsonRpcRequestProcessor {
|
||||
slot: Slot,
|
||||
encoding: Option<TransactionEncoding>,
|
||||
) -> Result<Option<ConfirmedBlock>> {
|
||||
if self.config.enable_rpc_transaction_history {
|
||||
if self.config.enable_rpc_transaction_history
|
||||
&& slot
|
||||
<= self
|
||||
.block_commitment_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.largest_confirmed_root()
|
||||
{
|
||||
Ok(self.blockstore.get_confirmed_block(slot, encoding).ok())
|
||||
} else {
|
||||
Ok(None)
|
||||
@@ -399,11 +428,13 @@ impl JsonRpcRequestProcessor {
|
||||
start_slot: Slot,
|
||||
end_slot: Option<Slot>,
|
||||
) -> Result<Vec<Slot>> {
|
||||
let end_slot = if let Some(end_slot) = end_slot {
|
||||
end_slot
|
||||
} else {
|
||||
self.bank(None)?.slot()
|
||||
};
|
||||
let end_slot = min(
|
||||
end_slot.unwrap_or(std::u64::MAX),
|
||||
self.block_commitment_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.largest_confirmed_root(),
|
||||
);
|
||||
if end_slot < start_slot {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
@@ -416,22 +447,32 @@ impl JsonRpcRequestProcessor {
|
||||
}
|
||||
|
||||
pub fn get_block_time(&self, slot: Slot) -> Result<Option<UnixTimestamp>> {
|
||||
// This calculation currently assumes that bank.slots_per_year will remain unchanged after
|
||||
// genesis (ie. that this bank's slot_per_year will be applicable to any rooted slot being
|
||||
// queried). If these values will be variable in the future, those timing parameters will
|
||||
// need to be stored persistently, and the slot_duration calculation will likely need to be
|
||||
// moved upstream into blockstore. Also, an explicit commitment level will need to be set.
|
||||
let bank = self.bank(None)?;
|
||||
let slot_duration = slot_duration_from_slots_per_year(bank.slots_per_year());
|
||||
let epoch = bank.epoch_schedule().get_epoch(slot);
|
||||
let stakes = HashMap::new();
|
||||
let stakes = bank.epoch_vote_accounts(epoch).unwrap_or(&stakes);
|
||||
if slot
|
||||
<= self
|
||||
.block_commitment_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.largest_confirmed_root()
|
||||
{
|
||||
// This calculation currently assumes that bank.slots_per_year will remain unchanged after
|
||||
// genesis (ie. that this bank's slot_per_year will be applicable to any rooted slot being
|
||||
// queried). If these values will be variable in the future, those timing parameters will
|
||||
// need to be stored persistently, and the slot_duration calculation will likely need to be
|
||||
// moved upstream into blockstore. Also, an explicit commitment level will need to be set.
|
||||
let bank = self.bank(None)?;
|
||||
let slot_duration = slot_duration_from_slots_per_year(bank.slots_per_year());
|
||||
let epoch = bank.epoch_schedule().get_epoch(slot);
|
||||
let stakes = HashMap::new();
|
||||
let stakes = bank.epoch_vote_accounts(epoch).unwrap_or(&stakes);
|
||||
|
||||
Ok(self
|
||||
.blockstore
|
||||
.get_block_time(slot, slot_duration, stakes)
|
||||
.ok()
|
||||
.unwrap_or(None))
|
||||
Ok(self
|
||||
.blockstore
|
||||
.get_block_time(slot, slot_duration, stakes)
|
||||
.ok()
|
||||
.unwrap_or(None))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_signature_confirmation_status(
|
||||
@@ -488,6 +529,13 @@ impl JsonRpcRequestProcessor {
|
||||
self.blockstore
|
||||
.get_transaction_status(signature)
|
||||
.map_err(|_| Error::internal_error())?
|
||||
.filter(|(slot, _status_meta)| {
|
||||
slot <= &self
|
||||
.block_commitment_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.largest_confirmed_root()
|
||||
})
|
||||
.map(|(slot, status_meta)| {
|
||||
let err = status_meta.status.clone().err();
|
||||
TransactionStatus {
|
||||
@@ -545,7 +593,15 @@ impl JsonRpcRequestProcessor {
|
||||
Ok(self
|
||||
.blockstore
|
||||
.get_confirmed_transaction(signature, encoding)
|
||||
.unwrap_or(None))
|
||||
.unwrap_or(None)
|
||||
.filter(|confirmed_transaction| {
|
||||
confirmed_transaction.slot
|
||||
<= self
|
||||
.block_commitment_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.largest_confirmed_root()
|
||||
}))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
@@ -558,6 +614,13 @@ impl JsonRpcRequestProcessor {
|
||||
end_slot: Slot,
|
||||
) -> Result<Vec<Signature>> {
|
||||
if self.config.enable_rpc_transaction_history {
|
||||
let end_slot = min(
|
||||
end_slot,
|
||||
self.block_commitment_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.largest_confirmed_root(),
|
||||
);
|
||||
Ok(self
|
||||
.blockstore
|
||||
.get_confirmed_signatures_for_address(pubkey, start_slot, end_slot)
|
||||
@@ -739,6 +802,13 @@ pub trait RpcSol {
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "getLargestAccounts")]
|
||||
fn get_largest_accounts(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> RpcResponse<Vec<RpcAccountBalance>>;
|
||||
|
||||
#[rpc(meta, name = "requestAirdrop")]
|
||||
fn request_airdrop(
|
||||
&self,
|
||||
@@ -1140,6 +1210,18 @@ impl RpcSol for RpcSolImpl {
|
||||
.get_total_supply(commitment)
|
||||
}
|
||||
|
||||
fn get_largest_accounts(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> RpcResponse<Vec<RpcAccountBalance>> {
|
||||
debug!("get_largest_accounts rpc request received");
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_largest_accounts(commitment)
|
||||
}
|
||||
|
||||
fn request_airdrop(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
@@ -1780,6 +1862,49 @@ pub mod tests {
|
||||
assert!(supply >= TEST_MINT_LAMPORTS);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_largest_accounts() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let RpcHandler {
|
||||
io, meta, alice, ..
|
||||
} = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getLargestAccounts"}}"#);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
|
||||
let largest_accounts: Vec<RpcAccountBalance> =
|
||||
serde_json::from_value(json["result"]["value"].clone())
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(largest_accounts.len(), 18);
|
||||
|
||||
// Get Alice balance
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["{}"]}}"#,
|
||||
alice.pubkey()
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
|
||||
let alice_balance: u64 = serde_json::from_value(json["result"]["value"].clone())
|
||||
.expect("actual response deserialization");
|
||||
assert!(largest_accounts.contains(&RpcAccountBalance {
|
||||
address: alice.pubkey().to_string(),
|
||||
lamports: alice_balance,
|
||||
}));
|
||||
|
||||
// Get Bob balance
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["{}"]}}"#,
|
||||
bob_pubkey
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
|
||||
let bob_balance: u64 = serde_json::from_value(json["result"]["value"].clone())
|
||||
.expect("actual response deserialization");
|
||||
assert!(largest_accounts.contains(&RpcAccountBalance {
|
||||
address: bob_pubkey.to_string(),
|
||||
lamports: bob_balance,
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_minimum_balance_for_rent_exemption() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
@@ -2735,11 +2860,21 @@ pub mod tests {
|
||||
fn test_get_block_time() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let base_timestamp = 1576183541;
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx_and_blockstore(
|
||||
let RpcHandler {
|
||||
io,
|
||||
meta,
|
||||
bank,
|
||||
block_commitment_cache,
|
||||
..
|
||||
} = start_rpc_handler_with_tx_and_blockstore(
|
||||
&bob_pubkey,
|
||||
vec![1, 2, 3, 4, 5, 6, 7],
|
||||
base_timestamp,
|
||||
);
|
||||
block_commitment_cache
|
||||
.write()
|
||||
.unwrap()
|
||||
.set_get_largest_confirmed_root(7);
|
||||
|
||||
let slot_duration = slot_duration_from_slots_per_year(bank.slots_per_year());
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
//! The `pubsub` module implements a threaded subscription service on client RPC request
|
||||
|
||||
use crate::rpc_subscriptions::{Confirmations, RpcSubscriptions, SlotInfo};
|
||||
use crate::rpc_subscriptions::{RpcSubscriptions, SlotInfo};
|
||||
use jsonrpc_core::{Error, ErrorCode, Result};
|
||||
use jsonrpc_derive::rpc;
|
||||
use jsonrpc_pubsub::{typed::Subscriber, Session, SubscriptionId};
|
||||
@@ -8,8 +8,12 @@ use solana_client::rpc_response::{
|
||||
Response as RpcResponse, RpcAccount, RpcKeyedAccount, RpcSignatureResult,
|
||||
};
|
||||
#[cfg(test)]
|
||||
use solana_ledger::blockstore::Blockstore;
|
||||
use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature};
|
||||
use solana_ledger::{bank_forks::BankForks, blockstore::Blockstore};
|
||||
use solana_sdk::{
|
||||
clock::Slot, commitment_config::CommitmentConfig, pubkey::Pubkey, signature::Signature,
|
||||
};
|
||||
#[cfg(test)]
|
||||
use std::sync::RwLock;
|
||||
use std::{
|
||||
str::FromStr,
|
||||
sync::{atomic, Arc},
|
||||
@@ -35,7 +39,7 @@ pub trait RpcSolPubSub {
|
||||
meta: Self::Metadata,
|
||||
subscriber: Subscriber<RpcResponse<RpcAccount>>,
|
||||
pubkey_str: String,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
);
|
||||
|
||||
// Unsubscribe from account notification subscription.
|
||||
@@ -59,7 +63,7 @@ pub trait RpcSolPubSub {
|
||||
meta: Self::Metadata,
|
||||
subscriber: Subscriber<RpcResponse<RpcKeyedAccount>>,
|
||||
pubkey_str: String,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
);
|
||||
|
||||
// Unsubscribe from account notification subscription.
|
||||
@@ -83,7 +87,7 @@ pub trait RpcSolPubSub {
|
||||
meta: Self::Metadata,
|
||||
subscriber: Subscriber<RpcResponse<RpcSignatureResult>>,
|
||||
signature_str: String,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
);
|
||||
|
||||
// Unsubscribe from signature notification subscription.
|
||||
@@ -135,9 +139,14 @@ impl RpcSolPubSubImpl {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn default_with_blockstore(blockstore: Arc<Blockstore>) -> Self {
|
||||
fn default_with_blockstore_bank_forks(
|
||||
blockstore: Arc<Blockstore>,
|
||||
bank_forks: Arc<RwLock<BankForks>>,
|
||||
) -> Self {
|
||||
let uid = Arc::new(atomic::AtomicUsize::default());
|
||||
let subscriptions = Arc::new(RpcSubscriptions::default_with_blockstore(blockstore));
|
||||
let subscriptions = Arc::new(RpcSubscriptions::default_with_blockstore_bank_forks(
|
||||
blockstore, bank_forks,
|
||||
));
|
||||
Self { uid, subscriptions }
|
||||
}
|
||||
}
|
||||
@@ -158,19 +167,15 @@ impl RpcSolPubSub for RpcSolPubSubImpl {
|
||||
_meta: Self::Metadata,
|
||||
subscriber: Subscriber<RpcResponse<RpcAccount>>,
|
||||
pubkey_str: String,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) {
|
||||
match param::<Pubkey>(&pubkey_str, "pubkey") {
|
||||
Ok(pubkey) => {
|
||||
let id = self.uid.fetch_add(1, atomic::Ordering::Relaxed);
|
||||
let sub_id = SubscriptionId::Number(id as u64);
|
||||
info!("account_subscribe: account={:?} id={:?}", pubkey, sub_id);
|
||||
self.subscriptions.add_account_subscription(
|
||||
pubkey,
|
||||
confirmations,
|
||||
sub_id,
|
||||
subscriber,
|
||||
)
|
||||
self.subscriptions
|
||||
.add_account_subscription(pubkey, commitment, sub_id, subscriber)
|
||||
}
|
||||
Err(e) => subscriber.reject(e).unwrap(),
|
||||
}
|
||||
@@ -198,19 +203,15 @@ impl RpcSolPubSub for RpcSolPubSubImpl {
|
||||
_meta: Self::Metadata,
|
||||
subscriber: Subscriber<RpcResponse<RpcKeyedAccount>>,
|
||||
pubkey_str: String,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) {
|
||||
match param::<Pubkey>(&pubkey_str, "pubkey") {
|
||||
Ok(pubkey) => {
|
||||
let id = self.uid.fetch_add(1, atomic::Ordering::Relaxed);
|
||||
let sub_id = SubscriptionId::Number(id as u64);
|
||||
info!("program_subscribe: account={:?} id={:?}", pubkey, sub_id);
|
||||
self.subscriptions.add_program_subscription(
|
||||
pubkey,
|
||||
confirmations,
|
||||
sub_id,
|
||||
subscriber,
|
||||
)
|
||||
self.subscriptions
|
||||
.add_program_subscription(pubkey, commitment, sub_id, subscriber)
|
||||
}
|
||||
Err(e) => subscriber.reject(e).unwrap(),
|
||||
}
|
||||
@@ -238,7 +239,7 @@ impl RpcSolPubSub for RpcSolPubSubImpl {
|
||||
_meta: Self::Metadata,
|
||||
subscriber: Subscriber<RpcResponse<RpcSignatureResult>>,
|
||||
signature_str: String,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) {
|
||||
info!("signature_subscribe");
|
||||
match param::<Signature>(&signature_str, "signature") {
|
||||
@@ -249,12 +250,8 @@ impl RpcSolPubSub for RpcSolPubSubImpl {
|
||||
"signature_subscribe: signature={:?} id={:?}",
|
||||
signature, sub_id
|
||||
);
|
||||
self.subscriptions.add_signature_subscription(
|
||||
signature,
|
||||
confirmations,
|
||||
sub_id,
|
||||
subscriber,
|
||||
);
|
||||
self.subscriptions
|
||||
.add_signature_subscription(signature, commitment, sub_id, subscriber);
|
||||
}
|
||||
Err(e) => subscriber.reject(e).unwrap(),
|
||||
}
|
||||
@@ -354,14 +351,15 @@ mod tests {
|
||||
bank_forks: &Arc<RwLock<BankForks>>,
|
||||
tx: &Transaction,
|
||||
subscriptions: &RpcSubscriptions,
|
||||
slot: Slot,
|
||||
) -> transaction::Result<()> {
|
||||
bank_forks
|
||||
.write()
|
||||
.unwrap()
|
||||
.get(0)
|
||||
.get(slot)
|
||||
.unwrap()
|
||||
.process_transaction(tx)?;
|
||||
subscriptions.notify_subscribers(0, &bank_forks);
|
||||
subscriptions.notify_subscribers(slot);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -387,6 +385,7 @@ mod tests {
|
||||
let rpc = RpcSolPubSubImpl {
|
||||
subscriptions: Arc::new(RpcSubscriptions::new(
|
||||
&Arc::new(AtomicBool::new(false)),
|
||||
bank_forks.clone(),
|
||||
Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
|
||||
)),
|
||||
@@ -401,7 +400,7 @@ mod tests {
|
||||
let (subscriber, _id_receiver, receiver) = Subscriber::new_test("signatureNotification");
|
||||
rpc.signature_subscribe(session, subscriber, tx.signatures[0].to_string(), None);
|
||||
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions).unwrap();
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions, 0).unwrap();
|
||||
|
||||
// Test signature confirmation notification
|
||||
let (response, _) = robust_poll_or_panic(receiver);
|
||||
@@ -430,15 +429,15 @@ mod tests {
|
||||
} = create_genesis_config(10_000);
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let arc_bank = Arc::new(bank);
|
||||
let blockhash = arc_bank.last_blockhash();
|
||||
let blockhash = bank.last_blockhash();
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
|
||||
let session = create_session();
|
||||
|
||||
let mut io = PubSubHandler::default();
|
||||
let rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore);
|
||||
let rpc = RpcSolPubSubImpl::default_with_blockstore_bank_forks(blockstore, bank_forks);
|
||||
io.extend_with(rpc.to_delegate());
|
||||
|
||||
let tx = system_transaction::transfer(&alice, &bob_pubkey, 20, blockhash);
|
||||
@@ -493,14 +492,22 @@ mod tests {
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let blockhash = bank.last_blockhash();
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let bank0 = bank_forks.read().unwrap().get(0).unwrap().clone();
|
||||
let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
|
||||
bank_forks.write().unwrap().insert(bank1);
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
|
||||
let rpc = RpcSolPubSubImpl {
|
||||
subscriptions: Arc::new(RpcSubscriptions::new(
|
||||
&Arc::new(AtomicBool::new(false)),
|
||||
bank_forks.clone(),
|
||||
Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore_bank(
|
||||
blockstore,
|
||||
bank_forks.read().unwrap().get(1).unwrap().clone(),
|
||||
1,
|
||||
),
|
||||
)),
|
||||
)),
|
||||
uid: Arc::new(atomic::AtomicUsize::default()),
|
||||
@@ -515,7 +522,7 @@ mod tests {
|
||||
);
|
||||
|
||||
let tx = system_transaction::transfer(&alice, &contract_funds.pubkey(), 51, blockhash);
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions).unwrap();
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions, 1).unwrap();
|
||||
|
||||
let ixs = budget_instruction::when_signed(
|
||||
&contract_funds.pubkey(),
|
||||
@@ -530,14 +537,14 @@ mod tests {
|
||||
ixs,
|
||||
blockhash,
|
||||
);
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions).unwrap();
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions, 1).unwrap();
|
||||
sleep(Duration::from_millis(200));
|
||||
|
||||
// Test signature confirmation notification #1
|
||||
let expected_data = bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(0)
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.get_account(&contract_state.pubkey())
|
||||
.unwrap()
|
||||
@@ -547,7 +554,7 @@ mod tests {
|
||||
"method": "accountNotification",
|
||||
"params": {
|
||||
"result": {
|
||||
"context": { "slot": 0 },
|
||||
"context": { "slot": 1 },
|
||||
"value": {
|
||||
"owner": budget_program_id.to_string(),
|
||||
"lamports": 51,
|
||||
@@ -564,7 +571,7 @@ mod tests {
|
||||
assert_eq!(serde_json::to_string(&expected).unwrap(), response);
|
||||
|
||||
let tx = system_transaction::transfer(&alice, &witness.pubkey(), 1, blockhash);
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions).unwrap();
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions, 1).unwrap();
|
||||
sleep(Duration::from_millis(200));
|
||||
let ix = budget_instruction::apply_signature(
|
||||
&witness.pubkey(),
|
||||
@@ -572,14 +579,14 @@ mod tests {
|
||||
&bob_pubkey,
|
||||
);
|
||||
let tx = Transaction::new_signed_instructions(&[&witness], vec![ix], blockhash);
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions).unwrap();
|
||||
process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions, 1).unwrap();
|
||||
sleep(Duration::from_millis(200));
|
||||
|
||||
assert_eq!(
|
||||
bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(0)
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.get_account(&contract_state.pubkey()),
|
||||
None
|
||||
@@ -593,9 +600,12 @@ mod tests {
|
||||
let session = create_session();
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, Bank::new(&genesis_config))));
|
||||
|
||||
let mut io = PubSubHandler::default();
|
||||
let rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore);
|
||||
let rpc =
|
||||
RpcSolPubSubImpl::default_with_blockstore_bank_forks(blockstore, bank_forks.clone());
|
||||
|
||||
io.extend_with(rpc.to_delegate());
|
||||
|
||||
@@ -630,7 +640,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_account_confirmations_not_fulfilled() {
|
||||
fn test_account_commitment_not_fulfilled() {
|
||||
let GenesisConfigInfo {
|
||||
genesis_config,
|
||||
mint_keypair: alice,
|
||||
@@ -638,15 +648,19 @@ mod tests {
|
||||
} = create_genesis_config(10_000);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let blockhash = bank.last_blockhash();
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(1, bank)));
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let bob = Keypair::new();
|
||||
|
||||
let mut rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore.clone());
|
||||
let mut rpc = RpcSolPubSubImpl::default_with_blockstore_bank_forks(
|
||||
blockstore.clone(),
|
||||
bank_forks.clone(),
|
||||
);
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let subscriptions = RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks.clone(),
|
||||
Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
|
||||
)),
|
||||
@@ -654,24 +668,29 @@ mod tests {
|
||||
rpc.subscriptions = Arc::new(subscriptions);
|
||||
let session = create_session();
|
||||
let (subscriber, _id_receiver, receiver) = Subscriber::new_test("accountNotification");
|
||||
rpc.account_subscribe(session, subscriber, bob.pubkey().to_string(), Some(2));
|
||||
rpc.account_subscribe(
|
||||
session,
|
||||
subscriber,
|
||||
bob.pubkey().to_string(),
|
||||
Some(CommitmentConfig::root()),
|
||||
);
|
||||
|
||||
let tx = system_transaction::transfer(&alice, &bob.pubkey(), 100, blockhash);
|
||||
bank_forks
|
||||
.write()
|
||||
.unwrap()
|
||||
.get(0)
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.process_transaction(&tx)
|
||||
.unwrap();
|
||||
rpc.subscriptions.notify_subscribers(0, &bank_forks);
|
||||
rpc.subscriptions.notify_subscribers(0);
|
||||
// allow 200ms for notification thread to wake
|
||||
std::thread::sleep(Duration::from_millis(200));
|
||||
let _panic = robust_poll_or_panic(receiver);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_account_confirmations() {
|
||||
fn test_account_commitment() {
|
||||
let GenesisConfigInfo {
|
||||
genesis_config,
|
||||
mint_keypair: alice,
|
||||
@@ -680,75 +699,65 @@ mod tests {
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let blockhash = bank.last_blockhash();
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let bank0 = bank_forks.read().unwrap().get(0).unwrap().clone();
|
||||
let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
|
||||
bank_forks.write().unwrap().insert(bank1);
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let bob = Keypair::new();
|
||||
|
||||
let mut rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore.clone());
|
||||
let mut rpc = RpcSolPubSubImpl::default_with_blockstore_bank_forks(
|
||||
blockstore.clone(),
|
||||
bank_forks.clone(),
|
||||
);
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let block_commitment_cache = Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore.clone()),
|
||||
));
|
||||
|
||||
let subscriptions = RpcSubscriptions::new(&exit, block_commitment_cache.clone());
|
||||
let subscriptions =
|
||||
RpcSubscriptions::new(&exit, bank_forks.clone(), block_commitment_cache.clone());
|
||||
rpc.subscriptions = Arc::new(subscriptions);
|
||||
let session = create_session();
|
||||
let (subscriber, _id_receiver, receiver) = Subscriber::new_test("accountNotification");
|
||||
rpc.account_subscribe(session, subscriber, bob.pubkey().to_string(), Some(2));
|
||||
rpc.account_subscribe(
|
||||
session,
|
||||
subscriber,
|
||||
bob.pubkey().to_string(),
|
||||
Some(CommitmentConfig::root()),
|
||||
);
|
||||
|
||||
let tx = system_transaction::transfer(&alice, &bob.pubkey(), 100, blockhash);
|
||||
bank_forks
|
||||
.write()
|
||||
.unwrap()
|
||||
.get(0)
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.process_transaction(&tx)
|
||||
.unwrap();
|
||||
rpc.subscriptions.notify_subscribers(0, &bank_forks);
|
||||
rpc.subscriptions.notify_subscribers(1);
|
||||
|
||||
let bank0 = bank_forks.read().unwrap()[0].clone();
|
||||
let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
|
||||
bank_forks.write().unwrap().insert(bank1);
|
||||
let bank1 = bank_forks.read().unwrap()[1].clone();
|
||||
|
||||
let mut cache0 = BlockCommitment::default();
|
||||
cache0.increase_confirmation_stake(1, 10);
|
||||
let mut block_commitment = HashMap::new();
|
||||
block_commitment.entry(0).or_insert(cache0.clone());
|
||||
let mut new_block_commitment = BlockCommitmentCache::new(
|
||||
block_commitment,
|
||||
0,
|
||||
10,
|
||||
bank1.clone(),
|
||||
blockstore.clone(),
|
||||
0,
|
||||
);
|
||||
let mut w_block_commitment_cache = block_commitment_cache.write().unwrap();
|
||||
std::mem::swap(&mut *w_block_commitment_cache, &mut new_block_commitment);
|
||||
drop(w_block_commitment_cache);
|
||||
|
||||
rpc.subscriptions.notify_subscribers(1, &bank_forks);
|
||||
let bank2 = Bank::new_from_parent(&bank1, &Pubkey::default(), 2);
|
||||
bank_forks.write().unwrap().insert(bank2);
|
||||
bank_forks.write().unwrap().set_root(1, &None, None);
|
||||
let bank2 = bank_forks.read().unwrap()[2].clone();
|
||||
|
||||
let mut cache0 = BlockCommitment::default();
|
||||
cache0.increase_confirmation_stake(2, 10);
|
||||
let mut block_commitment = HashMap::new();
|
||||
block_commitment.entry(0).or_insert(cache0.clone());
|
||||
let mut block_commitment: HashMap<Slot, BlockCommitment> = HashMap::new();
|
||||
block_commitment.insert(0, BlockCommitment::default());
|
||||
let mut new_block_commitment =
|
||||
BlockCommitmentCache::new(block_commitment, 0, 10, bank2, blockstore.clone(), 0);
|
||||
BlockCommitmentCache::new(block_commitment, 1, 10, bank2, blockstore.clone(), 1);
|
||||
let mut w_block_commitment_cache = block_commitment_cache.write().unwrap();
|
||||
std::mem::swap(&mut *w_block_commitment_cache, &mut new_block_commitment);
|
||||
drop(w_block_commitment_cache);
|
||||
|
||||
rpc.subscriptions.notify_subscribers(2, &bank_forks);
|
||||
rpc.subscriptions.notify_subscribers(2);
|
||||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "accountNotification",
|
||||
"params": {
|
||||
"result": {
|
||||
"context": { "slot": 0 },
|
||||
"context": { "slot": 1 },
|
||||
"value": {
|
||||
"owner": system_program::id().to_string(),
|
||||
"lamports": 100,
|
||||
@@ -769,7 +778,10 @@ mod tests {
|
||||
fn test_slot_subscribe() {
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore);
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let rpc = RpcSolPubSubImpl::default_with_blockstore_bank_forks(blockstore, bank_forks);
|
||||
let session = create_session();
|
||||
let (subscriber, _id_receiver, receiver) = Subscriber::new_test("slotNotification");
|
||||
rpc.slot_subscribe(session, subscriber);
|
||||
@@ -796,7 +808,10 @@ mod tests {
|
||||
fn test_slot_unsubscribe() {
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let rpc = RpcSolPubSubImpl::default_with_blockstore(blockstore);
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let rpc = RpcSolPubSubImpl::default_with_blockstore_bank_forks(blockstore, bank_forks);
|
||||
let session = create_session();
|
||||
let (subscriber, _id_receiver, receiver) = Subscriber::new_test("slotNotification");
|
||||
rpc.slot_subscribe(session, subscriber);
|
||||
|
@@ -73,7 +73,13 @@ impl PubSubService {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::commitment::BlockCommitmentCache;
|
||||
use solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path};
|
||||
use solana_ledger::{
|
||||
bank_forks::BankForks,
|
||||
blockstore::Blockstore,
|
||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||
get_tmp_ledger_path,
|
||||
};
|
||||
use solana_runtime::bank::Bank;
|
||||
use std::{
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
sync::RwLock,
|
||||
@@ -85,8 +91,12 @@ mod tests {
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks,
|
||||
Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
|
||||
)),
|
||||
|
@@ -14,9 +14,13 @@ use solana_client::rpc_response::{
|
||||
use solana_ledger::{bank_forks::BankForks, blockstore::Blockstore};
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_sdk::{
|
||||
account::Account, clock::Slot, pubkey::Pubkey, signature::Signature, transaction,
|
||||
account::Account,
|
||||
clock::Slot,
|
||||
commitment_config::{CommitmentConfig, CommitmentLevel},
|
||||
pubkey::Pubkey,
|
||||
signature::Signature,
|
||||
transaction,
|
||||
};
|
||||
use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc::{Receiver, RecvTimeoutError, SendError, Sender},
|
||||
@@ -24,7 +28,6 @@ use std::sync::{
|
||||
use std::thread::{Builder, JoinHandle};
|
||||
use std::time::Duration;
|
||||
use std::{
|
||||
cmp::min,
|
||||
collections::{HashMap, HashSet},
|
||||
iter,
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
@@ -33,8 +36,6 @@ use tokio::runtime::{Builder as RuntimeBuilder, Runtime, TaskExecutor};
|
||||
|
||||
const RECEIVE_DELAY_MILLIS: u64 = 100;
|
||||
|
||||
pub type Confirmations = usize;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
|
||||
pub struct SlotInfo {
|
||||
pub slot: Slot,
|
||||
@@ -45,7 +46,7 @@ pub struct SlotInfo {
|
||||
enum NotificationEntry {
|
||||
Slot(SlotInfo),
|
||||
Root(Slot),
|
||||
Bank((Slot, Arc<RwLock<BankForks>>)),
|
||||
Bank(Slot),
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for NotificationEntry {
|
||||
@@ -53,51 +54,57 @@ impl std::fmt::Debug for NotificationEntry {
|
||||
match self {
|
||||
NotificationEntry::Root(root) => write!(f, "Root({})", root),
|
||||
NotificationEntry::Slot(slot_info) => write!(f, "Slot({:?})", slot_info),
|
||||
NotificationEntry::Bank((current_slot, _)) => {
|
||||
NotificationEntry::Bank(current_slot) => {
|
||||
write!(f, "Bank({{current_slot: {:?}}})", current_slot)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SubscriptionData<S> {
|
||||
sink: Sink<S>,
|
||||
commitment: CommitmentConfig,
|
||||
last_notified_slot: RwLock<Slot>,
|
||||
}
|
||||
type RpcAccountSubscriptions =
|
||||
RwLock<HashMap<Pubkey, HashMap<SubscriptionId, (Sink<Response<RpcAccount>>, Confirmations)>>>;
|
||||
type RpcProgramSubscriptions = RwLock<
|
||||
HashMap<Pubkey, HashMap<SubscriptionId, (Sink<Response<RpcKeyedAccount>>, Confirmations)>>,
|
||||
>;
|
||||
RwLock<HashMap<Pubkey, HashMap<SubscriptionId, SubscriptionData<Response<RpcAccount>>>>>;
|
||||
type RpcProgramSubscriptions =
|
||||
RwLock<HashMap<Pubkey, HashMap<SubscriptionId, SubscriptionData<Response<RpcKeyedAccount>>>>>;
|
||||
type RpcSignatureSubscriptions = RwLock<
|
||||
HashMap<
|
||||
Signature,
|
||||
HashMap<SubscriptionId, (Sink<Response<RpcSignatureResult>>, Confirmations)>,
|
||||
>,
|
||||
HashMap<Signature, HashMap<SubscriptionId, SubscriptionData<Response<RpcSignatureResult>>>>,
|
||||
>;
|
||||
type RpcSlotSubscriptions = RwLock<HashMap<SubscriptionId, Sink<SlotInfo>>>;
|
||||
type RpcRootSubscriptions = RwLock<HashMap<SubscriptionId, Sink<Slot>>>;
|
||||
|
||||
fn add_subscription<K, S>(
|
||||
subscriptions: &mut HashMap<K, HashMap<SubscriptionId, (Sink<S>, Confirmations)>>,
|
||||
subscriptions: &mut HashMap<K, HashMap<SubscriptionId, SubscriptionData<S>>>,
|
||||
hashmap_key: K,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
sub_id: SubscriptionId,
|
||||
subscriber: Subscriber<S>,
|
||||
last_notified_slot: Slot,
|
||||
) where
|
||||
K: Eq + Hash,
|
||||
S: Clone,
|
||||
{
|
||||
let sink = subscriber.assign_id(sub_id.clone()).unwrap();
|
||||
let confirmations = confirmations.unwrap_or(0);
|
||||
let confirmations = min(confirmations, MAX_LOCKOUT_HISTORY + 1);
|
||||
let commitment = commitment.unwrap_or_else(CommitmentConfig::recent);
|
||||
let subscription_data = SubscriptionData {
|
||||
sink,
|
||||
commitment,
|
||||
last_notified_slot: RwLock::new(last_notified_slot),
|
||||
};
|
||||
if let Some(current_hashmap) = subscriptions.get_mut(&hashmap_key) {
|
||||
current_hashmap.insert(sub_id, (sink, confirmations));
|
||||
current_hashmap.insert(sub_id, subscription_data);
|
||||
return;
|
||||
}
|
||||
let mut hashmap = HashMap::new();
|
||||
hashmap.insert(sub_id, (sink, confirmations));
|
||||
hashmap.insert(sub_id, subscription_data);
|
||||
subscriptions.insert(hashmap_key, hashmap);
|
||||
}
|
||||
|
||||
fn remove_subscription<K, S>(
|
||||
subscriptions: &mut HashMap<K, HashMap<SubscriptionId, (Sink<S>, Confirmations)>>,
|
||||
subscriptions: &mut HashMap<K, HashMap<SubscriptionId, SubscriptionData<S>>>,
|
||||
sub_id: &SubscriptionId,
|
||||
) -> bool
|
||||
where
|
||||
@@ -119,8 +126,8 @@ where
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn check_confirmations_and_notify<K, S, B, F, X>(
|
||||
subscriptions: &HashMap<K, HashMap<SubscriptionId, (Sink<Response<S>>, Confirmations)>>,
|
||||
fn check_commitment_and_notify<K, S, B, F, X>(
|
||||
subscriptions: &HashMap<K, HashMap<SubscriptionId, SubscriptionData<Response<S>>>>,
|
||||
hashmap_key: &K,
|
||||
bank_forks: &Arc<RwLock<BankForks>>,
|
||||
block_commitment_cache: &Arc<RwLock<BlockCommitmentCache>>,
|
||||
@@ -132,53 +139,50 @@ where
|
||||
K: Eq + Hash + Clone + Copy,
|
||||
S: Clone + Serialize,
|
||||
B: Fn(&Bank, &K) -> X,
|
||||
F: Fn(X, u64) -> Box<dyn Iterator<Item = S>>,
|
||||
X: Clone + Serialize,
|
||||
F: Fn(X, Slot) -> (Box<dyn Iterator<Item = S>>, Slot),
|
||||
X: Clone + Serialize + Default,
|
||||
{
|
||||
let mut confirmation_slots: HashMap<usize, Slot> = HashMap::new();
|
||||
let r_block_commitment_cache = block_commitment_cache.read().unwrap();
|
||||
let current_slot = r_block_commitment_cache.slot();
|
||||
let root = r_block_commitment_cache.root();
|
||||
let current_ancestors = bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(current_slot)
|
||||
.unwrap()
|
||||
.ancestors
|
||||
.clone();
|
||||
for (slot, _) in current_ancestors.iter() {
|
||||
if let Some(confirmations) = r_block_commitment_cache.get_confirmation_count(*slot) {
|
||||
confirmation_slots.entry(confirmations).or_insert(*slot);
|
||||
}
|
||||
}
|
||||
let node_root = r_block_commitment_cache.root();
|
||||
let largest_confirmed_root = r_block_commitment_cache.largest_confirmed_root();
|
||||
drop(r_block_commitment_cache);
|
||||
|
||||
let mut notified_set: HashSet<SubscriptionId> = HashSet::new();
|
||||
if let Some(hashmap) = subscriptions.get(hashmap_key) {
|
||||
for (sub_id, (sink, confirmations)) in hashmap.iter() {
|
||||
let desired_slot = if *confirmations == 0 {
|
||||
Some(¤t_slot)
|
||||
} else if *confirmations == MAX_LOCKOUT_HISTORY + 1 {
|
||||
Some(&root)
|
||||
} else {
|
||||
confirmation_slots.get(confirmations)
|
||||
for (
|
||||
sub_id,
|
||||
SubscriptionData {
|
||||
sink,
|
||||
commitment,
|
||||
last_notified_slot,
|
||||
},
|
||||
) in hashmap.iter()
|
||||
{
|
||||
let slot = match commitment.commitment {
|
||||
CommitmentLevel::Max => largest_confirmed_root,
|
||||
CommitmentLevel::Recent => current_slot,
|
||||
CommitmentLevel::Root => node_root,
|
||||
};
|
||||
if let Some(&slot) = desired_slot {
|
||||
let results = {
|
||||
let bank_forks = bank_forks.read().unwrap();
|
||||
let desired_bank = bank_forks.get(slot).unwrap();
|
||||
bank_method(&desired_bank, hashmap_key)
|
||||
};
|
||||
for result in filter_results(results, root) {
|
||||
notifier.notify(
|
||||
Response {
|
||||
context: RpcResponseContext { slot },
|
||||
value: result,
|
||||
},
|
||||
sink,
|
||||
);
|
||||
notified_set.insert(sub_id.clone());
|
||||
}
|
||||
let results = {
|
||||
let bank_forks = bank_forks.read().unwrap();
|
||||
bank_forks
|
||||
.get(slot)
|
||||
.map(|desired_bank| bank_method(&desired_bank, hashmap_key))
|
||||
.unwrap_or_default()
|
||||
};
|
||||
let mut w_last_notified_slot = last_notified_slot.write().unwrap();
|
||||
let (filter_results, result_slot) = filter_results(results, *w_last_notified_slot);
|
||||
for result in filter_results {
|
||||
notifier.notify(
|
||||
Response {
|
||||
context: RpcResponseContext { slot },
|
||||
value: result,
|
||||
},
|
||||
sink,
|
||||
);
|
||||
notified_set.insert(sub_id.clone());
|
||||
*w_last_notified_slot = result_slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,50 +203,63 @@ impl RpcNotifier {
|
||||
|
||||
fn filter_account_result(
|
||||
result: Option<(Account, Slot)>,
|
||||
root: Slot,
|
||||
) -> Box<dyn Iterator<Item = RpcAccount>> {
|
||||
last_notified_slot: Slot,
|
||||
) -> (Box<dyn Iterator<Item = RpcAccount>>, Slot) {
|
||||
if let Some((account, fork)) = result {
|
||||
if fork >= root {
|
||||
return Box::new(iter::once(RpcAccount::encode(account)));
|
||||
if fork != last_notified_slot {
|
||||
return (Box::new(iter::once(RpcAccount::encode(account))), fork);
|
||||
}
|
||||
}
|
||||
Box::new(iter::empty())
|
||||
(Box::new(iter::empty()), last_notified_slot)
|
||||
}
|
||||
|
||||
fn filter_signature_result(
|
||||
result: Option<transaction::Result<()>>,
|
||||
_root: Slot,
|
||||
) -> Box<dyn Iterator<Item = RpcSignatureResult>> {
|
||||
Box::new(
|
||||
result
|
||||
.into_iter()
|
||||
.map(|result| RpcSignatureResult { err: result.err() }),
|
||||
last_notified_slot: Slot,
|
||||
) -> (Box<dyn Iterator<Item = RpcSignatureResult>>, Slot) {
|
||||
(
|
||||
Box::new(
|
||||
result
|
||||
.into_iter()
|
||||
.map(|result| RpcSignatureResult { err: result.err() }),
|
||||
),
|
||||
last_notified_slot,
|
||||
)
|
||||
}
|
||||
|
||||
fn filter_program_results(
|
||||
accounts: Vec<(Pubkey, Account)>,
|
||||
_root: Slot,
|
||||
) -> Box<dyn Iterator<Item = RpcKeyedAccount>> {
|
||||
Box::new(
|
||||
accounts
|
||||
.into_iter()
|
||||
.map(|(pubkey, account)| RpcKeyedAccount {
|
||||
pubkey: pubkey.to_string(),
|
||||
account: RpcAccount::encode(account),
|
||||
}),
|
||||
last_notified_slot: Slot,
|
||||
) -> (Box<dyn Iterator<Item = RpcKeyedAccount>>, Slot) {
|
||||
(
|
||||
Box::new(
|
||||
accounts
|
||||
.into_iter()
|
||||
.map(|(pubkey, account)| RpcKeyedAccount {
|
||||
pubkey: pubkey.to_string(),
|
||||
account: RpcAccount::encode(account),
|
||||
}),
|
||||
),
|
||||
last_notified_slot,
|
||||
)
|
||||
}
|
||||
|
||||
pub struct RpcSubscriptions {
|
||||
#[derive(Clone)]
|
||||
struct Subscriptions {
|
||||
account_subscriptions: Arc<RpcAccountSubscriptions>,
|
||||
program_subscriptions: Arc<RpcProgramSubscriptions>,
|
||||
signature_subscriptions: Arc<RpcSignatureSubscriptions>,
|
||||
slot_subscriptions: Arc<RpcSlotSubscriptions>,
|
||||
root_subscriptions: Arc<RpcRootSubscriptions>,
|
||||
}
|
||||
|
||||
pub struct RpcSubscriptions {
|
||||
subscriptions: Subscriptions,
|
||||
notification_sender: Arc<Mutex<Sender<NotificationEntry>>>,
|
||||
t_cleanup: Option<JoinHandle<()>>,
|
||||
notifier_runtime: Option<Runtime>,
|
||||
bank_forks: Arc<RwLock<BankForks>>,
|
||||
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
||||
exit: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
@@ -257,6 +274,7 @@ impl Drop for RpcSubscriptions {
|
||||
impl RpcSubscriptions {
|
||||
pub fn new(
|
||||
exit: &Arc<AtomicBool>,
|
||||
bank_forks: Arc<RwLock<BankForks>>,
|
||||
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
||||
) -> Self {
|
||||
let (notification_sender, notification_receiver): (
|
||||
@@ -271,12 +289,17 @@ impl RpcSubscriptions {
|
||||
let root_subscriptions = Arc::new(RpcRootSubscriptions::default());
|
||||
let notification_sender = Arc::new(Mutex::new(notification_sender));
|
||||
|
||||
let _bank_forks = bank_forks.clone();
|
||||
let _block_commitment_cache = block_commitment_cache.clone();
|
||||
let exit_clone = exit.clone();
|
||||
let account_subscriptions_clone = account_subscriptions.clone();
|
||||
let program_subscriptions_clone = program_subscriptions.clone();
|
||||
let signature_subscriptions_clone = signature_subscriptions.clone();
|
||||
let slot_subscriptions_clone = slot_subscriptions.clone();
|
||||
let root_subscriptions_clone = root_subscriptions.clone();
|
||||
let subscriptions = Subscriptions {
|
||||
account_subscriptions,
|
||||
program_subscriptions,
|
||||
signature_subscriptions,
|
||||
slot_subscriptions,
|
||||
root_subscriptions,
|
||||
};
|
||||
let _subscriptions = subscriptions.clone();
|
||||
|
||||
let notifier_runtime = RuntimeBuilder::new()
|
||||
.core_threads(1)
|
||||
@@ -292,32 +315,31 @@ impl RpcSubscriptions {
|
||||
exit_clone,
|
||||
notifier,
|
||||
notification_receiver,
|
||||
account_subscriptions_clone,
|
||||
program_subscriptions_clone,
|
||||
signature_subscriptions_clone,
|
||||
slot_subscriptions_clone,
|
||||
root_subscriptions_clone,
|
||||
block_commitment_cache,
|
||||
_subscriptions,
|
||||
_bank_forks,
|
||||
_block_commitment_cache,
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
account_subscriptions,
|
||||
program_subscriptions,
|
||||
signature_subscriptions,
|
||||
slot_subscriptions,
|
||||
root_subscriptions,
|
||||
subscriptions,
|
||||
notification_sender,
|
||||
notifier_runtime: Some(notifier_runtime),
|
||||
t_cleanup: Some(t_cleanup),
|
||||
bank_forks,
|
||||
block_commitment_cache,
|
||||
exit: exit.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_with_blockstore(blockstore: Arc<Blockstore>) -> Self {
|
||||
pub fn default_with_blockstore_bank_forks(
|
||||
blockstore: Arc<Blockstore>,
|
||||
bank_forks: Arc<RwLock<BankForks>>,
|
||||
) -> Self {
|
||||
Self::new(
|
||||
&Arc::new(AtomicBool::new(false)),
|
||||
bank_forks,
|
||||
Arc::new(RwLock::new(BlockCommitmentCache::default_with_blockstore(
|
||||
blockstore,
|
||||
))),
|
||||
@@ -332,12 +354,12 @@ impl RpcSubscriptions {
|
||||
notifier: &RpcNotifier,
|
||||
) {
|
||||
let subscriptions = account_subscriptions.read().unwrap();
|
||||
check_confirmations_and_notify(
|
||||
check_commitment_and_notify(
|
||||
&subscriptions,
|
||||
pubkey,
|
||||
bank_forks,
|
||||
block_commitment_cache,
|
||||
Bank::get_account_modified_since_parent,
|
||||
Bank::get_account_modified_slot,
|
||||
filter_account_result,
|
||||
notifier,
|
||||
);
|
||||
@@ -351,7 +373,7 @@ impl RpcSubscriptions {
|
||||
notifier: &RpcNotifier,
|
||||
) {
|
||||
let subscriptions = program_subscriptions.read().unwrap();
|
||||
check_confirmations_and_notify(
|
||||
check_commitment_and_notify(
|
||||
&subscriptions,
|
||||
program_id,
|
||||
bank_forks,
|
||||
@@ -370,7 +392,7 @@ impl RpcSubscriptions {
|
||||
notifier: &RpcNotifier,
|
||||
) {
|
||||
let mut subscriptions = signature_subscriptions.write().unwrap();
|
||||
let notified_ids = check_confirmations_and_notify(
|
||||
let notified_ids = check_commitment_and_notify(
|
||||
&subscriptions,
|
||||
signature,
|
||||
bank_forks,
|
||||
@@ -390,83 +412,109 @@ impl RpcSubscriptions {
|
||||
pub fn add_account_subscription(
|
||||
&self,
|
||||
pubkey: Pubkey,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
sub_id: SubscriptionId,
|
||||
subscriber: Subscriber<Response<RpcAccount>>,
|
||||
) {
|
||||
let mut subscriptions = self.account_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.account_subscriptions.write().unwrap();
|
||||
let slot = match commitment
|
||||
.unwrap_or_else(CommitmentConfig::recent)
|
||||
.commitment
|
||||
{
|
||||
CommitmentLevel::Max => self
|
||||
.block_commitment_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.largest_confirmed_root(),
|
||||
CommitmentLevel::Recent => self.block_commitment_cache.read().unwrap().slot(),
|
||||
CommitmentLevel::Root => self.block_commitment_cache.read().unwrap().root(),
|
||||
};
|
||||
let last_notified_slot = if let Some((_account, slot)) = self
|
||||
.bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(slot)
|
||||
.and_then(|bank| bank.get_account_modified_slot(&pubkey))
|
||||
{
|
||||
slot
|
||||
} else {
|
||||
0
|
||||
};
|
||||
add_subscription(
|
||||
&mut subscriptions,
|
||||
pubkey,
|
||||
confirmations,
|
||||
commitment,
|
||||
sub_id,
|
||||
subscriber,
|
||||
last_notified_slot,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn remove_account_subscription(&self, id: &SubscriptionId) -> bool {
|
||||
let mut subscriptions = self.account_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.account_subscriptions.write().unwrap();
|
||||
remove_subscription(&mut subscriptions, id)
|
||||
}
|
||||
|
||||
pub fn add_program_subscription(
|
||||
&self,
|
||||
program_id: Pubkey,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
sub_id: SubscriptionId,
|
||||
subscriber: Subscriber<Response<RpcKeyedAccount>>,
|
||||
) {
|
||||
let mut subscriptions = self.program_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.program_subscriptions.write().unwrap();
|
||||
add_subscription(
|
||||
&mut subscriptions,
|
||||
program_id,
|
||||
confirmations,
|
||||
commitment,
|
||||
sub_id,
|
||||
subscriber,
|
||||
0, // last_notified_slot is not utilized for program subscriptions
|
||||
);
|
||||
}
|
||||
|
||||
pub fn remove_program_subscription(&self, id: &SubscriptionId) -> bool {
|
||||
let mut subscriptions = self.program_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.program_subscriptions.write().unwrap();
|
||||
remove_subscription(&mut subscriptions, id)
|
||||
}
|
||||
|
||||
pub fn add_signature_subscription(
|
||||
&self,
|
||||
signature: Signature,
|
||||
confirmations: Option<Confirmations>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
sub_id: SubscriptionId,
|
||||
subscriber: Subscriber<Response<RpcSignatureResult>>,
|
||||
) {
|
||||
let mut subscriptions = self.signature_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.signature_subscriptions.write().unwrap();
|
||||
add_subscription(
|
||||
&mut subscriptions,
|
||||
signature,
|
||||
confirmations,
|
||||
commitment,
|
||||
sub_id,
|
||||
subscriber,
|
||||
0, // last_notified_slot is not utilized for signature subscriptions
|
||||
);
|
||||
}
|
||||
|
||||
pub fn remove_signature_subscription(&self, id: &SubscriptionId) -> bool {
|
||||
let mut subscriptions = self.signature_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.signature_subscriptions.write().unwrap();
|
||||
remove_subscription(&mut subscriptions, id)
|
||||
}
|
||||
|
||||
/// Notify subscribers of changes to any accounts or new signatures since
|
||||
/// the bank's last checkpoint.
|
||||
pub fn notify_subscribers(&self, current_slot: Slot, bank_forks: &Arc<RwLock<BankForks>>) {
|
||||
self.enqueue_notification(NotificationEntry::Bank((current_slot, bank_forks.clone())));
|
||||
pub fn notify_subscribers(&self, current_slot: Slot) {
|
||||
self.enqueue_notification(NotificationEntry::Bank(current_slot));
|
||||
}
|
||||
|
||||
pub fn add_slot_subscription(&self, sub_id: SubscriptionId, subscriber: Subscriber<SlotInfo>) {
|
||||
let sink = subscriber.assign_id(sub_id.clone()).unwrap();
|
||||
let mut subscriptions = self.slot_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.slot_subscriptions.write().unwrap();
|
||||
subscriptions.insert(sub_id, sink);
|
||||
}
|
||||
|
||||
pub fn remove_slot_subscription(&self, id: &SubscriptionId) -> bool {
|
||||
let mut subscriptions = self.slot_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.slot_subscriptions.write().unwrap();
|
||||
subscriptions.remove(id).is_some()
|
||||
}
|
||||
|
||||
@@ -476,12 +524,12 @@ impl RpcSubscriptions {
|
||||
|
||||
pub fn add_root_subscription(&self, sub_id: SubscriptionId, subscriber: Subscriber<Slot>) {
|
||||
let sink = subscriber.assign_id(sub_id.clone()).unwrap();
|
||||
let mut subscriptions = self.root_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.root_subscriptions.write().unwrap();
|
||||
subscriptions.insert(sub_id, sink);
|
||||
}
|
||||
|
||||
pub fn remove_root_subscription(&self, id: &SubscriptionId) -> bool {
|
||||
let mut subscriptions = self.root_subscriptions.write().unwrap();
|
||||
let mut subscriptions = self.subscriptions.root_subscriptions.write().unwrap();
|
||||
subscriptions.remove(id).is_some()
|
||||
}
|
||||
|
||||
@@ -513,11 +561,8 @@ impl RpcSubscriptions {
|
||||
exit: Arc<AtomicBool>,
|
||||
notifier: RpcNotifier,
|
||||
notification_receiver: Receiver<NotificationEntry>,
|
||||
account_subscriptions: Arc<RpcAccountSubscriptions>,
|
||||
program_subscriptions: Arc<RpcProgramSubscriptions>,
|
||||
signature_subscriptions: Arc<RpcSignatureSubscriptions>,
|
||||
slot_subscriptions: Arc<RpcSlotSubscriptions>,
|
||||
root_subscriptions: Arc<RpcRootSubscriptions>,
|
||||
subscriptions: Subscriptions,
|
||||
bank_forks: Arc<RwLock<BankForks>>,
|
||||
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
||||
) {
|
||||
loop {
|
||||
@@ -527,20 +572,20 @@ impl RpcSubscriptions {
|
||||
match notification_receiver.recv_timeout(Duration::from_millis(RECEIVE_DELAY_MILLIS)) {
|
||||
Ok(notification_entry) => match notification_entry {
|
||||
NotificationEntry::Slot(slot_info) => {
|
||||
let subscriptions = slot_subscriptions.read().unwrap();
|
||||
let subscriptions = subscriptions.slot_subscriptions.read().unwrap();
|
||||
for (_, sink) in subscriptions.iter() {
|
||||
notifier.notify(slot_info, sink);
|
||||
}
|
||||
}
|
||||
NotificationEntry::Root(root) => {
|
||||
let subscriptions = root_subscriptions.read().unwrap();
|
||||
let subscriptions = subscriptions.root_subscriptions.read().unwrap();
|
||||
for (_, sink) in subscriptions.iter() {
|
||||
notifier.notify(root, sink);
|
||||
}
|
||||
}
|
||||
NotificationEntry::Bank((_current_slot, bank_forks)) => {
|
||||
NotificationEntry::Bank(_current_slot) => {
|
||||
let pubkeys: Vec<_> = {
|
||||
let subs = account_subscriptions.read().unwrap();
|
||||
let subs = subscriptions.account_subscriptions.read().unwrap();
|
||||
subs.keys().cloned().collect()
|
||||
};
|
||||
for pubkey in &pubkeys {
|
||||
@@ -548,13 +593,13 @@ impl RpcSubscriptions {
|
||||
pubkey,
|
||||
&bank_forks,
|
||||
&block_commitment_cache,
|
||||
account_subscriptions.clone(),
|
||||
subscriptions.account_subscriptions.clone(),
|
||||
¬ifier,
|
||||
);
|
||||
}
|
||||
|
||||
let programs: Vec<_> = {
|
||||
let subs = program_subscriptions.read().unwrap();
|
||||
let subs = subscriptions.program_subscriptions.read().unwrap();
|
||||
subs.keys().cloned().collect()
|
||||
};
|
||||
for program_id in &programs {
|
||||
@@ -562,13 +607,13 @@ impl RpcSubscriptions {
|
||||
program_id,
|
||||
&bank_forks,
|
||||
&block_commitment_cache,
|
||||
program_subscriptions.clone(),
|
||||
subscriptions.program_subscriptions.clone(),
|
||||
¬ifier,
|
||||
);
|
||||
}
|
||||
|
||||
let signatures: Vec<_> = {
|
||||
let subs = signature_subscriptions.read().unwrap();
|
||||
let subs = subscriptions.signature_subscriptions.read().unwrap();
|
||||
subs.keys().cloned().collect()
|
||||
};
|
||||
for signature in &signatures {
|
||||
@@ -576,7 +621,7 @@ impl RpcSubscriptions {
|
||||
signature,
|
||||
&bank_forks,
|
||||
&block_commitment_cache,
|
||||
signature_subscriptions.clone(),
|
||||
subscriptions.signature_subscriptions.clone(),
|
||||
¬ifier,
|
||||
);
|
||||
}
|
||||
@@ -671,7 +716,35 @@ pub(crate) mod tests {
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let blockhash = bank.last_blockhash();
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let bank0 = bank_forks.read().unwrap().get(0).unwrap().clone();
|
||||
let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
|
||||
bank_forks.write().unwrap().insert(bank1);
|
||||
let alice = Keypair::new();
|
||||
|
||||
let (subscriber, _id_receiver, transport_receiver) =
|
||||
Subscriber::new_test("accountNotification");
|
||||
let sub_id = SubscriptionId::Number(0 as u64);
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let subscriptions = RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks.clone(),
|
||||
Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore_bank(
|
||||
blockstore,
|
||||
bank_forks.read().unwrap().get(1).unwrap().clone(),
|
||||
1,
|
||||
),
|
||||
)),
|
||||
);
|
||||
subscriptions.add_account_subscription(alice.pubkey(), None, sub_id.clone(), subscriber);
|
||||
|
||||
assert!(subscriptions
|
||||
.subscriptions
|
||||
.account_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
.contains_key(&alice.pubkey()));
|
||||
|
||||
let tx = system_transaction::create_account(
|
||||
&mint_keypair,
|
||||
&alice,
|
||||
@@ -683,37 +756,18 @@ pub(crate) mod tests {
|
||||
bank_forks
|
||||
.write()
|
||||
.unwrap()
|
||||
.get(0)
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.process_transaction(&tx)
|
||||
.unwrap();
|
||||
|
||||
let (subscriber, _id_receiver, transport_receiver) =
|
||||
Subscriber::new_test("accountNotification");
|
||||
let sub_id = SubscriptionId::Number(0 as u64);
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let subscriptions = RpcSubscriptions::new(
|
||||
&exit,
|
||||
Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
|
||||
)),
|
||||
);
|
||||
subscriptions.add_account_subscription(alice.pubkey(), None, sub_id.clone(), subscriber);
|
||||
|
||||
assert!(subscriptions
|
||||
.account_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
.contains_key(&alice.pubkey()));
|
||||
|
||||
subscriptions.notify_subscribers(0, &bank_forks);
|
||||
subscriptions.notify_subscribers(1);
|
||||
let (response, _) = robust_poll_or_panic(transport_receiver);
|
||||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "accountNotification",
|
||||
"params": {
|
||||
"result": {
|
||||
"context": { "slot": 0 },
|
||||
"context": { "slot": 1 },
|
||||
"value": {
|
||||
"data": "1111111111111111",
|
||||
"executable": false,
|
||||
@@ -729,6 +783,7 @@ pub(crate) mod tests {
|
||||
|
||||
subscriptions.remove_account_subscription(&sub_id);
|
||||
assert!(!subscriptions
|
||||
.subscriptions
|
||||
.account_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
@@ -771,6 +826,7 @@ pub(crate) mod tests {
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let subscriptions = RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks,
|
||||
Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
|
||||
)),
|
||||
@@ -783,12 +839,13 @@ pub(crate) mod tests {
|
||||
);
|
||||
|
||||
assert!(subscriptions
|
||||
.subscriptions
|
||||
.program_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
.contains_key(&solana_budget_program::id()));
|
||||
|
||||
subscriptions.notify_subscribers(0, &bank_forks);
|
||||
subscriptions.notify_subscribers(0);
|
||||
let (response, _) = robust_poll_or_panic(transport_receiver);
|
||||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
@@ -814,6 +871,7 @@ pub(crate) mod tests {
|
||||
|
||||
subscriptions.remove_program_subscription(&sub_id);
|
||||
assert!(!subscriptions
|
||||
.subscriptions
|
||||
.program_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
@@ -872,8 +930,11 @@ pub(crate) mod tests {
|
||||
BlockCommitmentCache::new(block_commitment, 0, 10, bank1, blockstore, 0);
|
||||
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let subscriptions =
|
||||
RpcSubscriptions::new(&exit, Arc::new(RwLock::new(block_commitment_cache)));
|
||||
let subscriptions = RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks,
|
||||
Arc::new(RwLock::new(block_commitment_cache)),
|
||||
);
|
||||
|
||||
let (past_bank_sub1, _id_receiver, past_bank_recv1) =
|
||||
Subscriber::new_test("signatureNotification");
|
||||
@@ -884,37 +945,41 @@ pub(crate) mod tests {
|
||||
|
||||
subscriptions.add_signature_subscription(
|
||||
past_bank_tx.signatures[0],
|
||||
Some(0),
|
||||
Some(CommitmentConfig::recent()),
|
||||
SubscriptionId::Number(1 as u64),
|
||||
past_bank_sub1,
|
||||
);
|
||||
subscriptions.add_signature_subscription(
|
||||
past_bank_tx.signatures[0],
|
||||
Some(1),
|
||||
Some(CommitmentConfig::root()),
|
||||
SubscriptionId::Number(2 as u64),
|
||||
past_bank_sub2,
|
||||
);
|
||||
subscriptions.add_signature_subscription(
|
||||
processed_tx.signatures[0],
|
||||
Some(0),
|
||||
Some(CommitmentConfig::recent()),
|
||||
SubscriptionId::Number(3 as u64),
|
||||
processed_sub,
|
||||
);
|
||||
subscriptions.add_signature_subscription(
|
||||
unprocessed_tx.signatures[0],
|
||||
Some(0),
|
||||
Some(CommitmentConfig::recent()),
|
||||
SubscriptionId::Number(4 as u64),
|
||||
Subscriber::new_test("signatureNotification").0,
|
||||
);
|
||||
|
||||
{
|
||||
let sig_subs = subscriptions.signature_subscriptions.read().unwrap();
|
||||
let sig_subs = subscriptions
|
||||
.subscriptions
|
||||
.signature_subscriptions
|
||||
.read()
|
||||
.unwrap();
|
||||
assert_eq!(sig_subs.get(&past_bank_tx.signatures[0]).unwrap().len(), 2);
|
||||
assert!(sig_subs.contains_key(&unprocessed_tx.signatures[0]));
|
||||
assert!(sig_subs.contains_key(&processed_tx.signatures[0]));
|
||||
}
|
||||
|
||||
subscriptions.notify_subscribers(1, &bank_forks);
|
||||
subscriptions.notify_subscribers(1);
|
||||
let expected_res = RpcSignatureResult { err: None };
|
||||
|
||||
struct Notification {
|
||||
@@ -954,7 +1019,11 @@ pub(crate) mod tests {
|
||||
assert_eq!(expected, response);
|
||||
|
||||
// Subscription should be automatically removed after notification
|
||||
let sig_subs = subscriptions.signature_subscriptions.read().unwrap();
|
||||
let sig_subs = subscriptions
|
||||
.subscriptions
|
||||
.signature_subscriptions
|
||||
.read()
|
||||
.unwrap();
|
||||
assert!(!sig_subs.contains_key(&processed_tx.signatures[0]));
|
||||
assert!(!sig_subs.contains_key(&past_bank_tx.signatures[0]));
|
||||
|
||||
@@ -974,8 +1043,12 @@ pub(crate) mod tests {
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let subscriptions = RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks,
|
||||
Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
|
||||
)),
|
||||
@@ -983,6 +1056,7 @@ pub(crate) mod tests {
|
||||
subscriptions.add_slot_subscription(sub_id.clone(), subscriber);
|
||||
|
||||
assert!(subscriptions
|
||||
.subscriptions
|
||||
.slot_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
@@ -1005,6 +1079,7 @@ pub(crate) mod tests {
|
||||
|
||||
subscriptions.remove_slot_subscription(&sub_id);
|
||||
assert!(!subscriptions
|
||||
.subscriptions
|
||||
.slot_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
@@ -1020,8 +1095,12 @@ pub(crate) mod tests {
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let subscriptions = RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks,
|
||||
Arc::new(RwLock::new(
|
||||
BlockCommitmentCache::new_for_tests_with_blockstore(blockstore),
|
||||
)),
|
||||
@@ -1029,6 +1108,7 @@ pub(crate) mod tests {
|
||||
subscriptions.add_root_subscription(sub_id.clone(), subscriber);
|
||||
|
||||
assert!(subscriptions
|
||||
.subscriptions
|
||||
.root_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
@@ -1050,6 +1130,7 @@ pub(crate) mod tests {
|
||||
|
||||
subscriptions.remove_root_subscription(&sub_id);
|
||||
assert!(!subscriptions
|
||||
.subscriptions
|
||||
.root_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
@@ -1059,7 +1140,7 @@ pub(crate) mod tests {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_add_and_remove_subscription() {
|
||||
let mut subscriptions: HashMap<u64, HashMap<SubscriptionId, (Sink<()>, Confirmations)>> =
|
||||
let mut subscriptions: HashMap<u64, HashMap<SubscriptionId, SubscriptionData<()>>> =
|
||||
HashMap::new();
|
||||
|
||||
let num_keys = 5;
|
||||
@@ -1067,7 +1148,7 @@ pub(crate) mod tests {
|
||||
let (subscriber, _id_receiver, _transport_receiver) =
|
||||
Subscriber::new_test("notification");
|
||||
let sub_id = SubscriptionId::Number(key);
|
||||
add_subscription(&mut subscriptions, key, None, sub_id, subscriber);
|
||||
add_subscription(&mut subscriptions, key, None, sub_id, subscriber, 0);
|
||||
}
|
||||
|
||||
// Add another subscription to the "0" key
|
||||
@@ -1079,6 +1160,7 @@ pub(crate) mod tests {
|
||||
None,
|
||||
extra_sub_id.clone(),
|
||||
subscriber,
|
||||
0,
|
||||
);
|
||||
|
||||
assert_eq!(subscriptions.len(), num_keys as usize);
|
||||
|
@@ -292,11 +292,12 @@ pub mod tests {
|
||||
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
|
||||
));
|
||||
let (retransmit_slots_sender, _retransmit_slots_receiver) = unbounded();
|
||||
let bank_forks = Arc::new(RwLock::new(bank_forks));
|
||||
let tvu = Tvu::new(
|
||||
&vote_keypair.pubkey(),
|
||||
vec![Arc::new(vote_keypair)],
|
||||
&storage_keypair,
|
||||
&Arc::new(RwLock::new(bank_forks)),
|
||||
&bank_forks,
|
||||
&cref1,
|
||||
{
|
||||
Sockets {
|
||||
@@ -309,7 +310,11 @@ pub mod tests {
|
||||
blockstore,
|
||||
&StorageState::default(),
|
||||
l_receiver,
|
||||
&Arc::new(RpcSubscriptions::new(&exit, block_commitment_cache.clone())),
|
||||
&Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks.clone(),
|
||||
block_commitment_cache.clone(),
|
||||
)),
|
||||
&poh_recorder,
|
||||
&leader_schedule_cache,
|
||||
&exit,
|
||||
|
@@ -241,7 +241,11 @@ impl Validator {
|
||||
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
|
||||
));
|
||||
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(&exit, block_commitment_cache.clone()));
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks.clone(),
|
||||
block_commitment_cache.clone(),
|
||||
));
|
||||
|
||||
let rpc_service = config.rpc_ports.map(|(rpc_port, rpc_pubsub_port)| {
|
||||
if ContactInfo::is_valid_address(&node.info.rpc) {
|
||||
|
@@ -6,7 +6,13 @@ use solana_core::{
|
||||
commitment::BlockCommitmentCache, rpc_pubsub_service::PubSubService,
|
||||
rpc_subscriptions::RpcSubscriptions, validator::TestValidator,
|
||||
};
|
||||
use solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path};
|
||||
use solana_ledger::{
|
||||
bank_forks::BankForks,
|
||||
blockstore::Blockstore,
|
||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||
get_tmp_ledger_path,
|
||||
};
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig, pubkey::Pubkey, rpc_port, signature::Signer,
|
||||
system_transaction,
|
||||
@@ -88,8 +94,12 @@ fn test_slot_subscription() {
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks,
|
||||
Arc::new(RwLock::new(BlockCommitmentCache::default_with_blockstore(
|
||||
blockstore,
|
||||
))),
|
||||
|
@@ -9,7 +9,7 @@ use reqwest::{self, header::CONTENT_TYPE};
|
||||
use serde_json::{json, Value};
|
||||
use solana_client::{
|
||||
rpc_client::{get_rpc_request_str, RpcClient},
|
||||
rpc_response::{Response, RpcSignatureResult},
|
||||
rpc_response::{Response, RpcAccount, RpcSignatureResult},
|
||||
};
|
||||
use solana_core::{rpc_pubsub::gen_client::Client as PubsubClient, validator::TestValidator};
|
||||
use solana_sdk::{
|
||||
@@ -217,9 +217,15 @@ fn test_rpc_subscriptions() {
|
||||
.iter()
|
||||
.map(|tx| tx.signatures[0].to_string())
|
||||
.collect();
|
||||
let account_set: HashSet<String> = transactions
|
||||
.iter()
|
||||
.map(|tx| tx.message.account_keys[1].to_string())
|
||||
.collect();
|
||||
|
||||
// Track when subscriptions are ready
|
||||
let (ready_sender, ready_receiver) = channel::<()>();
|
||||
// Track account notifications are received
|
||||
let (account_sender, account_receiver) = channel::<Response<RpcAccount>>();
|
||||
// Track when status notifications are received
|
||||
let (status_sender, status_receiver) = channel::<(String, Response<RpcSignatureResult>)>();
|
||||
|
||||
@@ -262,6 +268,22 @@ fn test_rpc_subscriptions() {
|
||||
eprintln!("slot sub err: {:#?}", err);
|
||||
}),
|
||||
);
|
||||
for pubkey in account_set {
|
||||
let account_sender = account_sender.clone();
|
||||
tokio::spawn(
|
||||
client
|
||||
.account_subscribe(pubkey, None)
|
||||
.and_then(move |account_stream| {
|
||||
account_stream.for_each(move |result| {
|
||||
account_sender.send(result).unwrap();
|
||||
future::ok(())
|
||||
})
|
||||
})
|
||||
.map_err(|err| {
|
||||
eprintln!("acct sub err: {:#?}", err);
|
||||
}),
|
||||
);
|
||||
}
|
||||
future::ok(())
|
||||
})
|
||||
.map_err(|_| ())
|
||||
@@ -315,6 +337,26 @@ fn test_rpc_subscriptions() {
|
||||
}
|
||||
}
|
||||
|
||||
let deadline = Instant::now() + Duration::from_secs(5);
|
||||
let mut account_notifications = transactions.len();
|
||||
while account_notifications > 0 {
|
||||
let timeout = deadline.saturating_duration_since(Instant::now());
|
||||
match account_receiver.recv_timeout(timeout) {
|
||||
Ok(result) => {
|
||||
assert_eq!(result.value.lamports, 1);
|
||||
account_notifications -= 1;
|
||||
}
|
||||
Err(_err) => {
|
||||
assert!(
|
||||
false,
|
||||
"recv_timeout, {}/{} accounts remaining",
|
||||
account_notifications,
|
||||
transactions.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rt.shutdown_now().wait().unwrap();
|
||||
server.close().unwrap();
|
||||
remove_dir_all(ledger_path).unwrap();
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-crate-features"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Crate Features"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -31,6 +31,7 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
|
||||
* [getGenesisHash](jsonrpc-api.md#getgenesishash)
|
||||
* [getIdentity](jsonrpc-api.md#getidentity)
|
||||
* [getInflation](jsonrpc-api.md#getinflation)
|
||||
* [getLargestAccounts](jsonrpc-api.md#getlargestaccounts)
|
||||
* [getLeaderSchedule](jsonrpc-api.md#getleaderschedule)
|
||||
* [getMinimumBalanceForRentExemption](jsonrpc-api.md#getminimumbalanceforrentexemption)
|
||||
* [getProgramAccounts](jsonrpc-api.md#getprogramaccounts)
|
||||
@@ -634,6 +635,32 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m
|
||||
{"jsonrpc":"2.0","result":{"foundation":0.05,"foundationTerm":7.0,"initial":0.15,"storage":0.1,"taper":0.15,"terminal":0.015},"id":1}
|
||||
```
|
||||
|
||||
### getLargestAccounts
|
||||
|
||||
Returns the 20 largest accounts, by lamport balance
|
||||
|
||||
#### Parameters:
|
||||
|
||||
* `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
The result will be an RpcResponse JSON object with `value` equal to an array of:
|
||||
|
||||
* `<object>` - otherwise, a JSON object containing:
|
||||
* `address: <string>`, base-58 encoded address of the account
|
||||
* `lamports: <u64>`, number of lamports in the account, as a u64
|
||||
|
||||
#### Example:
|
||||
|
||||
```bash
|
||||
// Request
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getLargestAccounts"}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":54},"value":[{"lamports":999974,"address":"99P8ZgtJYe1buSK8JXkvpLh8xPsCFuLYhz9hQFNw93WJ"},{"lamports":42,"address":"uPwWLo16MVehpyWqsLkK3Ka8nLowWvAHbBChqv2FZeL"},{"lamports":42,"address":"aYJCgU7REfu3XF8b3QhkqgqQvLizx8zxuLBHA25PzDS"},{"lamports":42,"address":"CTvHVtQ4gd4gUcw3bdVgZJJqApXE9nCbbbP4VTS5wE1D"},{"lamports":20,"address":"4fq3xJ6kfrh9RkJQsmVd5gNMvJbuSHfErywvEjNQDPxu"},{"lamports":4,"address":"AXJADheGVp9cruP8WYu46oNkRbeASngN5fPCMVGQqNHa"},{"lamports":2,"address":"8NT8yS6LiwNprgW4yM1jPPow7CwRUotddBVkrkWgYp24"},{"lamports":1,"address":"SysvarEpochSchedu1e111111111111111111111111"},{"lamports":1,"address":"11111111111111111111111111111111"},{"lamports":1,"address":"Stake11111111111111111111111111111111111111"},{"lamports":1,"address":"SysvarC1ock11111111111111111111111111111111"},{"lamports":1,"address":"StakeConfig11111111111111111111111111111111"},{"lamports":1,"address":"SysvarRent111111111111111111111111111111111"},{"lamports":1,"address":"Config1111111111111111111111111111111111111"},{"lamports":1,"address":"SysvarStakeHistory1111111111111111111111111"},{"lamports":1,"address":"SysvarRecentB1ockHashes11111111111111111111"},{"lamports":1,"address":"SysvarFees111111111111111111111111111111111"},{"lamports":1,"address":"Vote111111111111111111111111111111111111111"}]},"id":1}
|
||||
```
|
||||
|
||||
### getLeaderSchedule
|
||||
|
||||
Returns the leader schedule for an epoch
|
||||
@@ -981,7 +1008,7 @@ The result field will be a JSON object with the following fields:
|
||||
// Request
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getVersion"}' http://localhost:8899
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":{"solana-core": "1.1.8"},"id":1}
|
||||
{"jsonrpc":"2.0","result":{"solana-core": "1.1.10"},"id":1}
|
||||
```
|
||||
|
||||
### getVoteAccounts
|
||||
|
@@ -6,7 +6,7 @@ Solana takes a very different approach, which it calls _Proof of History_ or _Po
|
||||
|
||||
Solana technically never sends a _block_, but uses the term to describe the sequence of entries that validators vote on to achieve _confirmation_. In that way, Solana's confirmation times can be compared apples to apples to block-based systems. The current implementation sets block time to 800ms.
|
||||
|
||||
What's happening under the hood is that entries are streamed to validators as quickly as a leader node can batch a set of valid transactions into an entry. Validators process those entries long before it is time to vote on their validity. By processing the transactions optimistically, there is effectively no delay between the time the last entry is received and the time when the node can vote. In the event consensus is **not** achieved, a node simply rolls back its state. This optimisic processing technique was introduced in 1981 and called [Optimistic Concurrency Control](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.85.4735). It can be applied to blockchain architecture where a cluster votes on a hash that represents the full ledger up to some _block height_. In Solana, it is implemented trivially using the last entry's PoH hash.
|
||||
What's happening under the hood is that entries are streamed to validators as quickly as a leader node can batch a set of valid transactions into an entry. Validators process those entries long before it is time to vote on their validity. By processing the transactions optimistically, there is effectively no delay between the time the last entry is received and the time when the node can vote. In the event consensus is **not** achieved, a node simply rolls back its state. This optimisic processing technique was introduced in 1981 and called [Optimistic Concurrency Control](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.105.4735). It can be applied to blockchain architecture where a cluster votes on a hash that represents the full ledger up to some _block height_. In Solana, it is implemented trivially using the last entry's PoH hash.
|
||||
|
||||
## Relationship to VDFs
|
||||
|
||||
|
@@ -6,9 +6,9 @@ Solana is an open source project implementing a new, high-performance, permissio
|
||||
|
||||
## Why Solana?
|
||||
|
||||
It is possible for a centralized database to process 710,000 transactions per second on a standard gigabit network if the transactions are, on average, no more than 176 bytes. A centralized database can also replicate itself and maintain high availability without significantly compromising that transaction rate using the distributed system technique known as Optimistic Concurrency Control [\[H.T.Kung, J.T.Robinson (1981)\]](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.85.4735). At Solana, we are demonstrating that these same theoretical limits apply just as well to blockchain on an adversarial network. The key ingredient? Finding a way to share time when nodes cannot trust one-another. Once nodes can trust time, suddenly ~40 years of distributed systems research becomes applicable to blockchain!
|
||||
It is possible for a centralized database to process 710,000 transactions per second on a standard gigabit network if the transactions are, on average, no more than 176 bytes. A centralized database can also replicate itself and maintain high availability without significantly compromising that transaction rate using the distributed system technique known as Optimistic Concurrency Control [\[H.T.Kung, J.T.Robinson (1981)\]](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.105.4735). At Solana, we are demonstrating that these same theoretical limits apply just as well to blockchain on an adversarial network. The key ingredient? Finding a way to share time when nodes cannot trust one-another. Once nodes can trust time, suddenly ~40 years of distributed systems research becomes applicable to blockchain!
|
||||
|
||||
> Perhaps the most striking difference between algorithms obtained by our method and ones based upon timeout is that using timeout produces a traditional distributed algorithm in which the processes operate asynchronously, while our method produces a globally synchronous one in which every process does the same thing at (approximately) the same time. Our method seems to contradict the whole purpose of distributed processing, which is to permit different processes to operate independently and perform different functions. However, if a distributed system is really a single system, then the processes must be synchronized in some way. Conceptually, the easiest way to synchronize processes is to get them all to do the same thing at the same time. Therefore, our method is used to implement a kernel that performs the necessary synchronization--for example, making sure that two different processes do not try to modify a file at the same time. Processes might spend only a small fraction of their time executing the synchronizing kernel; the rest of the time, they can operate independently--e.g., accessing different files. This is an approach we have advocated even when fault-tolerance is not required. The method's basic simplicity makes it easier to understand the precise properties of a system, which is crucial if one is to know just how fault-tolerant the system is. [\[L.Lamport (1984)\]](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.81.1078)
|
||||
> Perhaps the most striking difference between algorithms obtained by our method and ones based upon timeout is that using timeout produces a traditional distributed algorithm in which the processes operate asynchronously, while our method produces a globally synchronous one in which every process does the same thing at (approximately) the same time. Our method seems to contradict the whole purpose of distributed processing, which is to permit different processes to operate independently and perform different functions. However, if a distributed system is really a single system, then the processes must be synchronized in some way. Conceptually, the easiest way to synchronize processes is to get them all to do the same thing at the same time. Therefore, our method is used to implement a kernel that performs the necessary synchronization--for example, making sure that two different processes do not try to modify a file at the same time. Processes might spend only a small fraction of their time executing the synchronizing kernel; the rest of the time, they can operate independently--e.g., accessing different files. This is an approach we have advocated even when fault-tolerance is not required. The method's basic simplicity makes it easier to understand the precise properties of a system, which is crucial if one is to know just how fault-tolerant the system is. [\[L.Lamport (1984)\]](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.101.1078)
|
||||
|
||||
Furthermore, and much to our surprise, it can be implemented using a mechanism that has existed in Bitcoin since day one. The Bitcoin feature is called nLocktime and it can be used to postdate transactions using block height instead of a timestamp. As a Bitcoin client, you would use block height instead of a timestamp if you don't trust the network. Block height turns out to be an instance of what's being called a Verifiable Delay Function in cryptography circles. It's a cryptographically secure way to say time has passed. In Solana, we use a far more granular verifiable delay function, a SHA 256 hash chain, to checkpoint the ledger and coordinate consensus. With it, we implement Optimistic Concurrency Control and are now well en route towards that theoretical limit of 710,000 transactions per second.
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-dos"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -13,10 +13,10 @@ clap = "2.33.0"
|
||||
log = "0.4.8"
|
||||
rand = "0.7.0"
|
||||
rayon = "1.3.0"
|
||||
solana-core = { path = "../core", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-core = { path = "../core", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-download-utils"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Download Utils"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,8 +14,8 @@ console = "0.10.0"
|
||||
indicatif = "0.14.0"
|
||||
log = "0.4.8"
|
||||
reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
tar = "0.4.26"
|
||||
|
||||
[lib]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-faucet"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Faucet"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -19,10 +19,10 @@ clap = "2.33"
|
||||
log = "0.4.8"
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
tokio = "0.1"
|
||||
tokio-codec = "0.1"
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-genesis-programs"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana genesis programs"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,13 +10,13 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = { version = "0.4.8" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.1.8" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.8" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.8" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "1.1.8" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.1.10" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.10" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.10" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "1.1.10" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -26,7 +26,17 @@ pub fn get_inflation(operating_mode: OperatingMode, epoch: Epoch) -> Option<Infl
|
||||
None
|
||||
}
|
||||
}
|
||||
OperatingMode::Stable | OperatingMode::Preview => {
|
||||
OperatingMode::Preview => {
|
||||
if epoch == 0 {
|
||||
// No inflation at epoch 0
|
||||
Some(Inflation::new_disabled())
|
||||
} else if epoch == 44 {
|
||||
Some(Inflation::default())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
OperatingMode::Stable => {
|
||||
if epoch == 0 {
|
||||
// No inflation at epoch 0
|
||||
Some(Inflation::new_disabled())
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-genesis"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -15,13 +15,13 @@ chrono = "0.4"
|
||||
serde = "1.0.105"
|
||||
serde_json = "1.0.48"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.8" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.8" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.1.10" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.10" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.10" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.10" }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -3,19 +3,19 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-gossip"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-core = { path = "../core", version = "1.1.8" }
|
||||
solana-client = { path = "../client", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-core = { path = "../core", version = "1.1.10" }
|
||||
solana-client = { path = "../client", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
|
||||
|
||||
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-install"
|
||||
description = "The solana cluster software installer"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -24,11 +24,11 @@ reqwest = { version = "0.10.4", default-features = false, features = ["blocking"
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-client = { path = "../client", version = "1.1.8" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-client = { path = "../client", version = "1.1.10" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
semver = "0.9.0"
|
||||
tar = "0.4.26"
|
||||
tempdir = "0.3.7"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-keygen"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana key generation utility"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -13,10 +13,10 @@ bs58 = "0.3.0"
|
||||
clap = "2.33"
|
||||
dirs = "2.0.2"
|
||||
num_cpus = "1.12.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.1.8" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.1.10" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
tiny-bip39 = "0.7.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-ledger-tool"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -14,15 +14,15 @@ clap = "2.33.0"
|
||||
histogram = "*"
|
||||
serde_json = "1.0.48"
|
||||
serde_yaml = "0.8.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-cli = { path = "../cli", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.8" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.8" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-cli = { path = "../cli", version = "1.1.10" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.10" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.10" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.10" }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-ledger"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana ledger"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -28,19 +28,19 @@ reed-solomon-erasure = { package = "solana-reed-solomon-erasure", version = "4.0
|
||||
regex = "1.3.6"
|
||||
serde = "1.0.105"
|
||||
serde_bytes = "0.11.3"
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.8" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-measure = { path = "../measure", version = "1.1.8" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.1.8" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.8" }
|
||||
solana-perf = { path = "../perf", version = "1.1.8" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.1.10" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-measure = { path = "../measure", version = "1.1.10" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.1.10" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.10" }
|
||||
solana-perf = { path = "../perf", version = "1.1.10" }
|
||||
ed25519-dalek = "1.0.0-pre.3"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.8" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.8" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.10" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.10" }
|
||||
symlink = "0.1.0"
|
||||
tar = "0.4.26"
|
||||
thiserror = "1.0"
|
||||
@@ -57,7 +57,7 @@ features = ["lz4"]
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.3.0"
|
||||
matches = "0.1.6"
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.8" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.10" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-local-cluster"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -12,24 +12,24 @@ homepage = "https://solana.com/"
|
||||
itertools = "0.9.0"
|
||||
log = "0.4.8"
|
||||
rand = "0.7.0"
|
||||
solana-archiver-lib = { path = "../archiver-lib", version = "1.1.8" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.1.8" }
|
||||
solana-core = { path = "../core", version = "1.1.8" }
|
||||
solana-client = { path = "../client", version = "1.1.8" }
|
||||
solana-download-utils = { path = "../download-utils", version = "1.1.8" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.8" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.1.8" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.1.8" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.8" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.8" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "1.1.8" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.8" }
|
||||
solana-archiver-lib = { path = "../archiver-lib", version = "1.1.10" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.1.10" }
|
||||
solana-core = { path = "../core", version = "1.1.10" }
|
||||
solana-client = { path = "../client", version = "1.1.10" }
|
||||
solana-download-utils = { path = "../download-utils", version = "1.1.10" }
|
||||
solana-faucet = { path = "../faucet", version = "1.1.10" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.1.10" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.1.10" }
|
||||
solana-ledger = { path = "../ledger", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-runtime = { path = "../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.1.10" }
|
||||
solana-storage-program = { path = "../programs/storage", version = "1.1.10" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "1.1.10" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.1.10" }
|
||||
tempfile = "3.1.0"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.1.8" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.3.0"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-log-analyzer"
|
||||
description = "The solana cluster network analysis tool"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -14,8 +14,8 @@ byte-unit = "3.0.3"
|
||||
clap = "2.33.0"
|
||||
serde = "1.0.105"
|
||||
serde_json = "1.0.48"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
|
||||
[[bin]]
|
||||
name = "solana-log-analyzer"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-logger"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Logger"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-measure"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "../README.md"
|
||||
@@ -12,8 +12,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.10" }
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
jemallocator = "0.3.2"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-merkle-tree"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Merkle Tree"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -9,7 +9,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
fast-math = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-metrics"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Metrics"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,7 +14,7 @@ gethostname = "0.2.1"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.8"
|
||||
reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.7.0"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-net-shaper"
|
||||
description = "The solana cluster network shaping tool"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -13,8 +13,8 @@ publish = false
|
||||
clap = "2.33.0"
|
||||
serde = "1.0.105"
|
||||
serde_json = "1.0.48"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
rand = "0.7.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-net-utils"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Network Utilities"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -18,8 +18,8 @@ rand = "0.7.0"
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
socket2 = "0.3.11"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
tokio = "0.1"
|
||||
tokio-codec = "0.1"
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-perf"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Performance APIs"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -17,11 +17,11 @@ serde = "1.0.105"
|
||||
dlopen_derive = "0.1.4"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.8"
|
||||
solana-sdk = { path = "../sdk", version = "1.1.8" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.1.8" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.8" }
|
||||
solana-logger = { path = "../logger", version = "1.1.8" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.8" }
|
||||
solana-sdk = { path = "../sdk", version = "1.1.10" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.1.10" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.1.10" }
|
||||
solana-logger = { path = "../logger", version = "1.1.10" }
|
||||
solana-metrics = { path = "../metrics", version = "1.1.10" }
|
||||
|
||||
[lib]
|
||||
name = "solana_perf"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-bpf-programs"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "README.md"
|
||||
@@ -22,10 +22,10 @@ walkdir = "2"
|
||||
bincode = "1.1.4"
|
||||
byteorder = "1.3.2"
|
||||
elf = "0.0.10"
|
||||
solana-bpf-loader-program = { path = "../bpf_loader", version = "1.1.8" }
|
||||
solana-logger = { path = "../../logger", version = "1.1.8" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-bpf-loader-program = { path = "../bpf_loader", version = "1.1.10" }
|
||||
solana-logger = { path = "../../logger", version = "1.1.10" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
solana_rbpf = "=0.1.25"
|
||||
|
||||
[[bench]]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-128bit"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,11 +12,11 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "1.1.10" }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-128bit-dep"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-alloc"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-dep-crate"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -13,10 +13,10 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
byteorder = { version = "1", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-dup-accounts"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-error-handling"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,11 +14,11 @@ edition = "2018"
|
||||
[dependencies]
|
||||
num-derive = "0.2"
|
||||
num-traits = "0.2"
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-external-spend"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-iter"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-many-args"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,11 +12,11 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "1.1.10" }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-many-args-dep"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-noop"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-panic"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-param-passing"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,11 +12,11 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "1.1.10" }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-param-passing-dep"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-sysval"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,10 +12,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.8", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.1.10", default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.8" }
|
||||
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "1.1.10" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-loader-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana BPF loader"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,8 +15,8 @@ libc = "0.2.68"
|
||||
log = "0.4.8"
|
||||
num-derive = { version = "0.3" }
|
||||
num-traits = { version = "0.2" }
|
||||
solana-logger = { path = "../../logger", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-logger = { path = "../../logger", version = "1.1.10" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
solana_rbpf = "=0.1.25"
|
||||
thiserror = "1.0"
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-btc-spv-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Bitcoin spv parsing program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,7 +15,7 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8"}
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10"}
|
||||
hex = "0.4.2"
|
||||
|
||||
[lib]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "btc_spv_bin"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Bitcoin spv parsing program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-budget-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Budget program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -16,11 +16,11 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.8" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.10" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-config-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Config program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,10 +14,10 @@ chrono = { version = "0.4.11", features = ["serde"] }
|
||||
log = "0.4.8"
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-logger = { path = "../../logger", version = "1.1.8" }
|
||||
solana-logger = { path = "../../logger", version = "1.1.10" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-exchange-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Exchange program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,13 +15,13 @@ num-derive = { version = "0.3" }
|
||||
num-traits = { version = "0.2" }
|
||||
serde = "1.0.105"
|
||||
serde_derive = "1.0.103"
|
||||
solana-logger = { path = "../../logger", version = "1.1.8" }
|
||||
solana-metrics = { path = "../../metrics", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-logger = { path = "../../logger", version = "1.1.10" }
|
||||
solana-metrics = { path = "../../metrics", version = "1.1.10" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.8" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.10" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-failure-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana failure program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -9,10 +9,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.8" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.10" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-librapay"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Libra Payment"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -11,10 +11,10 @@ edition = "2018"
|
||||
[dependencies]
|
||||
bincode = "1.2.0"
|
||||
log = "0.4.8"
|
||||
solana-logger = { path = "../../logger", version = "1.1.8" }
|
||||
solana-move-loader-program = { path = "../move_loader", version = "1.1.8" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-logger = { path = "../../logger", version = "1.1.10" }
|
||||
solana-move-loader-program = { path = "../move_loader", version = "1.1.10" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.10" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
types = { version = "0.0.1-sol4", package = "solana_libra_types" }
|
||||
|
||||
[lib]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-move-loader-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Move loader"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -16,8 +16,8 @@ serde = "1.0.104"
|
||||
serde_bytes = "0.11"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.46"
|
||||
solana-logger = { path = "../../logger", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-logger = { path = "../../logger", version = "1.1.10" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
|
||||
bytecode_verifier = { version = "0.0.1-sol4", package = "solana_libra_bytecode_verifier" }
|
||||
canonical_serialization = { version = "0.0.1-sol4", package = "solana_libra_canonical_serialization" }
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-noop-program"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "Solana Noop program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,8 +10,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
solana-logger = { path = "../../logger", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-logger = { path = "../../logger", version = "1.1.10" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-ownable"
|
||||
version = "1.1.8"
|
||||
version = "1.1.10"
|
||||
description = "ownable program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,13 +10,13 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.2.1"
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.8" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.1.10" }
|
||||
num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.8" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.1.10" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user