Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
83d08223fd | ||
|
6bb63f9abf | ||
|
d8293abc64 | ||
|
4d074a6716 | ||
|
3eee222667 | ||
|
a78c3c07f2 | ||
|
53f8e58300 | ||
|
b4fdce9443 | ||
|
39fe52fc06 | ||
|
db65b4e641 | ||
|
fe1c20c689 | ||
|
6566a0f6c8 | ||
|
3606de56f7 | ||
|
9a005855dc | ||
|
70bdcf06b4 | ||
|
f53f273585 | ||
|
e0584b77c5 | ||
|
39a5431790 | ||
|
715c5e64c4 |
733
Cargo.lock
generated
733
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-account-decoder"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana account decoder"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -19,10 +19,10 @@ lazy_static = "1.4.0"
|
||||
serde = "1.0.122"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-config-program = { path = "../programs/config", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-config-program = { path = "../programs/config", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
spl-token-v2-0 = { package = "spl-token", version = "=3.1.1", features = ["no-entrypoint"] }
|
||||
thiserror = "1.0"
|
||||
zstd = "0.5.1"
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-accounts-bench"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -11,11 +11,11 @@ publish = false
|
||||
[dependencies]
|
||||
log = "0.4.11"
|
||||
rayon = "1.5.0"
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
rand = "0.7.0"
|
||||
clap = "2.33.1"
|
||||
crossbeam-channel = "0.4"
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-accounts-cluster-bench"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -13,22 +13,22 @@ clap = "2.33.1"
|
||||
log = "0.4.11"
|
||||
rand = "0.7.0"
|
||||
rayon = "1.4.1"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-client = { path = "../client", version = "=1.6.22" }
|
||||
solana-core = { path = "../core", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.22" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.23" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-client = { path = "../client", version = "=1.6.23" }
|
||||
solana-core = { path = "../core", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.23" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
spl-token-v2-0 = { package = "spl-token", version = "=3.1.1", features = ["no-entrypoint"] }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-local-cluster = { path = "../local-cluster", version = "=1.6.22" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-banking-bench"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -14,16 +14,16 @@ crossbeam-channel = "0.4"
|
||||
log = "0.4.11"
|
||||
rand = "0.7.0"
|
||||
rayon = "1.5.0"
|
||||
solana-core = { path = "../core", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-streamer = { path = "../streamer", version = "=1.6.22" }
|
||||
solana-perf = { path = "../perf", version = "=1.6.22" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-core = { path = "../core", version = "=1.6.23" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-streamer = { path = "../streamer", version = "=1.6.23" }
|
||||
solana-perf = { path = "../perf", version = "=1.6.23" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-banks-client"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana banks client"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,16 +15,16 @@ borsh = "0.9.0"
|
||||
borsh-derive = "0.9.0"
|
||||
futures = "0.3"
|
||||
mio = "0.7.6"
|
||||
solana-banks-interface = { path = "../banks-interface", version = "=1.6.22" }
|
||||
solana-program = { path = "../sdk/program", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-banks-interface = { path = "../banks-interface", version = "=1.6.23" }
|
||||
solana-program = { path = "../sdk/program", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
tarpc = { version = "0.24.1", features = ["full"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-serde = { version = "0.8", features = ["bincode"] }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-banks-server = { path = "../banks-server", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-banks-server = { path = "../banks-server", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-banks-interface"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana banks RPC interface"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
mio = "0.7.6"
|
||||
serde = { version = "1.0.122", features = ["derive"] }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
tarpc = { version = "0.24.1", features = ["full"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-banks-server"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana banks server"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,10 +14,10 @@ bincode = "1.3.1"
|
||||
futures = "0.3"
|
||||
log = "0.4.11"
|
||||
mio = "0.7.6"
|
||||
solana-banks-interface = { path = "../banks-interface", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.22" }
|
||||
solana-banks-interface = { path = "../banks-interface", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.23" }
|
||||
tarpc = { version = "0.24.1", features = ["full"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-serde = { version = "0.8", features = ["bincode"] }
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-exchange"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -18,21 +18,21 @@ rand = "0.7.0"
|
||||
rayon = "1.5.0"
|
||||
serde_json = "1.0.56"
|
||||
serde_yaml = "0.8.13"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-core = { path = "../core", version = "=1.6.22" }
|
||||
solana-genesis = { path = "../genesis", version = "=1.6.22" }
|
||||
solana-client = { path = "../client", version = "=1.6.22" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.22" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-core = { path = "../core", version = "=1.6.23" }
|
||||
solana-genesis = { path = "../genesis", version = "=1.6.23" }
|
||||
solana-client = { path = "../client", version = "=1.6.23" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.23" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.23" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-local-cluster = { path = "../local-cluster", version = "=1.6.22" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-streamer"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -10,11 +10,11 @@ publish = false
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.1"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-streamer = { path = "../streamer", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-streamer = { path = "../streamer", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-tps"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -15,22 +15,22 @@ log = "0.4.11"
|
||||
rayon = "1.5.0"
|
||||
serde_json = "1.0.56"
|
||||
serde_yaml = "0.8.13"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-core = { path = "../core", version = "=1.6.22" }
|
||||
solana-genesis = { path = "../genesis", version = "=1.6.22" }
|
||||
solana-client = { path = "../client", version = "=1.6.22" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-core = { path = "../core", version = "=1.6.23" }
|
||||
solana-genesis = { path = "../genesis", version = "=1.6.23" }
|
||||
solana-client = { path = "../client", version = "=1.6.23" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.4.0"
|
||||
solana-local-cluster = { path = "../local-cluster", version = "=1.6.22" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-clap-utils"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana utilities for the clap"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,8 +12,8 @@ edition = "2018"
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
rpassword = "4.0"
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
thiserror = "1.0.21"
|
||||
tiny-bip39 = "0.8.0"
|
||||
uriparse = "0.6.3"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli-config"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli-output"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -19,13 +19,13 @@ indicatif = "0.15.0"
|
||||
serde = "1.0.122"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-client = { path = "../client", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.23" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-client = { path = "../client", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.23" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
|
@@ -140,7 +140,7 @@ fn format_account_mode(message: &Message, index: usize) -> String {
|
||||
} else {
|
||||
"-"
|
||||
},
|
||||
if message.is_writable(index, /*demote_sysvar_write_locks=*/ true) {
|
||||
if message.is_writable(index, /*demote_program_write_locks=*/ true) {
|
||||
"w" // comment for consistent rust fmt (no joking; lol)
|
||||
} else {
|
||||
"-"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -29,30 +29,30 @@ reqwest = { version = "0.11.2", default-features = false, features = ["blocking"
|
||||
serde = "1.0.122"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.22" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-cli-config = { path = "../cli-config", version = "=1.6.22" }
|
||||
solana-cli-output = { path = "../cli-output", version = "=1.6.22" }
|
||||
solana-client = { path = "../client", version = "=1.6.22" }
|
||||
solana-config-program = { path = "../programs/config", version = "=1.6.22" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.22" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.23" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.6.23" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-cli-config = { path = "../cli-config", version = "=1.6.23" }
|
||||
solana-cli-output = { path = "../cli-output", version = "=1.6.23" }
|
||||
solana-client = { path = "../client", version = "=1.6.23" }
|
||||
solana-config-program = { path = "../programs/config", version = "=1.6.23" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.23" }
|
||||
solana_rbpf = "=0.2.9"
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.23" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
|
||||
thiserror = "1.0.21"
|
||||
tiny-bip39 = "0.7.0"
|
||||
url = "2.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-core = { path = "../core", version = "=1.6.22" }
|
||||
solana-core = { path = "../core", version = "=1.6.23" }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-client"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Client"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,7 +15,7 @@ bincode = "1.3.1"
|
||||
bs58 = "0.3.1"
|
||||
clap = "2.33.0"
|
||||
indicatif = "0.15.0"
|
||||
jsonrpc-core = "17.0.0"
|
||||
jsonrpc-core = "18.0.0"
|
||||
log = "0.4.11"
|
||||
net2 = "0.2.37"
|
||||
rayon = "1.5.0"
|
||||
@@ -24,14 +24,14 @@ semver = "0.11.0"
|
||||
serde = "1.0.122"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.23" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.23" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tungstenite = "0.10.1"
|
||||
@@ -39,8 +39,8 @@ url = "2.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.3.0"
|
||||
jsonrpc-http-server = "17.0.0"
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
jsonrpc-http-server = "18.0.0"
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-core"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
homepage = "https://solana.com/"
|
||||
documentation = "https://docs.rs/solana-core"
|
||||
readme = "../README.md"
|
||||
@@ -29,12 +29,12 @@ fs_extra = "1.2.0"
|
||||
flate2 = "1.0"
|
||||
indexmap = { version = "1.5", features = ["rayon"] }
|
||||
itertools = "0.9.0"
|
||||
jsonrpc-core = "17.1.0"
|
||||
jsonrpc-core-client = { version = "17.1.0", features = ["ipc", "ws"] }
|
||||
jsonrpc-derive = "17.1.0"
|
||||
jsonrpc-http-server = "17.1.0"
|
||||
jsonrpc-pubsub = "17.1.0"
|
||||
jsonrpc-ws-server = "17.1.0"
|
||||
jsonrpc-core = "18.0.0"
|
||||
jsonrpc-core-client = { version = "18.0.0", features = ["ipc", "ws"] }
|
||||
jsonrpc-derive = "18.0.0"
|
||||
jsonrpc-http-server = "18.0.0"
|
||||
jsonrpc-pubsub = "18.0.0"
|
||||
jsonrpc-ws-server = "18.0.0"
|
||||
libc = "0.2.81"
|
||||
log = "0.4.11"
|
||||
lru = "0.6.1"
|
||||
@@ -52,37 +52,36 @@ serde = "1.0.122"
|
||||
serde_bytes = "0.11"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.22" }
|
||||
solana-banks-server = { path = "../banks-server", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-client = { path = "../client", version = "=1.6.22" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.22" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "=1.6.22" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.22" }
|
||||
solana-perf = { path = "../perf", version = "=1.6.22" }
|
||||
solana-program-test = { path = "../program-test", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-frozen-abi = { path = "../frozen-abi", version = "=1.6.22" }
|
||||
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.6.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.22" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.6.22" }
|
||||
solana-streamer = { path = "../streamer", version = "=1.6.22" }
|
||||
solana-sys-tuner = { path = "../sys-tuner", version = "=1.6.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.23" }
|
||||
solana-banks-server = { path = "../banks-server", version = "=1.6.23" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-client = { path = "../client", version = "=1.6.23" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.23" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "=1.6.23" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.23" }
|
||||
solana-perf = { path = "../perf", version = "=1.6.23" }
|
||||
solana-program-test = { path = "../program-test", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-frozen-abi = { path = "../frozen-abi", version = "=1.6.23" }
|
||||
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.6.23" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.23" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.6.23" }
|
||||
solana-streamer = { path = "../streamer", version = "=1.6.23" }
|
||||
solana-sys-tuner = { path = "../sys-tuner", version = "=1.6.23" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
spl-token-v2-0 = { package = "spl-token", version = "=3.1.1", features = ["no-entrypoint"] }
|
||||
tempfile = "3.1.0"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio_02 = { version = "0.2", package = "tokio", features = ["full"] }
|
||||
tokio-util = { version = "0.3", features = ["codec"] } # This crate needs to stay in sync with tokio_02, until that dependency can be removed
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.6.22" }
|
||||
tokio-util = { version = "0.6", features = ["codec"] }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.6.23" }
|
||||
trees = "0.2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -3,6 +3,7 @@
|
||||
//! can do its processing in parallel with signature verification on the GPU.
|
||||
use crate::{
|
||||
cluster_info::ClusterInfo,
|
||||
data_budget::DataBudget,
|
||||
packet_hasher::PacketHasher,
|
||||
poh_recorder::{PohRecorder, PohRecorderError, TransactionRecorder, WorkingBankEntry},
|
||||
poh_service::{self, PohService},
|
||||
@@ -260,6 +261,7 @@ impl BankingStage {
|
||||
LruCache::new(DEFAULT_LRU_SIZE),
|
||||
PacketHasher::default(),
|
||||
)));
|
||||
let data_budget = Arc::new(DataBudget::default());
|
||||
// Many banks that process transactions in parallel.
|
||||
let bank_thread_hdls: Vec<JoinHandle<()>> = (0..num_threads)
|
||||
.map(|i| {
|
||||
@@ -276,6 +278,7 @@ impl BankingStage {
|
||||
let transaction_status_sender = transaction_status_sender.clone();
|
||||
let gossip_vote_sender = gossip_vote_sender.clone();
|
||||
let duplicates = duplicates.clone();
|
||||
let data_budget = data_budget.clone();
|
||||
Builder::new()
|
||||
.name("solana-banking-stage-tx".to_string())
|
||||
.spawn(move || {
|
||||
@@ -292,6 +295,7 @@ impl BankingStage {
|
||||
transaction_status_sender,
|
||||
gossip_vote_sender,
|
||||
&duplicates,
|
||||
&data_budget,
|
||||
);
|
||||
})
|
||||
.unwrap()
|
||||
@@ -315,11 +319,21 @@ impl BankingStage {
|
||||
socket: &std::net::UdpSocket,
|
||||
tpu_forwards: &std::net::SocketAddr,
|
||||
unprocessed_packets: &UnprocessedPackets,
|
||||
data_budget: &DataBudget,
|
||||
) -> std::io::Result<()> {
|
||||
let packets = Self::filter_valid_packets_for_forwarding(unprocessed_packets.iter());
|
||||
inc_new_counter_info!("banking_stage-forwarded_packets", packets.len());
|
||||
const INTERVAL_MS: u64 = 100;
|
||||
const MAX_BYTES_PER_SECOND: usize = 10_000 * 1200;
|
||||
const MAX_BYTES_PER_INTERVAL: usize = MAX_BYTES_PER_SECOND * INTERVAL_MS as usize / 1000;
|
||||
const MAX_BYTES_BUDGET: usize = MAX_BYTES_PER_INTERVAL * 5;
|
||||
data_budget.update(INTERVAL_MS, |bytes| {
|
||||
std::cmp::min(bytes + MAX_BYTES_PER_INTERVAL, MAX_BYTES_BUDGET)
|
||||
});
|
||||
for p in packets {
|
||||
socket.send_to(&p.data[..p.meta.size], &tpu_forwards)?;
|
||||
if data_budget.take(p.meta.size) {
|
||||
socket.send_to(&p.data[..p.meta.size], &tpu_forwards)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -486,6 +500,7 @@ impl BankingStage {
|
||||
gossip_vote_sender: &ReplayVoteSender,
|
||||
banking_stage_stats: &BankingStageStats,
|
||||
recorder: &TransactionRecorder,
|
||||
data_budget: &DataBudget,
|
||||
) -> BufferedPacketsDecision {
|
||||
let bank_start;
|
||||
let (
|
||||
@@ -536,6 +551,7 @@ impl BankingStage {
|
||||
poh_recorder,
|
||||
socket,
|
||||
false,
|
||||
&data_budget,
|
||||
);
|
||||
}
|
||||
BufferedPacketsDecision::ForwardAndHold => {
|
||||
@@ -546,6 +562,7 @@ impl BankingStage {
|
||||
poh_recorder,
|
||||
socket,
|
||||
true,
|
||||
&data_budget,
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
@@ -560,6 +577,7 @@ impl BankingStage {
|
||||
poh_recorder: &Arc<Mutex<PohRecorder>>,
|
||||
socket: &UdpSocket,
|
||||
hold: bool,
|
||||
data_budget: &DataBudget,
|
||||
) {
|
||||
if !enable_forwarding {
|
||||
if !hold {
|
||||
@@ -572,7 +590,7 @@ impl BankingStage {
|
||||
Some(addr) => addr,
|
||||
None => return,
|
||||
};
|
||||
let _ = Self::forward_buffered_packets(socket, &addr, buffered_packets);
|
||||
let _ = Self::forward_buffered_packets(socket, &addr, buffered_packets, data_budget);
|
||||
if hold {
|
||||
buffered_packets.retain(|(_, index, _)| !index.is_empty());
|
||||
for (_, _, forwarded) in buffered_packets.iter_mut() {
|
||||
@@ -596,6 +614,7 @@ impl BankingStage {
|
||||
transaction_status_sender: Option<TransactionStatusSender>,
|
||||
gossip_vote_sender: ReplayVoteSender,
|
||||
duplicates: &Arc<Mutex<(LruCache<u64, ()>, PacketHasher)>>,
|
||||
data_budget: &DataBudget,
|
||||
) {
|
||||
let recorder = poh_recorder.lock().unwrap().recorder();
|
||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
@@ -614,6 +633,7 @@ impl BankingStage {
|
||||
&gossip_vote_sender,
|
||||
&banking_stage_stats,
|
||||
&recorder,
|
||||
&data_budget,
|
||||
);
|
||||
if matches!(decision, BufferedPacketsDecision::Hold)
|
||||
|| matches!(decision, BufferedPacketsDecision::ForwardAndHold)
|
||||
@@ -2694,6 +2714,55 @@ mod tests {
|
||||
Blockstore::destroy(&ledger_path).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_forwarder_budget() {
|
||||
solana_logger::setup();
|
||||
// Create `Packets` with 1 unprocessed element
|
||||
let single_element_packets = Packets::new(vec![Packet::default()]);
|
||||
let mut unprocessed_packets: UnprocessedPackets =
|
||||
vec![(single_element_packets, vec![0], false)]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(Node::new_localhost().info);
|
||||
|
||||
let genesis_config_info = create_slow_genesis_config(10_000);
|
||||
let GenesisConfigInfo { genesis_config, .. } = &genesis_config_info;
|
||||
|
||||
let bank = Arc::new(Bank::new_no_wallclock_throttle(&genesis_config));
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
{
|
||||
let blockstore = Arc::new(
|
||||
Blockstore::open(&ledger_path)
|
||||
.expect("Expected to be able to open database ledger"),
|
||||
);
|
||||
let poh_config = PohConfig {
|
||||
// limit tick count to avoid clearing working_bank at
|
||||
// PohRecord then PohRecorderError(MaxHeightReached) at BankingStage
|
||||
target_tick_count: Some(bank.max_tick_height() - 1),
|
||||
..PohConfig::default()
|
||||
};
|
||||
|
||||
let (exit, poh_recorder, poh_service, _entry_receiver) =
|
||||
create_test_recorder(&bank, &blockstore, Some(poh_config));
|
||||
|
||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
let data_budget = DataBudget::default();
|
||||
BankingStage::handle_forwarding(
|
||||
true,
|
||||
&cluster_info,
|
||||
&mut unprocessed_packets,
|
||||
&poh_recorder,
|
||||
&socket,
|
||||
false,
|
||||
&data_budget,
|
||||
);
|
||||
exit.store(true, Ordering::Relaxed);
|
||||
poh_service.join().unwrap();
|
||||
}
|
||||
Blockstore::destroy(&ledger_path).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_unprocessed_batch_limit() {
|
||||
solana_logger::setup();
|
||||
|
@@ -12,77 +12,79 @@
|
||||
//! * layer 2 - Everyone else, if layer 1 is `2^10`, layer 2 should be able to fit `2^20` number of nodes.
|
||||
//!
|
||||
//! Bank needs to provide an interface for us to query the stake weight
|
||||
use crate::{
|
||||
cluster_info_metrics::{submit_gossip_stats, Counter, GossipStats, ScopedTimer},
|
||||
contact_info::ContactInfo,
|
||||
crds::Cursor,
|
||||
crds_gossip::CrdsGossip,
|
||||
crds_gossip_error::CrdsGossipError,
|
||||
crds_gossip_pull::{CrdsFilter, ProcessPullStats, CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS},
|
||||
crds_value::{
|
||||
self, CrdsData, CrdsValue, CrdsValueLabel, EpochSlotsIndex, LowestSlot, NodeInstance,
|
||||
SnapshotHash, Version, Vote, MAX_WALLCLOCK,
|
||||
use {
|
||||
crate::{
|
||||
cluster_info_metrics::{submit_gossip_stats, Counter, GossipStats, ScopedTimer},
|
||||
contact_info::ContactInfo,
|
||||
crds::Cursor,
|
||||
crds_gossip::CrdsGossip,
|
||||
crds_gossip_error::CrdsGossipError,
|
||||
crds_gossip_pull::{CrdsFilter, ProcessPullStats, CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS},
|
||||
crds_value::{
|
||||
self, CrdsData, CrdsValue, CrdsValueLabel, EpochSlotsIndex, LowestSlot, NodeInstance,
|
||||
SnapshotHash, Version, Vote, MAX_WALLCLOCK,
|
||||
},
|
||||
data_budget::DataBudget,
|
||||
epoch_slots::EpochSlots,
|
||||
ping_pong::{self, PingCache, Pong},
|
||||
result::{Error, Result},
|
||||
weighted_shuffle::weighted_shuffle,
|
||||
},
|
||||
data_budget::DataBudget,
|
||||
epoch_slots::EpochSlots,
|
||||
ping_pong::{self, PingCache, Pong},
|
||||
result::{Error, Result},
|
||||
weighted_shuffle::weighted_shuffle,
|
||||
};
|
||||
use rand::{seq::SliceRandom, CryptoRng, Rng};
|
||||
use solana_ledger::shred::Shred;
|
||||
use solana_sdk::sanitize::{Sanitize, SanitizeError};
|
||||
|
||||
use bincode::{serialize, serialized_size};
|
||||
use itertools::Itertools;
|
||||
use rand::thread_rng;
|
||||
use rayon::prelude::*;
|
||||
use rayon::{ThreadPool, ThreadPoolBuilder};
|
||||
use serde::ser::Serialize;
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_measure::thread_mem_usage;
|
||||
use solana_metrics::{inc_new_counter_debug, inc_new_counter_error};
|
||||
use solana_net_utils::{
|
||||
bind_common, bind_common_in_range, bind_in_range, find_available_port_in_range,
|
||||
multi_bind_in_range, PortRange,
|
||||
};
|
||||
use solana_perf::packet::{
|
||||
limited_deserialize, to_packets_with_destination, Packet, Packets, PacketsRecycler,
|
||||
PACKET_DATA_SIZE,
|
||||
};
|
||||
use solana_rayon_threadlimit::get_thread_count;
|
||||
use solana_runtime::bank_forks::BankForks;
|
||||
use solana_sdk::{
|
||||
clock::{Slot, DEFAULT_MS_PER_SLOT, DEFAULT_SLOTS_PER_EPOCH},
|
||||
feature_set::{self, FeatureSet},
|
||||
hash::Hash,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signable, Signature, Signer},
|
||||
timing::timestamp,
|
||||
transaction::Transaction,
|
||||
};
|
||||
use solana_streamer::{
|
||||
sendmmsg::multicast,
|
||||
socket::is_global,
|
||||
streamer::{PacketReceiver, PacketSender},
|
||||
};
|
||||
use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{hash_map::Entry, HashMap, HashSet, VecDeque},
|
||||
fmt::Debug,
|
||||
fs::{self, File},
|
||||
io::BufReader,
|
||||
iter::repeat,
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, UdpSocket},
|
||||
ops::{Deref, DerefMut, Div},
|
||||
path::{Path, PathBuf},
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
bincode::{serialize, serialized_size},
|
||||
itertools::Itertools,
|
||||
rand::thread_rng,
|
||||
rand::{seq::SliceRandom, CryptoRng, Rng},
|
||||
rayon::prelude::*,
|
||||
rayon::{ThreadPool, ThreadPoolBuilder},
|
||||
serde::ser::Serialize,
|
||||
solana_ledger::shred::Shred,
|
||||
solana_measure::measure::Measure,
|
||||
solana_measure::thread_mem_usage,
|
||||
solana_metrics::{inc_new_counter_debug, inc_new_counter_error},
|
||||
solana_net_utils::{
|
||||
bind_common, bind_common_in_range, bind_in_range, find_available_port_in_range,
|
||||
multi_bind_in_range, PortRange,
|
||||
},
|
||||
solana_perf::packet::{
|
||||
limited_deserialize, to_packets_with_destination, Packet, Packets, PacketsRecycler,
|
||||
PACKET_DATA_SIZE,
|
||||
},
|
||||
solana_rayon_threadlimit::get_thread_count,
|
||||
solana_runtime::bank_forks::BankForks,
|
||||
solana_sdk::{
|
||||
clock::{Slot, DEFAULT_MS_PER_SLOT, DEFAULT_SLOTS_PER_EPOCH},
|
||||
feature_set::{self, FeatureSet},
|
||||
hash::Hash,
|
||||
pubkey::Pubkey,
|
||||
sanitize::{Sanitize, SanitizeError},
|
||||
signature::{Keypair, Signable, Signature, Signer},
|
||||
timing::timestamp,
|
||||
transaction::Transaction,
|
||||
},
|
||||
solana_streamer::{
|
||||
sendmmsg::multicast,
|
||||
socket::is_global,
|
||||
streamer::{PacketReceiver, PacketSender},
|
||||
},
|
||||
solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY,
|
||||
std::{
|
||||
borrow::Cow,
|
||||
collections::{hash_map::Entry, HashMap, HashSet, VecDeque},
|
||||
fmt::Debug,
|
||||
fs::{self, File},
|
||||
io::BufReader,
|
||||
iter::repeat,
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, UdpSocket},
|
||||
ops::{Deref, DerefMut, Div},
|
||||
path::{Path, PathBuf},
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc::{Receiver, RecvTimeoutError, Sender},
|
||||
{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
},
|
||||
thread::{sleep, Builder, JoinHandle},
|
||||
time::{Duration, Instant},
|
||||
},
|
||||
thread::{sleep, Builder, JoinHandle},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
pub const VALIDATOR_PORT_RANGE: PortRange = (8000, 10_000);
|
||||
@@ -235,7 +237,7 @@ impl Default for ClusterInfo {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, AbiExample)]
|
||||
struct PruneData {
|
||||
pub(crate) struct PruneData {
|
||||
/// Pubkey of the node that sent this prune data
|
||||
pubkey: Pubkey,
|
||||
/// Pubkeys of nodes that should be pruned
|
||||
@@ -329,7 +331,7 @@ pub(crate) type Ping = ping_pong::Ping<[u8; GOSSIP_PING_TOKEN_SIZE]>;
|
||||
#[frozen_abi(digest = "CH5BWuhAyvUiUQYgu2Lcwu7eoiW6bQitvtLS1yFsdmrE")]
|
||||
#[derive(Serialize, Deserialize, Debug, AbiEnumVisitor, AbiExample)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
enum Protocol {
|
||||
pub(crate) enum Protocol {
|
||||
/// Gossip protocol messages
|
||||
PullRequest(CrdsFilter, CrdsValue),
|
||||
PullResponse(Pubkey, Vec<CrdsValue>),
|
||||
@@ -897,29 +899,24 @@ impl ClusterInfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_epoch_slots(&self, update: &[Slot]) {
|
||||
let mut num = 0;
|
||||
let mut current_slots: Vec<_> = (0..crds_value::MAX_EPOCH_SLOTS)
|
||||
.filter_map(|ix| {
|
||||
Some((
|
||||
self.time_gossip_read_lock(
|
||||
"lookup_epoch_slots",
|
||||
&self.stats.epoch_slots_lookup,
|
||||
)
|
||||
.crds
|
||||
.get(&CrdsValueLabel::EpochSlots(ix, self.id()))
|
||||
.and_then(|v| v.value.epoch_slots())
|
||||
.and_then(|x| Some((x.wallclock, x.first_slot()?)))?,
|
||||
ix,
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
current_slots.sort_unstable();
|
||||
pub(crate) fn push_epoch_slots(&self, mut update: &[Slot]) {
|
||||
let current_slots: Vec<_> = {
|
||||
let gossip =
|
||||
self.time_gossip_read_lock("lookup_epoch_slots", &self.stats.epoch_slots_lookup);
|
||||
(0..crds_value::MAX_EPOCH_SLOTS)
|
||||
.filter_map(|ix| {
|
||||
let label = CrdsValueLabel::EpochSlots(ix, self.id());
|
||||
let epoch_slots = gossip.crds.get(&label)?.value.epoch_slots()?;
|
||||
let first_slot = epoch_slots.first_slot()?;
|
||||
Some((epoch_slots.wallclock, first_slot, ix))
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
let min_slot: Slot = current_slots
|
||||
.iter()
|
||||
.map(|((_, s), _)| *s)
|
||||
.map(|(_wallclock, slot, _index)| *slot)
|
||||
.min()
|
||||
.unwrap_or(0);
|
||||
.unwrap_or_default();
|
||||
let max_slot: Slot = update.iter().max().cloned().unwrap_or(0);
|
||||
let total_slots = max_slot as isize - min_slot as isize;
|
||||
// WARN if CRDS is not storing at least a full epoch worth of slots
|
||||
@@ -934,8 +931,11 @@ impl ClusterInfo {
|
||||
);
|
||||
}
|
||||
let mut reset = false;
|
||||
let mut epoch_slot_index = current_slots.last().map(|(_, x)| *x).unwrap_or(0);
|
||||
while num < update.len() {
|
||||
let mut epoch_slot_index = match current_slots.iter().max() {
|
||||
Some((_wallclock, _slot, index)) => *index,
|
||||
None => 0,
|
||||
};
|
||||
while !update.is_empty() {
|
||||
let ix = (epoch_slot_index % crds_value::MAX_EPOCH_SLOTS) as u8;
|
||||
let now = timestamp();
|
||||
let mut slots = if !reset {
|
||||
@@ -943,7 +943,8 @@ impl ClusterInfo {
|
||||
} else {
|
||||
EpochSlots::new(self.id(), now)
|
||||
};
|
||||
let n = slots.fill(&update[num..], now);
|
||||
let n = slots.fill(update, now);
|
||||
update = &update[n..];
|
||||
if n > 0 {
|
||||
let entry = CrdsValue::new_signed(CrdsData::EpochSlots(ix, slots), &self.keypair);
|
||||
self.local_message_pending_push_queue
|
||||
@@ -951,11 +952,8 @@ impl ClusterInfo {
|
||||
.unwrap()
|
||||
.push(entry);
|
||||
}
|
||||
num += n;
|
||||
if num < update.len() {
|
||||
epoch_slot_index += 1;
|
||||
reset = true;
|
||||
}
|
||||
epoch_slot_index += 1;
|
||||
reset = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1161,10 +1159,19 @@ impl ClusterInfo {
|
||||
.map(map)
|
||||
}
|
||||
|
||||
/// Returns epoch-slots inserted since the given cursor.
|
||||
/// Excludes entries from nodes with unkown or different shred version.
|
||||
pub(crate) fn get_epoch_slots(&self, cursor: &mut Cursor) -> Vec<EpochSlots> {
|
||||
let self_shred_version = self.my_shred_version();
|
||||
let gossip = self.gossip.read().unwrap();
|
||||
let entries = gossip.crds.get_epoch_slots(cursor);
|
||||
entries
|
||||
.filter(
|
||||
|entry| match gossip.crds.get_contact_info(entry.value.pubkey()) {
|
||||
Some(node) => node.shred_version == self_shred_version,
|
||||
None => false,
|
||||
},
|
||||
)
|
||||
.map(|entry| match &entry.value.data {
|
||||
CrdsData::EpochSlots(_, slots) => slots.clone(),
|
||||
_ => panic!("this should not happen!"),
|
||||
@@ -1751,11 +1758,14 @@ impl ClusterInfo {
|
||||
.map(|k| k.id)
|
||||
.chain(std::iter::once(self.id))
|
||||
.collect();
|
||||
self.stats.trim_crds_table.add_relaxed(1);
|
||||
let mut gossip = self.gossip.write().unwrap();
|
||||
match gossip.crds.trim(cap, &keep, stakes, timestamp()) {
|
||||
Err(err) => {
|
||||
self.stats.trim_crds_table_failed.add_relaxed(1);
|
||||
error!("crds table trim failed: {:?}", err);
|
||||
// TODO: Stakes are comming from the root-bank. Debug why/when
|
||||
// they are empty/zero.
|
||||
debug!("crds table trim failed: {:?}", err);
|
||||
}
|
||||
Ok(num_purged) => {
|
||||
self.stats
|
||||
@@ -1771,9 +1781,8 @@ impl ClusterInfo {
|
||||
bank_forks: Option<Arc<RwLock<BankForks>>>,
|
||||
sender: PacketSender,
|
||||
gossip_validators: Option<HashSet<Pubkey>>,
|
||||
exit: &Arc<AtomicBool>,
|
||||
exit: Arc<AtomicBool>,
|
||||
) -> JoinHandle<()> {
|
||||
let exit = exit.clone();
|
||||
let thread_pool = ThreadPoolBuilder::new()
|
||||
.num_threads(std::cmp::min(get_thread_count(), 8))
|
||||
.thread_name(|i| format!("ClusterInfo::gossip-{}", i))
|
||||
@@ -1956,8 +1965,13 @@ impl ClusterInfo {
|
||||
self.stats
|
||||
.pull_requests_count
|
||||
.add_relaxed(requests.len() as u64);
|
||||
let response =
|
||||
self.handle_pull_requests(recycler, requests, stakes, require_stake_for_gossip);
|
||||
let response = self.handle_pull_requests(
|
||||
thread_pool,
|
||||
recycler,
|
||||
requests,
|
||||
stakes,
|
||||
require_stake_for_gossip,
|
||||
);
|
||||
if !response.is_empty() {
|
||||
self.stats
|
||||
.packets_sent_pull_responses_count
|
||||
@@ -2027,6 +2041,7 @@ impl ClusterInfo {
|
||||
// and tries to send back to them the values it detects are missing.
|
||||
fn handle_pull_requests(
|
||||
&self,
|
||||
thread_pool: &ThreadPool,
|
||||
recycler: &PacketsRecycler,
|
||||
requests: Vec<PullData>,
|
||||
stakes: &HashMap<Pubkey, u64>,
|
||||
@@ -2058,7 +2073,7 @@ impl ClusterInfo {
|
||||
"generate_pull_responses",
|
||||
&self.stats.generate_pull_responses,
|
||||
)
|
||||
.generate_pull_responses(&caller_and_filters, output_size_limit, now);
|
||||
.generate_pull_responses(thread_pool, &caller_and_filters, output_size_limit, now);
|
||||
if require_stake_for_gossip {
|
||||
for resp in &mut pull_responses {
|
||||
retain_staked(resp, stakes);
|
||||
@@ -2495,7 +2510,7 @@ impl ClusterInfo {
|
||||
|
||||
fn process_packets(
|
||||
&self,
|
||||
packets: VecDeque<Packet>,
|
||||
packets: VecDeque<(/*from:*/ SocketAddr, Protocol)>,
|
||||
thread_pool: &ThreadPool,
|
||||
recycler: &PacketsRecycler,
|
||||
response_sender: &PacketSender,
|
||||
@@ -2505,24 +2520,6 @@ impl ClusterInfo {
|
||||
should_check_duplicate_instance: bool,
|
||||
) -> Result<()> {
|
||||
let _st = ScopedTimer::from(&self.stats.process_gossip_packets_time);
|
||||
self.stats
|
||||
.packets_received_count
|
||||
.add_relaxed(packets.len() as u64);
|
||||
let packets: Vec<_> = thread_pool.install(|| {
|
||||
packets
|
||||
.into_par_iter()
|
||||
.filter_map(|packet| {
|
||||
let protocol: Protocol =
|
||||
limited_deserialize(&packet.data[..packet.meta.size]).ok()?;
|
||||
protocol.sanitize().ok()?;
|
||||
let protocol = protocol.par_verify()?;
|
||||
Some((packet.meta.addr(), protocol))
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
self.stats
|
||||
.packets_received_verified_count
|
||||
.add_relaxed(packets.len() as u64);
|
||||
// Check if there is a duplicate instance of
|
||||
// this node with more recent timestamp.
|
||||
let check_duplicate_instance = |values: &[CrdsValue]| {
|
||||
@@ -2607,12 +2604,54 @@ impl ClusterInfo {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Consumes packets received from the socket, deserializing, sanitizing and
|
||||
// verifying them and then sending them down the channel for the actual
|
||||
// handling of requests/messages.
|
||||
fn run_socket_consume(
|
||||
&self,
|
||||
receiver: &PacketReceiver,
|
||||
sender: &Sender<Vec<(/*from:*/ SocketAddr, Protocol)>>,
|
||||
thread_pool: &ThreadPool,
|
||||
) -> Result<()> {
|
||||
const RECV_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
let packets: Vec<_> = receiver.recv_timeout(RECV_TIMEOUT)?.packets.into();
|
||||
let mut packets = VecDeque::from(packets);
|
||||
for payload in receiver.try_iter() {
|
||||
packets.extend(payload.packets.iter().cloned());
|
||||
let excess_count = packets.len().saturating_sub(MAX_GOSSIP_TRAFFIC);
|
||||
if excess_count > 0 {
|
||||
packets.drain(0..excess_count);
|
||||
self.stats
|
||||
.gossip_packets_dropped_count
|
||||
.add_relaxed(excess_count as u64);
|
||||
}
|
||||
}
|
||||
self.stats
|
||||
.packets_received_count
|
||||
.add_relaxed(packets.len() as u64);
|
||||
let verify_packet = |packet: Packet| {
|
||||
let data = &packet.data[..packet.meta.size];
|
||||
let protocol: Protocol = limited_deserialize(data).ok()?;
|
||||
protocol.sanitize().ok()?;
|
||||
let protocol = protocol.par_verify()?;
|
||||
Some((packet.meta.addr(), protocol))
|
||||
};
|
||||
let packets: Vec<_> = {
|
||||
let _st = ScopedTimer::from(&self.stats.verify_gossip_packets_time);
|
||||
thread_pool.install(|| packets.into_par_iter().filter_map(verify_packet).collect())
|
||||
};
|
||||
self.stats
|
||||
.packets_received_verified_count
|
||||
.add_relaxed(packets.len() as u64);
|
||||
Ok(sender.send(packets)?)
|
||||
}
|
||||
|
||||
/// Process messages from the network
|
||||
fn run_listen(
|
||||
&self,
|
||||
recycler: &PacketsRecycler,
|
||||
bank_forks: Option<&RwLock<BankForks>>,
|
||||
requests_receiver: &PacketReceiver,
|
||||
receiver: &Receiver<Vec<(/*from:*/ SocketAddr, Protocol)>>,
|
||||
response_sender: &PacketSender,
|
||||
thread_pool: &ThreadPool,
|
||||
last_print: &mut Instant,
|
||||
@@ -2620,10 +2659,9 @@ impl ClusterInfo {
|
||||
) -> Result<()> {
|
||||
const RECV_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
const SUBMIT_GOSSIP_STATS_INTERVAL: Duration = Duration::from_secs(2);
|
||||
let packets: Vec<_> = requests_receiver.recv_timeout(RECV_TIMEOUT)?.packets.into();
|
||||
let mut packets = VecDeque::from(packets);
|
||||
while let Ok(packet) = requests_receiver.try_recv() {
|
||||
packets.extend(packet.packets.into_iter());
|
||||
let mut packets = VecDeque::from(receiver.recv_timeout(RECV_TIMEOUT)?);
|
||||
for payload in receiver.try_iter() {
|
||||
packets.extend(payload);
|
||||
let excess_count = packets.len().saturating_sub(MAX_GOSSIP_TRAFFIC);
|
||||
if excess_count > 0 {
|
||||
packets.drain(0..excess_count);
|
||||
@@ -2660,26 +2698,53 @@ impl ClusterInfo {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn listen(
|
||||
pub(crate) fn start_socket_consume_thread(
|
||||
self: Arc<Self>,
|
||||
receiver: PacketReceiver,
|
||||
sender: Sender<Vec<(/*from:*/ SocketAddr, Protocol)>>,
|
||||
exit: Arc<AtomicBool>,
|
||||
) -> JoinHandle<()> {
|
||||
let thread_pool = ThreadPoolBuilder::new()
|
||||
.num_threads(get_thread_count().min(8))
|
||||
.thread_name(|i| format!("gossip-consume-{}", i))
|
||||
.build()
|
||||
.unwrap();
|
||||
let run_consume = move || {
|
||||
while !exit.load(Ordering::Relaxed) {
|
||||
match self.run_socket_consume(&receiver, &sender, &thread_pool) {
|
||||
Err(Error::RecvTimeoutError(RecvTimeoutError::Disconnected)) => break,
|
||||
Err(Error::RecvTimeoutError(RecvTimeoutError::Timeout)) => (),
|
||||
// A send operation can only fail if the receiving end of a
|
||||
// channel is disconnected.
|
||||
Err(Error::SendError) => break,
|
||||
Err(err) => error!("gossip consume: {}", err),
|
||||
Ok(()) => (),
|
||||
}
|
||||
}
|
||||
};
|
||||
let thread_name = String::from("gossip-consume");
|
||||
Builder::new().name(thread_name).spawn(run_consume).unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn listen(
|
||||
self: Arc<Self>,
|
||||
bank_forks: Option<Arc<RwLock<BankForks>>>,
|
||||
requests_receiver: PacketReceiver,
|
||||
requests_receiver: Receiver<Vec<(/*from:*/ SocketAddr, Protocol)>>,
|
||||
response_sender: PacketSender,
|
||||
should_check_duplicate_instance: bool,
|
||||
exit: &Arc<AtomicBool>,
|
||||
exit: Arc<AtomicBool>,
|
||||
) -> JoinHandle<()> {
|
||||
let exit = exit.clone();
|
||||
let recycler =
|
||||
PacketsRecycler::new_without_limit("cluster-info-listen-recycler-shrink-stats");
|
||||
let mut last_print = Instant::now();
|
||||
let thread_pool = ThreadPoolBuilder::new()
|
||||
.num_threads(get_thread_count().min(8))
|
||||
.thread_name(|i| format!("sol-gossip-work-{}", i))
|
||||
.build()
|
||||
.unwrap();
|
||||
Builder::new()
|
||||
.name("solana-listen".to_string())
|
||||
.spawn(move || {
|
||||
let thread_pool = ThreadPoolBuilder::new()
|
||||
.num_threads(std::cmp::min(get_thread_count(), 8))
|
||||
.thread_name(|i| format!("sol-gossip-work-{}", i))
|
||||
.build()
|
||||
.unwrap();
|
||||
let mut last_print = Instant::now();
|
||||
while !exit.load(Ordering::Relaxed) {
|
||||
if let Err(err) = self.run_listen(
|
||||
&recycler,
|
||||
@@ -2691,7 +2756,8 @@ impl ClusterInfo {
|
||||
should_check_duplicate_instance,
|
||||
) {
|
||||
match err {
|
||||
Error::RecvTimeoutError(_) => {
|
||||
Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => break,
|
||||
Error::RecvTimeoutError(RecvTimeoutError::Timeout) => {
|
||||
let table_size = self.gossip.read().unwrap().crds.len();
|
||||
debug!(
|
||||
"{}: run_listen timeout, table size: {}",
|
||||
@@ -3769,6 +3835,43 @@ mod tests {
|
||||
|
||||
let slots = cluster_info.get_epoch_slots(&mut cursor);
|
||||
assert!(slots.is_empty());
|
||||
|
||||
// Test with different shred versions.
|
||||
let mut rng = rand::thread_rng();
|
||||
let node_pubkey = Pubkey::new_unique();
|
||||
let mut node = ContactInfo::new_rand(&mut rng, Some(node_pubkey));
|
||||
node.shred_version = 42;
|
||||
let epoch_slots = EpochSlots::new_rand(&mut rng, Some(node_pubkey));
|
||||
let entries = vec![
|
||||
CrdsValue::new_unsigned(CrdsData::ContactInfo(node)),
|
||||
CrdsValue::new_unsigned(CrdsData::EpochSlots(0, epoch_slots)),
|
||||
];
|
||||
{
|
||||
let mut gossip = cluster_info.gossip.write().unwrap();
|
||||
for entry in entries {
|
||||
assert!(gossip.crds.insert(entry, /*now=*/ 0).is_ok());
|
||||
}
|
||||
}
|
||||
// Should exclude other node's epoch-slot because of different
|
||||
// shred-version.
|
||||
let slots = cluster_info.get_epoch_slots(&mut Cursor::default());
|
||||
assert_eq!(slots.len(), 1);
|
||||
assert_eq!(slots[0].from, cluster_info.id);
|
||||
// Match shred versions.
|
||||
{
|
||||
let mut node = cluster_info.my_contact_info.write().unwrap();
|
||||
node.shred_version = 42;
|
||||
}
|
||||
cluster_info.push_self(
|
||||
&HashMap::default(), // stakes
|
||||
None, // gossip validators
|
||||
);
|
||||
cluster_info.flush_push_queue();
|
||||
// Should now include both epoch slots.
|
||||
let slots = cluster_info.get_epoch_slots(&mut Cursor::default());
|
||||
assert_eq!(slots.len(), 2);
|
||||
assert_eq!(slots[0].from, cluster_info.id);
|
||||
assert_eq!(slots[1].from, node_pubkey);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@@ -113,9 +113,11 @@ pub(crate) struct GossipStats {
|
||||
pub(crate) skip_pull_response_shred_version: Counter,
|
||||
pub(crate) skip_pull_shred_version: Counter,
|
||||
pub(crate) skip_push_message_shred_version: Counter,
|
||||
pub(crate) trim_crds_table: Counter,
|
||||
pub(crate) trim_crds_table_failed: Counter,
|
||||
pub(crate) trim_crds_table_purged_values_count: Counter,
|
||||
pub(crate) tvu_peers: Counter,
|
||||
pub(crate) verify_gossip_packets_time: Counter,
|
||||
}
|
||||
|
||||
pub(crate) fn submit_gossip_stats(
|
||||
@@ -169,6 +171,11 @@ pub(crate) fn submit_gossip_stats(
|
||||
stats.process_gossip_packets_time.clear(),
|
||||
i64
|
||||
),
|
||||
(
|
||||
"verify_gossip_packets_time",
|
||||
stats.verify_gossip_packets_time.clear(),
|
||||
i64
|
||||
),
|
||||
(
|
||||
"handle_batch_ping_messages_time",
|
||||
stats.handle_batch_ping_messages_time.clear(),
|
||||
@@ -390,6 +397,7 @@ pub(crate) fn submit_gossip_stats(
|
||||
stats.require_stake_for_gossip_unknown_stakes.clear(),
|
||||
i64
|
||||
),
|
||||
("trim_crds_table", stats.trim_crds_table.clear(), i64),
|
||||
(
|
||||
"trim_crds_table_failed",
|
||||
stats.trim_crds_table_failed.clear(),
|
||||
|
@@ -136,6 +136,9 @@ impl ClusterSlots {
|
||||
}
|
||||
|
||||
pub fn compute_weights(&self, slot: Slot, repair_peers: &[ContactInfo]) -> Vec<u64> {
|
||||
if repair_peers.is_empty() {
|
||||
return Vec::default();
|
||||
}
|
||||
let stakes = {
|
||||
let validator_stakes = self.validator_stakes.read().unwrap();
|
||||
repair_peers
|
||||
|
@@ -383,22 +383,20 @@ impl Crds {
|
||||
// returns crds labels of old values to be evicted.
|
||||
let evict = |pubkey, index: &IndexSet<usize>| {
|
||||
let timeout = timeouts.get(pubkey).copied().unwrap_or(default_timeout);
|
||||
let local_timestamp = {
|
||||
let origin = CrdsValueLabel::ContactInfo(*pubkey);
|
||||
match self.table.get(&origin) {
|
||||
Some(origin) => origin.local_timestamp,
|
||||
None => 0,
|
||||
// If the origin's contact-info hasn't expired yet then preserve
|
||||
// all associated values.
|
||||
let origin = CrdsValueLabel::ContactInfo(*pubkey);
|
||||
if let Some(origin) = self.table.get(&origin) {
|
||||
if now < origin.local_timestamp.saturating_add(timeout) {
|
||||
return vec![];
|
||||
}
|
||||
};
|
||||
}
|
||||
// Otherwise check each value's timestamp individually.
|
||||
index
|
||||
.into_iter()
|
||||
.filter_map(|ix| {
|
||||
let (label, value) = self.table.get_index(*ix).unwrap();
|
||||
let expiry_timestamp = value
|
||||
.local_timestamp
|
||||
.max(local_timestamp)
|
||||
.saturating_add(timeout);
|
||||
if expiry_timestamp <= now {
|
||||
if value.local_timestamp.saturating_add(timeout) <= now {
|
||||
Some(label.clone())
|
||||
} else {
|
||||
None
|
||||
@@ -511,7 +509,7 @@ impl Crds {
|
||||
stakes: &HashMap<Pubkey, u64>,
|
||||
now: u64,
|
||||
) -> Result</*num purged:*/ usize, CrdsError> {
|
||||
if stakes.is_empty() {
|
||||
if stakes.values().all(|&stake| stake == 0) {
|
||||
return Err(CrdsError::UnknownStakes);
|
||||
}
|
||||
let mut keys: Vec<_> = self
|
||||
|
@@ -254,12 +254,13 @@ impl CrdsGossip {
|
||||
|
||||
pub fn generate_pull_responses(
|
||||
&self,
|
||||
thread_pool: &ThreadPool,
|
||||
filters: &[(CrdsValue, CrdsFilter)],
|
||||
output_size_limit: usize, // Limit number of crds values returned.
|
||||
now: u64,
|
||||
) -> Vec<Vec<CrdsValue>> {
|
||||
self.pull
|
||||
.generate_pull_responses(&self.crds, filters, output_size_limit, now)
|
||||
.generate_pull_responses(thread_pool, &self.crds, filters, output_size_limit, now)
|
||||
}
|
||||
|
||||
pub fn filter_pull_responses(
|
||||
|
@@ -9,32 +9,38 @@
|
||||
//! with random hash functions. So each subsequent request will have a different distribution
|
||||
//! of false positives.
|
||||
|
||||
use crate::{
|
||||
cluster_info::{Ping, CRDS_UNIQUE_PUBKEY_CAPACITY},
|
||||
contact_info::ContactInfo,
|
||||
crds::Crds,
|
||||
crds_gossip::{get_stake, get_weight},
|
||||
crds_gossip_error::CrdsGossipError,
|
||||
crds_value::CrdsValue,
|
||||
ping_pong::PingCache,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use lru::LruCache;
|
||||
use rand::distributions::{Distribution, WeightedIndex};
|
||||
use rand::Rng;
|
||||
use rayon::{prelude::*, ThreadPool};
|
||||
use solana_runtime::bloom::{AtomicBloom, Bloom};
|
||||
use solana_sdk::{
|
||||
hash::{hash, Hash},
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet, VecDeque},
|
||||
convert::TryInto,
|
||||
net::SocketAddr,
|
||||
sync::Mutex,
|
||||
time::{Duration, Instant},
|
||||
use {
|
||||
crate::{
|
||||
cluster_info::{Ping, CRDS_UNIQUE_PUBKEY_CAPACITY},
|
||||
contact_info::ContactInfo,
|
||||
crds::Crds,
|
||||
crds_gossip::{get_stake, get_weight},
|
||||
crds_gossip_error::CrdsGossipError,
|
||||
crds_value::CrdsValue,
|
||||
ping_pong::PingCache,
|
||||
},
|
||||
lru::LruCache,
|
||||
rand::{
|
||||
distributions::{Distribution, WeightedIndex},
|
||||
Rng,
|
||||
},
|
||||
rayon::{prelude::*, ThreadPool},
|
||||
solana_runtime::bloom::{AtomicBloom, Bloom},
|
||||
solana_sdk::{
|
||||
hash::{hash, Hash},
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
},
|
||||
std::{
|
||||
collections::{HashMap, HashSet, VecDeque},
|
||||
convert::TryInto,
|
||||
net::SocketAddr,
|
||||
sync::{
|
||||
atomic::{AtomicI64, AtomicUsize, Ordering},
|
||||
Mutex,
|
||||
},
|
||||
time::{Duration, Instant},
|
||||
},
|
||||
};
|
||||
|
||||
pub const CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS: u64 = 15000;
|
||||
@@ -333,12 +339,13 @@ impl CrdsGossipPull {
|
||||
/// Create gossip responses to pull requests
|
||||
pub fn generate_pull_responses(
|
||||
&self,
|
||||
thread_pool: &ThreadPool,
|
||||
crds: &Crds,
|
||||
requests: &[(CrdsValue, CrdsFilter)],
|
||||
output_size_limit: usize, // Limit number of crds values returned.
|
||||
now: u64,
|
||||
) -> Vec<Vec<CrdsValue>> {
|
||||
self.filter_crds_values(crds, requests, output_size_limit, now)
|
||||
self.filter_crds_values(thread_pool, crds, requests, output_size_limit, now)
|
||||
}
|
||||
|
||||
// Checks if responses should be inserted and
|
||||
@@ -472,9 +479,10 @@ impl CrdsGossipPull {
|
||||
/// filter values that fail the bloom filter up to max_bytes
|
||||
fn filter_crds_values(
|
||||
&self,
|
||||
thread_pool: &ThreadPool,
|
||||
crds: &Crds,
|
||||
filters: &[(CrdsValue, CrdsFilter)],
|
||||
mut output_size_limit: usize, // Limit number of crds values returned.
|
||||
output_size_limit: usize, // Limit number of crds values returned.
|
||||
now: u64,
|
||||
) -> Vec<Vec<CrdsValue>> {
|
||||
let msg_timeout = CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS;
|
||||
@@ -482,46 +490,53 @@ impl CrdsGossipPull {
|
||||
//skip filters from callers that are too old
|
||||
let caller_wallclock_window =
|
||||
now.saturating_sub(msg_timeout)..now.saturating_add(msg_timeout);
|
||||
let mut dropped_requests = 0;
|
||||
let mut total_skipped = 0;
|
||||
let ret: Vec<_> = filters
|
||||
.iter()
|
||||
.map(|(caller, filter)| {
|
||||
if output_size_limit == 0 {
|
||||
return None;
|
||||
}
|
||||
let caller_wallclock = caller.wallclock();
|
||||
if !caller_wallclock_window.contains(&caller_wallclock) {
|
||||
dropped_requests += 1;
|
||||
return Some(vec![]);
|
||||
}
|
||||
let caller_wallclock = caller_wallclock.checked_add(jitter).unwrap_or(0);
|
||||
let out: Vec<_> = crds
|
||||
.filter_bitmask(filter.mask, filter.mask_bits)
|
||||
.filter_map(|item| {
|
||||
debug_assert!(filter.test_mask(&item.value_hash));
|
||||
//skip values that are too new
|
||||
if item.value.wallclock() > caller_wallclock {
|
||||
total_skipped += 1;
|
||||
None
|
||||
} else if filter.filter_contains(&item.value_hash) {
|
||||
None
|
||||
} else {
|
||||
Some(item.value.clone())
|
||||
}
|
||||
})
|
||||
.take(output_size_limit)
|
||||
.collect();
|
||||
output_size_limit -= out.len();
|
||||
Some(out)
|
||||
})
|
||||
.while_some()
|
||||
.collect();
|
||||
let dropped_requests = AtomicUsize::default();
|
||||
let total_skipped = AtomicUsize::default();
|
||||
let output_size_limit = output_size_limit.try_into().unwrap_or(i64::MAX);
|
||||
let output_size_limit = AtomicI64::new(output_size_limit);
|
||||
let apply_filter = |caller: &CrdsValue, filter: &CrdsFilter| {
|
||||
if output_size_limit.load(Ordering::Relaxed) <= 0 {
|
||||
return Vec::default();
|
||||
}
|
||||
let caller_wallclock = caller.wallclock();
|
||||
if !caller_wallclock_window.contains(&caller_wallclock) {
|
||||
dropped_requests.fetch_add(1, Ordering::Relaxed);
|
||||
return Vec::default();
|
||||
}
|
||||
let caller_wallclock = caller_wallclock.checked_add(jitter).unwrap_or(0);
|
||||
let out: Vec<_> = crds
|
||||
.filter_bitmask(filter.mask, filter.mask_bits)
|
||||
.filter_map(|item| {
|
||||
debug_assert!(filter.test_mask(&item.value_hash));
|
||||
//skip values that are too new
|
||||
if item.value.wallclock() > caller_wallclock {
|
||||
total_skipped.fetch_add(1, Ordering::Relaxed);
|
||||
None
|
||||
} else if filter.filter_contains(&item.value_hash) {
|
||||
None
|
||||
} else {
|
||||
Some(item.value.clone())
|
||||
}
|
||||
})
|
||||
.take(output_size_limit.load(Ordering::Relaxed).max(0) as usize)
|
||||
.collect();
|
||||
output_size_limit.fetch_sub(out.len() as i64, Ordering::Relaxed);
|
||||
out
|
||||
};
|
||||
let ret: Vec<_> = thread_pool.install(|| {
|
||||
filters
|
||||
.par_iter()
|
||||
.map(|(caller, filter)| apply_filter(caller, filter))
|
||||
.collect()
|
||||
});
|
||||
inc_new_counter_info!(
|
||||
"gossip_filter_crds_values-dropped_requests",
|
||||
dropped_requests + filters.len() - ret.len()
|
||||
dropped_requests.into_inner()
|
||||
);
|
||||
inc_new_counter_info!(
|
||||
"gossip_filter_crds_values-dropped_values",
|
||||
total_skipped.into_inner()
|
||||
);
|
||||
inc_new_counter_info!("gossip_filter_crds_values-dropped_values", total_skipped);
|
||||
ret
|
||||
}
|
||||
|
||||
@@ -1098,10 +1113,11 @@ pub(crate) mod tests {
|
||||
let (_, filters) = req.unwrap();
|
||||
let mut filters: Vec<_> = filters.into_iter().map(|f| (caller.clone(), f)).collect();
|
||||
let rsp = dest.generate_pull_responses(
|
||||
&thread_pool,
|
||||
&dest_crds,
|
||||
&filters,
|
||||
/*output_size_limit=*/ usize::MAX,
|
||||
0,
|
||||
usize::MAX, // output_size_limit
|
||||
0, // now
|
||||
);
|
||||
|
||||
assert_eq!(rsp[0].len(), 0);
|
||||
@@ -1116,10 +1132,11 @@ pub(crate) mod tests {
|
||||
|
||||
//should skip new value since caller is to old
|
||||
let rsp = dest.generate_pull_responses(
|
||||
&thread_pool,
|
||||
&dest_crds,
|
||||
&filters,
|
||||
/*output_size_limit=*/ usize::MAX,
|
||||
CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS,
|
||||
usize::MAX, // output_size_limit
|
||||
CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS, // now
|
||||
);
|
||||
assert_eq!(rsp[0].len(), 0);
|
||||
assert_eq!(filters.len(), MIN_NUM_BLOOM_FILTERS);
|
||||
@@ -1134,9 +1151,10 @@ pub(crate) mod tests {
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let rsp = dest.generate_pull_responses(
|
||||
&thread_pool,
|
||||
&dest_crds,
|
||||
&filters,
|
||||
/*output_size_limit=*/ usize::MAX,
|
||||
usize::MAX, // output_size_limit
|
||||
CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS,
|
||||
);
|
||||
assert_eq!(rsp.len(), 2 * MIN_NUM_BLOOM_FILTERS);
|
||||
@@ -1186,10 +1204,11 @@ pub(crate) mod tests {
|
||||
let (_, filters) = req.unwrap();
|
||||
let filters: Vec<_> = filters.into_iter().map(|f| (caller.clone(), f)).collect();
|
||||
let rsp = dest.generate_pull_responses(
|
||||
&thread_pool,
|
||||
&dest_crds,
|
||||
&filters,
|
||||
/*output_size_limit=*/ usize::MAX,
|
||||
0,
|
||||
usize::MAX, // output_size_limit
|
||||
0, // now
|
||||
);
|
||||
dest.process_pull_requests(
|
||||
&mut dest_crds,
|
||||
@@ -1258,10 +1277,11 @@ pub(crate) mod tests {
|
||||
let (_, filters) = req.unwrap();
|
||||
let filters: Vec<_> = filters.into_iter().map(|f| (caller.clone(), f)).collect();
|
||||
let rsp = dest.generate_pull_responses(
|
||||
&thread_pool,
|
||||
&dest_crds,
|
||||
&filters,
|
||||
/*output_size_limit=*/ usize::MAX,
|
||||
0,
|
||||
usize::MAX, // output_size_limit
|
||||
0, // now
|
||||
);
|
||||
dest.process_pull_requests(
|
||||
&mut dest_crds,
|
||||
|
@@ -51,24 +51,40 @@ impl GossipService {
|
||||
"gossip_receiver",
|
||||
1,
|
||||
);
|
||||
let (response_sender, response_receiver) = channel();
|
||||
let t_responder = streamer::responder("gossip", gossip_socket, response_receiver);
|
||||
let t_listen = ClusterInfo::listen(
|
||||
cluster_info.clone(),
|
||||
bank_forks.clone(),
|
||||
let (consume_sender, listen_receiver) = channel();
|
||||
// https://github.com/rust-lang/rust/issues/39364#issuecomment-634545136
|
||||
let _consume_sender = consume_sender.clone();
|
||||
let t_socket_consume = cluster_info.clone().start_socket_consume_thread(
|
||||
request_receiver,
|
||||
consume_sender,
|
||||
exit.clone(),
|
||||
);
|
||||
let (response_sender, response_receiver) = channel();
|
||||
let t_listen = cluster_info.clone().listen(
|
||||
bank_forks.clone(),
|
||||
listen_receiver,
|
||||
response_sender.clone(),
|
||||
should_check_duplicate_instance,
|
||||
exit,
|
||||
exit.clone(),
|
||||
);
|
||||
let t_gossip = ClusterInfo::gossip(
|
||||
cluster_info.clone(),
|
||||
let t_gossip = cluster_info.clone().gossip(
|
||||
bank_forks,
|
||||
response_sender,
|
||||
gossip_validators,
|
||||
exit,
|
||||
exit.clone(),
|
||||
);
|
||||
let thread_hdls = vec![t_receiver, t_responder, t_listen, t_gossip];
|
||||
// To work around:
|
||||
// https://github.com/rust-lang/rust/issues/54267
|
||||
// responder thread should start after response_sender.clone(). see:
|
||||
// https://github.com/rust-lang/rust/issues/39364#issuecomment-381446873
|
||||
let t_responder = streamer::responder("gossip", gossip_socket, response_receiver);
|
||||
let thread_hdls = vec![
|
||||
t_receiver,
|
||||
t_responder,
|
||||
t_socket_consume,
|
||||
t_listen,
|
||||
t_gossip,
|
||||
];
|
||||
Self { thread_hdls }
|
||||
}
|
||||
|
||||
|
@@ -64,6 +64,8 @@ impl OptimisticallyConfirmedBankTracker {
|
||||
) -> Self {
|
||||
let exit_ = exit.clone();
|
||||
let mut pending_optimistically_confirmed_banks = HashSet::new();
|
||||
let mut last_notified_confirmed_slot: Slot = 0;
|
||||
let mut highest_confirmed_slot: Slot = 0;
|
||||
let thread_hdl = Builder::new()
|
||||
.name("solana-optimistic-bank-tracker".to_string())
|
||||
.spawn(move || loop {
|
||||
@@ -77,6 +79,8 @@ impl OptimisticallyConfirmedBankTracker {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
) {
|
||||
break;
|
||||
}
|
||||
@@ -91,6 +95,8 @@ impl OptimisticallyConfirmedBankTracker {
|
||||
optimistically_confirmed_bank: &Arc<RwLock<OptimisticallyConfirmedBank>>,
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
mut pending_optimistically_confirmed_banks: &mut HashSet<Slot>,
|
||||
mut last_notified_confirmed_slot: &mut Slot,
|
||||
mut highest_confirmed_slot: &mut Slot,
|
||||
) -> Result<(), RecvTimeoutError> {
|
||||
let notification = receiver.recv_timeout(Duration::from_secs(1))?;
|
||||
Self::process_notification(
|
||||
@@ -99,31 +105,91 @@ impl OptimisticallyConfirmedBankTracker {
|
||||
optimistically_confirmed_bank,
|
||||
subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn notify_or_defer(
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
bank_forks: &Arc<RwLock<BankForks>>,
|
||||
bank: &Arc<Bank>,
|
||||
last_notified_confirmed_slot: &mut Slot,
|
||||
pending_optimistically_confirmed_banks: &mut HashSet<Slot>,
|
||||
) {
|
||||
if bank.is_frozen() {
|
||||
if bank.slot() > *last_notified_confirmed_slot {
|
||||
debug!(
|
||||
"notify_or_defer notifying via notify_gossip_subscribers for slot {:?}",
|
||||
bank.slot()
|
||||
);
|
||||
subscriptions.notify_gossip_subscribers(bank.slot());
|
||||
*last_notified_confirmed_slot = bank.slot();
|
||||
}
|
||||
} else if bank.slot() > bank_forks.read().unwrap().root_bank().slot() {
|
||||
pending_optimistically_confirmed_banks.insert(bank.slot());
|
||||
debug!("notify_or_defer defer notifying for slot {:?}", bank.slot());
|
||||
}
|
||||
}
|
||||
|
||||
fn notify_or_defer_confirmed_banks(
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
bank_forks: &Arc<RwLock<BankForks>>,
|
||||
bank: &Arc<Bank>,
|
||||
slot_threshold: Slot,
|
||||
mut last_notified_confirmed_slot: &mut Slot,
|
||||
mut pending_optimistically_confirmed_banks: &mut HashSet<Slot>,
|
||||
) {
|
||||
for confirmed_bank in bank.clone().parents_inclusive().iter().rev() {
|
||||
if confirmed_bank.slot() > slot_threshold {
|
||||
debug!(
|
||||
"Calling notify_or_defer for confirmed_bank {:?}",
|
||||
confirmed_bank.slot()
|
||||
);
|
||||
Self::notify_or_defer(
|
||||
subscriptions,
|
||||
bank_forks,
|
||||
confirmed_bank,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn process_notification(
|
||||
notification: BankNotification,
|
||||
bank_forks: &Arc<RwLock<BankForks>>,
|
||||
optimistically_confirmed_bank: &Arc<RwLock<OptimisticallyConfirmedBank>>,
|
||||
subscriptions: &Arc<RpcSubscriptions>,
|
||||
pending_optimistically_confirmed_banks: &mut HashSet<Slot>,
|
||||
mut pending_optimistically_confirmed_banks: &mut HashSet<Slot>,
|
||||
mut last_notified_confirmed_slot: &mut Slot,
|
||||
highest_confirmed_slot: &mut Slot,
|
||||
) {
|
||||
debug!("received bank notification: {:?}", notification);
|
||||
match notification {
|
||||
BankNotification::OptimisticallyConfirmed(slot) => {
|
||||
if let Some(bank) = bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(slot)
|
||||
.filter(|b| b.is_frozen())
|
||||
{
|
||||
if let Some(bank) = bank_forks.read().unwrap().get(slot) {
|
||||
let mut w_optimistically_confirmed_bank =
|
||||
optimistically_confirmed_bank.write().unwrap();
|
||||
if bank.slot() > w_optimistically_confirmed_bank.bank.slot() {
|
||||
|
||||
if bank.slot() > w_optimistically_confirmed_bank.bank.slot() && bank.is_frozen()
|
||||
{
|
||||
w_optimistically_confirmed_bank.bank = bank.clone();
|
||||
subscriptions.notify_gossip_subscribers(slot);
|
||||
}
|
||||
|
||||
if slot > *highest_confirmed_slot {
|
||||
Self::notify_or_defer_confirmed_banks(
|
||||
subscriptions,
|
||||
bank_forks,
|
||||
bank,
|
||||
*highest_confirmed_slot,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
|
||||
*highest_confirmed_slot = slot;
|
||||
}
|
||||
drop(w_optimistically_confirmed_bank);
|
||||
} else if slot > bank_forks.read().unwrap().root_bank().slot() {
|
||||
@@ -157,11 +223,24 @@ impl OptimisticallyConfirmedBankTracker {
|
||||
}
|
||||
|
||||
if pending_optimistically_confirmed_banks.remove(&bank.slot()) {
|
||||
debug!(
|
||||
"Calling notify_gossip_subscribers to send deferred notification {:?}",
|
||||
frozen_slot
|
||||
);
|
||||
|
||||
Self::notify_or_defer_confirmed_banks(
|
||||
subscriptions,
|
||||
bank_forks,
|
||||
&bank,
|
||||
*last_notified_confirmed_slot,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
);
|
||||
|
||||
let mut w_optimistically_confirmed_bank =
|
||||
optimistically_confirmed_bank.write().unwrap();
|
||||
if frozen_slot > w_optimistically_confirmed_bank.bank.slot() {
|
||||
w_optimistically_confirmed_bank.bank = bank;
|
||||
subscriptions.notify_gossip_subscribers(frozen_slot);
|
||||
}
|
||||
drop(w_optimistically_confirmed_bank);
|
||||
}
|
||||
@@ -227,14 +306,19 @@ mod tests {
|
||||
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 0);
|
||||
|
||||
let mut highest_confirmed_slot: Slot = 0;
|
||||
let mut last_notified_confirmed_slot: Slot = 0;
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(2),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 2);
|
||||
assert_eq!(highest_confirmed_slot, 2);
|
||||
|
||||
// Test max optimistically confirmed bank remains in the cache
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
@@ -243,8 +327,11 @@ mod tests {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 2);
|
||||
assert_eq!(highest_confirmed_slot, 2);
|
||||
|
||||
// Test bank will only be cached when frozen
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
@@ -253,21 +340,30 @@ mod tests {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 2);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.len(), 1);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.contains(&3), true);
|
||||
assert!(pending_optimistically_confirmed_banks.contains(&3));
|
||||
assert_eq!(highest_confirmed_slot, 3);
|
||||
|
||||
// Test bank will only be cached when frozen
|
||||
let bank3 = bank_forks.read().unwrap().get(3).unwrap().clone();
|
||||
bank3.freeze();
|
||||
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::Frozen(bank3),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 3);
|
||||
assert_eq!(highest_confirmed_slot, 3);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.len(), 0);
|
||||
|
||||
// Test higher root will be cached and clear pending_optimistically_confirmed_banks
|
||||
let bank3 = bank_forks.read().unwrap().get(3).unwrap().clone();
|
||||
@@ -279,10 +375,13 @@ mod tests {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 3);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.len(), 1);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.contains(&4), true);
|
||||
assert!(pending_optimistically_confirmed_banks.contains(&4));
|
||||
assert_eq!(highest_confirmed_slot, 4);
|
||||
|
||||
let bank4 = bank_forks.read().unwrap().get(4).unwrap().clone();
|
||||
let bank5 = Bank::new_from_parent(&bank4, &Pubkey::default(), 5);
|
||||
@@ -294,10 +393,13 @@ mod tests {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 5);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.len(), 0);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.contains(&4), false);
|
||||
assert!(!pending_optimistically_confirmed_banks.contains(&4));
|
||||
assert_eq!(highest_confirmed_slot, 4);
|
||||
|
||||
// Banks <= root do not get added to pending list, even if not frozen
|
||||
let bank5 = bank_forks.read().unwrap().get(5).unwrap().clone();
|
||||
@@ -316,9 +418,12 @@ mod tests {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
assert_eq!(optimistically_confirmed_bank.read().unwrap().bank.slot(), 5);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.len(), 0);
|
||||
assert_eq!(pending_optimistically_confirmed_banks.contains(&6), false);
|
||||
assert!(!pending_optimistically_confirmed_banks.contains(&6));
|
||||
assert_eq!(highest_confirmed_slot, 4);
|
||||
}
|
||||
}
|
||||
|
@@ -6,9 +6,10 @@ use crate::{
|
||||
cluster_slots::ClusterSlots,
|
||||
repair_weight::RepairWeight,
|
||||
result::Result,
|
||||
serve_repair::{RepairType, ServeRepair, DEFAULT_NONCE},
|
||||
serve_repair::{RepairType, ServeRepair, DEFAULT_NONCE, REPAIR_PEERS_CACHE_CAPACITY},
|
||||
};
|
||||
use crossbeam_channel::{Receiver as CrossbeamReceiver, Sender as CrossbeamSender};
|
||||
use lru::LruCache;
|
||||
use solana_ledger::{
|
||||
blockstore::{Blockstore, SlotMeta},
|
||||
shred::Nonce,
|
||||
@@ -181,6 +182,7 @@ impl RepairService {
|
||||
let mut last_stats = Instant::now();
|
||||
let duplicate_slot_repair_statuses: HashMap<Slot, DuplicateSlotRepairStatus> =
|
||||
HashMap::new();
|
||||
let mut peers_cache = LruCache::new(REPAIR_PEERS_CACHE_CAPACITY);
|
||||
|
||||
loop {
|
||||
if exit.load(Ordering::Relaxed) {
|
||||
@@ -259,13 +261,12 @@ impl RepairService {
|
||||
)
|
||||
};
|
||||
|
||||
let mut cache = HashMap::new();
|
||||
let mut send_repairs_elapsed = Measure::start("send_repairs_elapsed");
|
||||
repairs.into_iter().for_each(|repair_request| {
|
||||
if let Ok((to, req)) = serve_repair.repair_request(
|
||||
&cluster_slots,
|
||||
repair_request,
|
||||
&mut cache,
|
||||
&mut peers_cache,
|
||||
&mut repair_stats,
|
||||
&repair_info.repair_validators,
|
||||
) {
|
||||
|
269
core/src/rpc.rs
269
core/src/rpc.rs
@@ -11,7 +11,7 @@ use crate::{
|
||||
validator::ValidatorExit,
|
||||
};
|
||||
use bincode::{config::Options, serialize};
|
||||
use jsonrpc_core::{types::error, Error, Metadata, Result};
|
||||
use jsonrpc_core::{futures::future, types::error, BoxFuture, Error, Metadata, Result};
|
||||
use jsonrpc_derive::rpc;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use solana_account_decoder::{
|
||||
@@ -91,7 +91,6 @@ use std::{
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
pub const MAX_REQUEST_PAYLOAD_SIZE: usize = 50 * (1 << 10); // 50kB
|
||||
pub const PERFORMANCE_SAMPLES_LIMIT: usize = 720;
|
||||
@@ -154,7 +153,6 @@ pub struct JsonRpcRequestProcessor {
|
||||
cluster_info: Arc<ClusterInfo>,
|
||||
genesis_hash: Hash,
|
||||
transaction_sender: Arc<Mutex<Sender<TransactionInfo>>>,
|
||||
runtime: Arc<Runtime>,
|
||||
bigtable_ledger_storage: Option<solana_storage_bigtable::LedgerStorage>,
|
||||
optimistically_confirmed_bank: Arc<RwLock<OptimisticallyConfirmedBank>>,
|
||||
largest_accounts_cache: Arc<RwLock<LargestAccountsCache>>,
|
||||
@@ -240,7 +238,6 @@ impl JsonRpcRequestProcessor {
|
||||
health: Arc<RpcHealth>,
|
||||
cluster_info: Arc<ClusterInfo>,
|
||||
genesis_hash: Hash,
|
||||
runtime: Arc<Runtime>,
|
||||
bigtable_ledger_storage: Option<solana_storage_bigtable::LedgerStorage>,
|
||||
optimistically_confirmed_bank: Arc<RwLock<OptimisticallyConfirmedBank>>,
|
||||
largest_accounts_cache: Arc<RwLock<LargestAccountsCache>>,
|
||||
@@ -261,7 +258,6 @@ impl JsonRpcRequestProcessor {
|
||||
cluster_info,
|
||||
genesis_hash,
|
||||
transaction_sender: Arc::new(Mutex::new(sender)),
|
||||
runtime,
|
||||
bigtable_ledger_storage,
|
||||
optimistically_confirmed_bank,
|
||||
largest_accounts_cache,
|
||||
@@ -302,7 +298,6 @@ impl JsonRpcRequestProcessor {
|
||||
cluster_info,
|
||||
genesis_hash,
|
||||
transaction_sender: Arc::new(Mutex::new(sender)),
|
||||
runtime: Arc::new(Runtime::new().expect("Runtime")),
|
||||
bigtable_ledger_storage: None,
|
||||
optimistically_confirmed_bank: Arc::new(RwLock::new(OptimisticallyConfirmedBank {
|
||||
bank: bank.clone(),
|
||||
@@ -402,14 +397,14 @@ impl JsonRpcRequestProcessor {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_inflation_reward(
|
||||
pub async fn get_inflation_reward(
|
||||
&self,
|
||||
addresses: Vec<Pubkey>,
|
||||
config: Option<RpcEpochConfig>,
|
||||
) -> Result<Vec<Option<RpcInflationReward>>> {
|
||||
let config = config.unwrap_or_default();
|
||||
let epoch_schedule = self.get_epoch_schedule();
|
||||
let first_available_block = self.get_first_available_block();
|
||||
let first_available_block = self.get_first_available_block().await;
|
||||
let epoch = config.epoch.unwrap_or_else(|| {
|
||||
epoch_schedule
|
||||
.get_epoch(self.get_slot(config.commitment))
|
||||
@@ -434,7 +429,8 @@ impl JsonRpcRequestProcessor {
|
||||
}
|
||||
|
||||
let first_confirmed_block_in_epoch = *self
|
||||
.get_confirmed_blocks_with_limit(first_slot_in_epoch, 1, config.commitment)?
|
||||
.get_confirmed_blocks_with_limit(first_slot_in_epoch, 1, config.commitment)
|
||||
.await?
|
||||
.get(0)
|
||||
.ok_or(RpcCustomError::BlockNotAvailable {
|
||||
slot: first_slot_in_epoch,
|
||||
@@ -444,7 +440,9 @@ impl JsonRpcRequestProcessor {
|
||||
.get_confirmed_block(
|
||||
first_confirmed_block_in_epoch,
|
||||
Some(RpcConfirmedBlockConfig::rewards_with_commitment(config.commitment).into()),
|
||||
) {
|
||||
)
|
||||
.await
|
||||
{
|
||||
first_confirmed_block
|
||||
} else {
|
||||
return Err(RpcCustomError::BlockNotAvailable {
|
||||
@@ -914,7 +912,7 @@ impl JsonRpcRequestProcessor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_confirmed_block(
|
||||
pub async fn get_confirmed_block(
|
||||
&self,
|
||||
slot: Slot,
|
||||
config: Option<RpcEncodingConfigWrapper<RpcConfirmedBlockConfig>>,
|
||||
@@ -941,9 +939,8 @@ impl JsonRpcRequestProcessor {
|
||||
self.check_blockstore_root(&result, slot)?;
|
||||
if result.is_err() {
|
||||
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
|
||||
let bigtable_result = self
|
||||
.runtime
|
||||
.block_on(bigtable_ledger_storage.get_confirmed_block(slot));
|
||||
let bigtable_result =
|
||||
bigtable_ledger_storage.get_confirmed_block(slot).await;
|
||||
self.check_bigtable_result(&bigtable_result)?;
|
||||
return Ok(bigtable_result.ok().map(|confirmed_block| {
|
||||
confirmed_block.configure(encoding, transaction_details, show_rewards)
|
||||
@@ -989,7 +986,7 @@ impl JsonRpcRequestProcessor {
|
||||
Err(RpcCustomError::BlockNotAvailable { slot }.into())
|
||||
}
|
||||
|
||||
pub fn get_confirmed_blocks(
|
||||
pub async fn get_confirmed_blocks(
|
||||
&self,
|
||||
start_slot: Slot,
|
||||
end_slot: Option<Slot>,
|
||||
@@ -1028,12 +1025,9 @@ impl JsonRpcRequestProcessor {
|
||||
// [start_slot..end_slot] can be fetched from BigTable. This range should not ever run
|
||||
// into unfinalized confirmed blocks due to MAX_GET_CONFIRMED_BLOCKS_RANGE
|
||||
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
|
||||
return self
|
||||
.runtime
|
||||
.block_on(
|
||||
bigtable_ledger_storage
|
||||
.get_confirmed_blocks(start_slot, (end_slot - start_slot) as usize + 1), // increment limit by 1 to ensure returned range is inclusive of both start_slot and end_slot
|
||||
)
|
||||
return bigtable_ledger_storage
|
||||
.get_confirmed_blocks(start_slot, (end_slot - start_slot) as usize + 1) // increment limit by 1 to ensure returned range is inclusive of both start_slot and end_slot
|
||||
.await
|
||||
.map(|mut bigtable_blocks| {
|
||||
bigtable_blocks.retain(|&slot| slot <= end_slot);
|
||||
bigtable_blocks
|
||||
@@ -1073,7 +1067,7 @@ impl JsonRpcRequestProcessor {
|
||||
Ok(blocks)
|
||||
}
|
||||
|
||||
pub fn get_confirmed_blocks_with_limit(
|
||||
pub async fn get_confirmed_blocks_with_limit(
|
||||
&self,
|
||||
start_slot: Slot,
|
||||
limit: usize,
|
||||
@@ -1096,9 +1090,9 @@ impl JsonRpcRequestProcessor {
|
||||
// range can be fetched from BigTable. This range should not ever run into unfinalized
|
||||
// confirmed blocks due to MAX_GET_CONFIRMED_BLOCKS_RANGE
|
||||
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
|
||||
return Ok(self
|
||||
.runtime
|
||||
.block_on(bigtable_ledger_storage.get_confirmed_blocks(start_slot, limit))
|
||||
return Ok(bigtable_ledger_storage
|
||||
.get_confirmed_blocks(start_slot, limit)
|
||||
.await
|
||||
.unwrap_or_default());
|
||||
}
|
||||
}
|
||||
@@ -1137,7 +1131,7 @@ impl JsonRpcRequestProcessor {
|
||||
Ok(blocks)
|
||||
}
|
||||
|
||||
pub fn get_block_time(&self, slot: Slot) -> Result<Option<UnixTimestamp>> {
|
||||
pub async fn get_block_time(&self, slot: Slot) -> Result<Option<UnixTimestamp>> {
|
||||
if slot
|
||||
<= self
|
||||
.block_commitment_cache
|
||||
@@ -1149,9 +1143,7 @@ impl JsonRpcRequestProcessor {
|
||||
self.check_blockstore_root(&result, slot)?;
|
||||
if result.is_err() || matches!(result, Ok(None)) {
|
||||
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
|
||||
let bigtable_result = self
|
||||
.runtime
|
||||
.block_on(bigtable_ledger_storage.get_confirmed_block(slot));
|
||||
let bigtable_result = bigtable_ledger_storage.get_confirmed_block(slot).await;
|
||||
self.check_bigtable_result(&bigtable_result)?;
|
||||
return Ok(bigtable_result
|
||||
.ok()
|
||||
@@ -1196,7 +1188,7 @@ impl JsonRpcRequestProcessor {
|
||||
Some(status)
|
||||
}
|
||||
|
||||
pub fn get_signature_statuses(
|
||||
pub async fn get_signature_statuses(
|
||||
&self,
|
||||
signatures: Vec<Signature>,
|
||||
config: Option<RpcSignatureStatusConfig>,
|
||||
@@ -1216,7 +1208,8 @@ impl JsonRpcRequestProcessor {
|
||||
let status = if let Some(status) = self.get_transaction_status(signature, &bank) {
|
||||
Some(status)
|
||||
} else if self.config.enable_rpc_transaction_history && search_transaction_history {
|
||||
self.blockstore
|
||||
if let Some(status) = self
|
||||
.blockstore
|
||||
.get_rooted_transaction_status(signature)
|
||||
.map_err(|_| Error::internal_error())?
|
||||
.filter(|(slot, _status_meta)| {
|
||||
@@ -1236,16 +1229,17 @@ impl JsonRpcRequestProcessor {
|
||||
confirmation_status: Some(TransactionConfirmationStatus::Finalized),
|
||||
}
|
||||
})
|
||||
.or_else(|| {
|
||||
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
|
||||
self.runtime
|
||||
.block_on(bigtable_ledger_storage.get_signature_status(&signature))
|
||||
.map(Some)
|
||||
.unwrap_or(None)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
{
|
||||
Some(status)
|
||||
} else if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
|
||||
bigtable_ledger_storage
|
||||
.get_signature_status(&signature)
|
||||
.await
|
||||
.map(Some)
|
||||
.unwrap_or(None)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -1291,7 +1285,7 @@ impl JsonRpcRequestProcessor {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_confirmed_transaction(
|
||||
pub async fn get_confirmed_transaction(
|
||||
&self,
|
||||
signature: Signature,
|
||||
config: Option<RpcEncodingConfigWrapper<RpcConfirmedTransactionConfig>>,
|
||||
@@ -1339,9 +1333,9 @@ impl JsonRpcRequestProcessor {
|
||||
}
|
||||
None => {
|
||||
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
|
||||
return Ok(self
|
||||
.runtime
|
||||
.block_on(bigtable_ledger_storage.get_confirmed_transaction(&signature))
|
||||
return Ok(bigtable_ledger_storage
|
||||
.get_confirmed_transaction(&signature)
|
||||
.await
|
||||
.unwrap_or(None)
|
||||
.map(|confirmed| confirmed.encode(encoding)));
|
||||
}
|
||||
@@ -1377,7 +1371,7 @@ impl JsonRpcRequestProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_confirmed_signatures_for_address2(
|
||||
pub async fn get_confirmed_signatures_for_address2(
|
||||
&self,
|
||||
address: Pubkey,
|
||||
mut before: Option<Signature>,
|
||||
@@ -1413,14 +1407,14 @@ impl JsonRpcRequestProcessor {
|
||||
before = results.last().map(|x| x.signature);
|
||||
}
|
||||
|
||||
let bigtable_results = self.runtime.block_on(
|
||||
bigtable_ledger_storage.get_confirmed_signatures_for_address(
|
||||
let bigtable_results = bigtable_ledger_storage
|
||||
.get_confirmed_signatures_for_address(
|
||||
&address,
|
||||
before.as_ref(),
|
||||
until.as_ref(),
|
||||
limit,
|
||||
),
|
||||
);
|
||||
)
|
||||
.await;
|
||||
match bigtable_results {
|
||||
Ok(bigtable_results) => {
|
||||
results.extend(bigtable_results.into_iter().map(|x| x.0));
|
||||
@@ -1455,16 +1449,16 @@ impl JsonRpcRequestProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_first_available_block(&self) -> Slot {
|
||||
pub async fn get_first_available_block(&self) -> Slot {
|
||||
let slot = self
|
||||
.blockstore
|
||||
.get_first_available_block()
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
|
||||
let bigtable_slot = self
|
||||
.runtime
|
||||
.block_on(bigtable_ledger_storage.get_first_available_block())
|
||||
let bigtable_slot = bigtable_ledger_storage
|
||||
.get_first_available_block()
|
||||
.await
|
||||
.unwrap_or(None)
|
||||
.unwrap_or(slot);
|
||||
|
||||
@@ -1935,6 +1929,28 @@ fn verify_token_account_filter(
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_and_parse_signatures_for_address_params(
|
||||
address: String,
|
||||
before: Option<String>,
|
||||
until: Option<String>,
|
||||
limit: Option<usize>,
|
||||
) -> Result<(Pubkey, Option<Signature>, Option<Signature>, usize)> {
|
||||
let address = verify_pubkey(&address)?;
|
||||
let before = before
|
||||
.map(|ref before| verify_signature(before))
|
||||
.transpose()?;
|
||||
let until = until.map(|ref until| verify_signature(until)).transpose()?;
|
||||
let limit = limit.unwrap_or(MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT);
|
||||
|
||||
if limit == 0 || limit > MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT {
|
||||
return Err(Error::invalid_params(format!(
|
||||
"Invalid limit; max {}",
|
||||
MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT
|
||||
)));
|
||||
}
|
||||
Ok((address, before, until, limit))
|
||||
}
|
||||
|
||||
fn check_is_at_least_confirmed(commitment: CommitmentConfig) -> Result<()> {
|
||||
if !commitment.is_at_least_confirmed() {
|
||||
return Err(Error::invalid_params(
|
||||
@@ -2475,7 +2491,7 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
address_strs: Vec<String>,
|
||||
config: Option<RpcEpochConfig>,
|
||||
) -> Result<Vec<Option<RpcInflationReward>>>;
|
||||
) -> BoxFuture<Result<Vec<Option<RpcInflationReward>>>>;
|
||||
|
||||
#[rpc(meta, name = "getInflationGovernor")]
|
||||
fn get_inflation_governor(
|
||||
@@ -2544,7 +2560,7 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
signature_strs: Vec<String>,
|
||||
config: Option<RpcSignatureStatusConfig>,
|
||||
) -> Result<RpcResponse<Vec<Option<TransactionStatus>>>>;
|
||||
) -> BoxFuture<Result<RpcResponse<Vec<Option<TransactionStatus>>>>>;
|
||||
|
||||
#[rpc(meta, name = "getMaxRetransmitSlot")]
|
||||
fn get_max_retransmit_slot(&self, meta: Self::Metadata) -> Result<Slot>;
|
||||
@@ -2623,11 +2639,14 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
slot: Slot,
|
||||
config: Option<RpcEncodingConfigWrapper<RpcConfirmedBlockConfig>>,
|
||||
) -> Result<Option<UiConfirmedBlock>>;
|
||||
) -> BoxFuture<Result<Option<UiConfirmedBlock>>>;
|
||||
|
||||
#[rpc(meta, name = "getBlockTime")]
|
||||
fn get_block_time(&self, meta: Self::Metadata, slot: Slot)
|
||||
-> Result<Option<UnixTimestamp>>;
|
||||
fn get_block_time(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
slot: Slot,
|
||||
) -> BoxFuture<Result<Option<UnixTimestamp>>>;
|
||||
|
||||
#[rpc(meta, name = "getConfirmedBlocks")]
|
||||
fn get_confirmed_blocks(
|
||||
@@ -2636,7 +2655,7 @@ pub mod rpc_full {
|
||||
start_slot: Slot,
|
||||
config: Option<RpcConfirmedBlocksConfigWrapper>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Vec<Slot>>;
|
||||
) -> BoxFuture<Result<Vec<Slot>>>;
|
||||
|
||||
#[rpc(meta, name = "getConfirmedBlocksWithLimit")]
|
||||
fn get_confirmed_blocks_with_limit(
|
||||
@@ -2645,7 +2664,7 @@ pub mod rpc_full {
|
||||
start_slot: Slot,
|
||||
limit: usize,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Vec<Slot>>;
|
||||
) -> BoxFuture<Result<Vec<Slot>>>;
|
||||
|
||||
#[rpc(meta, name = "getConfirmedTransaction")]
|
||||
fn get_confirmed_transaction(
|
||||
@@ -2653,7 +2672,7 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
signature_str: String,
|
||||
config: Option<RpcEncodingConfigWrapper<RpcConfirmedTransactionConfig>>,
|
||||
) -> Result<Option<EncodedConfirmedTransaction>>;
|
||||
) -> BoxFuture<Result<Option<EncodedConfirmedTransaction>>>;
|
||||
|
||||
// DEPRECATED
|
||||
#[rpc(meta, name = "getConfirmedSignaturesForAddress")]
|
||||
@@ -2671,10 +2690,10 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
address: String,
|
||||
config: Option<RpcGetConfirmedSignaturesForAddress2Config>,
|
||||
) -> Result<Vec<RpcConfirmedTransactionStatusWithSignature>>;
|
||||
) -> BoxFuture<Result<Vec<RpcConfirmedTransactionStatusWithSignature>>>;
|
||||
|
||||
#[rpc(meta, name = "getFirstAvailableBlock")]
|
||||
fn get_first_available_block(&self, meta: Self::Metadata) -> Result<Slot>;
|
||||
fn get_first_available_block(&self, meta: Self::Metadata) -> BoxFuture<Result<Slot>>;
|
||||
|
||||
#[rpc(meta, name = "getStakeActivation")]
|
||||
fn get_stake_activation(
|
||||
@@ -3018,22 +3037,27 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
signature_strs: Vec<String>,
|
||||
config: Option<RpcSignatureStatusConfig>,
|
||||
) -> Result<RpcResponse<Vec<Option<TransactionStatus>>>> {
|
||||
) -> BoxFuture<Result<RpcResponse<Vec<Option<TransactionStatus>>>>> {
|
||||
debug!(
|
||||
"get_signature_statuses rpc request received: {:?}",
|
||||
signature_strs.len()
|
||||
);
|
||||
if signature_strs.len() > MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS {
|
||||
return Err(Error::invalid_params(format!(
|
||||
return Box::pin(future::err(Error::invalid_params(format!(
|
||||
"Too many inputs provided; max {}",
|
||||
MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS
|
||||
)));
|
||||
))));
|
||||
}
|
||||
let mut signatures: Vec<Signature> = vec![];
|
||||
for signature_str in signature_strs {
|
||||
signatures.push(verify_signature(&signature_str)?);
|
||||
match verify_signature(&signature_str) {
|
||||
Ok(signature) => {
|
||||
signatures.push(signature);
|
||||
}
|
||||
Err(err) => return Box::pin(future::err(err)),
|
||||
}
|
||||
}
|
||||
meta.get_signature_statuses(signatures, config)
|
||||
Box::pin(async move { meta.get_signature_statuses(signatures, config).await })
|
||||
}
|
||||
|
||||
fn get_max_retransmit_slot(&self, meta: Self::Metadata) -> Result<Slot> {
|
||||
@@ -3343,9 +3367,9 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
slot: Slot,
|
||||
config: Option<RpcEncodingConfigWrapper<RpcConfirmedBlockConfig>>,
|
||||
) -> Result<Option<UiConfirmedBlock>> {
|
||||
) -> BoxFuture<Result<Option<UiConfirmedBlock>>> {
|
||||
debug!("get_confirmed_block rpc request received: {:?}", slot);
|
||||
meta.get_confirmed_block(slot, config)
|
||||
Box::pin(async move { meta.get_confirmed_block(slot, config).await })
|
||||
}
|
||||
|
||||
fn get_confirmed_blocks(
|
||||
@@ -3354,14 +3378,17 @@ pub mod rpc_full {
|
||||
start_slot: Slot,
|
||||
config: Option<RpcConfirmedBlocksConfigWrapper>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Vec<Slot>> {
|
||||
) -> BoxFuture<Result<Vec<Slot>>> {
|
||||
let (end_slot, maybe_commitment) =
|
||||
config.map(|config| config.unzip()).unwrap_or_default();
|
||||
debug!(
|
||||
"get_confirmed_blocks rpc request received: {}-{:?}",
|
||||
start_slot, end_slot
|
||||
);
|
||||
meta.get_confirmed_blocks(start_slot, end_slot, commitment.or(maybe_commitment))
|
||||
Box::pin(async move {
|
||||
meta.get_confirmed_blocks(start_slot, end_slot, commitment.or(maybe_commitment))
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
||||
fn get_confirmed_blocks_with_limit(
|
||||
@@ -3370,20 +3397,23 @@ pub mod rpc_full {
|
||||
start_slot: Slot,
|
||||
limit: usize,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Vec<Slot>> {
|
||||
) -> BoxFuture<Result<Vec<Slot>>> {
|
||||
debug!(
|
||||
"get_confirmed_blocks_with_limit rpc request received: {}-{}",
|
||||
start_slot, limit,
|
||||
);
|
||||
meta.get_confirmed_blocks_with_limit(start_slot, limit, commitment)
|
||||
Box::pin(async move {
|
||||
meta.get_confirmed_blocks_with_limit(start_slot, limit, commitment)
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
||||
fn get_block_time(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
slot: Slot,
|
||||
) -> Result<Option<UnixTimestamp>> {
|
||||
meta.get_block_time(slot)
|
||||
) -> BoxFuture<Result<Option<UnixTimestamp>>> {
|
||||
Box::pin(async move { meta.get_block_time(slot).await })
|
||||
}
|
||||
|
||||
fn get_confirmed_transaction(
|
||||
@@ -3391,13 +3421,19 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
signature_str: String,
|
||||
config: Option<RpcEncodingConfigWrapper<RpcConfirmedTransactionConfig>>,
|
||||
) -> Result<Option<EncodedConfirmedTransaction>> {
|
||||
) -> BoxFuture<Result<Option<EncodedConfirmedTransaction>>> {
|
||||
debug!(
|
||||
"get_confirmed_transaction rpc request received: {:?}",
|
||||
signature_str
|
||||
);
|
||||
let signature = verify_signature(&signature_str)?;
|
||||
meta.get_confirmed_transaction(signature, config)
|
||||
let signature = verify_signature(&signature_str);
|
||||
if let Err(err) = signature {
|
||||
return Box::pin(future::err(err));
|
||||
}
|
||||
Box::pin(async move {
|
||||
meta.get_confirmed_transaction(signature.unwrap(), config)
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
||||
fn get_confirmed_signatures_for_address(
|
||||
@@ -3436,41 +3472,29 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
address: String,
|
||||
config: Option<RpcGetConfirmedSignaturesForAddress2Config>,
|
||||
) -> Result<Vec<RpcConfirmedTransactionStatusWithSignature>> {
|
||||
let address = verify_pubkey(&address)?;
|
||||
|
||||
) -> BoxFuture<Result<Vec<RpcConfirmedTransactionStatusWithSignature>>> {
|
||||
let config = config.unwrap_or_default();
|
||||
let before = config
|
||||
.before
|
||||
.map(|ref before| verify_signature(before))
|
||||
.transpose()?;
|
||||
let until = config
|
||||
.until
|
||||
.map(|ref until| verify_signature(until))
|
||||
.transpose()?;
|
||||
let limit = config
|
||||
.limit
|
||||
.unwrap_or(MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT);
|
||||
|
||||
if limit == 0 || limit > MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT {
|
||||
return Err(Error::invalid_params(format!(
|
||||
"Invalid limit; max {}",
|
||||
MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT
|
||||
)));
|
||||
}
|
||||
|
||||
meta.get_confirmed_signatures_for_address2(
|
||||
let commitment = config.commitment;
|
||||
let verification = verify_and_parse_signatures_for_address_params(
|
||||
address,
|
||||
before,
|
||||
until,
|
||||
limit,
|
||||
config.commitment,
|
||||
)
|
||||
config.before,
|
||||
config.until,
|
||||
config.limit,
|
||||
);
|
||||
match verification {
|
||||
Err(err) => Box::pin(future::err(err)),
|
||||
Ok((address, before, until, limit)) => Box::pin(async move {
|
||||
meta.get_confirmed_signatures_for_address2(
|
||||
address, before, until, limit, commitment,
|
||||
)
|
||||
.await
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_first_available_block(&self, meta: Self::Metadata) -> Result<Slot> {
|
||||
fn get_first_available_block(&self, meta: Self::Metadata) -> BoxFuture<Result<Slot>> {
|
||||
debug!("get_first_available_block rpc request received");
|
||||
Ok(meta.get_first_available_block())
|
||||
Box::pin(async move { Ok(meta.get_first_available_block().await) })
|
||||
}
|
||||
|
||||
fn get_block_production(
|
||||
@@ -3581,7 +3605,7 @@ pub mod rpc_full {
|
||||
meta: Self::Metadata,
|
||||
address_strs: Vec<String>,
|
||||
config: Option<RpcEpochConfig>,
|
||||
) -> Result<Vec<Option<RpcInflationReward>>> {
|
||||
) -> BoxFuture<Result<Vec<Option<RpcInflationReward>>>> {
|
||||
debug!(
|
||||
"get_inflation_reward rpc request received: {:?}",
|
||||
address_strs.len()
|
||||
@@ -3589,10 +3613,15 @@ pub mod rpc_full {
|
||||
|
||||
let mut addresses: Vec<Pubkey> = vec![];
|
||||
for address_str in address_strs {
|
||||
addresses.push(verify_pubkey(&address_str)?);
|
||||
match verify_pubkey(&address_str) {
|
||||
Ok(pubkey) => {
|
||||
addresses.push(pubkey);
|
||||
}
|
||||
Err(err) => return Box::pin(future::err(err)),
|
||||
}
|
||||
}
|
||||
|
||||
meta.get_inflation_reward(addresses, config)
|
||||
Box::pin(async move { meta.get_inflation_reward(addresses, config).await })
|
||||
}
|
||||
|
||||
fn get_token_account_balance(
|
||||
@@ -3959,7 +3988,6 @@ pub mod tests {
|
||||
RpcHealth::stub(),
|
||||
cluster_info.clone(),
|
||||
Hash::default(),
|
||||
Arc::new(tokio::runtime::Runtime::new().unwrap()),
|
||||
None,
|
||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks),
|
||||
Arc::new(RwLock::new(LargestAccountsCache::new(30))),
|
||||
@@ -5627,7 +5655,6 @@ pub mod tests {
|
||||
health.clone(),
|
||||
cluster_info,
|
||||
Hash::default(),
|
||||
Arc::new(tokio::runtime::Runtime::new().unwrap()),
|
||||
None,
|
||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks),
|
||||
Arc::new(RwLock::new(LargestAccountsCache::new(30))),
|
||||
@@ -5904,7 +5931,6 @@ pub mod tests {
|
||||
RpcHealth::stub(),
|
||||
cluster_info,
|
||||
Hash::default(),
|
||||
Arc::new(tokio::runtime::Runtime::new().unwrap()),
|
||||
None,
|
||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks),
|
||||
Arc::new(RwLock::new(LargestAccountsCache::new(30))),
|
||||
@@ -7330,7 +7356,6 @@ pub mod tests {
|
||||
RpcHealth::stub(),
|
||||
cluster_info,
|
||||
Hash::default(),
|
||||
Arc::new(tokio::runtime::Runtime::new().unwrap()),
|
||||
None,
|
||||
optimistically_confirmed_bank.clone(),
|
||||
Arc::new(RwLock::new(LargestAccountsCache::new(30))),
|
||||
@@ -7349,6 +7374,8 @@ pub mod tests {
|
||||
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
|
||||
let slot: Slot = serde_json::from_value(json["result"].clone()).unwrap();
|
||||
assert_eq!(slot, 0);
|
||||
let mut highest_confirmed_slot: Slot = 0;
|
||||
let mut last_notified_confirmed_slot: Slot = 0;
|
||||
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(2),
|
||||
@@ -7356,6 +7383,8 @@ pub mod tests {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
let req =
|
||||
r#"{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment": "confirmed"}]}"#;
|
||||
@@ -7371,6 +7400,8 @@ pub mod tests {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
let req =
|
||||
r#"{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment": "confirmed"}]}"#;
|
||||
@@ -7386,6 +7417,8 @@ pub mod tests {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
let req =
|
||||
r#"{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment": "confirmed"}]}"#;
|
||||
@@ -7402,6 +7435,8 @@ pub mod tests {
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
let req =
|
||||
r#"{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment": "confirmed"}]}"#;
|
||||
|
@@ -34,7 +34,6 @@ use std::{
|
||||
sync::{mpsc::channel, Arc, Mutex, RwLock},
|
||||
thread::{self, Builder, JoinHandle},
|
||||
};
|
||||
use tokio::runtime;
|
||||
use tokio_util::codec::{BytesCodec, FramedRead};
|
||||
|
||||
const LARGEST_ACCOUNTS_CACHE_DURATION: u64 = 60 * 60 * 2;
|
||||
@@ -112,10 +111,8 @@ impl RpcRequestMiddleware {
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
async fn open_no_follow(path: impl AsRef<Path>) -> std::io::Result<tokio_02::fs::File> {
|
||||
// Stuck on tokio 0.2 until the jsonrpc crates upgrade
|
||||
use tokio_02::fs::os::unix::OpenOptionsExt;
|
||||
tokio_02::fs::OpenOptions::new()
|
||||
async fn open_no_follow(path: impl AsRef<Path>) -> std::io::Result<tokio::fs::File> {
|
||||
tokio::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(false)
|
||||
.create(false)
|
||||
@@ -125,10 +122,9 @@ impl RpcRequestMiddleware {
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
async fn open_no_follow(path: impl AsRef<Path>) -> std::io::Result<tokio_02::fs::File> {
|
||||
async fn open_no_follow(path: impl AsRef<Path>) -> std::io::Result<tokio::fs::File> {
|
||||
// TODO: Is there any way to achieve the same on Windows?
|
||||
// Stuck on tokio 0.2 until the jsonrpc crates upgrade
|
||||
tokio_02::fs::File::open(path).await
|
||||
tokio::fs::File::open(path).await
|
||||
}
|
||||
|
||||
fn process_file_get(&self, path: &str) -> RequestMiddlewareAction {
|
||||
@@ -294,9 +290,17 @@ impl JsonRpcService {
|
||||
)));
|
||||
|
||||
let tpu_address = cluster_info.my_contact_info().tpu;
|
||||
|
||||
// sadly, some parts of our current rpc implemention block the jsonrpc's
|
||||
// _socket-listening_ event loop for too long, due to (blocking) long IO or intesive CPU,
|
||||
// causing no further processing of incoming requests and ultimatily innocent clients timing-out.
|
||||
// So create a (shared) multi-threaded event_loop for jsonrpc and set its .threads() to 1,
|
||||
// so that we avoid the single-threaded event loops from being created automatically by
|
||||
// jsonrpc for threads when .threads(N > 1) is given.
|
||||
let runtime = Arc::new(
|
||||
runtime::Builder::new_multi_thread()
|
||||
.thread_name("rpc-runtime")
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(rpc_threads)
|
||||
.thread_name("sol-rpc-el")
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("Runtime"),
|
||||
@@ -351,7 +355,6 @@ impl JsonRpcService {
|
||||
health.clone(),
|
||||
cluster_info.clone(),
|
||||
genesis_hash,
|
||||
runtime,
|
||||
bigtable_ledger_storage,
|
||||
optimistically_confirmed_bank,
|
||||
largest_accounts_cache,
|
||||
@@ -376,23 +379,6 @@ impl JsonRpcService {
|
||||
|
||||
let ledger_path = ledger_path.to_path_buf();
|
||||
|
||||
// sadly, some parts of our current rpc implemention block the jsonrpc's
|
||||
// _socket-listening_ event loop for too long, due to (blocking) long IO or intesive CPU,
|
||||
// causing no further processing of incoming requests and ultimatily innocent clients timing-out.
|
||||
// So create a (shared) multi-threaded event_loop for jsonrpc and set its .threads() to 1,
|
||||
// so that we avoid the single-threaded event loops from being created automatically by
|
||||
// jsonrpc for threads when .threads(N > 1) is given.
|
||||
let event_loop = {
|
||||
// Stuck on tokio 0.2 until the jsonrpc crates upgrade
|
||||
tokio_02::runtime::Builder::new()
|
||||
.core_threads(rpc_threads)
|
||||
.threaded_scheduler()
|
||||
.enable_all()
|
||||
.thread_name("sol-rpc-el")
|
||||
.build()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let (close_handle_sender, close_handle_receiver) = channel();
|
||||
let thread_hdl = Builder::new()
|
||||
.name("solana-jsonrpc".to_string())
|
||||
@@ -414,7 +400,7 @@ impl JsonRpcService {
|
||||
io,
|
||||
move |_req: &hyper::Request<hyper::Body>| request_processor.clone(),
|
||||
)
|
||||
.event_loop_executor(event_loop.handle().clone())
|
||||
.event_loop_executor(runtime.handle().clone())
|
||||
.threads(1)
|
||||
.cors(DomainsValidation::AllowOnly(vec![
|
||||
AccessControlAllowOrigin::Any,
|
||||
@@ -481,6 +467,7 @@ mod tests {
|
||||
use solana_sdk::{genesis_config::ClusterType, signature::Signer};
|
||||
use std::io::Write;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
#[test]
|
||||
fn test_rpc_new() {
|
||||
@@ -613,7 +600,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_process_file_get() {
|
||||
let mut runtime = tokio_02::runtime::Runtime::new().unwrap();
|
||||
let runtime = Runtime::new().unwrap();
|
||||
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
std::fs::create_dir(&ledger_path).unwrap();
|
||||
|
@@ -1343,7 +1343,10 @@ pub(crate) mod tests {
|
||||
system_instruction, system_program, system_transaction,
|
||||
transaction::Transaction,
|
||||
};
|
||||
use std::{fmt::Debug, sync::mpsc::channel};
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
sync::{atomic::Ordering::Relaxed, mpsc::channel},
|
||||
};
|
||||
use tokio::{
|
||||
runtime::Runtime,
|
||||
time::{sleep, timeout},
|
||||
@@ -1615,6 +1618,454 @@ pub(crate) mod tests {
|
||||
.contains_key(&solana_stake_program::id()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_check_program_subscribe_for_missing_optimistically_confirmed_slot() {
|
||||
// Testing if we can get the pubsub notification if a slot does not
|
||||
// receive OptimisticallyConfirmed but its descendant slot get the confirmed
|
||||
// notification.
|
||||
let GenesisConfigInfo {
|
||||
genesis_config,
|
||||
mint_keypair,
|
||||
..
|
||||
} = create_genesis_config(100);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
bank.lazy_rent_collection.store(true, Relaxed);
|
||||
|
||||
let blockhash = bank.last_blockhash();
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(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 bank1 = bank_forks.read().unwrap().get(1).unwrap().clone();
|
||||
|
||||
// add account for alice and process the transaction at bank1
|
||||
let alice = Keypair::new();
|
||||
let tx = system_transaction::create_account(
|
||||
&mint_keypair,
|
||||
&alice,
|
||||
blockhash,
|
||||
1,
|
||||
16,
|
||||
&solana_stake_program::id(),
|
||||
);
|
||||
|
||||
bank1.process_transaction(&tx).unwrap();
|
||||
|
||||
let bank2 = Bank::new_from_parent(&bank1, &Pubkey::default(), 2);
|
||||
bank_forks.write().unwrap().insert(bank2);
|
||||
|
||||
// add account for bob and process the transaction at bank2
|
||||
let bob = Keypair::new();
|
||||
let tx = system_transaction::create_account(
|
||||
&mint_keypair,
|
||||
&bob,
|
||||
blockhash,
|
||||
2,
|
||||
16,
|
||||
&solana_stake_program::id(),
|
||||
);
|
||||
let bank2 = bank_forks.read().unwrap().get(2).unwrap().clone();
|
||||
|
||||
bank2.process_transaction(&tx).unwrap();
|
||||
|
||||
let bank3 = Bank::new_from_parent(&bank2, &Pubkey::default(), 3);
|
||||
bank_forks.write().unwrap().insert(bank3);
|
||||
|
||||
// add account for joe and process the transaction at bank3
|
||||
let joe = Keypair::new();
|
||||
let tx = system_transaction::create_account(
|
||||
&mint_keypair,
|
||||
&joe,
|
||||
blockhash,
|
||||
3,
|
||||
16,
|
||||
&solana_stake_program::id(),
|
||||
);
|
||||
let bank3 = bank_forks.read().unwrap().get(3).unwrap().clone();
|
||||
|
||||
bank3.process_transaction(&tx).unwrap();
|
||||
|
||||
// now add programSubscribe at the "confirmed" commitment level
|
||||
let (subscriber, _id_receiver, transport_receiver) =
|
||||
Subscriber::new_test("programNotification");
|
||||
let sub_id = SubscriptionId::Number(0);
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let optimistically_confirmed_bank =
|
||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||
let mut pending_optimistically_confirmed_banks = HashSet::new();
|
||||
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks.clone(),
|
||||
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots(
|
||||
1, 1,
|
||||
))),
|
||||
optimistically_confirmed_bank.clone(),
|
||||
));
|
||||
subscriptions.add_program_subscription(
|
||||
solana_stake_program::id(),
|
||||
Some(RpcProgramAccountsConfig {
|
||||
account_config: RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::confirmed()),
|
||||
..RpcAccountInfoConfig::default()
|
||||
},
|
||||
..RpcProgramAccountsConfig::default()
|
||||
}),
|
||||
sub_id.clone(),
|
||||
subscriber,
|
||||
);
|
||||
|
||||
assert!(subscriptions
|
||||
.subscriptions
|
||||
.gossip_program_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
.contains_key(&solana_stake_program::id()));
|
||||
|
||||
let mut highest_confirmed_slot: Slot = 0;
|
||||
let mut last_notified_confirmed_slot: Slot = 0;
|
||||
// Optimistically notifying slot 3 without notifying slot 1 and 2, bank3 is unfrozen, we expect
|
||||
// to see transaction for alice and bob to be notified in order.
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(3),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
|
||||
// a closure to reduce code duplications in building expected responses:
|
||||
let build_expected_resp = |slot: Slot, lamports: u64, pubkey: &str, subscription: i32| {
|
||||
json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "programNotification",
|
||||
"params": {
|
||||
"result": {
|
||||
"context": { "slot": slot },
|
||||
"value": {
|
||||
"account": {
|
||||
"data": "1111111111111111",
|
||||
"executable": false,
|
||||
"lamports": lamports,
|
||||
"owner": "Stake11111111111111111111111111111111111111",
|
||||
"rentEpoch": 0,
|
||||
},
|
||||
"pubkey": pubkey,
|
||||
},
|
||||
},
|
||||
"subscription": subscription,
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let (response, transport_receiver) = robust_poll_or_panic(transport_receiver);
|
||||
let expected = build_expected_resp(1, 1, &alice.pubkey().to_string(), 0);
|
||||
assert_eq!(serde_json::to_string(&expected).unwrap(), response);
|
||||
|
||||
let (response, transport_receiver) = robust_poll_or_panic(transport_receiver);
|
||||
let expected = build_expected_resp(2, 2, &bob.pubkey().to_string(), 0);
|
||||
assert_eq!(serde_json::to_string(&expected).unwrap(), response);
|
||||
|
||||
bank3.freeze();
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::Frozen(bank3),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
|
||||
let (response, _) = robust_poll_or_panic(transport_receiver);
|
||||
let expected = build_expected_resp(3, 3, &joe.pubkey().to_string(), 0);
|
||||
assert_eq!(serde_json::to_string(&expected).unwrap(), response);
|
||||
subscriptions.remove_program_subscription(&sub_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
#[should_panic]
|
||||
fn test_check_program_subscribe_for_missing_optimistically_confirmed_slot_with_no_banks_no_notifications(
|
||||
) {
|
||||
// Testing if we can get the pubsub notification if a slot does not
|
||||
// receive OptimisticallyConfirmed but its descendant slot get the confirmed
|
||||
// notification with a bank in the BankForks. We are not expecting to receive any notifications -- should panic.
|
||||
let GenesisConfigInfo {
|
||||
genesis_config,
|
||||
mint_keypair,
|
||||
..
|
||||
} = create_genesis_config(100);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
bank.lazy_rent_collection.store(true, Relaxed);
|
||||
|
||||
let blockhash = bank.last_blockhash();
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(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 bank1 = bank_forks.read().unwrap().get(1).unwrap().clone();
|
||||
|
||||
// add account for alice and process the transaction at bank1
|
||||
let alice = Keypair::new();
|
||||
let tx = system_transaction::create_account(
|
||||
&mint_keypair,
|
||||
&alice,
|
||||
blockhash,
|
||||
1,
|
||||
16,
|
||||
&solana_stake_program::id(),
|
||||
);
|
||||
|
||||
bank1.process_transaction(&tx).unwrap();
|
||||
|
||||
let bank2 = Bank::new_from_parent(&bank1, &Pubkey::default(), 2);
|
||||
bank_forks.write().unwrap().insert(bank2);
|
||||
|
||||
// add account for bob and process the transaction at bank2
|
||||
let bob = Keypair::new();
|
||||
let tx = system_transaction::create_account(
|
||||
&mint_keypair,
|
||||
&bob,
|
||||
blockhash,
|
||||
2,
|
||||
16,
|
||||
&solana_stake_program::id(),
|
||||
);
|
||||
let bank2 = bank_forks.read().unwrap().get(2).unwrap().clone();
|
||||
|
||||
bank2.process_transaction(&tx).unwrap();
|
||||
|
||||
// now add programSubscribe at the "confirmed" commitment level
|
||||
let (subscriber, _id_receiver, transport_receiver) =
|
||||
Subscriber::new_test("programNotification");
|
||||
let sub_id = SubscriptionId::Number(0);
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let optimistically_confirmed_bank =
|
||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||
let mut pending_optimistically_confirmed_banks = HashSet::new();
|
||||
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks.clone(),
|
||||
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots(
|
||||
1, 1,
|
||||
))),
|
||||
optimistically_confirmed_bank.clone(),
|
||||
));
|
||||
subscriptions.add_program_subscription(
|
||||
solana_stake_program::id(),
|
||||
Some(RpcProgramAccountsConfig {
|
||||
account_config: RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::confirmed()),
|
||||
..RpcAccountInfoConfig::default()
|
||||
},
|
||||
..RpcProgramAccountsConfig::default()
|
||||
}),
|
||||
sub_id,
|
||||
subscriber,
|
||||
);
|
||||
|
||||
assert!(subscriptions
|
||||
.subscriptions
|
||||
.gossip_program_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
.contains_key(&solana_stake_program::id()));
|
||||
|
||||
let mut highest_confirmed_slot: Slot = 0;
|
||||
let mut last_notified_confirmed_slot: Slot = 0;
|
||||
// Optimistically notifying slot 3 without notifying slot 1 and 2, bank3 is not in the bankforks, we do not
|
||||
// expect to see any RPC notifications.
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(3),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
|
||||
// The following should panic
|
||||
let (_response, _transport_receiver) = robust_poll_or_panic(transport_receiver);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_check_program_subscribe_for_missing_optimistically_confirmed_slot_with_no_banks() {
|
||||
// Testing if we can get the pubsub notification if a slot does not
|
||||
// receive OptimisticallyConfirmed but its descendant slot get the confirmed
|
||||
// notification. It differs from the test_check_program_subscribe_for_missing_optimistically_confirmed_slot
|
||||
// test in that when the descendant get confirmed, the descendant does not have a bank yet.
|
||||
let GenesisConfigInfo {
|
||||
genesis_config,
|
||||
mint_keypair,
|
||||
..
|
||||
} = create_genesis_config(100);
|
||||
let bank = Bank::new(&genesis_config);
|
||||
bank.lazy_rent_collection.store(true, Relaxed);
|
||||
|
||||
let blockhash = bank.last_blockhash();
|
||||
let bank_forks = Arc::new(RwLock::new(BankForks::new(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 bank1 = bank_forks.read().unwrap().get(1).unwrap().clone();
|
||||
|
||||
// add account for alice and process the transaction at bank1
|
||||
let alice = Keypair::new();
|
||||
let tx = system_transaction::create_account(
|
||||
&mint_keypair,
|
||||
&alice,
|
||||
blockhash,
|
||||
1,
|
||||
16,
|
||||
&solana_stake_program::id(),
|
||||
);
|
||||
|
||||
bank1.process_transaction(&tx).unwrap();
|
||||
|
||||
let bank2 = Bank::new_from_parent(&bank1, &Pubkey::default(), 2);
|
||||
bank_forks.write().unwrap().insert(bank2);
|
||||
|
||||
// add account for bob and process the transaction at bank2
|
||||
let bob = Keypair::new();
|
||||
let tx = system_transaction::create_account(
|
||||
&mint_keypair,
|
||||
&bob,
|
||||
blockhash,
|
||||
2,
|
||||
16,
|
||||
&solana_stake_program::id(),
|
||||
);
|
||||
let bank2 = bank_forks.read().unwrap().get(2).unwrap().clone();
|
||||
|
||||
bank2.process_transaction(&tx).unwrap();
|
||||
|
||||
// now add programSubscribe at the "confirmed" commitment level
|
||||
let (subscriber, _id_receiver, transport_receiver) =
|
||||
Subscriber::new_test("programNotification");
|
||||
let sub_id = SubscriptionId::Number(0);
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let optimistically_confirmed_bank =
|
||||
OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
|
||||
let mut pending_optimistically_confirmed_banks = HashSet::new();
|
||||
|
||||
let subscriptions = Arc::new(RpcSubscriptions::new(
|
||||
&exit,
|
||||
bank_forks.clone(),
|
||||
Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots(
|
||||
1, 1,
|
||||
))),
|
||||
optimistically_confirmed_bank.clone(),
|
||||
));
|
||||
subscriptions.add_program_subscription(
|
||||
solana_stake_program::id(),
|
||||
Some(RpcProgramAccountsConfig {
|
||||
account_config: RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::confirmed()),
|
||||
..RpcAccountInfoConfig::default()
|
||||
},
|
||||
..RpcProgramAccountsConfig::default()
|
||||
}),
|
||||
sub_id.clone(),
|
||||
subscriber,
|
||||
);
|
||||
|
||||
assert!(subscriptions
|
||||
.subscriptions
|
||||
.gossip_program_subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
.contains_key(&solana_stake_program::id()));
|
||||
|
||||
let mut highest_confirmed_slot: Slot = 0;
|
||||
let mut last_notified_confirmed_slot: Slot = 0;
|
||||
// Optimistically notifying slot 3 without notifying slot 1 and 2, bank3 is not in the bankforks, we expect
|
||||
// to see transaction for alice and bob to be notified only when bank3 is added to the fork and
|
||||
// frozen. The notifications should be in the increasing order of the slot.
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(3),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
|
||||
// a closure to reduce code duplications in building expected responses:
|
||||
let build_expected_resp = |slot: Slot, lamports: u64, pubkey: &str, subscription: i32| {
|
||||
json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "programNotification",
|
||||
"params": {
|
||||
"result": {
|
||||
"context": { "slot": slot },
|
||||
"value": {
|
||||
"account": {
|
||||
"data": "1111111111111111",
|
||||
"executable": false,
|
||||
"lamports": lamports,
|
||||
"owner": "Stake11111111111111111111111111111111111111",
|
||||
"rentEpoch": 0,
|
||||
},
|
||||
"pubkey": pubkey,
|
||||
},
|
||||
},
|
||||
"subscription": subscription,
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let bank3 = Bank::new_from_parent(&bank2, &Pubkey::default(), 3);
|
||||
bank_forks.write().unwrap().insert(bank3);
|
||||
|
||||
// add account for joe and process the transaction at bank3
|
||||
let joe = Keypair::new();
|
||||
let tx = system_transaction::create_account(
|
||||
&mint_keypair,
|
||||
&joe,
|
||||
blockhash,
|
||||
3,
|
||||
16,
|
||||
&solana_stake_program::id(),
|
||||
);
|
||||
let bank3 = bank_forks.read().unwrap().get(3).unwrap().clone();
|
||||
|
||||
bank3.process_transaction(&tx).unwrap();
|
||||
bank3.freeze();
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::Frozen(bank3),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
|
||||
let (response, transport_receiver) = robust_poll_or_panic(transport_receiver);
|
||||
let expected = build_expected_resp(1, 1, &alice.pubkey().to_string(), 0);
|
||||
assert_eq!(serde_json::to_string(&expected).unwrap(), response);
|
||||
|
||||
let (response, transport_receiver) = robust_poll_or_panic(transport_receiver);
|
||||
let expected = build_expected_resp(2, 2, &bob.pubkey().to_string(), 0);
|
||||
assert_eq!(serde_json::to_string(&expected).unwrap(), response);
|
||||
|
||||
let (response, _) = robust_poll_or_panic(transport_receiver);
|
||||
let expected = build_expected_resp(3, 3, &joe.pubkey().to_string(), 0);
|
||||
assert_eq!(serde_json::to_string(&expected).unwrap(), response);
|
||||
subscriptions.remove_program_subscription(&sub_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_check_signature_subscribe() {
|
||||
@@ -2058,21 +2509,28 @@ pub(crate) mod tests {
|
||||
.unwrap();
|
||||
|
||||
// First, notify the unfrozen bank first to queue pending notification
|
||||
let mut highest_confirmed_slot: Slot = 0;
|
||||
let mut last_notified_confirmed_slot: Slot = 0;
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(2),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
|
||||
// Now, notify the frozen bank and ensure its notifications are processed
|
||||
highest_confirmed_slot = 0;
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::OptimisticallyConfirmed(1),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
|
||||
let (response, _) = robust_poll_or_panic(transport_receiver0);
|
||||
@@ -2109,12 +2567,16 @@ pub(crate) mod tests {
|
||||
);
|
||||
|
||||
let bank2 = bank_forks.read().unwrap().get(2).unwrap().clone();
|
||||
bank2.freeze();
|
||||
highest_confirmed_slot = 0;
|
||||
OptimisticallyConfirmedBankTracker::process_notification(
|
||||
BankNotification::Frozen(bank2),
|
||||
&bank_forks,
|
||||
&optimistically_confirmed_bank,
|
||||
&subscriptions,
|
||||
&mut pending_optimistically_confirmed_banks,
|
||||
&mut last_notified_confirmed_slot,
|
||||
&mut highest_confirmed_slot,
|
||||
);
|
||||
let (response, _) = robust_poll_or_panic(transport_receiver1);
|
||||
let expected = json!({
|
||||
|
@@ -8,7 +8,11 @@ use crate::{
|
||||
weighted_shuffle::weighted_best,
|
||||
};
|
||||
use bincode::serialize;
|
||||
use rand::distributions::{Distribution, WeightedIndex};
|
||||
use lru::LruCache;
|
||||
use rand::{
|
||||
distributions::{Distribution, WeightedError, WeightedIndex},
|
||||
Rng,
|
||||
};
|
||||
use solana_ledger::{blockstore::Blockstore, shred::Nonce};
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_measure::thread_mem_usage;
|
||||
@@ -22,7 +26,7 @@ use solana_sdk::{
|
||||
};
|
||||
use solana_streamer::streamer::{PacketReceiver, PacketSender};
|
||||
use std::{
|
||||
collections::{hash_map::Entry, HashMap, HashSet},
|
||||
collections::HashSet,
|
||||
net::SocketAddr,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
sync::{Arc, RwLock},
|
||||
@@ -34,6 +38,11 @@ use std::{
|
||||
pub const MAX_ORPHAN_REPAIR_RESPONSES: usize = 10;
|
||||
pub const DEFAULT_NONCE: u32 = 42;
|
||||
|
||||
// Number of slots to cache their respective repair peers and sampling weights.
|
||||
pub(crate) const REPAIR_PEERS_CACHE_CAPACITY: usize = 128;
|
||||
// Limit cache entries ttl in order to avoid re-using outdated data.
|
||||
const REPAIR_PEERS_CACHE_TTL: Duration = Duration::from_secs(10);
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||
pub enum RepairType {
|
||||
Orphan(Slot),
|
||||
@@ -81,7 +90,38 @@ pub struct ServeRepair {
|
||||
cluster_info: Arc<ClusterInfo>,
|
||||
}
|
||||
|
||||
type RepairCache = HashMap<Slot, (Vec<ContactInfo>, WeightedIndex<u64>)>;
|
||||
// Cache entry for repair peers for a slot.
|
||||
pub(crate) struct RepairPeers {
|
||||
asof: Instant,
|
||||
peers: Vec<(Pubkey, /*ContactInfo.serve_repair:*/ SocketAddr)>,
|
||||
weighted_index: WeightedIndex<u64>,
|
||||
}
|
||||
|
||||
impl RepairPeers {
|
||||
fn new(asof: Instant, peers: &[ContactInfo], weights: &[u64]) -> Result<Self> {
|
||||
if peers.is_empty() {
|
||||
return Err(Error::from(ClusterInfoError::NoPeers));
|
||||
}
|
||||
if peers.len() != weights.len() {
|
||||
return Err(Error::from(WeightedError::InvalidWeight));
|
||||
}
|
||||
let weighted_index = WeightedIndex::new(weights)?;
|
||||
let peers = peers
|
||||
.iter()
|
||||
.map(|peer| (peer.id, peer.serve_repair))
|
||||
.collect();
|
||||
Ok(Self {
|
||||
asof,
|
||||
peers,
|
||||
weighted_index,
|
||||
})
|
||||
}
|
||||
|
||||
fn sample<R: Rng>(&self, rng: &mut R) -> (Pubkey, SocketAddr) {
|
||||
let index = self.weighted_index.sample(rng);
|
||||
self.peers[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl ServeRepair {
|
||||
/// Without a valid keypair gossip will not function. Only useful for tests.
|
||||
@@ -377,39 +417,30 @@ impl ServeRepair {
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub fn repair_request(
|
||||
pub(crate) fn repair_request(
|
||||
&self,
|
||||
cluster_slots: &ClusterSlots,
|
||||
repair_request: RepairType,
|
||||
cache: &mut RepairCache,
|
||||
peers_cache: &mut LruCache<Slot, RepairPeers>,
|
||||
repair_stats: &mut RepairStats,
|
||||
repair_validators: &Option<HashSet<Pubkey>>,
|
||||
) -> Result<(SocketAddr, Vec<u8>)> {
|
||||
// find a peer that appears to be accepting replication and has the desired slot, as indicated
|
||||
// by a valid tvu port location
|
||||
let slot = repair_request.slot();
|
||||
let (repair_peers, weighted_index) = match cache.entry(slot) {
|
||||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
Entry::Vacant(entry) => {
|
||||
let repair_peers = self.repair_peers(&repair_validators, slot);
|
||||
if repair_peers.is_empty() {
|
||||
return Err(Error::from(ClusterInfoError::NoPeers));
|
||||
}
|
||||
let repair_peers = match peers_cache.get(&slot) {
|
||||
Some(entry) if entry.asof.elapsed() < REPAIR_PEERS_CACHE_TTL => entry,
|
||||
_ => {
|
||||
peers_cache.pop(&slot);
|
||||
let repair_peers = self.repair_peers(repair_validators, slot);
|
||||
let weights = cluster_slots.compute_weights(slot, &repair_peers);
|
||||
debug_assert_eq!(weights.len(), repair_peers.len());
|
||||
let weighted_index = WeightedIndex::new(weights)?;
|
||||
entry.insert((repair_peers, weighted_index))
|
||||
let repair_peers = RepairPeers::new(Instant::now(), &repair_peers, &weights)?;
|
||||
peers_cache.put(slot, repair_peers);
|
||||
peers_cache.get(&slot).unwrap()
|
||||
}
|
||||
};
|
||||
let n = weighted_index.sample(&mut rand::thread_rng());
|
||||
let addr = repair_peers[n].serve_repair; // send the request to the peer's serve_repair port
|
||||
let repair_peer_id = repair_peers[n].id;
|
||||
let out = self.map_repair_request(
|
||||
&repair_request,
|
||||
&repair_peer_id,
|
||||
repair_stats,
|
||||
DEFAULT_NONCE,
|
||||
)?;
|
||||
let (peer, addr) = repair_peers.sample(&mut rand::thread_rng());
|
||||
let out = self.map_repair_request(&repair_request, &peer, repair_stats, DEFAULT_NONCE)?;
|
||||
Ok((addr, out))
|
||||
}
|
||||
|
||||
@@ -755,7 +786,7 @@ mod tests {
|
||||
let rv = serve_repair.repair_request(
|
||||
&cluster_slots,
|
||||
RepairType::Shred(0, 0),
|
||||
&mut HashMap::new(),
|
||||
&mut LruCache::new(100),
|
||||
&mut RepairStats::default(),
|
||||
&None,
|
||||
);
|
||||
@@ -782,7 +813,7 @@ mod tests {
|
||||
.repair_request(
|
||||
&cluster_slots,
|
||||
RepairType::Shred(0, 0),
|
||||
&mut HashMap::new(),
|
||||
&mut LruCache::new(100),
|
||||
&mut RepairStats::default(),
|
||||
&None,
|
||||
)
|
||||
@@ -815,7 +846,7 @@ mod tests {
|
||||
.repair_request(
|
||||
&cluster_slots,
|
||||
RepairType::Shred(0, 0),
|
||||
&mut HashMap::new(),
|
||||
&mut LruCache::new(100),
|
||||
&mut RepairStats::default(),
|
||||
&None,
|
||||
)
|
||||
@@ -991,7 +1022,7 @@ mod tests {
|
||||
.repair_request(
|
||||
&cluster_slots,
|
||||
RepairType::Shred(0, 0),
|
||||
&mut HashMap::new(),
|
||||
&mut LruCache::new(100),
|
||||
&mut RepairStats::default(),
|
||||
&trusted_validators,
|
||||
)
|
||||
@@ -1007,7 +1038,7 @@ mod tests {
|
||||
.repair_request(
|
||||
&cluster_slots,
|
||||
RepairType::Shred(0, 0),
|
||||
&mut HashMap::new(),
|
||||
&mut LruCache::new(100),
|
||||
&mut RepairStats::default(),
|
||||
&trusted_validators,
|
||||
)
|
||||
@@ -1027,7 +1058,7 @@ mod tests {
|
||||
.repair_request(
|
||||
&cluster_slots,
|
||||
RepairType::Shred(0, 0),
|
||||
&mut HashMap::new(),
|
||||
&mut LruCache::new(100),
|
||||
&mut RepairStats::default(),
|
||||
&None,
|
||||
)
|
||||
|
@@ -7,7 +7,9 @@ use solana_ledger::{
|
||||
use solana_runtime::bank::{
|
||||
Bank, InnerInstructionsList, NonceRollbackInfo, TransactionLogMessages,
|
||||
};
|
||||
use solana_transaction_status::{InnerInstructions, Reward, TransactionStatusMeta};
|
||||
use solana_transaction_status::{
|
||||
extract_and_fmt_memos, InnerInstructions, Reward, TransactionStatusMeta,
|
||||
};
|
||||
use std::{
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicU64, Ordering},
|
||||
@@ -109,7 +111,7 @@ impl TransactionStatusService {
|
||||
let fee = fee_calculator.calculate_fee(transaction.message());
|
||||
let (writable_keys, readonly_keys) = transaction
|
||||
.message
|
||||
.get_account_keys_by_lock_type(bank.demote_sysvar_write_locks());
|
||||
.get_account_keys_by_lock_type(bank.demote_program_write_locks());
|
||||
|
||||
let inner_instructions = inner_instructions.map(|inner_instructions| {
|
||||
inner_instructions
|
||||
@@ -140,6 +142,12 @@ impl TransactionStatusService {
|
||||
.collect(),
|
||||
);
|
||||
|
||||
if let Some(memos) = extract_and_fmt_memos(transaction.message()) {
|
||||
blockstore
|
||||
.write_transaction_memos(&transaction.signatures[0], memos)
|
||||
.expect("Expect database write to succeed: TransactionMemos");
|
||||
}
|
||||
|
||||
blockstore
|
||||
.write_transaction_status(
|
||||
slot,
|
||||
@@ -158,7 +166,7 @@ impl TransactionStatusService {
|
||||
rewards,
|
||||
},
|
||||
)
|
||||
.expect("Expect database write to succeed");
|
||||
.expect("Expect database write to succeed: TransactionStatus");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -78,7 +78,7 @@ use std::{
|
||||
};
|
||||
|
||||
const MAX_COMPLETED_DATA_SETS_IN_CHANNEL: usize = 100_000;
|
||||
const WAIT_FOR_SUPERMAJORITY_THRESHOLD_PERCENT: u64 = 90;
|
||||
const WAIT_FOR_SUPERMAJORITY_THRESHOLD_PERCENT: u64 = 80;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ValidatorConfig {
|
||||
|
@@ -483,7 +483,7 @@ fn network_run_pull(
|
||||
.collect()
|
||||
};
|
||||
let transfered: Vec<_> = requests
|
||||
.into_par_iter()
|
||||
.into_iter()
|
||||
.map(|(to, filters, caller_info)| {
|
||||
let mut bytes: usize = 0;
|
||||
let mut msgs: usize = 0;
|
||||
@@ -506,8 +506,9 @@ fn network_run_pull(
|
||||
.lock()
|
||||
.unwrap()
|
||||
.generate_pull_responses(
|
||||
thread_pool,
|
||||
&filters,
|
||||
/*output_size_limit=*/ usize::MAX,
|
||||
usize::MAX, // output_size_limit
|
||||
now,
|
||||
)
|
||||
.into_iter()
|
||||
|
@@ -27,7 +27,7 @@ use std::{
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use tokio_02::runtime::Runtime;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
macro_rules! json_req {
|
||||
($method: expr, $params: expr) => {{
|
||||
@@ -159,7 +159,7 @@ fn test_rpc_slot_updates() {
|
||||
let connect = ws::try_connect::<PubsubClient>(&rpc_pubsub_url).unwrap();
|
||||
let client = connect.await.unwrap();
|
||||
|
||||
tokio_02::spawn(async move {
|
||||
tokio::spawn(async move {
|
||||
let mut update_sub = client.slots_updates_subscribe().unwrap();
|
||||
loop {
|
||||
let response = update_sub.next().await.unwrap();
|
||||
@@ -268,7 +268,7 @@ fn test_rpc_subscriptions() {
|
||||
)
|
||||
.unwrap_or_else(|err| panic!("sig sub err: {:#?}", err));
|
||||
|
||||
tokio_02::spawn(async move {
|
||||
tokio::spawn(async move {
|
||||
let response = sig_sub.next().await.unwrap();
|
||||
status_sender
|
||||
.send((sig.clone(), response.unwrap()))
|
||||
@@ -288,7 +288,7 @@ fn test_rpc_subscriptions() {
|
||||
}),
|
||||
)
|
||||
.unwrap_or_else(|err| panic!("acct sub err: {:#?}", err));
|
||||
tokio_02::spawn(async move {
|
||||
tokio::spawn(async move {
|
||||
let response = client_sub.next().await.unwrap();
|
||||
account_sender.send(response.unwrap()).unwrap();
|
||||
});
|
||||
@@ -298,7 +298,7 @@ fn test_rpc_subscriptions() {
|
||||
let mut slot_sub = client
|
||||
.slot_subscribe()
|
||||
.unwrap_or_else(|err| panic!("sig sub err: {:#?}", err));
|
||||
tokio_02::spawn(async move {
|
||||
tokio::spawn(async move {
|
||||
let _response = slot_sub.next().await.unwrap();
|
||||
ready_sender.send(()).unwrap();
|
||||
});
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-crate-features"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Crate Features"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -24,7 +24,6 @@ serde = { version = "1.0.100", features = ["rc"] }
|
||||
ed25519-dalek = { version = "=1.0.1", features = ["serde"] }
|
||||
syn_0_15 = { package = "syn", version = "0.15.42", features = ["extra-traits", "fold", "full"] }
|
||||
syn_1_0 = { package = "syn", version = "1.0.3", features = ["extra-traits", "fold", "full"] }
|
||||
tokio = { version = "0.1.22",features=["bytes", "codec", "default", "fs", "io", "mio", "num_cpus", "reactor", "rt-full", "sync", "tcp", "timer", "tokio-codec", "tokio-current-thread", "tokio-executor", "tokio-io", "tokio-io", "tokio-reactor", "tokio-tcp", "tokio-tcp", "tokio-threadpool", "tokio-timer", "tokio-udp", "tokio-uds", "udp", "uds"] }
|
||||
winapi = { version = "0.3.8", features=["basetsd", "consoleapi", "errhandlingapi", "fileapi", "handleapi", "impl-debug", "impl-default", "knownfolders", "libloaderapi", "memoryapi", "minwinbase", "minwindef", "ntdef", "ntsecapi", "ntstatus", "objbase", "processenv", "processthreadsapi", "profileapi", "shlobj", "std", "synchapi", "sysinfoapi", "timezoneapi", "utilapiset", "winbase", "wincon", "windef", "winerror", "winnls", "winnt", "winreg", "winsock2", "winuser", "ws2def", "ws2ipdef", "ws2tcpip", "wtypesbase"] }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
|
@@ -3034,7 +3034,7 @@ curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d '
|
||||
|
||||
Result:
|
||||
```json
|
||||
{"jsonrpc":"2.0","result":{"solana-core": "1.6.22"},"id":1}
|
||||
{"jsonrpc":"2.0","result":{"solana-core": "1.6.23"},"id":1}
|
||||
```
|
||||
|
||||
### getVoteAccounts
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-dos"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -14,15 +14,15 @@ clap = "2.33.1"
|
||||
log = "0.4.11"
|
||||
rand = "0.7.0"
|
||||
rayon = "1.5.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-core = { path = "../core", version = "=1.6.22" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-client = { path = "../client", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-core = { path = "../core", version = "=1.6.23" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
solana-client = { path = "../client", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-download-utils"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Download Utils"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,8 +15,8 @@ console = "0.11.3"
|
||||
indicatif = "0.15.0"
|
||||
log = "0.4.11"
|
||||
reqwest = { version = "0.11.2", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
tar = "0.4.28"
|
||||
|
||||
[lib]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-faucet"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Faucet"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -16,12 +16,12 @@ clap = "2.33"
|
||||
log = "0.4.11"
|
||||
serde = "1.0.122"
|
||||
serde_derive = "1.0.103"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-cli-config = { path = "../cli-config", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-cli-config = { path = "../cli-config", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-frozen-abi"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Frozen ABI"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -16,11 +16,11 @@ log = "0.4.11"
|
||||
serde = "1.0.122"
|
||||
serde_derive = "1.0.103"
|
||||
sha2 = "0.9.2"
|
||||
solana-frozen-abi-macro = { path = "macro", version = "=1.6.22" }
|
||||
solana-frozen-abi-macro = { path = "macro", version = "=1.6.23" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[target.'cfg(not(target_arch = "bpf"))'.dependencies]
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
generic-array = { version = "0.14.3", default-features = false, features = ["serde", "more_lengths"]}
|
||||
memmap2 = "0.1.0"
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-frozen-abi-macro"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Frozen ABI Macro"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-genesis"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -16,18 +16,18 @@ chrono = "0.4"
|
||||
serde = "1.0.122"
|
||||
serde_json = "1.0.56"
|
||||
serde_yaml = "0.8.13"
|
||||
solana-budget-program = { path = "../programs/budget", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-cli-config = { path = "../cli-config", version = "=1.6.22" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "=1.6.22" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "=1.6.23" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-cli-config = { path = "../cli-config", version = "=1.6.23" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "=1.6.23" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-gossip"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -11,12 +11,12 @@ documentation = "https://docs.rs/solana-gossip"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.1"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-core = { path = "../core", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-core = { path = "../core", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-install"
|
||||
description = "The solana cluster software installer"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -25,12 +25,12 @@ reqwest = { version = "0.11.2", default-features = false, features = ["blocking"
|
||||
serde = { version = "1.0.122", features = ["derive"] }
|
||||
serde_json = "1.0.62"
|
||||
serde_yaml = "0.8.13"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-client = { path = "../client", version = "=1.6.22" }
|
||||
solana-config-program = { path = "../programs/config", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-client = { path = "../client", version = "=1.6.23" }
|
||||
solana-config-program = { path = "../programs/config", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
semver = "0.9.0"
|
||||
tar = "0.4.28"
|
||||
tempfile = "3.1.0"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-keygen"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana key generation utility"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,11 +14,11 @@ bs58 = "0.3.1"
|
||||
clap = "2.33"
|
||||
dirs-next = "2.0.0"
|
||||
num_cpus = "1.13.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-cli-config = { path = "../cli-config", version = "=1.6.22" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-cli-config = { path = "../cli-config", version = "=1.6.23" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
tiny-bip39 = "0.7.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-ledger-tool"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -23,18 +23,18 @@ regex = "1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.56"
|
||||
serde_yaml = "0.8.13"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-cli-output = { path = "../cli-output", version = "=1.6.22" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.22" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.6.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-cli-output = { path = "../cli-output", version = "=1.6.23" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.23" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.6.23" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
tempfile = "3.1.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-ledger"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana ledger"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -34,22 +34,22 @@ reed-solomon-erasure = { version = "4.0.2", features = ["simd-accel"] }
|
||||
serde = "1.0.122"
|
||||
serde_bytes = "0.11.4"
|
||||
sha2 = "0.9.2"
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.6.22" }
|
||||
solana-frozen-abi = { path = "../frozen-abi", version = "=1.6.22" }
|
||||
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.6.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "=1.6.22" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.22" }
|
||||
solana-perf = { path = "../perf", version = "=1.6.22" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.22" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.6.22" }
|
||||
solana-storage-proto = { path = "../storage-proto", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.6.23" }
|
||||
solana-frozen-abi = { path = "../frozen-abi", version = "=1.6.23" }
|
||||
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.6.23" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "=1.6.23" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.23" }
|
||||
solana-perf = { path = "../perf", version = "=1.6.23" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.23" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.6.23" }
|
||||
solana-storage-proto = { path = "../storage-proto", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
tempfile = "3.1.0"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
@@ -66,8 +66,8 @@ features = ["lz4"]
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.3.0"
|
||||
matches = "0.1.6"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.22" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "=1.6.22" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.6.23" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "=1.6.23" }
|
||||
|
||||
[build-dependencies]
|
||||
rustc_version = "0.2"
|
||||
|
@@ -139,6 +139,7 @@ pub struct Blockstore {
|
||||
code_shred_cf: LedgerColumn<cf::ShredCode>,
|
||||
transaction_status_cf: LedgerColumn<cf::TransactionStatus>,
|
||||
address_signatures_cf: LedgerColumn<cf::AddressSignatures>,
|
||||
transaction_memos_cf: LedgerColumn<cf::TransactionMemos>,
|
||||
transaction_status_index_cf: LedgerColumn<cf::TransactionStatusIndex>,
|
||||
active_transaction_status_index: RwLock<u64>,
|
||||
rewards_cf: LedgerColumn<cf::Rewards>,
|
||||
@@ -313,6 +314,7 @@ impl Blockstore {
|
||||
let code_shred_cf = db.column();
|
||||
let transaction_status_cf = db.column();
|
||||
let address_signatures_cf = db.column();
|
||||
let transaction_memos_cf = db.column();
|
||||
let transaction_status_index_cf = db.column();
|
||||
let rewards_cf = db.column();
|
||||
let blocktime_cf = db.column();
|
||||
@@ -362,6 +364,7 @@ impl Blockstore {
|
||||
code_shred_cf,
|
||||
transaction_status_cf,
|
||||
address_signatures_cf,
|
||||
transaction_memos_cf,
|
||||
transaction_status_index_cf,
|
||||
active_transaction_status_index: RwLock::new(active_transaction_status_index),
|
||||
rewards_cf,
|
||||
@@ -2016,6 +2019,14 @@ impl Blockstore {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_transaction_memos(&self, signature: Signature) -> Result<Option<String>> {
|
||||
self.transaction_memos_cf.get(signature)
|
||||
}
|
||||
|
||||
pub fn write_transaction_memos(&self, signature: &Signature, memos: String) -> Result<()> {
|
||||
self.transaction_memos_cf.put(*signature, &memos)
|
||||
}
|
||||
|
||||
fn ensure_lowest_cleanup_slot(&self) -> (std::sync::RwLockReadGuard<Slot>, Slot) {
|
||||
// Ensures consistent result by using lowest_cleanup_slot as the lower bound
|
||||
// for reading columns that do not employ strong read consistency with slot-based
|
||||
@@ -2499,12 +2510,13 @@ impl Blockstore {
|
||||
let transaction_status =
|
||||
self.get_transaction_status(signature, &confirmed_unrooted_slots)?;
|
||||
let err = transaction_status.and_then(|(_slot, status)| status.status.err());
|
||||
let memo = self.read_transaction_memos(signature)?;
|
||||
let block_time = self.get_block_time(slot)?;
|
||||
infos.push(ConfirmedTransactionStatusWithSignature {
|
||||
signature,
|
||||
slot,
|
||||
err,
|
||||
memo: None,
|
||||
memo,
|
||||
block_time,
|
||||
});
|
||||
}
|
||||
|
@@ -61,6 +61,8 @@ const CODE_SHRED_CF: &str = "code_shred";
|
||||
const TRANSACTION_STATUS_CF: &str = "transaction_status";
|
||||
/// Column family for Address Signatures
|
||||
const ADDRESS_SIGNATURES_CF: &str = "address_signatures";
|
||||
/// Column family for TransactionMemos
|
||||
const TRANSACTION_MEMOS_CF: &str = "transaction_memos";
|
||||
/// Column family for the Transaction Status Index.
|
||||
/// This column family is used for tracking the active primary index for columns that for
|
||||
/// query performance reasons should not be indexed by Slot.
|
||||
@@ -163,6 +165,10 @@ pub mod columns {
|
||||
/// The address signatures column
|
||||
pub struct AddressSignatures;
|
||||
|
||||
#[derive(Debug)]
|
||||
// The transaction memos column
|
||||
pub struct TransactionMemos;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// The transaction status index column
|
||||
pub struct TransactionStatusIndex;
|
||||
@@ -332,6 +338,10 @@ impl Rocks {
|
||||
AddressSignatures::NAME,
|
||||
get_cf_options::<AddressSignatures>(&access_type, &oldest_slot),
|
||||
);
|
||||
let transaction_memos_cf_descriptor = ColumnFamilyDescriptor::new(
|
||||
TransactionMemos::NAME,
|
||||
get_cf_options::<TransactionMemos>(&access_type, &oldest_slot),
|
||||
);
|
||||
let transaction_status_index_cf_descriptor = ColumnFamilyDescriptor::new(
|
||||
TransactionStatusIndex::NAME,
|
||||
get_cf_options::<TransactionStatusIndex>(&access_type, &oldest_slot),
|
||||
@@ -372,6 +382,7 @@ impl Rocks {
|
||||
(ShredCode::NAME, shred_code_cf_descriptor),
|
||||
(TransactionStatus::NAME, transaction_status_cf_descriptor),
|
||||
(AddressSignatures::NAME, address_signatures_cf_descriptor),
|
||||
(TransactionMemos::NAME, transaction_memos_cf_descriptor),
|
||||
(
|
||||
TransactionStatusIndex::NAME,
|
||||
transaction_status_index_cf_descriptor,
|
||||
@@ -494,6 +505,7 @@ impl Rocks {
|
||||
ShredCode::NAME,
|
||||
TransactionStatus::NAME,
|
||||
AddressSignatures::NAME,
|
||||
TransactionMemos::NAME,
|
||||
TransactionStatusIndex::NAME,
|
||||
Rewards::NAME,
|
||||
Blocktime::NAME,
|
||||
@@ -589,6 +601,10 @@ impl TypedColumn for columns::AddressSignatures {
|
||||
type Type = blockstore_meta::AddressSignatureMeta;
|
||||
}
|
||||
|
||||
impl TypedColumn for columns::TransactionMemos {
|
||||
type Type = String;
|
||||
}
|
||||
|
||||
impl TypedColumn for columns::TransactionStatusIndex {
|
||||
type Type = blockstore_meta::TransactionStatusIndexMeta;
|
||||
}
|
||||
@@ -703,6 +719,37 @@ impl ColumnName for columns::AddressSignatures {
|
||||
const NAME: &'static str = ADDRESS_SIGNATURES_CF;
|
||||
}
|
||||
|
||||
impl Column for columns::TransactionMemos {
|
||||
type Index = Signature;
|
||||
|
||||
fn key(signature: Signature) -> Vec<u8> {
|
||||
let mut key = vec![0; 64]; // size_of Signature
|
||||
key[0..64].clone_from_slice(&signature.as_ref()[0..64]);
|
||||
key
|
||||
}
|
||||
|
||||
fn index(key: &[u8]) -> Signature {
|
||||
Signature::new(&key[0..64])
|
||||
}
|
||||
|
||||
fn primary_index(_index: Self::Index) -> u64 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn slot(_index: Self::Index) -> Slot {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn as_index(_index: u64) -> Self::Index {
|
||||
Signature::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl ColumnName for columns::TransactionMemos {
|
||||
const NAME: &'static str = TRANSACTION_MEMOS_CF;
|
||||
}
|
||||
|
||||
impl Column for columns::TransactionStatusIndex {
|
||||
type Index = u64;
|
||||
|
||||
@@ -1364,6 +1411,7 @@ fn excludes_from_compaction(cf_name: &str) -> bool {
|
||||
let no_compaction_cfs: HashSet<&'static str> = vec![
|
||||
columns::TransactionStatusIndex::NAME,
|
||||
columns::ProgramCosts::NAME,
|
||||
columns::TransactionMemos::NAME,
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
@@ -1431,6 +1479,7 @@ pub mod tests {
|
||||
columns::TransactionStatusIndex::NAME
|
||||
));
|
||||
assert!(excludes_from_compaction(columns::ProgramCosts::NAME));
|
||||
assert!(excludes_from_compaction(columns::TransactionMemos::NAME));
|
||||
assert!(!excludes_from_compaction("something else"));
|
||||
}
|
||||
}
|
||||
|
@@ -244,13 +244,11 @@ pub fn verify_shreds_gpu(
|
||||
shred_gpu_offsets(pubkeys_len, batches, recycler_cache);
|
||||
let mut out = recycler_cache.buffer().allocate().unwrap();
|
||||
out.set_pinnable();
|
||||
elems.push(
|
||||
perf_libs::Elems {
|
||||
#![allow(clippy::cast_ptr_alignment)]
|
||||
elems: pubkeys.as_ptr() as *const solana_sdk::packet::Packet,
|
||||
num: num_packets as u32,
|
||||
},
|
||||
);
|
||||
elems.push(perf_libs::Elems {
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
elems: pubkeys.as_ptr() as *const solana_sdk::packet::Packet,
|
||||
num: num_packets as u32,
|
||||
});
|
||||
|
||||
for p in batches {
|
||||
elems.push(perf_libs::Elems {
|
||||
@@ -383,13 +381,11 @@ pub fn sign_shreds_gpu(
|
||||
let mut signatures_out = recycler_cache.buffer().allocate().unwrap();
|
||||
signatures_out.set_pinnable();
|
||||
signatures_out.resize(total_sigs * sig_size, 0);
|
||||
elems.push(
|
||||
perf_libs::Elems {
|
||||
#![allow(clippy::cast_ptr_alignment)]
|
||||
elems: pinned_keypair.as_ptr() as *const solana_sdk::packet::Packet,
|
||||
num: num_keypair_packets as u32,
|
||||
},
|
||||
);
|
||||
elems.push(perf_libs::Elems {
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
elems: pinned_keypair.as_ptr() as *const solana_sdk::packet::Packet,
|
||||
num: num_keypair_packets as u32,
|
||||
});
|
||||
|
||||
for p in batches.iter() {
|
||||
elems.push(perf_libs::Elems {
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-local-cluster"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -17,21 +17,21 @@ fs_extra = "1.2.0"
|
||||
log = "0.4.11"
|
||||
rand = "0.7.0"
|
||||
rayon = "1.5.0"
|
||||
solana-config-program = { path = "../programs/config", version = "=1.6.22" }
|
||||
solana-core = { path = "../core", version = "=1.6.22" }
|
||||
solana-client = { path = "../client", version = "=1.6.22" }
|
||||
solana-download-utils = { path = "../download-utils", version = "=1.6.22" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.22" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "=1.6.22" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.22" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-config-program = { path = "../programs/config", version = "=1.6.23" }
|
||||
solana-core = { path = "../core", version = "=1.6.23" }
|
||||
solana-client = { path = "../client", version = "=1.6.23" }
|
||||
solana-download-utils = { path = "../download-utils", version = "=1.6.23" }
|
||||
solana-faucet = { path = "../faucet", version = "=1.6.23" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "=1.6.23" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.23" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
tempfile = "3.1.0"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.6.22" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.6.23" }
|
||||
|
||||
[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.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -14,9 +14,9 @@ byte-unit = "4.0.9"
|
||||
clap = "2.33.1"
|
||||
serde = "1.0.122"
|
||||
serde_json = "1.0.56"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
|
||||
[[bin]]
|
||||
name = "solana-log-analyzer"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-logger"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Logger"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-measure"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
homepage = "https://solana.com/"
|
||||
documentation = "https://docs.rs/solana-measure"
|
||||
readme = "../README.md"
|
||||
@@ -12,8 +12,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.11"
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.23" }
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
jemallocator = "0.3.2"
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-merkle-root-bench"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -10,11 +10,11 @@ publish = false
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.11"
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
clap = "2.33.1"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-merkle-tree"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Merkle Tree"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-merkle-tree"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../sdk/program", version = "=1.6.23" }
|
||||
fast-math = "0.1"
|
||||
|
||||
# This can go once the BPF toolchain target Rust 1.42.0+
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-metrics"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Metrics"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,7 +15,7 @@ gethostname = "0.2.1"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.11"
|
||||
reqwest = { version = "0.11.2", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.7.0"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-net-shaper"
|
||||
description = "The solana cluster network shaping tool"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -13,8 +13,8 @@ publish = false
|
||||
clap = "2.33.1"
|
||||
serde = "1.0.122"
|
||||
serde_json = "1.0.56"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
rand = "0.7.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-net-utils"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Network Utilities"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -18,9 +18,9 @@ rand = "0.7.0"
|
||||
serde = "1.0.122"
|
||||
serde_derive = "1.0.103"
|
||||
socket2 = "0.3.17"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
url = "2.1.1"
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-notifier"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Notifier"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-perf"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana Performance APIs"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -18,12 +18,12 @@ serde = "1.0.122"
|
||||
dlopen_derive = "0.1.4"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.11"
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.6.22" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.6.23" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.6.23" }
|
||||
curve25519-dalek = { version = "2" }
|
||||
|
||||
[lib]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
edition = "2018"
|
||||
name = "solana-poh-bench"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -13,13 +13,13 @@ clap = "2.33.1"
|
||||
log = "0.4.11"
|
||||
rand = "0.7.0"
|
||||
rayon = "1.5.0"
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.22" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.22" }
|
||||
solana-version = { path = "../version", version = "=1.6.22" }
|
||||
solana-perf = { path = "../perf", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-ledger = { path = "../ledger", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "=1.6.23" }
|
||||
solana-measure = { path = "../measure", version = "=1.6.23" }
|
||||
solana-version = { path = "../version", version = "=1.6.23" }
|
||||
solana-perf = { path = "../perf", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -5,7 +5,7 @@ edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
name = "solana-program-test"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.42"
|
||||
@@ -17,16 +17,16 @@ log = "0.4.11"
|
||||
mio = "0.7.6"
|
||||
serde = "1.0.112"
|
||||
serde_derive = "1.0.103"
|
||||
solana-banks-client = { path = "../banks-client", version = "=1.6.22" }
|
||||
solana-banks-server = { path = "../banks-server", version = "=1.6.22" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.6.22" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.22" }
|
||||
solana-banks-client = { path = "../banks-client", version = "=1.6.23" }
|
||||
solana-banks-server = { path = "../banks-server", version = "=1.6.23" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.6.23" }
|
||||
solana-logger = { path = "../logger", version = "=1.6.23" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.23" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.6.23" }
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.3.0"
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.6.23" }
|
||||
|
@@ -19,7 +19,7 @@ use {
|
||||
clock::{Clock, Slot},
|
||||
entrypoint::{ProgramResult, SUCCESS},
|
||||
epoch_schedule::EpochSchedule,
|
||||
feature_set::demote_sysvar_write_locks,
|
||||
feature_set::demote_program_write_locks,
|
||||
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||
genesis_config::{ClusterType, GenesisConfig},
|
||||
hash::Hash,
|
||||
@@ -256,14 +256,14 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
|
||||
}
|
||||
panic!("Program id {} wasn't found in account_infos", program_id);
|
||||
};
|
||||
let demote_sysvar_write_locks =
|
||||
invoke_context.is_feature_active(&demote_sysvar_write_locks::id());
|
||||
let demote_program_write_locks =
|
||||
invoke_context.is_feature_active(&demote_program_write_locks::id());
|
||||
// TODO don't have the caller's keyed_accounts so can't validate writer or signer escalation or deescalation yet
|
||||
let caller_privileges = message
|
||||
.account_keys
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| message.is_writable(i, demote_sysvar_write_locks))
|
||||
.map(|(i, _)| message.is_writable(i, demote_program_write_locks))
|
||||
.collect::<Vec<bool>>();
|
||||
|
||||
stable_log::program_invoke(&logger, &program_id, invoke_context.invoke_depth());
|
||||
@@ -334,7 +334,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
|
||||
|
||||
// Copy writeable account modifications back into the caller's AccountInfos
|
||||
for (i, account_pubkey) in message.account_keys.iter().enumerate() {
|
||||
if !message.is_writable(i, true) {
|
||||
if !message.is_writable(i, demote_program_write_locks) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
642
programs/bpf/Cargo.lock
generated
642
programs/bpf/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-bpf-programs"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "README.md"
|
||||
@@ -25,15 +25,15 @@ elf = "0.0.10"
|
||||
itertools = "0.10.0"
|
||||
miow = "0.2.2"
|
||||
net2 = "0.2.37"
|
||||
solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.6.22" }
|
||||
solana-cli-output = { path = "../../cli-output", version = "=1.6.22" }
|
||||
solana-logger = { path = "../../logger", version = "=1.6.22" }
|
||||
solana-measure = { path = "../../measure", version = "=1.6.22" }
|
||||
solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.6.23" }
|
||||
solana-cli-output = { path = "../../cli-output", version = "=1.6.23" }
|
||||
solana-logger = { path = "../../logger", version = "=1.6.23" }
|
||||
solana-measure = { path = "../../measure", version = "=1.6.23" }
|
||||
solana_rbpf = "=0.2.9"
|
||||
solana-runtime = { path = "../../runtime", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../../sdk", version = "=1.6.22" }
|
||||
solana-transaction-status = { path = "../../transaction-status", version = "=1.6.22" }
|
||||
solana-account-decoder = { path = "../../account-decoder", version = "=1.6.22" }
|
||||
solana-runtime = { path = "../../runtime", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../../sdk", version = "=1.6.23" }
|
||||
solana-transaction-status = { path = "../../transaction-status", version = "=1.6.23" }
|
||||
solana-account-decoder = { path = "../../account-decoder", version = "=1.6.23" }
|
||||
|
||||
|
||||
[[bench]]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-128bit"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,8 +10,8 @@ documentation = "https://docs.rs/solana-bpf-rust-128bit"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-128bit-dep"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-128bit-dep"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-alloc"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-alloc"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-call-depth"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-call-depth"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-caller-access"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-caller-access"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-custom-heap"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-custom-heap"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[features]
|
||||
default = ["custom-heap"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-dep-crate"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -11,7 +11,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
byteorder = { version = "1", default-features = false }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-deprecated-loader"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-deprecated-loader"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-dup-accounts"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-dup-accounts"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-error-handling"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
num-derive = "0.2"
|
||||
num-traits = "0.2"
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[lib]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-external-spend"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-external-spend"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-finalize"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-finalize"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-instruction-introspection"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-instruction-introspection"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-invoke"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -11,7 +11,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-bpf-rust-invoked = { path = "../invoked", default-features = false }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-invoke-and-error"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-invoke-and-error"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-invoke-and-ok"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-invoke-and-ok"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-invoke-and-return"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-invoke-and-return"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-invoked"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-invoked"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[features]
|
||||
default = ["program"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-iter"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-iter"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-many-args"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,8 +10,8 @@ documentation = "https://docs.rs/solana-bpf-rust-many-args"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-many-args-dep"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-many-args-dep"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-mem"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -13,11 +13,11 @@ edition = "2018"
|
||||
no-entrypoint = []
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-program-test = { path = "../../../../program-test", version = "=1.6.22" }
|
||||
solana-sdk = { path = "../../../../sdk", version = "=1.6.22" }
|
||||
solana-program-test = { path = "../../../../program-test", version = "=1.6.23" }
|
||||
solana-sdk = { path = "../../../../sdk", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-membuiltins"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,8 +10,8 @@ documentation = "https://docs.rs/solana-bpf-rust-mem"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-bpf-rust-mem = { path = "../mem", version = "=1.6.22", features = [ "no-entrypoint" ] }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-bpf-rust-mem = { path = "../mem", version = "=1.6.23", features = [ "no-entrypoint" ] }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-noop"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-noop"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-panic"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-panic"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[features]
|
||||
default = ["custom-panic"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-param-passing"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,8 +10,8 @@ documentation = "https://docs.rs/solana-bpf-rust-param-passing"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-param-passing-dep"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-param-passing-dep"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-rand"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
getrandom = { version = "0.1.14", features = ["dummy"] }
|
||||
rand = "0.7"
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-ro-modify"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-ro-modify"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-sanity"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-sanity"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-sha"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-sha"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-rust-spoof1"
|
||||
version = "1.6.22"
|
||||
version = "1.6.23"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-bpf-rust-spoof1"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.22" }
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.6.23" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user