Compare commits

...

19 Commits

Author SHA1 Message Date
sakridge
83d08223fd More transaction forwarding (#19834) 2021-09-14 16:08:53 +02:00
mergify[bot]
6bb63f9abf Silence vercel github comments (#19827) (#19832)
(cherry picked from commit 8ac12c29ed)

Co-authored-by: Justin Starry <justin@solana.com>
2021-09-13 17:51:39 -05:00
behzad nouri
d8293abc64 debug logs when crds table trim failed (#18307)
reports of this error being possibly spammy:
https://discord.com/channels/428295358100013066/689412830075551748/859441080054710293

The commit changes the log level to debug.
Additionally adding a new metric to understand the frequency of this error.

(cherry picked from commit 9d983a34a0)
2021-09-10 20:02:13 -07:00
Michael Vines
4d074a6716 Reduce wait for supermajority threshold back to 80%
(cherry picked from commit 4386e09710)
2021-09-09 21:44:42 -07:00
mergify[bot]
3eee222667 Return error if Transaction contains writable executable or ProgramData accounts (backport #19629) (#19729)
* Return error if Transaction contains writable executable or ProgramData accounts (#19629)

* Return error if Transaction locks an executable as writable

* Return error if a ProgramData account is writable but the upgradable loader isn't present

* Remove unreachable clause

* Fixup bpf tests

* Review comments

* Add new TransactionError

* Disallow writes to any upgradeable-loader account when loader not present; remove is_upgradeable_loader_present exception for all other executables

(cherry picked from commit 38bbb77989)

# Conflicts:
#	programs/bpf/tests/programs.rs
#	runtime/src/accounts.rs
#	runtime/src/bank.rs
#	sdk/src/transaction.rs
#	storage-proto/proto/transaction_by_addr.proto
#	storage-proto/src/convert.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-09-09 03:06:02 +00:00
mergify[bot]
a78c3c07f2 filters crds values in parallel when responding to gossip pull-requests (backport #18877) (#19450)
* filters crds values in parallel when responding to gossip pull-requests (#18877)

When responding to gossip pull-requests, filter_crds_values takes a lot of time
while holding onto read-lock:
https://github.com/solana-labs/solana/blob/f51d64868/gossip/src/crds_gossip_pull.rs#L509-L566

This commit will filter-crds-values in parallel using rayon thread-pools.

(cherry picked from commit f1198fc6d5)

* removes backport merge conflicts

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-09-08 17:09:35 +00:00
mergify[bot]
53f8e58300 Demote write locks on transaction program ids (backport #19593) (backport #19633) (#19637)
* Demote write locks on transaction program ids (backport #19593) (#19633)

* Demote write locks on transaction program ids (#19593)

* Add feature

* Demote write lock on program ids

* Fixup bpf tests

* Update MappedMessage::is_writable

* Comma nit

* Review comments

(cherry picked from commit decec3cd8b)

# Conflicts:
#	core/src/banking_stage.rs
#	core/src/cost_model.rs
#	core/src/cost_tracker.rs
#	ledger-tool/src/main.rs
#	program-runtime/src/instruction_processor.rs
#	programs/bpf/tests/programs.rs
#	programs/bpf_loader/src/syscalls.rs
#	rpc/src/transaction_status_service.rs
#	runtime/src/accounts.rs
#	runtime/src/bank.rs
#	runtime/src/message_processor.rs
#	sdk/benches/serialize_instructions.rs
#	sdk/program/src/message/mapped.rs
#	sdk/program/src/message/sanitized.rs
#	sdk/src/transaction/sanitized.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
(cherry picked from commit fcda5d4a7d)

# Conflicts:
#	cli-output/src/display.rs
#	core/src/transaction_status_service.rs
#	program-test/src/lib.rs
#	programs/bpf_loader/src/syscalls.rs
#	runtime/src/accounts.rs
#	runtime/src/bank.rs
#	runtime/src/message_processor.rs
#	sdk/benches/serialize_instructions.rs
#	sdk/program/src/message.rs
#	sdk/src/feature_set.rs
#	transaction-status/src/parse_accounts.rs

* Replace feature and fix conflicts

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-09-04 09:10:57 +00:00
mergify[bot]
b4fdce9443 Populate memo in blockstore signatures-for-address (#19515) (#19604)
* Add TransactionMemos column family

* Traitify extract_memos

* Write TransactionMemos in TransactionStatusService

* Populate memos from column

* Dedupe and add unit test

(cherry picked from commit 5fa3e5744c)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-09-03 18:38:57 +00:00
mergify[bot]
39fe52fc06 Fix clippy (#17214) (#19609)
Newer clippy from +nightly have new errors about where annotations can and
cannot go.  This commit fixes two of them.

(cherry picked from commit b074e86ad2)

Co-authored-by: Brooks Prumo <brooks@solana.com>
2021-09-03 17:00:25 +00:00
mergify[bot]
db65b4e641 Populate memo in bigtable transaction structs (backport #19512) (#19606)
* Populate memo in bigtable transaction structs (#19512)

* Populate memo in bigtable transaction structs

* Preface memos with len

(cherry picked from commit f4ae450f34)

# Conflicts:
#	transaction-status/src/parse_instruction.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-09-03 09:26:08 +00:00
mergify[bot]
fe1c20c689 excludes epoch-slots from nodes with unknown or different shred version (backport #17899) (#19551)
* excludes epoch-slots from nodes with unknown or different shred version (#17899)

Inspecting TDS gossip table shows that crds values of nodes with
different shred-versions are creeping in. Their epoch-slots are
accumulated in ClusterSlots causing bogus slots very far from current
root which are not purged and so cause ClusterSlots keep consuming more
memory:
https://github.com/solana-labs/solana/issues/17789
https://github.com/solana-labs/solana/issues/14366#issuecomment-769896036
https://github.com/solana-labs/solana/issues/14366#issuecomment-832754654

This commit updates ClusterInfo::get_epoch_slots, and discards entries
from nodes with unknown or different shred-version.

Follow up commits will patch gossip not to waste bandwidth and memory
over crds values of nodes with different shred-version.

(cherry picked from commit 985280ec0b)

# Conflicts:
#	core/src/cluster_info.rs

* removes backport merge conflicts

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-09-01 18:50:56 +00:00
mergify[bot]
6566a0f6c8 short cuts expiration check if origin's contact-info is still valid (#17918) (#19552)
Crds::find_old_labels can skip checking values timestamps if the
origin's contact info hasn't expired yet:
https://github.com/solana-labs/solana/blob/985280ec0/gossip/src/crds.rs#L394-L408

(cherry picked from commit cca46308bc)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-09-01 18:47:40 +00:00
mergify[bot]
3606de56f7 Fix tests that make assumptions about tx fee rate (#19538) (#19543)
(cherry picked from commit 4fb43bbd90)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-09-01 05:57:30 +00:00
mergify[bot]
9a005855dc persists repair-peers cache across repair service loops (backport #18400) (#19526)
* persists repair-peers cache across repair service loops (#18400)

The repair-peers cache is reset each time repair service loop runs,
and so computed repeatedly for the same slots:
https://github.com/solana-labs/solana/blob/d2b07dca9/core/src/repair_service.rs#L275

This commit uses an LRU cache to persists repair-peers for each slot.
In addition to LRU eviction rules, in order to avoid re-using outdated
data, each entry also has 10 seconds TTL.

(cherry picked from commit a0551b4054)

# Conflicts:
#	core/src/repair_service.rs
#	core/src/serve_repair.rs

* removes backport merge conflicts

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-08-31 21:17:22 +00:00
mergify[bot]
70bdcf06b4 locks gossip only once in push_epoch_slots (backport #17355) (#19484)
* locks gossip only once in push_epoch_slots

push_epoch_slots is unlocking and locking again gossip when iterating
over epoch slot indices which is wasteful:
https://github.com/solana-labs/solana/blob/0486df02b/core/src/cluster_info.rs#L915-L929

(cherry picked from commit 9339a6f8f3)

# Conflicts:
#	core/src/cluster_info.rs

* removes redundant slots sort in push_epoch_slots

(cherry picked from commit 9471ba61c5)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-08-29 17:09:59 +00:00
mergify[bot]
f53f273585 parallelizes gossip packets receiver with processing of requests (backport #17647) (#19474)
* parallelizes gossip packets receiver with processing of requests (#17647)

Gossip packet processing is composed of two stages:
  * The first is consuming packets from the socket, deserializing,
    sanitizing and verifying them:
    https://github.com/solana-labs/solana/blob/7f0349b29/gossip/src/cluster_info.rs#L2510-L2521
  * The second is actually processing the requests/messages:
    https://github.com/solana-labs/solana/blob/7f0349b29/gossip/src/cluster_info.rs#L2585-L2605

The former does not acquire any locks and so can be parallelized with
the later, allowing better pipelineing properties and smaller latency in
responding to gossip requests or propagating messages.

(cherry picked from commit cab30e2356)

# Conflicts:
#	core/src/cluster_info.rs

* removes backport merge conflicts

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-08-27 22:13:14 +00:00
mergify[bot]
e0584b77c5 Fixing missing pubsub notification for programSubscribe and logsSubscribe (backport #19092) (#19455)
* Fixing missing pubsub notification for programSubscribe and logsSubscribe (#19092)

#18587: programSubscribe is missing notifications randomly. The issue is because of two reasons

Not all rooted slots get OptimisticallyConfirmed notifications
The OptimisticallyConfirmed notifications can be out of order for slots: slot A and B with A < B can see notification for B first before A.
Summary of Changes

Changed OptimisticallyConfirmedBankTracker to send notifications for parent banks if they have not been notified yet. We use a new variable last_notified_slot to track that.

Tests:
With my validator running against testnet, before the fix, it was failing 75% of time, with the fix, it is passing consistently. Using the program mentioned in #18587.

(cherry picked from commit 1a372a792e)

# Conflicts:
#	core/src/optimistically_confirmed_bank_tracker.rs
#	core/src/rpc_subscriptions.rs

* Fix conflicts

Co-authored-by: Lijun Wang <83639177+lijunwangs@users.noreply.github.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-08-27 01:31:51 +00:00
Tyera Eulberg
39a5431790 Bump jsonrpc crates and remove old tokio (#19454) 2021-08-26 23:53:44 +00:00
sakridge
715c5e64c4 Bump version to 1.6.23 (#19447) 2021-08-26 18:09:15 +00:00
161 changed files with 3057 additions and 2345 deletions

733
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"] }

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"

View File

@@ -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/"

View File

@@ -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]

View File

@@ -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 {
"-"

View File

@@ -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]]

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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();

View File

@@ -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]

View File

@@ -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(),

View File

@@ -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

View File

@@ -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

View File

@@ -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(

View File

@@ -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,

View File

@@ -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 }
}

View File

@@ -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);
}
}

View File

@@ -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,
) {

View File

@@ -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"}]}"#;

View File

@@ -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();

View File

@@ -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!({

View File

@@ -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,
)

View File

@@ -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");
}
}
}

View File

@@ -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 {

View File

@@ -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()

View File

@@ -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();
});

View File

@@ -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]

View File

@@ -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

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"] }

View File

@@ -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"

View File

@@ -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"

View File

@@ -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]]

View File

@@ -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"]

View File

@@ -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"

View File

@@ -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]]

View File

@@ -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"] }

View File

@@ -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"

View File

@@ -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,
});
}

View File

@@ -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"));
}
}

View File

@@ -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 {

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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]

View File

@@ -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+

View File

@@ -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"

View File

@@ -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]]

View File

@@ -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"

View File

@@ -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"

View File

@@ -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]

View File

@@ -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"]

View File

@@ -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" }

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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]]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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