Compare commits

...

79 Commits

Author SHA1 Message Date
mergify[bot]
8d5c7b7d89 hides implementation details of vote-accounts from public interface (#24087) (#24102)
(cherry picked from commit ef3e3dce7a)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2022-04-04 15:08:21 +00:00
mergify[bot]
ca1a282a60 demotes WeightedShuffle failures to error metrics (#24079) (#24088)
Since call-sites are calling unwrap anyways, panicking seems too punitive
for our use cases.

(cherry picked from commit 7cb3b6cbe2)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2022-04-03 18:10:00 +00:00
mergify[bot]
3f661f25fb improves Stakes::activate_epoch performance (#24068) (#24081)
Tested with mainnet stakes obtained from the ledger at 5 recent epoch
boundaries, this code is ~30% faster than current master.

Current code:
  epoch: 289, elapsed: 82901us
  epoch: 290, elapsed: 80525us
  epoch: 291, elapsed: 79122us
  epoch: 292, elapsed: 79961us
  epoch: 293, elapsed: 78965us

This commit:
  epoch: 289, elapsed: 61710us
  epoch: 290, elapsed: 55721us
  epoch: 291, elapsed: 55886us
  epoch: 292, elapsed: 55399us
  epoch: 293, elapsed: 56803us

(cherry picked from commit fa7eb7f30c)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2022-04-03 13:44:19 +00:00
mergify[bot]
b157a9111f Note this is a modified backport that does not SAVE the new fields, but does load them. (#24074)
Original:
Start saving/loading prior_roots(_with_hash) to snapshot (#23844)

    * Start saving/loading prior_roots(_with_hash) to snapshot

    * Update runtime/src/accounts_index.rs

    Co-authored-by: Michael Vines <mvines@gmail.com>

    * Update runtime/src/accounts_index.rs

    Co-authored-by: Michael Vines <mvines@gmail.com>

    * update comment

    Co-authored-by: Michael Vines <mvines@gmail.com>
    (cherry picked from commit 396b49a7c1)

Co-authored-by: Jeff Washington (jwash) <wash678@gmail.com>
2022-04-02 17:22:33 +00:00
mergify[bot]
f2f20af768 Fix typo in documentation (#24076) (#24077)
(cherry picked from commit 4968e7d38c)

Co-authored-by: blake <572337+bartenbach@users.noreply.github.com>
2022-04-02 13:35:39 +00:00
mergify[bot]
a8855386c1 zk-token-sdk: handle edge cases for transfer with fee (#23804) (#23818)
* zk-token-sdk: handle edge cases for transfer with fee

* zk-token-sdk: clippy

* zk-token-sdk: clippy

* zk-token-sdk: cargo fmt

(cherry picked from commit 10eeafd3d6)

Co-authored-by: samkim-crypto <skim13@cs.stanford.edu>
2022-04-01 20:02:10 -04:00
mergify[bot]
6048b71640 Revert voting service to use UDP instead of QUIC (backport #24032) (#24052)
* Revert voting service to use UDP instead of QUIC (#24032)

(cherry picked from commit df4d92f9cf)

# Conflicts:
#	core/src/voting_service.rs

* resolve merge conflicts

Co-authored-by: Pankaj Garg <pankaj@solana.com>
2022-04-01 18:52:27 +00:00
mergify[bot]
4a4a1db836 expands lifetime of SlotStats (#23872) (#24002)
Current slot stats are removed when the slot is full or every 30 seconds
if the slot is before root:
https://github.com/solana-labs/solana/blob/493a8e234/ledger/src/blockstore.rs#L2017-L2027

In order to track if the slot is ultimately marked as dead or rooted and
emit more metrics, this commit expands lifetime of SlotStats while
bounding total size of cache using an LRU eviction policy.

(cherry picked from commit 1f9c89c1e8)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2022-04-01 14:50:12 +00:00
mergify[bot]
c7889f8def uses first_coding_index for erasure meta obtained from coding shreds (#23974) (#24001)
Now that nodes correctly populate position field in coding shreds, and
first_coding_index in erasure meta, the old code to maintain backward
compatibility can be removed.
The commit is working towards changing erasure coding schema to 32:64.

(cherry picked from commit cda3d66b21)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2022-04-01 14:49:39 +00:00
Michael Vines
832f524687 Update Version CrdsData on node identity changes
(cherry picked from commit 7ef18f220a)
2022-03-28 19:57:48 -07:00
Will Hickey
a639282c0f Bump version to 1.10.6 (#23969) 2022-03-28 10:56:01 -05:00
mergify[bot]
5eb085fcaf Implement forwarding via TpuConnection (#23817) (#23936)
(cherry picked from commit 6b85c2104c)

Co-authored-by: ryleung-solana <91908731+ryleung-solana@users.noreply.github.com>
2022-03-28 16:38:44 +02:00
mergify[bot]
c66d086db1 fix: thread enforce_ulimit_nofile config down when opening blockstore (#23925) (#23958)
(cherry picked from commit f44c8f296f)

Co-authored-by: Steven Luscher <steveluscher@users.noreply.github.com>
2022-03-26 20:09:49 +00:00
mergify[bot]
0c740ebba6 Specify if archive size datapoint is for full or incremental snapshots (#23941) (#23957)
(cherry picked from commit 31b707b625)

Co-authored-by: Brooks Prumo <brooks@solana.com>
2022-03-26 19:25:39 +00:00
Will Hickey
fd49ed1959 Bump version to 1.10.5 (#23955) 2022-03-26 11:34:12 -05:00
Michael Vines
df9f4193af improve arg documentation 2022-03-25 21:37:35 -07:00
Trent Nelson
be99d1d55d cli: allow skipping fee-checks when writing program buffers (hidden) 2022-03-25 18:17:15 -06:00
mergify[bot]
22af384700 Add get_confirmed_blocks_with_data method (backport #23618) (#23940)
* add get_confirmed_blocks_with_data and get_protobuf_or_bincode_cells

(cherry picked from commit f3219fb695)

* appease clippy

(cherry picked from commit 5533e9393c)

* use &[T] instead of Vec<T> where appropriate

clippy

(cherry picked from commit fbcf6a0802)

* modify get_protobuf_or_bincode_cells to accept and return an iterator

(cherry picked from commit f717fda9a3)

* make get_protobuf_or_bincode_cells accept IntoIter on row_keys, make get_confirmed_blocks_with_data return an Iterator

(cherry picked from commit d8be0d9430)

Co-authored-by: Edgar Xi <edgarxi97@gmail.com>
2022-03-25 22:45:01 +00:00
mergify[bot]
30059510cc Add solana-faucet to the list of dependencies referenced by downstream projects (#23935) (#23938)
(cherry picked from commit c6dda3b324)

Co-authored-by: Will Hickey <will.hickey@solana.com>
2022-03-25 13:36:29 -05:00
mergify[bot]
c0d3cd145e Optimize TpuConnection and its implementations and refactor connection-cache to not use dyn in order to enable those changes (#23877) (#23909)
Co-authored-by: ryleung-solana <91908731+ryleung-solana@users.noreply.github.com>
2022-03-25 19:09:26 +01:00
mergify[bot]
af79a86a72 ci: don't allow mergify to add automerge label to merged PRs (#23931)
(cherry picked from commit e34c52934c)

Co-authored-by: Trent Nelson <trent@solana.com>
2022-03-25 16:20:09 +00:00
Michael Vines
86acc8c59b vote-authorize-voter now accepts either the vote or withdraw authority
(cherry picked from commit c8c3c4359f)
2022-03-25 08:37:44 -07:00
mergify[bot]
8222f3a675 Update TpuConnection interface to be compatible with versioned txs (#23760) (#23913)
* Update TpuConnection interface to be compatible with versioned txs

* Add convenience method for sending txs

* use parallel iterator to serialize transactions

(cherry picked from commit 016d3c450a)

Co-authored-by: Justin Starry <justin@solana.com>
2022-03-24 22:09:34 +00:00
mergify[bot]
d135e3b839 Use QUIC client in voting service (#23713) (#23813)
* Use QUIC client in voting service

* guard quic-client usage with a flag

* add measure to time the quic client

* move time measure outside if block

* remove quic vs UDP flag from voting service

(cherry picked from commit 5d03b188c8)

Co-authored-by: Pankaj Garg <pankaj@solana.com>
2022-03-24 22:03:33 +00:00
Lijun Wang
821261a2d1 Use connection cache in send transaction (#23712) (#23900)
Use connection cache in send transaction (#23712)
2022-03-24 13:24:57 -07:00
mergify[bot]
f0c5962817 disable 'check_hash' on accounts hash calc (#23873) (#23902)
(cherry picked from commit 5a892af2fe)

Co-authored-by: Jeff Washington (jwash) <wash678@gmail.com>
2022-03-24 18:33:50 +00:00
mergify[bot]
1b930a1485 Make find_program_address client example runnable (#23492) (#23901)
(cherry picked from commit 6428602cd9)

Co-authored-by: Brian Anderson <andersrb@gmail.com>
2022-03-24 15:00:32 +00:00
mergify[bot]
2ed9655958 Set accounts_data_len on feature activation (#23730) (#23810)
(cherry picked from commit cb06126388)

Co-authored-by: Brooks Prumo <brooks@solana.com>
2022-03-21 21:50:31 +00:00
mergify[bot]
c63782f833 Made connection cache configurable. (#23783) (#23812)
Added command-line argument tpu-use-quic argument.
Changed connection cache to return different connections based on the config.

(cherry picked from commit ae76fe2bd7)

Co-authored-by: Lijun Wang <83639177+lijunwangs@users.noreply.github.com>
2022-03-21 21:42:53 +00:00
mergify[bot]
258f752e5d Add ability to get the latest incremental snapshot via RPC (#23788) (#23809)
(cherry picked from commit 739e43ba58)

Co-authored-by: DimAn <diman@diman.io>
2022-03-21 20:19:30 +00:00
Justin Starry
15357480ec Refactor instruction compilation and update message account key ordering (#23729)
* Refactor: Make instruction compilation usable for other message versions

* apply trents feedback

* Fix tests

* Fix bpf compatiblity
2022-03-21 20:53:32 +08:00
axleiro
a1a29b0b86 Increased timeout limit of coverage and stable-perf by 10 mins each (#23797)
* Increased timeout limit of coverage and stable-perf by 10 mins each

* Increasing timeout for in disk CI by 10 min
2022-03-21 15:08:23 +05:30
Jeff Washington (jwash)
258db77100 AcctIdx: factor 'scan' out of flush_internal (#23777) 2022-03-20 22:00:38 -05:00
carllin
f34434f96b Drop lock (#23765) 2022-03-20 21:27:24 -04:00
Jeff Washington (jwash)
dd69f3baf5 throttle index adding to allow disk flushing to keep up and reduce startup ram usage (#23773) 2022-03-20 19:56:20 -05:00
Brooks Prumo
335c4b668b Fix bug in bank/sysvar_cache tests (#23780) 2022-03-19 21:38:18 -05:00
Ikko Ashimine
848093b9fd Fix typo in processor.rs (#23786)
relavant -> relevant
2022-03-19 15:24:40 -05:00
Jeff Washington (jwash)
df29276eb0 AcctIdx: remove -> evict (#23775) 2022-03-18 17:13:21 -05:00
Tao Zhu
71ea05c176 replace nested for_each with flat_map 2022-03-18 16:37:41 -05:00
Tao Zhu
1c369fb55f Scan entire UnprocessedPacketBatches buffer to produce stake and locator of each packet 2022-03-18 16:37:41 -05:00
Jack May
1f052c6234 disable deprecated BPF loader deploys (#23757) 2022-03-18 14:29:49 -07:00
Jack May
7e358c654f add test to assert type assumption (#23769) 2022-03-18 14:15:59 -07:00
g1stavo
c556811c0f docs: fix stake state typo (#23776) 2022-03-18 13:45:07 -06:00
Jeff Washington (jwash)
a419374fa4 factor out function (#23742) 2022-03-18 14:10:52 -05:00
Jack May
0e64fb1fab don't rely on align_offset to check alignment (#23770) 2022-03-18 11:30:52 -07:00
Brian Anderson
fcea92ec6c Improve correctness of Rust-side type definitions for C invoke syscall (#23624)
* Make Rust definitions of C types repr(C)

* Make SolInstruction field types agree with C definitions

* Use correct SolSignerSeedsC type in SyscallInvokeSignedC

* rustfmt

* Change asserts to debug asserts in syscall.rs
2022-03-18 11:30:30 -07:00
Yueh-Hsuan Chiang
f999eef452 (LedgerStore) Rename BlockstoreAdvancedOptions to LedgerColumnOptions (#23764)
This PR renames BlockstoreAdvancedOptions to LedgerColumnOptions, as we will
pass-down this struct to LedgerColumn to allow it to perform metric reporting.
2022-03-18 11:13:35 -07:00
Tao Zhu
56428be629 Not exposing inner cost_table to encapsulating implementation details,
making future change easier.
2022-03-18 12:58:43 -05:00
dependabot[bot]
00ddf6576c chore: bump crossbeam-channel from 0.5.2 to 0.5.3 (#23698)
* chore: bump crossbeam-channel from 0.5.2 to 0.5.3

Bumps [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) from 0.5.2 to 0.5.3.
- [Release notes](https://github.com/crossbeam-rs/crossbeam/releases)
- [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-channel-0.5.2...crossbeam-channel-0.5.3)

---
updated-dependencies:
- dependency-name: crossbeam-channel
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* [auto-commit] Update all Cargo lock files

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot-buildkite <you@example.com>
2022-03-18 11:44:33 -06:00
Jeff Washington (jwash)
998e7d18f9 AcctIdx: never retry a bucket flush (#23732) 2022-03-18 12:20:42 -05:00
Brian Anderson
c9b8977226 Add crate docs for solana-program (#23363)
* Add crate docs for solana-program

* Rework solana-program docs for pr feedback

* Clarify log module docs

* Remove address lookup table program from solana-program docs
2022-03-18 08:27:51 -07:00
HaoranYi
f54e746fc5 Support u8 slice digester in frozen abi struct. (#23726)
* support u8 slice in frozen abi digester

* use slice in account struct

* add bpf cargo lock file

* no need to pass account.data to serializer

* fix comments
2022-03-18 09:31:07 -05:00
Kirill Lykov
c694703e14 address PR comments 2022-03-18 14:55:33 +01:00
Kirill Lykov
2da896fa40 add documentation 2022-03-18 14:55:33 +01:00
Kirill Lykov
7074ebf45a address PR comments 2022-03-18 14:55:33 +01:00
klykov
957bc0db6b add tests to dos tool 2022-03-18 14:55:33 +01:00
klykov
d9dbfc83d5 upd Cargo.lock 2022-03-18 14:55:33 +01:00
klykov
f5339882cb refactor cmdline interface 2022-03-18 14:55:33 +01:00
klykov
a63dee87ec add transaction parameters dump 2022-03-18 14:55:33 +01:00
klykov
1b0c9ad4c0 add option payer to dos tool 2022-03-18 14:55:33 +01:00
klykov
cf73f6dc74 fix typo in dos 2022-03-18 14:55:33 +01:00
klykov
dce5d1c1fa avoid signatures if unnecessary in dos 2022-03-18 14:55:33 +01:00
klykov
1641d1d329 fix: cache blockhash in dos tool 2022-03-18 14:55:33 +01:00
klykov
cb537e80d7 add transaction options to dos 2022-03-18 14:55:33 +01:00
klykov
d4d95f1811 add valid blockhash option to dos 2022-03-18 14:55:33 +01:00
klykov
797c3324f0 add number of signatures to dos 2022-03-18 14:55:33 +01:00
Tao Zhu
0ed23899e7 directly use compute_budget MAX_UNITS and DEFAULT_UNITS 2022-03-18 08:53:11 -05:00
Tao Zhu
a4cacf3389 add deterministic default cost 2022-03-18 08:53:11 -05:00
Trent Nelson
ce2e82cfb6 validator: --only-known-rpc requires a --known-validator ... 2022-03-18 07:02:16 +00:00
Jeff Washington (jwash)
857576d76f AcctIdx: move write to disk outside in mem write lock (#23731) 2022-03-17 23:09:41 -05:00
Brooks Prumo
7ff8c80e25 Add accounts_data_len to bank snapshot (#23714) 2022-03-17 20:14:54 -05:00
Tao Zhu
c478fe2047 add timing metrics, some renaming 2022-03-17 19:31:28 -05:00
Tao Zhu
fd515097d8 leader qos part 2: add stage to find sender stake, set to packet meta 2022-03-17 19:31:28 -05:00
Stephen Akridge
976b138e76 Add tx weighting stage 2022-03-17 19:31:28 -05:00
Jeff Washington (jwash)
664deb2157 AcctIdx: get rid of unused is_dirty (#23733) 2022-03-17 16:29:36 -05:00
Lijun Wang
8b230b86cc Use borrow instead of move in interfaces defined by TpuConnection (#23734)
* Use borrow instead of move in interfaces defined by TpuConnection to avoid data copy

* Removed a few more unnecessary whole array slicing.
2022-03-17 13:31:11 -07:00
behzad nouri
6b0d34d70d removes redundant Arcs from Blockstore (#23735) 2022-03-17 19:43:57 +00:00
Jeff Washington (jwash)
342f1ab1cb clean up/add comments (#23727) 2022-03-17 14:23:08 -05:00
Will Hickey
2f58c9e501 Bump version to 1.10.4 (#23743) 2022-03-17 14:02:13 -05:00
243 changed files with 5739 additions and 3250 deletions

View File

@@ -93,6 +93,7 @@ pull_request_rules:
- author=mergify[bot]
- head~=^mergify/bp/
- "#status-failure=0"
- "-merged"
actions:
label:
add:

365
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.10.3"
version = "1.10.6"
description = "Solana account decoder"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -19,9 +19,9 @@ lazy_static = "1.4.0"
serde = "1.0.136"
serde_derive = "1.0.103"
serde_json = "1.0.79"
solana-config-program = { path = "../programs/config", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-config-program = { path = "../programs/config", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
spl-token = { version = "=3.2.0", features = ["no-entrypoint"] }
thiserror = "1.0"
zstd = "0.11.1"

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-accounts-bench"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -12,11 +12,11 @@ publish = false
clap = "2.33.1"
log = "0.4.14"
rayon = "1.5.1"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-accounts-cluster-bench"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -13,25 +13,25 @@ clap = "2.33.1"
log = "0.4.14"
rand = "0.7.0"
rayon = "1.5.1"
solana-account-decoder = { path = "../account-decoder", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-client = { path = "../client", version = "=1.10.3" }
solana-faucet = { path = "../faucet", version = "=1.10.3" }
solana-gossip = { path = "../gossip", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-net-utils = { path = "../net-utils", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-account-decoder = { path = "../account-decoder", version = "=1.10.6" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-client = { path = "../client", version = "=1.10.6" }
solana-faucet = { path = "../faucet", version = "=1.10.6" }
solana-gossip = { path = "../gossip", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-net-utils = { path = "../net-utils", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
spl-token = { version = "=3.2.0", features = ["no-entrypoint"] }
[dev-dependencies]
solana-core = { path = "../core", version = "=1.10.3" }
solana-local-cluster = { path = "../local-cluster", version = "=1.10.3" }
solana-test-validator = { path = "../test-validator", version = "=1.10.3" }
solana-core = { path = "../core", version = "=1.10.6" }
solana-local-cluster = { path = "../local-cluster", version = "=1.10.6" }
solana-test-validator = { path = "../test-validator", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-banking-bench"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -14,17 +14,17 @@ crossbeam-channel = "0.5"
log = "0.4.14"
rand = "0.7.0"
rayon = "1.5.1"
solana-core = { path = "../core", version = "=1.10.3" }
solana-gossip = { path = "../gossip", version = "=1.10.3" }
solana-ledger = { path = "../ledger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-poh = { path = "../poh", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-core = { path = "../core", version = "=1.10.6" }
solana-gossip = { path = "../gossip", version = "=1.10.6" }
solana-ledger = { path = "../ledger", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-perf = { path = "../perf", version = "=1.10.6" }
solana-poh = { path = "../poh", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-banks-client"
version = "1.10.3"
version = "1.10.6"
description = "Solana banks client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -12,17 +12,17 @@ edition = "2021"
[dependencies]
borsh = "0.9.3"
futures = "0.3"
solana-banks-interface = { path = "../banks-interface", version = "=1.10.3" }
solana-program = { path = "../sdk/program", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-banks-interface = { path = "../banks-interface", version = "=1.10.6" }
solana-program = { path = "../sdk/program", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
tarpc = { version = "0.27.2", features = ["full"] }
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }
tokio-serde = { version = "0.8", features = ["bincode"] }
[dev-dependencies]
solana-banks-server = { path = "../banks-server", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-banks-server = { path = "../banks-server", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
[lib]
crate-type = ["lib"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-banks-interface"
version = "1.10.3"
version = "1.10.6"
description = "Solana banks RPC interface"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -11,7 +11,7 @@ edition = "2021"
[dependencies]
serde = { version = "1.0.136", features = ["derive"] }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
tarpc = { version = "0.27.2", features = ["full"] }
[lib]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-banks-server"
version = "1.10.3"
version = "1.10.6"
description = "Solana banks server"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -13,10 +13,10 @@ edition = "2021"
bincode = "1.3.3"
crossbeam-channel = "0.5"
futures = "0.3"
solana-banks-interface = { path = "../banks-interface", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-send-transaction-service = { path = "../send-transaction-service", version = "=1.10.3" }
solana-banks-interface = { path = "../banks-interface", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-send-transaction-service = { path = "../send-transaction-service", version = "=1.10.6" }
tarpc = { version = "0.27.2", features = ["full"] }
tokio = { version = "1", features = ["full"] }
tokio-serde = { version = "0.8", features = ["bincode"] }

View File

@@ -24,7 +24,7 @@ use {
transaction::{self, SanitizedTransaction, Transaction},
},
solana_send_transaction_service::{
send_transaction_service::{SendTransactionService, TransactionInfo},
send_transaction_service::{SendTransactionService, TransactionInfo, DEFAULT_TPU_USE_QUIC},
tpu_info::NullTpuInfo,
},
std::{
@@ -399,6 +399,7 @@ pub async fn start_tcp_server(
receiver,
5_000,
0,
DEFAULT_TPU_USE_QUIC,
);
let server = BanksServer::new(

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-bench-streamer"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -11,9 +11,9 @@ publish = false
[dependencies]
clap = "2.33.1"
crossbeam-channel = "0.5"
solana-net-utils = { path = "../net-utils", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-net-utils = { path = "../net-utils", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-bench-tps"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -15,23 +15,23 @@ log = "0.4.14"
rayon = "1.5.1"
serde_json = "1.0.79"
serde_yaml = "0.8.23"
solana-client = { path = "../client", version = "=1.10.3" }
solana-core = { path = "../core", version = "=1.10.3" }
solana-faucet = { path = "../faucet", version = "=1.10.3" }
solana-genesis = { path = "../genesis", version = "=1.10.3" }
solana-gossip = { path = "../gossip", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-net-utils = { path = "../net-utils", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-client = { path = "../client", version = "=1.10.6" }
solana-core = { path = "../core", version = "=1.10.6" }
solana-faucet = { path = "../faucet", version = "=1.10.6" }
solana-genesis = { path = "../genesis", version = "=1.10.6" }
solana-gossip = { path = "../gossip", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-net-utils = { path = "../net-utils", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
[dev-dependencies]
serial_test = "0.6.0"
solana-local-cluster = { path = "../local-cluster", version = "=1.10.3" }
solana-local-cluster = { path = "../local-cluster", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-bloom"
version = "1.10.3"
version = "1.10.6"
description = "Solana bloom filter"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -17,9 +17,9 @@ rand = "0.7.0"
rayon = "1.5.1"
serde = { version = "1.0.136", features = ["rc"] }
serde_derive = "1.0.103"
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.3" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.6" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
[lib]
crate-type = ["lib"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-bucket-map"
version = "1.10.3"
version = "1.10.6"
description = "solana-bucket-map"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-bucket-map"
@@ -15,14 +15,14 @@ log = { version = "0.4.11" }
memmap2 = "0.5.3"
modular-bitfield = "0.11.2"
rand = "0.7.0"
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
tempfile = "3.3.0"
[dev-dependencies]
fs_extra = "1.2.0"
rayon = "1.5.0"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[lib]
crate-type = ["lib"]

View File

@@ -137,7 +137,7 @@ all_test_steps() {
^ci/test-coverage.sh \
^scripts/coverage.sh \
; then
command_step coverage ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-coverage.sh" 40
command_step coverage ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-coverage.sh" 50
wait_step
else
annotate --style info --context test-coverage \
@@ -152,14 +152,14 @@ all_test_steps() {
^ci/test-coverage.sh \
^scripts/coverage-in-disk.sh \
; then
command_step coverage-in-disk ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-coverage.sh" 40
command_step coverage-in-disk ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-coverage.sh" 50
wait_step
else
annotate --style info --context test-coverage \
"Coverage skipped as no .rs files were modified"
fi
# Full test suite
command_step stable ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-stable.sh" 60
command_step stable ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-stable.sh" 70
wait_step
# BPF test suite

View File

@@ -139,7 +139,7 @@ all_test_steps() {
^ci/test-coverage.sh \
^scripts/coverage.sh \
; then
command_step coverage ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-coverage.sh" 40
command_step coverage ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-coverage.sh" 50
wait_step
else
annotate --style info --context test-coverage \
@@ -147,7 +147,7 @@ all_test_steps() {
fi
# Full test suite
command_step stable ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-stable.sh" 60
command_step stable ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-stable.sh" 70
wait_step
# BPF test suite

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-clap-utils"
version = "1.10.3"
version = "1.10.6"
description = "Solana utilities for the clap"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -13,9 +13,9 @@ edition = "2021"
chrono = "0.4"
clap = "2.33.0"
rpassword = "6.0"
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.3", default-features = false }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.6" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.6", default-features = false }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
thiserror = "1.0.30"
tiny-bip39 = "0.8.2"
uriparse = "0.6.3"

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-cli-config"
description = "Blockchain, Rebuilt for Scale"
version = "1.10.3"
version = "1.10.6"
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 = "2021"
name = "solana-cli-output"
description = "Blockchain, Rebuilt for Scale"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -19,12 +19,12 @@ humantime = "2.0.1"
indicatif = "0.16.2"
serde = "1.0.136"
serde_json = "1.0.79"
solana-account-decoder = { path = "../account-decoder", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-client = { path = "../client", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-account-decoder = { path = "../account-decoder", version = "=1.10.6" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-client = { path = "../client", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
[dev-dependencies]

View File

@@ -2776,10 +2776,10 @@ mod tests {
let expected_msg = "AwECBwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDgTl3Dqh9\
F19Wo1Rmw0x+zMuNipG07jeiXfYPW4/Js5QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE\
BAQEBAYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBQUFBQUFBQUFBQUFBQUFBQUF\
BQUFBQUFBQUFBQUFBQUGp9UXGSxWjuCKhF9z0peIzwNcMUWyGrNE2AYuqUAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcH\
BwcCBgMDBQIEBAAAAAYCAQQMAgAAACoAAAAAAAAA"
BAQEBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBgYGBgYGBgYGBgYGBgYGBgYG\
BgYGBgYGBgYGBgYGBgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAan1RcZLFaO\
4IqEX3PSl4jPA1wxRbIas0TYBi6pQAAABwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcH\
BwcCBQMEBgIEBAAAAAUCAQMMAgAAACoAAAAAAAAA"
.to_string();
let config = ReturnSignersConfig {
dump_transaction_message: true,

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-cli"
description = "Blockchain, Rebuilt for Scale"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -27,29 +27,29 @@ semver = "1.0.6"
serde = "1.0.136"
serde_derive = "1.0.103"
serde_json = "1.0.79"
solana-account-decoder = { path = "../account-decoder", version = "=1.10.3" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-cli-config = { path = "../cli-config", version = "=1.10.3" }
solana-cli-output = { path = "../cli-output", version = "=1.10.3" }
solana-client = { path = "../client", version = "=1.10.3" }
solana-config-program = { path = "../programs/config", version = "=1.10.3" }
solana-faucet = { path = "../faucet", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.3" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-account-decoder = { path = "../account-decoder", version = "=1.10.6" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.10.6" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-cli-config = { path = "../cli-config", version = "=1.10.6" }
solana-cli-output = { path = "../cli-output", version = "=1.10.6" }
solana-client = { path = "../client", version = "=1.10.6" }
solana-config-program = { path = "../programs/config", version = "=1.10.6" }
solana-faucet = { path = "../faucet", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.6" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
solana_rbpf = "=0.2.24"
spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
thiserror = "1.0.30"
tiny-bip39 = "0.8.2"
[dev-dependencies]
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-test-validator = { path = "../test-validator", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-test-validator = { path = "../test-validator", version = "=1.10.6" }
tempfile = "3.3.0"
[[bin]]

View File

@@ -162,6 +162,7 @@ pub enum CliCommand {
address: Option<SignerIndex>,
use_deprecated_loader: bool,
allow_excessive_balance: bool,
skip_fee_check: bool,
},
Program(ProgramCliCommand),
// Stake Commands
@@ -744,6 +745,7 @@ pub fn parse_command(
signers.push(signer);
1
});
let skip_fee_check = matches.is_present("skip_fee_check");
Ok(CliCommandInfo {
command: CliCommand::Deploy {
@@ -751,6 +753,7 @@ pub fn parse_command(
address,
use_deprecated_loader: matches.is_present("use_deprecated_loader"),
allow_excessive_balance: matches.is_present("allow_excessive_balance"),
skip_fee_check,
},
signers,
})
@@ -1129,6 +1132,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
address,
use_deprecated_loader,
allow_excessive_balance,
skip_fee_check,
} => process_deploy(
rpc_client,
config,
@@ -1136,6 +1140,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
*address,
*use_deprecated_loader,
*allow_excessive_balance,
*skip_fee_check,
),
CliCommand::Program(program_subcommand) => {
process_program_subcommand(rpc_client, config, program_subcommand)
@@ -1967,6 +1972,7 @@ mod tests {
address: None,
use_deprecated_loader: false,
allow_excessive_balance: false,
skip_fee_check: false,
},
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
@@ -1989,6 +1995,7 @@ mod tests {
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: false,
skip_fee_check: false,
},
signers: vec![
read_keypair_file(&keypair_file).unwrap().into(),
@@ -2382,6 +2389,7 @@ mod tests {
address: None,
use_deprecated_loader: false,
allow_excessive_balance: false,
skip_fee_check: false,
};
config.output_format = OutputFormat::JsonCompact;
let result = process_command(&config);
@@ -2402,6 +2410,7 @@ mod tests {
address: None,
use_deprecated_loader: false,
allow_excessive_balance: false,
skip_fee_check: false,
};
assert!(process_command(&config).is_err());
}

View File

@@ -33,7 +33,7 @@ use {
rpc_request::DELINQUENT_VALIDATOR_SLOT_DISTANCE,
rpc_response::SlotInfo,
},
solana_program_runtime::compute_budget::ComputeBudget,
solana_program_runtime::compute_budget,
solana_remote_wallet::remote_wallet::RemoteWalletManager,
solana_sdk::{
account::from_account,
@@ -1409,7 +1409,7 @@ pub fn process_ping(
)];
if let Some(additional_fee) = additional_fee {
ixs.push(ComputeBudgetInstruction::request_units(
ComputeBudget::new(false).max_units as u32,
compute_budget::DEFAULT_UNITS,
*additional_fee,
));
}

View File

@@ -66,6 +66,7 @@ pub enum ProgramCliCommand {
is_final: bool,
max_len: Option<usize>,
allow_excessive_balance: bool,
skip_fee_check: bool,
},
WriteBuffer {
program_location: String,
@@ -73,6 +74,7 @@ pub enum ProgramCliCommand {
buffer_pubkey: Option<Pubkey>,
buffer_authority_signer_index: Option<SignerIndex>,
max_len: Option<usize>,
skip_fee_check: bool,
},
SetBufferAuthority {
buffer_pubkey: Pubkey,
@@ -114,6 +116,13 @@ impl ProgramSubCommands for App<'_, '_> {
SubCommand::with_name("program")
.about("Program management")
.setting(AppSettings::SubcommandRequiredElseHelp)
.arg(
Arg::with_name("skip_fee_check")
.long("skip-fee-check")
.hidden(true)
.takes_value(false)
.global(true)
)
.subcommand(
SubCommand::with_name("deploy")
.about("Deploy a program")
@@ -406,6 +415,12 @@ impl ProgramSubCommands for App<'_, '_> {
.long("allow-excessive-deploy-account-balance")
.takes_value(false)
.help("Use the designated program id, even if the account already holds a large balance of SOL")
)
.arg(
Arg::with_name("skip_fee_check")
.long("skip-fee-check")
.hidden(true)
.takes_value(false)
),
)
}
@@ -416,7 +431,14 @@ pub fn parse_program_subcommand(
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let response = match matches.subcommand() {
let (subcommand, sub_matches) = matches.subcommand();
let matches_skip_fee_check = matches.is_present("skip_fee_check");
let sub_matches_skip_fee_check = sub_matches
.map(|m| m.is_present("skip_fee_check"))
.unwrap_or(false);
let skip_fee_check = matches_skip_fee_check || sub_matches_skip_fee_check;
let response = match (subcommand, sub_matches) {
("deploy", Some(matches)) => {
let mut bulk_signers = vec![Some(
default_signer.signer_from_path(matches, wallet_manager)?,
@@ -476,6 +498,7 @@ pub fn parse_program_subcommand(
is_final: matches.is_present("final"),
max_len,
allow_excessive_balance: matches.is_present("allow_excessive_balance"),
skip_fee_check,
}),
signers: signer_info.signers,
}
@@ -521,6 +544,7 @@ pub fn parse_program_subcommand(
buffer_authority_signer_index: signer_info
.index_of_or_none(buffer_authority_pubkey),
max_len,
skip_fee_check,
}),
signers: signer_info.signers,
}
@@ -669,6 +693,7 @@ pub fn process_program_subcommand(
is_final,
max_len,
allow_excessive_balance,
skip_fee_check,
} => process_program_deploy(
rpc_client,
config,
@@ -681,6 +706,7 @@ pub fn process_program_subcommand(
*is_final,
*max_len,
*allow_excessive_balance,
*skip_fee_check,
),
ProgramCliCommand::WriteBuffer {
program_location,
@@ -688,6 +714,7 @@ pub fn process_program_subcommand(
buffer_pubkey,
buffer_authority_signer_index,
max_len,
skip_fee_check,
} => process_write_buffer(
rpc_client,
config,
@@ -696,6 +723,7 @@ pub fn process_program_subcommand(
*buffer_pubkey,
*buffer_authority_signer_index,
*max_len,
*skip_fee_check,
),
ProgramCliCommand::SetBufferAuthority {
buffer_pubkey,
@@ -793,6 +821,7 @@ fn process_program_deploy(
is_final: bool,
max_len: Option<usize>,
allow_excessive_balance: bool,
skip_fee_check: bool,
) -> ProcessResult {
let (words, mnemonic, buffer_keypair) = create_ephemeral_keypair()?;
let (buffer_provided, buffer_signer, buffer_pubkey) = if let Some(i) = buffer_signer_index {
@@ -947,6 +976,7 @@ fn process_program_deploy(
&buffer_pubkey,
Some(upgrade_authority_signer),
allow_excessive_balance,
skip_fee_check,
)
} else {
do_process_program_upgrade(
@@ -957,6 +987,7 @@ fn process_program_deploy(
config.signers[upgrade_authority_signer_index],
&buffer_pubkey,
buffer_signer,
skip_fee_check,
)
};
if result.is_ok() && is_final {
@@ -983,6 +1014,7 @@ fn process_write_buffer(
buffer_pubkey: Option<Pubkey>,
buffer_authority_signer_index: Option<SignerIndex>,
max_len: Option<usize>,
skip_fee_check: bool,
) -> ProcessResult {
// Create ephemeral keypair to use for Buffer account, if not provided
let (words, mnemonic, buffer_keypair) = create_ephemeral_keypair()?;
@@ -1050,6 +1082,7 @@ fn process_write_buffer(
&buffer_pubkey,
Some(buffer_authority),
true,
skip_fee_check,
);
if result.is_err() && buffer_signer_index.is_none() && buffer_signer.is_some() {
@@ -1636,6 +1669,7 @@ pub fn process_deploy(
buffer_signer_index: Option<SignerIndex>,
use_deprecated_loader: bool,
allow_excessive_balance: bool,
skip_fee_check: bool,
) -> ProcessResult {
// Create ephemeral keypair to use for Buffer account, if not provided
let (words, mnemonic, buffer_keypair) = create_ephemeral_keypair()?;
@@ -1666,6 +1700,7 @@ pub fn process_deploy(
&buffer_signer.pubkey(),
Some(buffer_signer),
allow_excessive_balance,
skip_fee_check,
);
if result.is_err() && buffer_signer_index.is_none() {
report_ephemeral_mnemonic(words, mnemonic);
@@ -1704,6 +1739,7 @@ fn do_process_program_write_and_deploy(
buffer_pubkey: &Pubkey,
buffer_authority_signer: Option<&dyn Signer>,
allow_excessive_balance: bool,
skip_fee_check: bool,
) -> ProcessResult {
// Build messages to calculate fees
let mut messages: Vec<&Message> = Vec::new();
@@ -1834,7 +1870,9 @@ fn do_process_program_write_and_deploy(
messages.push(message);
}
check_payer(&rpc_client, config, balance_needed, &messages)?;
if !skip_fee_check {
check_payer(&rpc_client, config, balance_needed, &messages)?;
}
send_deploy_messages(
rpc_client,
@@ -1868,6 +1906,7 @@ fn do_process_program_upgrade(
upgrade_authority: &dyn Signer,
buffer_pubkey: &Pubkey,
buffer_signer: Option<&dyn Signer>,
skip_fee_check: bool,
) -> ProcessResult {
let loader_id = bpf_loader_upgradeable::id();
let data_len = program_data.len();
@@ -1967,7 +2006,10 @@ fn do_process_program_upgrade(
);
messages.push(&final_message);
check_payer(&rpc_client, config, balance_needed, &messages)?;
if !skip_fee_check {
check_payer(&rpc_client, config, balance_needed, &messages)?;
}
send_deploy_messages(
rpc_client,
config,
@@ -2255,6 +2297,7 @@ mod tests {
is_final: false,
max_len: None,
allow_excessive_balance: false,
skip_fee_check: false,
}),
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
@@ -2281,6 +2324,7 @@ mod tests {
is_final: false,
max_len: Some(42),
allow_excessive_balance: false,
skip_fee_check: false,
}),
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
@@ -2309,6 +2353,7 @@ mod tests {
is_final: false,
max_len: None,
allow_excessive_balance: false,
skip_fee_check: false,
}),
signers: vec![
read_keypair_file(&keypair_file).unwrap().into(),
@@ -2339,6 +2384,7 @@ mod tests {
is_final: false,
max_len: None,
allow_excessive_balance: false,
skip_fee_check: false,
}),
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
@@ -2368,6 +2414,7 @@ mod tests {
is_final: false,
max_len: None,
allow_excessive_balance: false,
skip_fee_check: false,
}),
signers: vec![
read_keypair_file(&keypair_file).unwrap().into(),
@@ -2400,6 +2447,7 @@ mod tests {
is_final: false,
max_len: None,
allow_excessive_balance: false,
skip_fee_check: false,
}),
signers: vec![
read_keypair_file(&keypair_file).unwrap().into(),
@@ -2427,6 +2475,7 @@ mod tests {
upgrade_authority_signer_index: 0,
is_final: true,
max_len: None,
skip_fee_check: false,
allow_excessive_balance: false,
}),
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
@@ -2460,6 +2509,7 @@ mod tests {
buffer_pubkey: None,
buffer_authority_signer_index: Some(0),
max_len: None,
skip_fee_check: false,
}),
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
@@ -2483,6 +2533,7 @@ mod tests {
buffer_pubkey: None,
buffer_authority_signer_index: Some(0),
max_len: Some(42),
skip_fee_check: false,
}),
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
@@ -2509,6 +2560,7 @@ mod tests {
buffer_pubkey: Some(buffer_keypair.pubkey()),
buffer_authority_signer_index: Some(0),
max_len: None,
skip_fee_check: false,
}),
signers: vec![
read_keypair_file(&keypair_file).unwrap().into(),
@@ -2538,6 +2590,7 @@ mod tests {
buffer_pubkey: None,
buffer_authority_signer_index: Some(1),
max_len: None,
skip_fee_check: false,
}),
signers: vec![
read_keypair_file(&keypair_file).unwrap().into(),
@@ -2572,6 +2625,7 @@ mod tests {
buffer_pubkey: Some(buffer_keypair.pubkey()),
buffer_authority_signer_index: Some(2),
max_len: None,
skip_fee_check: false,
}),
signers: vec![
read_keypair_file(&keypair_file).unwrap().into(),
@@ -3014,6 +3068,7 @@ mod tests {
is_final: false,
max_len: None,
allow_excessive_balance: false,
skip_fee_check: false,
}),
signers: vec![&default_keypair],
output_format: OutputFormat::JsonCompact,

View File

@@ -1383,17 +1383,12 @@ pub fn process_stake_authorize(
};
if let Some(authorized) = authorized {
match authorization_type {
StakeAuthorize::Staker => {
// first check authorized withdrawer
check_current_authority(&authorized.withdrawer, &authority.pubkey())
.or_else(|_| {
// ...then check authorized staker. If neither matches, error will
// print the stake key as `expected`
check_current_authority(&authorized.staker, &authority.pubkey())
})?;
}
StakeAuthorize::Staker => check_current_authority(
&[authorized.withdrawer, authorized.staker],
&authority.pubkey(),
)?,
StakeAuthorize::Withdrawer => {
check_current_authority(&authorized.withdrawer, &authority.pubkey())?;
check_current_authority(&[authorized.withdrawer], &authority.pubkey())?;
}
}
} else {
@@ -1935,7 +1930,7 @@ pub fn process_stake_set_lockup(
};
if let Some(lockup) = lockup {
if lockup.custodian != Pubkey::default() {
check_current_authority(&lockup.custodian, &custodian.pubkey())?;
check_current_authority(&[lockup.custodian], &custodian.pubkey())?;
}
} else {
return Err(CliError::RpcRequestError(format!(
@@ -2119,13 +2114,13 @@ fn get_stake_account_state(
}
pub(crate) fn check_current_authority(
account_current_authority: &Pubkey,
permitted_authorities: &[Pubkey],
provided_current_authority: &Pubkey,
) -> Result<(), CliError> {
if account_current_authority != provided_current_authority {
if !permitted_authorities.contains(provided_current_authority) {
Err(CliError::RpcRequestError(format!(
"Invalid current authority provided: {:?}, expected {:?}",
provided_current_authority, account_current_authority
"Invalid authority provided: {:?}, expected {:?}",
provided_current_authority, permitted_authorities
)))
} else {
Ok(())

View File

@@ -910,7 +910,10 @@ pub fn process_vote_authorize(
"Invalid vote account state; no authorized voters found".to_string(),
)
})?;
check_current_authority(&current_authorized_voter, &authorized.pubkey())?;
check_current_authority(
&[current_authorized_voter, vote_state.authorized_withdrawer],
&authorized.pubkey(),
)?;
if let Some(signer) = new_authorized_signer {
if signer.is_interactive() {
return Err(CliError::BadParameter(format!(
@@ -927,7 +930,7 @@ pub fn process_vote_authorize(
(new_authorized_pubkey, "new_authorized_pubkey".to_string()),
)?;
if let Some(vote_state) = vote_state {
check_current_authority(&vote_state.authorized_withdrawer, &authorized.pubkey())?
check_current_authority(&[vote_state.authorized_withdrawer], &authorized.pubkey())?
}
}
}

View File

@@ -62,6 +62,7 @@ fn test_cli_program_deploy_non_upgradeable() {
address: None,
use_deprecated_loader: false,
allow_excessive_balance: false,
skip_fee_check: false,
};
config.output_format = OutputFormat::JsonCompact;
let response = process_command(&config);
@@ -91,6 +92,7 @@ fn test_cli_program_deploy_non_upgradeable() {
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: false,
skip_fee_check: false,
};
process_command(&config).unwrap();
let account1 = rpc_client
@@ -118,6 +120,7 @@ fn test_cli_program_deploy_non_upgradeable() {
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: false,
skip_fee_check: false,
};
process_command(&config).unwrap_err();
@@ -127,6 +130,7 @@ fn test_cli_program_deploy_non_upgradeable() {
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: true,
skip_fee_check: false,
};
process_command(&config).unwrap();
let account2 = rpc_client
@@ -193,6 +197,7 @@ fn test_cli_program_deploy_no_authority() {
upgrade_authority_signer_index: 1,
is_final: true,
max_len: None,
skip_fee_check: false,
});
config.output_format = OutputFormat::JsonCompact;
let response = process_command(&config);
@@ -218,6 +223,7 @@ fn test_cli_program_deploy_no_authority() {
upgrade_authority_signer_index: 1,
is_final: false,
max_len: None,
skip_fee_check: false,
});
process_command(&config).unwrap_err();
}
@@ -278,6 +284,7 @@ fn test_cli_program_deploy_with_authority() {
upgrade_authority_signer_index: 1,
is_final: false,
max_len: Some(max_len),
skip_fee_check: false,
});
config.output_format = OutputFormat::JsonCompact;
let response = process_command(&config);
@@ -325,6 +332,7 @@ fn test_cli_program_deploy_with_authority() {
upgrade_authority_signer_index: 1,
is_final: false,
max_len: Some(max_len),
skip_fee_check: false,
});
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -366,6 +374,7 @@ fn test_cli_program_deploy_with_authority() {
upgrade_authority_signer_index: 1,
is_final: false,
max_len: Some(max_len),
skip_fee_check: false,
});
process_command(&config).unwrap();
let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -420,6 +429,7 @@ fn test_cli_program_deploy_with_authority() {
upgrade_authority_signer_index: 1,
is_final: false,
max_len: None,
skip_fee_check: false,
});
process_command(&config).unwrap();
let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -494,6 +504,7 @@ fn test_cli_program_deploy_with_authority() {
upgrade_authority_signer_index: 1,
is_final: false,
max_len: None,
skip_fee_check: false,
});
process_command(&config).unwrap_err();
@@ -509,6 +520,7 @@ fn test_cli_program_deploy_with_authority() {
upgrade_authority_signer_index: 1,
is_final: true,
max_len: None,
skip_fee_check: false,
});
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -611,6 +623,7 @@ fn test_cli_program_close_program() {
upgrade_authority_signer_index: 1,
is_final: false,
max_len: Some(max_len),
skip_fee_check: false,
});
config.output_format = OutputFormat::JsonCompact;
process_command(&config).unwrap();
@@ -695,6 +708,7 @@ fn test_cli_program_write_buffer() {
buffer_pubkey: None,
buffer_authority_signer_index: None,
max_len: None,
skip_fee_check: false,
});
config.output_format = OutputFormat::JsonCompact;
let response = process_command(&config);
@@ -729,6 +743,7 @@ fn test_cli_program_write_buffer() {
buffer_pubkey: Some(buffer_keypair.pubkey()),
buffer_authority_signer_index: None,
max_len: Some(max_len),
skip_fee_check: false,
});
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -790,6 +805,7 @@ fn test_cli_program_write_buffer() {
buffer_pubkey: Some(buffer_keypair.pubkey()),
buffer_authority_signer_index: Some(2),
max_len: None,
skip_fee_check: false,
});
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -827,6 +843,7 @@ fn test_cli_program_write_buffer() {
buffer_pubkey: None,
buffer_authority_signer_index: Some(2),
max_len: None,
skip_fee_check: false,
});
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -899,6 +916,7 @@ fn test_cli_program_write_buffer() {
buffer_pubkey: None,
buffer_authority_signer_index: None,
max_len: None,
skip_fee_check: false,
});
config.output_format = OutputFormat::JsonCompact;
let response = process_command(&config);
@@ -938,6 +956,7 @@ fn test_cli_program_write_buffer() {
buffer_pubkey: Some(buffer_keypair.pubkey()),
buffer_authority_signer_index: None,
max_len: None, //Some(max_len),
skip_fee_check: false,
});
process_command(&config).unwrap();
config.signers = vec![&keypair, &buffer_keypair];
@@ -951,6 +970,7 @@ fn test_cli_program_write_buffer() {
upgrade_authority_signer_index: 1,
is_final: true,
max_len: None,
skip_fee_check: false,
});
config.output_format = OutputFormat::JsonCompact;
let error = process_command(&config).unwrap_err();
@@ -1008,6 +1028,7 @@ fn test_cli_program_set_buffer_authority() {
buffer_pubkey: Some(buffer_keypair.pubkey()),
buffer_authority_signer_index: None,
max_len: None,
skip_fee_check: false,
});
process_command(&config).unwrap();
let buffer_account = rpc_client.get_account(&buffer_keypair.pubkey()).unwrap();
@@ -1123,6 +1144,7 @@ fn test_cli_program_mismatch_buffer_authority() {
buffer_pubkey: Some(buffer_keypair.pubkey()),
buffer_authority_signer_index: Some(2),
max_len: None,
skip_fee_check: false,
});
process_command(&config).unwrap();
let buffer_account = rpc_client.get_account(&buffer_keypair.pubkey()).unwrap();
@@ -1145,6 +1167,7 @@ fn test_cli_program_mismatch_buffer_authority() {
upgrade_authority_signer_index: 1,
is_final: true,
max_len: None,
skip_fee_check: false,
});
process_command(&config).unwrap_err();
@@ -1160,6 +1183,7 @@ fn test_cli_program_mismatch_buffer_authority() {
upgrade_authority_signer_index: 1,
is_final: true,
max_len: None,
skip_fee_check: false,
});
process_command(&config).unwrap();
}
@@ -1216,6 +1240,7 @@ fn test_cli_program_show() {
buffer_pubkey: Some(buffer_keypair.pubkey()),
buffer_authority_signer_index: Some(2),
max_len: None,
skip_fee_check: false,
});
process_command(&config).unwrap();
@@ -1275,6 +1300,7 @@ fn test_cli_program_show() {
upgrade_authority_signer_index: 1,
is_final: false,
max_len: Some(max_len),
skip_fee_check: false,
});
config.output_format = OutputFormat::JsonCompact;
let min_slot = rpc_client.get_slot().unwrap();
@@ -1401,6 +1427,7 @@ fn test_cli_program_dump() {
buffer_pubkey: Some(buffer_keypair.pubkey()),
buffer_authority_signer_index: Some(2),
max_len: None,
skip_fee_check: false,
});
process_command(&config).unwrap();

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-client-test"
version = "1.10.3"
version = "1.10.6"
description = "Solana RPC Test"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -14,25 +14,25 @@ publish = false
futures-util = "0.3.21"
serde_json = "1.0.79"
serial_test = "0.6.0"
solana-client = { path = "../client", version = "=1.10.3" }
solana-ledger = { path = "../ledger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-merkle-tree = { path = "../merkle-tree", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.3" }
solana-rpc = { path = "../rpc", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-test-validator = { path = "../test-validator", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-client = { path = "../client", version = "=1.10.6" }
solana-ledger = { path = "../ledger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-merkle-tree = { path = "../merkle-tree", version = "=1.10.6" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-perf = { path = "../perf", version = "=1.10.6" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.6" }
solana-rpc = { path = "../rpc", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-test-validator = { path = "../test-validator", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
systemstat = "0.1.10"
tokio = { version = "1", features = ["full"] }
[dev-dependencies]
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-client"
version = "1.10.3"
version = "1.10.6"
description = "Solana Client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -35,15 +35,16 @@ semver = "1.0.6"
serde = "1.0.136"
serde_derive = "1.0.103"
serde_json = "1.0.79"
solana-account-decoder = { path = "../account-decoder", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-faucet = { path = "../faucet", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-net-utils = { path = "../net-utils", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-account-decoder = { path = "../account-decoder", version = "=1.10.6" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-faucet = { path = "../faucet", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-net-utils = { path = "../net-utils", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1.8"
@@ -54,7 +55,7 @@ url = "2.2.2"
[dev-dependencies]
assert_matches = "1.5.0"
jsonrpc-http-server = "18.0.0"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,6 +1,9 @@
use {
crate::{tpu_connection::TpuConnection, udp_client::UdpTpuConnection},
crate::{
quic_client::QuicTpuConnection, tpu_connection::TpuConnection, udp_client::UdpTpuConnection,
},
lazy_static::lazy_static,
solana_sdk::{transaction::VersionedTransaction, transport::TransportError},
std::{
collections::{hash_map::Entry, BTreeMap, HashMap},
net::{SocketAddr, UdpSocket},
@@ -11,9 +14,15 @@ use {
// Should be non-zero
static MAX_CONNECTIONS: usize = 64;
#[derive(Clone)]
enum Connection {
Udp(Arc<UdpTpuConnection>),
Quic(Arc<QuicTpuConnection>),
}
struct ConnMap {
// Keeps track of the connection associated with an addr and the last time it was used
map: HashMap<SocketAddr, (Arc<dyn TpuConnection + 'static + Sync + Send>, u64)>,
map: HashMap<SocketAddr, (Connection, u64)>,
// Helps to find the least recently used connection. The search and inserts are O(log(n))
// but since we're bounding the size of the collections, this should be constant
// (and hopefully negligible) time. In theory, we can do this in constant time
@@ -23,6 +32,7 @@ struct ConnMap {
// that seems non-"Rust-y" and low bang/buck. This is still pretty terrible though...
last_used_times: BTreeMap<u64, SocketAddr>,
ticks: u64,
use_quic: bool,
}
impl ConnMap {
@@ -31,21 +41,31 @@ impl ConnMap {
map: HashMap::new(),
last_used_times: BTreeMap::new(),
ticks: 0,
use_quic: false,
}
}
pub fn set_use_quic(&mut self, use_quic: bool) {
self.use_quic = use_quic;
}
}
lazy_static! {
static ref CONNECTION_MAP: Mutex<ConnMap> = Mutex::new(ConnMap::new());
}
pub fn set_use_quic(use_quic: bool) {
let mut map = (*CONNECTION_MAP).lock().unwrap();
map.set_use_quic(use_quic);
}
#[allow(dead_code)]
// TODO: see https://github.com/solana-labs/solana/issues/23661
// remove lazy_static and optimize and refactor this
pub fn get_connection(addr: &SocketAddr) -> Arc<dyn TpuConnection + 'static + Sync + Send> {
fn get_connection(addr: &SocketAddr) -> Connection {
let mut map = (*CONNECTION_MAP).lock().unwrap();
let ticks = map.ticks;
let use_quic = map.use_quic;
let (conn, target_ticks) = match map.map.entry(*addr) {
Entry::Occupied(mut entry) => {
let mut pair = entry.get_mut();
@@ -57,12 +77,15 @@ pub fn get_connection(addr: &SocketAddr) -> Arc<dyn TpuConnection + 'static + Sy
let send_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
// TODO: see https://github.com/solana-labs/solana/issues/23659
// make it configurable (e.g. via the command line) whether to use UDP or Quic
let conn = Arc::new(UdpTpuConnection::new(send_socket, *addr));
let conn = if use_quic {
Connection::Quic(Arc::new(QuicTpuConnection::new(send_socket, *addr)))
} else {
Connection::Udp(Arc::new(UdpTpuConnection::new(send_socket, *addr)))
};
entry.insert((conn.clone(), ticks));
(
conn as Arc<dyn TpuConnection + 'static + Sync + Send>,
ticks,
)
(conn, ticks)
}
};
@@ -85,13 +108,69 @@ pub fn get_connection(addr: &SocketAddr) -> Arc<dyn TpuConnection + 'static + Sy
conn
}
// TODO: see https://github.com/solana-labs/solana/issues/23851
// use enum_dispatch and get rid of this tedious code.
// The main blocker to using enum_dispatch right now is that
// the it doesn't work with static methods like TpuConnection::new
// which is used by thin_client. This will be eliminated soon
// once thin_client is moved to using this connection cache.
// Once that is done, we will migrate to using enum_dispatch
// This will be done in a followup to
// https://github.com/solana-labs/solana/pull/23817
pub fn send_wire_transaction_batch(
packets: &[&[u8]],
addr: &SocketAddr,
) -> Result<(), TransportError> {
let conn = get_connection(addr);
match conn {
Connection::Udp(conn) => conn.send_wire_transaction_batch(packets),
Connection::Quic(conn) => conn.send_wire_transaction_batch(packets),
}
}
pub fn send_wire_transaction(
wire_transaction: &[u8],
addr: &SocketAddr,
) -> Result<(), TransportError> {
let conn = get_connection(addr);
match conn {
Connection::Udp(conn) => conn.send_wire_transaction(wire_transaction),
Connection::Quic(conn) => conn.send_wire_transaction(wire_transaction),
}
}
pub fn serialize_and_send_transaction(
transaction: &VersionedTransaction,
addr: &SocketAddr,
) -> Result<(), TransportError> {
let conn = get_connection(addr);
match conn {
Connection::Udp(conn) => conn.serialize_and_send_transaction(transaction),
Connection::Quic(conn) => conn.serialize_and_send_transaction(transaction),
}
}
pub fn par_serialize_and_send_transaction_batch(
transactions: &[VersionedTransaction],
addr: &SocketAddr,
) -> Result<(), TransportError> {
let conn = get_connection(addr);
match conn {
Connection::Udp(conn) => conn.par_serialize_and_send_transaction_batch(transactions),
Connection::Quic(conn) => conn.par_serialize_and_send_transaction_batch(transactions),
}
}
#[cfg(test)]
mod tests {
use {
crate::connection_cache::{get_connection, CONNECTION_MAP, MAX_CONNECTIONS},
crate::{
connection_cache::{get_connection, Connection, CONNECTION_MAP, MAX_CONNECTIONS},
tpu_connection::TpuConnection,
},
rand::{Rng, SeedableRng},
rand_chacha::ChaChaRng,
std::net::SocketAddr,
std::net::{IpAddr, SocketAddr},
};
fn get_addr(rng: &mut ChaChaRng) -> SocketAddr {
@@ -105,6 +184,13 @@ mod tests {
addr_str.parse().expect("Invalid address")
}
fn ip(conn: Connection) -> IpAddr {
match conn {
Connection::Udp(conn) => conn.tpu_addr().ip(),
Connection::Quic(conn) => conn.tpu_addr().ip(),
}
}
#[test]
fn test_connection_cache() {
// Allow the test to run deterministically
@@ -120,7 +206,7 @@ mod tests {
// be lazy and not connect until first use or handle connection errors somehow
// (without crashing, as would be required in a real practical validator)
let first_addr = get_addr(&mut rng);
assert!(get_connection(&first_addr).tpu_addr().ip() == first_addr.ip());
assert!(ip(get_connection(&first_addr)) == first_addr.ip());
let addrs = (0..MAX_CONNECTIONS)
.into_iter()
.map(|_| {
@@ -133,7 +219,7 @@ mod tests {
let map = (*CONNECTION_MAP).lock().unwrap();
addrs.iter().for_each(|a| {
let conn = map.map.get(a).expect("Address not found");
assert!(a.ip() == conn.0.tpu_addr().ip());
assert!(a.ip() == ip(conn.0.clone()));
});
assert!(map.map.get(&first_addr).is_none());

View File

@@ -7,10 +7,8 @@ use {
futures::future::join_all,
itertools::Itertools,
quinn::{ClientConfig, Endpoint, EndpointConfig, NewConnection, WriteError},
rayon::iter::{IntoParallelIterator, ParallelIterator},
solana_sdk::{
quic::{QUIC_MAX_CONCURRENT_STREAMS, QUIC_PORT_OFFSET},
transaction::Transaction,
transport::Result as TransportResult,
},
std::{
@@ -65,21 +63,22 @@ impl TpuConnection for QuicTpuConnection {
&self.client.addr
}
fn send_wire_transaction(&self, data: Vec<u8>) -> TransportResult<()> {
fn send_wire_transaction<T>(&self, wire_transaction: T) -> TransportResult<()>
where
T: AsRef<[u8]>,
{
let _guard = self.client.runtime.enter();
let send_buffer = self.client.send_buffer(&data[..]);
let send_buffer = self.client.send_buffer(wire_transaction);
self.client.runtime.block_on(send_buffer)?;
Ok(())
}
fn send_batch(&self, transactions: Vec<Transaction>) -> TransportResult<()> {
let buffers = transactions
.into_par_iter()
.map(|tx| bincode::serialize(&tx).expect("serialize Transaction in send_batch"))
.collect::<Vec<_>>();
fn send_wire_transaction_batch<T>(&self, buffers: &[T]) -> TransportResult<()>
where
T: AsRef<[u8]>,
{
let _guard = self.client.runtime.enter();
let send_batch = self.client.send_batch(&buffers[..]);
let send_batch = self.client.send_batch(buffers);
self.client.runtime.block_on(send_batch)?;
Ok(())
}
@@ -162,12 +161,18 @@ impl QuicClient {
}
}
pub async fn send_buffer(&self, data: &[u8]) -> Result<(), ClientErrorKind> {
self._send_buffer(data).await?;
pub async fn send_buffer<T>(&self, data: T) -> Result<(), ClientErrorKind>
where
T: AsRef<[u8]>,
{
self._send_buffer(data.as_ref()).await?;
Ok(())
}
pub async fn send_batch(&self, buffers: &[Vec<u8>]) -> Result<(), ClientErrorKind> {
pub async fn send_batch<T>(&self, buffers: &[T]) -> Result<(), ClientErrorKind>
where
T: AsRef<[u8]>,
{
// Start off by "testing" the connection by sending the first transaction
// This will also connect to the server if not already connected
// and reconnect and retry if the first send attempt failed
@@ -182,7 +187,7 @@ impl QuicClient {
if buffers.is_empty() {
return Ok(());
}
let connection = self._send_buffer(&buffers[0][..]).await?;
let connection = self._send_buffer(buffers[0].as_ref()).await?;
// Used to avoid dereferencing the Arc multiple times below
// by just getting a reference to the NewConnection once
@@ -196,7 +201,7 @@ impl QuicClient {
join_all(
buffs
.into_iter()
.map(|buf| Self::_send_buffer_using_conn(&buf[..], connection_ref)),
.map(|buf| Self::_send_buffer_using_conn(buf.as_ref(), connection_ref)),
)
});

View File

@@ -24,7 +24,7 @@ use {
signers::Signers,
system_instruction,
timing::duration_as_ms,
transaction::{self, Transaction},
transaction::{self, Transaction, VersionedTransaction},
transport::Result as TransportResult,
},
std::{
@@ -215,10 +215,13 @@ impl<C: 'static + TpuConnection> ThinClient<C> {
let mut num_confirmed = 0;
let mut wait_time = MAX_PROCESSING_AGE;
// resend the same transaction until the transaction has no chance of succeeding
let wire_transaction =
bincode::serialize(&transaction).expect("transaction serialization failed");
while now.elapsed().as_secs() < wait_time as u64 {
if num_confirmed == 0 {
// Send the transaction if there has been no confirmation (e.g. the first time)
self.tpu_connection().send_transaction(transaction)?;
self.tpu_connection()
.send_wire_transaction(&wire_transaction)?;
}
if let Ok(confirmed_blocks) = self.poll_for_signature_confirmation(
@@ -601,12 +604,17 @@ impl<C: 'static + TpuConnection> SyncClient for ThinClient<C> {
impl<C: 'static + TpuConnection> AsyncClient for ThinClient<C> {
fn async_send_transaction(&self, transaction: Transaction) -> TransportResult<Signature> {
self.tpu_connection().send_transaction(&transaction)?;
let transaction = VersionedTransaction::from(transaction);
self.tpu_connection()
.serialize_and_send_transaction(&transaction)?;
Ok(transaction.signatures[0])
}
fn async_send_batch(&self, transactions: Vec<Transaction>) -> TransportResult<()> {
self.tpu_connection().send_batch(transactions)
let batch: Vec<VersionedTransaction> = transactions.into_iter().map(Into::into).collect();
self.tpu_connection()
.par_serialize_and_send_transaction_batch(&batch[..])?;
Ok(())
}
fn async_send_message<T: Signers>(

View File

@@ -1,21 +1,40 @@
use {
solana_sdk::{transaction::Transaction, transport::Result as TransportResult},
rayon::iter::{IntoParallelIterator, ParallelIterator},
solana_sdk::{transaction::VersionedTransaction, transport::Result as TransportResult},
std::net::{SocketAddr, UdpSocket},
};
pub trait TpuConnection {
fn new(client_socket: UdpSocket, tpu_addr: SocketAddr) -> Self
where
Self: Sized;
fn new(client_socket: UdpSocket, tpu_addr: SocketAddr) -> Self;
fn tpu_addr(&self) -> &SocketAddr;
fn send_transaction(&self, tx: &Transaction) -> TransportResult<()> {
let data = bincode::serialize(tx).expect("serialize Transaction in send_transaction");
self.send_wire_transaction(data)
fn serialize_and_send_transaction(
&self,
transaction: &VersionedTransaction,
) -> TransportResult<()> {
let wire_transaction =
bincode::serialize(transaction).expect("serialize Transaction in send_batch");
self.send_wire_transaction(&wire_transaction)
}
fn send_wire_transaction(&self, data: Vec<u8>) -> TransportResult<()>;
fn send_wire_transaction<T>(&self, wire_transaction: T) -> TransportResult<()>
where
T: AsRef<[u8]>;
fn send_batch(&self, transactions: Vec<Transaction>) -> TransportResult<()>;
fn par_serialize_and_send_transaction_batch(
&self,
transactions: &[VersionedTransaction],
) -> TransportResult<()> {
let buffers = transactions
.into_par_iter()
.map(|tx| bincode::serialize(&tx).expect("serialize Transaction in send_batch"))
.collect::<Vec<_>>();
self.send_wire_transaction_batch(&buffers)
}
fn send_wire_transaction_batch<T>(&self, buffers: &[T]) -> TransportResult<()>
where
T: AsRef<[u8]>;
}

View File

@@ -3,7 +3,9 @@
use {
crate::tpu_connection::TpuConnection,
solana_sdk::{transaction::Transaction, transport::Result as TransportResult},
core::iter::repeat,
solana_sdk::transport::Result as TransportResult,
solana_streamer::sendmmsg::batch_send,
std::net::{SocketAddr, UdpSocket},
};
@@ -24,19 +26,20 @@ impl TpuConnection for UdpTpuConnection {
&self.addr
}
fn send_wire_transaction(&self, data: Vec<u8>) -> TransportResult<()> {
self.socket.send_to(&data[..], self.addr)?;
fn send_wire_transaction<T>(&self, wire_transaction: T) -> TransportResult<()>
where
T: AsRef<[u8]>,
{
self.socket.send_to(wire_transaction.as_ref(), self.addr)?;
Ok(())
}
fn send_batch(&self, transactions: Vec<Transaction>) -> TransportResult<()> {
transactions
.into_iter()
.map(|tx| bincode::serialize(&tx).expect("serialize Transaction in send_batch"))
.try_for_each(|buff| -> TransportResult<()> {
self.socket.send_to(&buff[..], self.addr)?;
Ok(())
})?;
fn send_wire_transaction_batch<T>(&self, buffers: &[T]) -> TransportResult<()>
where
T: AsRef<[u8]>,
{
let pkts: Vec<_> = buffers.iter().zip(repeat(self.tpu_addr())).collect();
batch_send(&self.socket, &pkts)?;
Ok(())
}
}

View File

@@ -1,7 +1,7 @@
[package]
name = "solana-core"
description = "Blockchain, Rebuilt for Scale"
version = "1.10.3"
version = "1.10.6"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-core"
readme = "../README.md"
@@ -33,30 +33,30 @@ rayon = "1.5.1"
retain_mut = "0.1.7"
serde = "1.0.136"
serde_derive = "1.0.103"
solana-address-lookup-table-program = { path = "../programs/address-lookup-table", version = "=1.10.3" }
solana-bloom = { path = "../bloom", version = "=1.10.3" }
solana-client = { path = "../client", version = "=1.10.3" }
solana-entry = { path = "../entry", version = "=1.10.3" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.3" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.3" }
solana-geyser-plugin-manager = { path = "../geyser-plugin-manager", version = "=1.10.3" }
solana-gossip = { path = "../gossip", version = "=1.10.3" }
solana-ledger = { path = "../ledger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-net-utils = { path = "../net-utils", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-poh = { path = "../poh", version = "=1.10.3" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.3" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.3" }
solana-replica-lib = { path = "../replica-lib", version = "=1.10.3" }
solana-rpc = { path = "../rpc", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-send-transaction-service = { path = "../send-transaction-service", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-address-lookup-table-program = { path = "../programs/address-lookup-table", version = "=1.10.6" }
solana-bloom = { path = "../bloom", version = "=1.10.6" }
solana-client = { path = "../client", version = "=1.10.6" }
solana-entry = { path = "../entry", version = "=1.10.6" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.6" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.6" }
solana-geyser-plugin-manager = { path = "../geyser-plugin-manager", version = "=1.10.6" }
solana-gossip = { path = "../gossip", version = "=1.10.6" }
solana-ledger = { path = "../ledger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-net-utils = { path = "../net-utils", version = "=1.10.6" }
solana-perf = { path = "../perf", version = "=1.10.6" }
solana-poh = { path = "../poh", version = "=1.10.6" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.6" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.6" }
solana-replica-lib = { path = "../replica-lib", version = "=1.10.6" }
solana-rpc = { path = "../rpc", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-send-transaction-service = { path = "../send-transaction-service", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
sys-info = "0.9.1"
tempfile = "3.3.0"
thiserror = "1.0"
@@ -69,10 +69,10 @@ raptorq = "1.6.5"
reqwest = { version = "0.11.10", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde_json = "1.0.79"
serial_test = "0.6.0"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.3" }
solana-stake-program = { path = "../programs/stake", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.6" }
solana-stake-program = { path = "../programs/stake", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
static_assertions = "1.1.0"
systemstat = "0.1.10"

View File

@@ -159,7 +159,7 @@ fn bench_sigverify_stage(bencher: &mut Bencher) {
for _ in 0..batches.len() {
if let Some(batch) = batches.pop() {
sent_len += batch.packets.len();
packet_s.send(batch).unwrap();
packet_s.send(vec![batch]).unwrap();
}
}
let mut received = 0;

View File

@@ -14,6 +14,7 @@ use {
histogram::Histogram,
itertools::Itertools,
retain_mut::RetainMut,
solana_client::connection_cache::send_wire_transaction_batch,
solana_entry::entry::hash_transactions,
solana_gossip::{cluster_info::ClusterInfo, contact_info::ContactInfo},
solana_ledger::blockstore_processor::TransactionStatusSender,
@@ -51,8 +52,8 @@ use {
transaction::{
self, AddressLoader, SanitizedTransaction, TransactionError, VersionedTransaction,
},
transport::TransportError,
},
solana_streamer::sendmmsg::{batch_send, SendPktsError},
solana_transaction_status::token_balances::{
collect_token_balances, TransactionTokenBalancesSet,
},
@@ -60,7 +61,7 @@ use {
cmp,
collections::HashMap,
env,
net::{SocketAddr, UdpSocket},
net::SocketAddr,
sync::{
atomic::{AtomicU64, AtomicUsize, Ordering},
Arc, Mutex, RwLock,
@@ -482,11 +483,10 @@ impl BankingStage {
/// Forwards all valid, unprocessed packets in the buffer, up to a rate limit. Returns
/// the number of successfully forwarded packets in second part of tuple
fn forward_buffered_packets(
socket: &std::net::UdpSocket,
tpu_forwards: &std::net::SocketAddr,
packets: Vec<&Packet>,
data_budget: &DataBudget,
) -> (std::io::Result<()>, usize) {
) -> (std::result::Result<(), TransportError>, usize) {
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;
@@ -502,18 +502,35 @@ impl BankingStage {
.iter()
.filter_map(|p| {
if !p.meta.forwarded() && data_budget.take(p.meta.size) {
Some((&p.data[..p.meta.size], tpu_forwards))
Some(&p.data[..p.meta.size])
} else {
None
}
})
.collect();
// TODO: see https://github.com/solana-labs/solana/issues/23819
// fix this so returns the correct number of succeeded packets
// when there's an error sending the batch. This was left as-is for now
// in favor of shipping Quic support, which was considered higher-priority
if !packet_vec.is_empty() {
inc_new_counter_info!("banking_stage-forwarded_packets", packet_vec.len());
if let Err(SendPktsError::IoError(ioerr, num_failed)) = batch_send(socket, &packet_vec)
{
return (Err(ioerr), packet_vec.len().saturating_sub(num_failed));
let mut measure = Measure::start("banking_stage-forward-us");
let res = send_wire_transaction_batch(&packet_vec, tpu_forwards);
measure.stop();
inc_new_counter_info!(
"banking_stage-forward-us",
measure.as_us() as usize,
1000,
1000
);
if let Err(err) = res {
inc_new_counter_info!("banking_stage-forward_packets-failed-batches", 1);
return (Err(err), 0);
}
}
@@ -766,7 +783,6 @@ impl BankingStage {
#[allow(clippy::too_many_arguments)]
fn process_buffered_packets(
my_pubkey: &Pubkey,
socket: &std::net::UdpSocket,
poh_recorder: &Arc<Mutex<PohRecorder>>,
cluster_info: &ClusterInfo,
buffered_packet_batches: &mut UnprocessedPacketBatches,
@@ -846,7 +862,6 @@ impl BankingStage {
cluster_info,
buffered_packet_batches,
poh_recorder,
socket,
false,
data_budget,
slot_metrics_tracker,
@@ -865,7 +880,6 @@ impl BankingStage {
cluster_info,
buffered_packet_batches,
poh_recorder,
socket,
true,
data_budget,
slot_metrics_tracker,
@@ -887,7 +901,6 @@ impl BankingStage {
cluster_info: &ClusterInfo,
buffered_packet_batches: &mut UnprocessedPacketBatches,
poh_recorder: &Arc<Mutex<PohRecorder>>,
socket: &UdpSocket,
hold: bool,
data_budget: &DataBudget,
slot_metrics_tracker: &mut LeaderSlotMetricsTracker,
@@ -913,7 +926,7 @@ impl BankingStage {
Self::filter_valid_packets_for_forwarding(buffered_packet_batches.iter());
let forwardable_packets_len = forwardable_packets.len();
let (_forward_result, sucessful_forwarded_packets_count) =
Self::forward_buffered_packets(socket, &addr, forwardable_packets, data_budget);
Self::forward_buffered_packets(&addr, forwardable_packets, data_budget);
let failed_forwarded_packets_count =
forwardable_packets_len.saturating_sub(sucessful_forwarded_packets_count);
@@ -958,7 +971,6 @@ impl BankingStage {
cost_model: Arc<RwLock<CostModel>>,
) {
let recorder = poh_recorder.lock().unwrap().recorder();
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let mut buffered_packet_batches = UnprocessedPacketBatches::with_capacity(batch_limit);
let mut banking_stage_stats = BankingStageStats::new(id);
let qos_service = QosService::new(cost_model, id);
@@ -970,7 +982,6 @@ impl BankingStage {
|_| {
Self::process_buffered_packets(
&my_pubkey,
&socket,
poh_recorder,
cluster_info,
&mut buffered_packet_batches,
@@ -3835,7 +3846,6 @@ mod tests {
let local_node = Node::new_localhost_with_pubkey(validator_pubkey);
let cluster_info = new_test_cluster_info(local_node.info);
let send_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let recv_socket = &local_node.sockets.tpu_forwards[0];
let test_cases = vec![
@@ -3857,7 +3867,6 @@ mod tests {
&cluster_info,
&mut unprocessed_packet_batches,
&poh_recorder,
&send_socket,
true,
&data_budget,
&mut LeaderSlotMetricsTracker::new(0),
@@ -3935,7 +3944,6 @@ mod tests {
let local_node = Node::new_localhost_with_pubkey(validator_pubkey);
let cluster_info = new_test_cluster_info(local_node.info);
let send_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let recv_socket = &local_node.sockets.tpu_forwards[0];
let test_cases = vec![
@@ -3969,7 +3977,6 @@ mod tests {
&cluster_info,
&mut unprocessed_packet_batches,
&poh_recorder,
&send_socket,
hold,
&DataBudget::default(),
&mut LeaderSlotMetricsTracker::new(0),

View File

@@ -326,7 +326,7 @@ pub fn new_cluster_nodes<T: 'static>(
.collect();
let broadcast = TypeId::of::<T>() == TypeId::of::<BroadcastStage>();
let stakes: Vec<u64> = nodes.iter().map(|node| node.stake).collect();
let mut weighted_shuffle = WeightedShuffle::new(&stakes).unwrap();
let mut weighted_shuffle = WeightedShuffle::new("cluster-nodes", &stakes);
if broadcast {
weighted_shuffle.remove_index(index[&self_pubkey]);
}

View File

@@ -134,10 +134,6 @@ impl CostUpdateService {
.upsert_instruction_cost(program_id, units);
update_count += 1;
}
debug!(
"after replayed into bank, updated cost model instruction cost table, current values: {:?}",
cost_model.read().unwrap().get_instruction_cost_table()
);
update_count
}
}
@@ -150,15 +146,10 @@ mod tests {
fn test_update_cost_model_with_empty_execute_timings() {
let cost_model = Arc::new(RwLock::new(CostModel::default()));
let mut empty_execute_timings = ExecuteTimings::default();
CostUpdateService::update_cost_model(&cost_model, &mut empty_execute_timings);
assert_eq!(
0,
cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.len()
CostUpdateService::update_cost_model(&cost_model, &mut empty_execute_timings),
);
}
@@ -188,22 +179,16 @@ mod tests {
total_errored_units,
},
);
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings);
assert_eq!(
1,
cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.len()
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings),
);
assert_eq!(
Some(&expected_cost),
expected_cost,
cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.get(&program_key_1)
.find_instruction_cost(&program_key_1)
);
}
@@ -225,22 +210,16 @@ mod tests {
total_errored_units: 0,
},
);
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings);
assert_eq!(
1,
cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.len()
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings),
);
assert_eq!(
Some(&expected_cost),
expected_cost,
cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.get(&program_key_1)
.find_instruction_cost(&program_key_1)
);
}
}
@@ -264,20 +243,46 @@ mod tests {
total_errored_units: 0,
},
);
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings);
// If both the `errored_txs_compute_consumed` is empty and `count == 0`, then
// nothing should be inserted into the cost model
assert!(cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.is_empty());
assert_eq!(
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings),
0
);
}
// set up current instruction cost to 100
let current_program_cost = 100;
{
execute_timings.details.per_program_timings.insert(
program_key_1,
ProgramTiming {
accumulated_us: 1000,
accumulated_units: current_program_cost,
count: 1,
errored_txs_compute_consumed: vec![],
total_errored_units: 0,
},
);
assert_eq!(
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings),
1
);
assert_eq!(
current_program_cost,
cost_model
.read()
.unwrap()
.find_instruction_cost(&program_key_1)
);
}
// Test updating cost model with only erroring compute costs where the `cost_per_error` is
// greater than the current instruction cost for the program. Should update with the
// new erroring compute costs
let cost_per_error = 1000;
// the expect cost is (previous_cost + new_cost)/2 = (100 + 1000)/2 = 550
let expected_units = 550;
{
let errored_txs_compute_consumed = vec![cost_per_error; 3];
let total_errored_units = errored_txs_compute_consumed.iter().sum();
@@ -291,29 +296,23 @@ mod tests {
total_errored_units,
},
);
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings);
assert_eq!(
1,
cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.len()
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings),
1
);
assert_eq!(
Some(&cost_per_error),
expected_units,
cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.get(&program_key_1)
.find_instruction_cost(&program_key_1)
);
}
// Test updating cost model with only erroring compute costs where the error cost is
// `smaller_cost_per_error`, less than the current instruction cost for the program.
// The cost should not decrease for these new lesser errors
let smaller_cost_per_error = cost_per_error - 10;
let smaller_cost_per_error = expected_units - 10;
{
let errored_txs_compute_consumed = vec![smaller_cost_per_error; 3];
let total_errored_units = errored_txs_compute_consumed.iter().sum();
@@ -327,22 +326,16 @@ mod tests {
total_errored_units,
},
);
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings);
assert_eq!(
1,
cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.len()
CostUpdateService::update_cost_model(&cost_model, &mut execute_timings),
1
);
assert_eq!(
Some(&cost_per_error),
expected_units,
cost_model
.read()
.unwrap()
.get_instruction_cost_table()
.get(&program_key_1)
.find_instruction_cost(&program_key_1)
);
}
}

View File

@@ -0,0 +1,185 @@
use {
crossbeam_channel::{Receiver, RecvTimeoutError, Sender},
rayon::{prelude::*, ThreadPool},
solana_gossip::cluster_info::ClusterInfo,
solana_measure::measure::Measure,
solana_perf::packet::PacketBatch,
solana_rayon_threadlimit::get_thread_count,
solana_runtime::bank_forks::BankForks,
solana_sdk::timing::timestamp,
solana_streamer::streamer::{self, StreamerError},
std::{
cell::RefCell,
collections::HashMap,
net::IpAddr,
sync::{Arc, RwLock},
thread::{self, Builder, JoinHandle},
time::{Duration, Instant},
},
};
const IP_TO_STAKE_REFRESH_DURATION: Duration = Duration::from_secs(5);
thread_local!(static PAR_THREAD_POOL: RefCell<ThreadPool> = RefCell::new(rayon::ThreadPoolBuilder::new()
.num_threads(get_thread_count())
.thread_name(|ix| format!("transaction_sender_stake_stage_{}", ix))
.build()
.unwrap()));
pub type FindPacketSenderStakeSender = Sender<Vec<PacketBatch>>;
pub type FindPacketSenderStakeReceiver = Receiver<Vec<PacketBatch>>;
#[derive(Debug, Default)]
struct FindPacketSenderStakeStats {
last_print: u64,
refresh_ip_to_stake_time: u64,
apply_sender_stakes_time: u64,
send_batches_time: u64,
receive_batches_time: u64,
total_batches: u64,
total_packets: u64,
}
impl FindPacketSenderStakeStats {
fn report(&mut self) {
let now = timestamp();
let elapsed_ms = now - self.last_print;
if elapsed_ms > 2000 {
datapoint_info!(
"find_packet_sender_stake-services_stats",
(
"refresh_ip_to_stake_time",
self.refresh_ip_to_stake_time as i64,
i64
),
(
"apply_sender_stakes_time",
self.apply_sender_stakes_time as i64,
i64
),
("send_batches_time", self.send_batches_time as i64, i64),
(
"receive_batches_time",
self.receive_batches_time as i64,
i64
),
("total_batches", self.total_batches as i64, i64),
("total_packets", self.total_packets as i64, i64),
);
*self = FindPacketSenderStakeStats::default();
self.last_print = now;
}
}
}
pub struct FindPacketSenderStakeStage {
thread_hdl: JoinHandle<()>,
}
impl FindPacketSenderStakeStage {
pub fn new(
packet_receiver: streamer::PacketBatchReceiver,
sender: FindPacketSenderStakeSender,
bank_forks: Arc<RwLock<BankForks>>,
cluster_info: Arc<ClusterInfo>,
) -> Self {
let mut stats = FindPacketSenderStakeStats::default();
let thread_hdl = Builder::new()
.name("find-packet-sender-stake".to_string())
.spawn(move || {
let mut last_stakes = Instant::now();
let mut ip_to_stake: HashMap<IpAddr, u64> = HashMap::new();
loop {
let mut refresh_ip_to_stake_time = Measure::start("refresh_ip_to_stake_time");
Self::try_refresh_ip_to_stake(
&mut last_stakes,
&mut ip_to_stake,
bank_forks.clone(),
cluster_info.clone(),
);
refresh_ip_to_stake_time.stop();
stats.refresh_ip_to_stake_time = stats
.refresh_ip_to_stake_time
.saturating_add(refresh_ip_to_stake_time.as_us());
match streamer::recv_packet_batches(&packet_receiver) {
Ok((mut batches, num_packets, recv_duration)) => {
let num_batches = batches.len();
let mut apply_sender_stakes_time =
Measure::start("apply_sender_stakes_time");
Self::apply_sender_stakes(&mut batches, &ip_to_stake);
apply_sender_stakes_time.stop();
let mut send_batches_time = Measure::start("send_batches_time");
if let Err(e) = sender.send(batches) {
info!("Sender error: {:?}", e);
}
send_batches_time.stop();
stats.apply_sender_stakes_time = stats
.apply_sender_stakes_time
.saturating_add(apply_sender_stakes_time.as_us());
stats.send_batches_time = stats
.send_batches_time
.saturating_add(send_batches_time.as_us());
stats.receive_batches_time = stats
.receive_batches_time
.saturating_add(recv_duration.as_nanos() as u64);
stats.total_batches =
stats.total_batches.saturating_add(num_batches as u64);
stats.total_packets =
stats.total_packets.saturating_add(num_packets as u64);
}
Err(e) => match e {
StreamerError::RecvTimeout(RecvTimeoutError::Disconnected) => break,
StreamerError::RecvTimeout(RecvTimeoutError::Timeout) => (),
_ => error!("error: {:?}", e),
},
}
stats.report();
}
})
.unwrap();
Self { thread_hdl }
}
fn try_refresh_ip_to_stake(
last_stakes: &mut Instant,
ip_to_stake: &mut HashMap<IpAddr, u64>,
bank_forks: Arc<RwLock<BankForks>>,
cluster_info: Arc<ClusterInfo>,
) {
if last_stakes.elapsed() > IP_TO_STAKE_REFRESH_DURATION {
let root_bank = bank_forks.read().unwrap().root_bank();
let staked_nodes = root_bank.staked_nodes();
*ip_to_stake = cluster_info
.tvu_peers()
.into_iter()
.filter_map(|node| {
let stake = staked_nodes.get(&node.id)?;
Some((node.tvu.ip(), *stake))
})
.collect();
*last_stakes = Instant::now();
}
}
fn apply_sender_stakes(batches: &mut [PacketBatch], ip_to_stake: &HashMap<IpAddr, u64>) {
PAR_THREAD_POOL.with(|thread_pool| {
thread_pool.borrow().install(|| {
batches
.into_par_iter()
.flat_map(|batch| batch.packets.par_iter_mut())
.for_each(|packet| {
packet.meta.sender_stake =
*ip_to_stake.get(&packet.meta.addr().ip()).unwrap_or(&0);
});
})
});
}
pub fn join(self) -> thread::Result<()> {
self.thread_hdl.join()
}
}

View File

@@ -24,6 +24,7 @@ pub mod cost_update_service;
pub mod drop_bank_service;
pub mod duplicate_repair_status;
pub mod fetch_stage;
pub mod find_packet_sender_stake_stage;
pub mod fork_choice;
pub mod gen_keys;
pub mod heaviest_subtree_fork_choice;

View File

@@ -2,17 +2,17 @@
use {
crate::packet_hasher::PacketHasher,
crossbeam_channel::unbounded,
crossbeam_channel::{unbounded, Sender},
lru::LruCache,
solana_ledger::shred::{get_shred_slot_index_type, ShredFetchStats},
solana_perf::{
cuda_runtime::PinnedVec,
packet::{Packet, PacketBatchRecycler, PacketFlags},
packet::{Packet, PacketBatch, PacketBatchRecycler, PacketFlags},
recycler::Recycler,
},
solana_runtime::bank_forks::BankForks,
solana_sdk::clock::{Slot, DEFAULT_MS_PER_SLOT},
solana_streamer::streamer::{self, PacketBatchReceiver, PacketBatchSender},
solana_streamer::streamer::{self, PacketBatchReceiver},
std::{
net::UdpSocket,
sync::{atomic::AtomicBool, Arc, RwLock},
@@ -65,7 +65,7 @@ impl ShredFetchStage {
// updates packets received on a channel and sends them on another channel
fn modify_packets<F>(
recvr: PacketBatchReceiver,
sendr: PacketBatchSender,
sendr: Sender<Vec<PacketBatch>>,
bank_forks: Option<Arc<RwLock<BankForks>>>,
name: &'static str,
modify: F,
@@ -125,7 +125,7 @@ impl ShredFetchStage {
stats = ShredFetchStats::default();
last_stats = Instant::now();
}
if sendr.send(packet_batch).is_err() {
if sendr.send(vec![packet_batch]).is_err() {
break;
}
}
@@ -134,7 +134,7 @@ impl ShredFetchStage {
fn packet_modifier<F>(
sockets: Vec<Arc<UdpSocket>>,
exit: &Arc<AtomicBool>,
sender: PacketBatchSender,
sender: Sender<Vec<PacketBatch>>,
recycler: Recycler<PinnedVec<Packet>>,
bank_forks: Option<Arc<RwLock<BankForks>>>,
name: &'static str,
@@ -170,7 +170,7 @@ impl ShredFetchStage {
sockets: Vec<Arc<UdpSocket>>,
forward_sockets: Vec<Arc<UdpSocket>>,
repair_socket: Arc<UdpSocket>,
sender: &PacketBatchSender,
sender: &Sender<Vec<PacketBatch>>,
bank_forks: Option<Arc<RwLock<BankForks>>>,
exit: &Arc<AtomicBool>,
) -> Self {

View File

@@ -6,9 +6,9 @@
//! if perf-libs are available
use {
crate::sigverify,
crate::{find_packet_sender_stake_stage, sigverify},
core::time::Duration,
crossbeam_channel::{Receiver, RecvTimeoutError, SendError, Sender},
crossbeam_channel::{RecvTimeoutError, SendError, Sender},
itertools::Itertools,
solana_measure::measure::Measure,
solana_perf::{
@@ -16,7 +16,7 @@ use {
sigverify::{count_valid_packets, shrink_batches, Deduper},
},
solana_sdk::timing,
solana_streamer::streamer::{self, PacketBatchReceiver, StreamerError},
solana_streamer::streamer::{self, StreamerError},
std::{
thread::{self, Builder, JoinHandle},
time::Instant,
@@ -192,7 +192,7 @@ impl SigVerifier for DisabledSigVerifier {
impl SigVerifyStage {
#[allow(clippy::new_ret_no_self)]
pub fn new<T: SigVerifier + 'static + Send + Clone>(
packet_receiver: Receiver<PacketBatch>,
packet_receiver: find_packet_sender_stake_stage::FindPacketSenderStakeReceiver,
verified_sender: Sender<Vec<PacketBatch>>,
verifier: T,
) -> Self {
@@ -227,12 +227,12 @@ impl SigVerifyStage {
fn verifier<T: SigVerifier>(
deduper: &Deduper,
recvr: &PacketBatchReceiver,
recvr: &find_packet_sender_stake_stage::FindPacketSenderStakeReceiver,
sendr: &Sender<Vec<PacketBatch>>,
verifier: &T,
stats: &mut SigVerifierStats,
) -> Result<()> {
let (mut batches, num_packets, recv_duration) = streamer::recv_packet_batches(recvr)?;
let (mut batches, num_packets, recv_duration) = streamer::recv_vec_packet_batches(recvr)?;
let batches_len = batches.len();
debug!(
@@ -312,7 +312,7 @@ impl SigVerifyStage {
}
fn verifier_service<T: SigVerifier + 'static + Send + Clone>(
packet_receiver: PacketBatchReceiver,
packet_receiver: find_packet_sender_stake_stage::FindPacketSenderStakeReceiver,
verified_sender: Sender<Vec<PacketBatch>>,
verifier: &T,
) -> JoinHandle<()> {
@@ -358,7 +358,7 @@ impl SigVerifyStage {
}
fn verifier_services<T: SigVerifier + 'static + Send + Clone>(
packet_receiver: PacketBatchReceiver,
packet_receiver: find_packet_sender_stake_stage::FindPacketSenderStakeReceiver,
verified_sender: Sender<Vec<PacketBatch>>,
verifier: T,
) -> JoinHandle<()> {
@@ -445,7 +445,7 @@ mod tests {
for _ in 0..batches.len() {
if let Some(batch) = batches.pop() {
sent_len += batch.packets.len();
packet_s.send(batch).unwrap();
packet_s.send(vec![batch]).unwrap();
}
}
let mut received = 0;

View File

@@ -10,6 +10,7 @@ use {
GossipVerifiedVoteHashSender, VerifiedVoteSender, VoteTracker,
},
fetch_stage::FetchStage,
find_packet_sender_stake_stage::FindPacketSenderStakeStage,
sigverify::TransactionSigVerifier,
sigverify_stage::SigVerifyStage,
},
@@ -55,6 +56,8 @@ pub struct Tpu {
cluster_info_vote_listener: ClusterInfoVoteListener,
broadcast_stage: BroadcastStage,
tpu_quic_t: thread::JoinHandle<()>,
find_packet_sender_stake_stage: FindPacketSenderStakeStage,
vote_find_packet_sender_stake_stage: FindPacketSenderStakeStage,
}
impl Tpu {
@@ -103,6 +106,26 @@ impl Tpu {
poh_recorder,
tpu_coalesce_ms,
);
let (find_packet_sender_stake_sender, find_packet_sender_stake_receiver) = unbounded();
let find_packet_sender_stake_stage = FindPacketSenderStakeStage::new(
packet_receiver,
find_packet_sender_stake_sender,
bank_forks.clone(),
cluster_info.clone(),
);
let (vote_find_packet_sender_stake_sender, vote_find_packet_sender_stake_receiver) =
unbounded();
let vote_find_packet_sender_stake_stage = FindPacketSenderStakeStage::new(
vote_packet_receiver,
vote_find_packet_sender_stake_sender,
bank_forks.clone(),
cluster_info.clone(),
);
let (verified_sender, verified_receiver) = unbounded();
let tpu_quic_t = solana_streamer::quic::spawn_server(
@@ -117,7 +140,7 @@ impl Tpu {
let sigverify_stage = {
let verifier = TransactionSigVerifier::default();
SigVerifyStage::new(packet_receiver, verified_sender, verifier)
SigVerifyStage::new(find_packet_sender_stake_receiver, verified_sender, verifier)
};
let (verified_tpu_vote_packets_sender, verified_tpu_vote_packets_receiver) = unbounded();
@@ -125,7 +148,7 @@ impl Tpu {
let vote_sigverify_stage = {
let verifier = TransactionSigVerifier::new_reject_non_vote();
SigVerifyStage::new(
vote_packet_receiver,
vote_find_packet_sender_stake_receiver,
verified_tpu_vote_packets_sender,
verifier,
)
@@ -179,6 +202,8 @@ impl Tpu {
cluster_info_vote_listener,
broadcast_stage,
tpu_quic_t,
find_packet_sender_stake_stage,
vote_find_packet_sender_stake_stage,
}
}
@@ -189,6 +214,8 @@ impl Tpu {
self.vote_sigverify_stage.join(),
self.cluster_info_vote_listener.join(),
self.banking_stage.join(),
self.find_packet_sender_stake_stage.join(),
self.vote_find_packet_sender_stake_stage.join(),
];
self.tpu_quic_t.join()?;
let broadcast_result = self.broadcast_stage.join();

View File

@@ -37,6 +37,17 @@ pub struct DeserializedPacketBatch {
pub unprocessed_packets: HashMap<usize, DeserializedPacket>,
}
/// References to a packet in `UnprocessedPacketBatches`, where
/// - batch_index references to `DeserializedPacketBatch`,
/// - packet_index references to `packet` within `DeserializedPacketBatch.packet_batch`
#[derive(Debug, Default)]
pub struct PacketLocator {
#[allow(dead_code)]
batch_index: usize,
#[allow(dead_code)]
packet_index: usize,
}
/// Currently each banking_stage thread has a `UnprocessedPacketBatches` buffer to store
/// PacketBatch's received from sigverify. Banking thread continuously scans the buffer
/// to pick proper packets to add to the block.
@@ -79,6 +90,50 @@ impl UnprocessedPacketBatches {
pub fn with_capacity(capacity: usize) -> Self {
UnprocessedPacketBatches(VecDeque::with_capacity(capacity))
}
/// Returns total number of all packets (including unprocessed and processed) in buffer
#[allow(dead_code)]
fn get_packets_count(&self) -> usize {
self.iter()
.map(|deserialized_packet_batch| deserialized_packet_batch.packet_batch.packets.len())
.sum()
}
/// Returns total number of unprocessed packets in buffer
#[allow(dead_code)]
fn get_unprocessed_packets_count(&self) -> usize {
self.iter()
.map(|deserialized_packet_batch| deserialized_packet_batch.unprocessed_packets.len())
.sum()
}
/// Iterates the inner `Vec<DeserializedPacketBatch>`.
/// Returns the flattened result of mapping each
/// `DeserializedPacketBatch` to a list the batch's inner
/// packets' sender's stake and their `PacketLocator`'s within the
/// `Vec<DeserializedPacketBatch>`.
#[allow(dead_code)]
fn get_stakes_and_locators(&self) -> (Vec<u64>, Vec<PacketLocator>) {
self.iter()
.enumerate()
.flat_map(|(batch_index, deserialized_packet_batch)| {
let packet_batch = &deserialized_packet_batch.packet_batch;
deserialized_packet_batch
.unprocessed_packets
.keys()
.map(move |packet_index| {
let p = &packet_batch.packets[*packet_index];
(
p.meta.sender_stake,
PacketLocator {
batch_index,
packet_index: *packet_index,
},
)
})
})
.unzip()
}
}
impl DeserializedPacketBatch {
@@ -135,8 +190,8 @@ impl DeserializedPacketBatch {
Some(&packet.data[msg_start..msg_end])
}
// Returns whether the given `PacketBatch` has any more remaining unprocessed
// transactions
/// Returns whether the given `PacketBatch` has any more remaining unprocessed
/// transactions
pub fn update_buffered_packets_with_new_unprocessed(
&mut self,
_original_unprocessed_indexes: &[usize],
@@ -159,8 +214,24 @@ mod tests {
use {
super::*,
solana_sdk::{signature::Keypair, system_transaction},
std::net::IpAddr,
};
fn packet_with_sender_stake(sender_stake: u64, ip: Option<IpAddr>) -> Packet {
let tx = system_transaction::transfer(
&Keypair::new(),
&solana_sdk::pubkey::new_rand(),
1,
Hash::new_unique(),
);
let mut packet = Packet::from_data(None, &tx).unwrap();
packet.meta.sender_stake = sender_stake;
if let Some(ip) = ip {
packet.meta.addr = ip;
}
packet
}
#[test]
fn test_packet_message() {
let keypair = Keypair::new();
@@ -175,4 +246,92 @@ mod tests {
transaction.message_data()
);
}
#[test]
fn test_get_packets_count() {
// create a buffer with 3 batches, each has 2 packets but only first one is valid
let batch_size = 2usize;
let batch_count = 3usize;
let unprocessed_packet_batches: UnprocessedPacketBatches = (0..batch_count)
.map(|_batch_index| {
DeserializedPacketBatch::new(
PacketBatch::new(
(0..batch_size)
.map(|packet_index| packet_with_sender_stake(packet_index as u64, None))
.collect(),
),
vec![0],
false,
)
})
.collect();
// Assert total packets count, and unprocessed packets count
assert_eq!(
batch_size * batch_count,
unprocessed_packet_batches.get_packets_count()
);
assert_eq!(
batch_count,
unprocessed_packet_batches.get_unprocessed_packets_count()
);
}
#[test]
fn test_get_stakes_and_locators_from_empty_buffer() {
let unprocessed_packet_batches = UnprocessedPacketBatches::default();
let (stakes, locators) = unprocessed_packet_batches.get_stakes_and_locators();
assert!(stakes.is_empty());
assert!(locators.is_empty());
}
#[test]
fn test_get_stakes_and_locators() {
solana_logger::setup();
// setup senders' address and stake
let senders: Vec<(IpAddr, u64)> = vec![
(IpAddr::from([127, 0, 0, 1]), 1),
(IpAddr::from([127, 0, 0, 2]), 2),
(IpAddr::from([127, 0, 0, 3]), 3),
];
// create a buffer with 3 batches, each has 2 packet from above sender.
// buffer looks like:
// [127.0.0.1, 127.0.0.2]
// [127.0.0.3, 127.0.0.1]
// [127.0.0.2, 127.0.0.3]
let batch_size = 2usize;
let batch_count = 3usize;
let unprocessed_packet_batches: UnprocessedPacketBatches = (0..batch_count)
.map(|batch_index| {
DeserializedPacketBatch::new(
PacketBatch::new(
(0..batch_size)
.map(|packet_index| {
let n = (batch_index * batch_size + packet_index) % senders.len();
packet_with_sender_stake(senders[n].1, Some(senders[n].0))
})
.collect(),
),
(0..batch_size).collect(),
false,
)
})
.collect();
let (stakes, locators) = unprocessed_packet_batches.get_stakes_and_locators();
// Produced stakes and locators should both have "batch_size * batch_count" entries;
assert_eq!(batch_size * batch_count, stakes.len());
assert_eq!(batch_size * batch_count, locators.len());
// Assert stakes and locators are in good order
locators.iter().enumerate().for_each(|(index, locator)| {
assert_eq!(
stakes[index],
senders[(locator.batch_index * batch_size + locator.packet_index) % senders.len()]
.1
);
});
}
}

View File

@@ -38,7 +38,7 @@ use {
blockstore::{
Blockstore, BlockstoreError, BlockstoreSignals, CompletedSlotsReceiver, PurgeType,
},
blockstore_db::{BlockstoreAdvancedOptions, BlockstoreOptions, BlockstoreRecoveryMode},
blockstore_db::{BlockstoreOptions, BlockstoreRecoveryMode, LedgerColumnOptions},
blockstore_processor::{self, TransactionStatusSender},
leader_schedule::FixedSchedule,
leader_schedule_cache::LeaderScheduleCache,
@@ -168,7 +168,7 @@ pub struct ValidatorConfig {
pub no_wait_for_vote_to_start_leader: bool,
pub accounts_shrink_ratio: AccountShrinkThreshold,
pub wait_to_vote_slot: Option<Slot>,
pub blockstore_advanced_options: BlockstoreAdvancedOptions,
pub ledger_column_options: LedgerColumnOptions,
}
impl Default for ValidatorConfig {
@@ -230,7 +230,7 @@ impl Default for ValidatorConfig {
accounts_shrink_ratio: AccountShrinkThreshold::default(),
accounts_db_config: None,
wait_to_vote_slot: None,
blockstore_advanced_options: BlockstoreAdvancedOptions::default(),
ledger_column_options: LedgerColumnOptions::default(),
}
}
}
@@ -1297,7 +1297,8 @@ fn load_blockstore(
ledger_path,
BlockstoreOptions {
recovery_mode: config.wal_recovery_mode.clone(),
advanced_options: config.blockstore_advanced_options.clone(),
column_options: config.ledger_column_options.clone(),
enforce_ulimit_nofile: config.enforce_ulimit_nofile,
..BlockstoreOptions::default()
},
)

View File

@@ -10,7 +10,7 @@ mod tests {
solana_ledger::{
blockstore::{make_many_slot_shreds, Blockstore},
blockstore_db::{
BlockstoreAdvancedOptions, BlockstoreOptions, BlockstoreRocksFifoOptions,
BlockstoreOptions, BlockstoreRocksFifoOptions, LedgerColumnOptions,
ShredStorageType,
},
get_tmp_ledger_path,
@@ -351,7 +351,7 @@ mod tests {
&ledger_path,
if config.fifo_compaction {
BlockstoreOptions {
advanced_options: BlockstoreAdvancedOptions {
column_options: LedgerColumnOptions {
shred_storage_type: ShredStorageType::RocksFifo(
BlockstoreRocksFifoOptions {
shred_data_cf_size: config.shred_data_cf_size,

View File

@@ -681,8 +681,8 @@ console.log(`Stake balance: ${stakeBalance}`)
// We can verify the state of our stake. This may take some time to become active
let stakeState = await connection.getStakeActivation(stakeAccount.publicKey);
console.log(`Stake Stake: ${stakeState.state}`);
// Stake State: inactive
console.log(`Stake state: ${stakeState.state}`);
// Stake state: inactive
// To delegate our stake, we get the current vote accounts and choose the first
let voteAccounts = await connection.getVoteAccounts();

View File

@@ -1531,7 +1531,7 @@ Returns the latest blockhash
- `RpcResponse<object>` - RpcResponse JSON object with `value` field set to a JSON object including:
- `blockhash: <string>` - a Hash as base-58 encoded string
- `lastValidBlockHeight: u64` - Slot
- `lastValidBlockHeight: <u64>` - last [block height](../../terminology.md#block-height) at which the blockhash will be valid
#### Example:
@@ -3059,7 +3059,7 @@ curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d '
Result:
```json
{ "jsonrpc": "2.0", "result": { "solana-core": "1.10.3" }, "id": 1 }
{ "jsonrpc": "2.0", "result": { "solana-core": "1.10.6" }, "id": 1 }
```
### getVoteAccounts
@@ -5147,7 +5147,7 @@ The result will be an RpcResponse JSON object with `value` set to a JSON object
- `blockhash: <string>` - a Hash as base-58 encoded string
- `feeCalculator: <object>` - FeeCalculator object, the fee schedule for this block hash
- `lastValidSlot: <u64>` - DEPRECATED - this value is inaccurate and should not be relied upon
- `lastValidBlockHeight: <u64>` - last [block height](../../terminology.md#block-height) at which a blockhash will be valid
- `lastValidBlockHeight: <u64>` - last [block height](../../terminology.md#block-height) at which the blockhash will be valid
#### Example:

View File

@@ -95,7 +95,7 @@ solana-validator ... \
```
Note that once running your validator *will terminate* if it's not able to write
its tower into etcd before submitting a vote transactioin, so it's essential
its tower into etcd before submitting a vote transaction, so it's essential
that your etcd endpoint remain accessible at all times.
### Secondary Validator

View File

@@ -2,29 +2,31 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-dos"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
publish = false
description = "Tool to send various requests to cluster in order to evaluate the effect on performance"
[dependencies]
bincode = "1.3.3"
clap = "2.33.1"
clap = {version = "3.1.5", features = ["derive", "cargo"]}
log = "0.4.14"
rand = "0.7.0"
solana-client = { path = "../client", version = "=1.10.3" }
solana-core = { path = "../core", version = "=1.10.3" }
solana-gossip = { path = "../gossip", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-net-utils = { path = "../net-utils", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
serde = "1.0.136"
solana-client = { path = "../client", version = "=1.10.6" }
solana-core = { path = "../core", version = "=1.10.6" }
solana-gossip = { path = "../gossip", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-net-utils = { path = "../net-utils", version = "=1.10.6" }
solana-perf = { path = "../perf", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dev-dependencies]
solana-local-cluster = { path = "../local-cluster", version = "=1.10.3" }
solana-local-cluster = { path = "../local-cluster", version = "=1.10.6" }

View File

@@ -1,12 +1,50 @@
//! DoS tool
//!
//! Sends requests to cluster in a loop to measure
//! the effect of handling these requests on the performance of the cluster.
//!
//! * `mode` argument defines interface to use (e.g. rpc, tvu, tpu)
//! * `data-type` argument specifies the type of the request.
//! Some request types might be used only with particular `mode` value.
//! For example, `get-account-info` is valid only with `mode=rpc`.
//!
//! Most options are provided for `data-type = transaction`.
//! These options allow to compose transaction which fails at
//! a particular stage of the processing pipeline.
//!
//! Example 1: send random transactions to TPU
//! ```bash
//! solana-dos --entrypoint 127.0.0.1:8001 --mode tpu --data-type random
//! ```
//!
//! Example 2: send unique transactions with valid recent blockhash to TPU
//! ```bash
//! solana-dos --entrypoint 127.0.0.1:8001 --mode tpu --data-type random
//! solana-dos --entrypoint 127.0.0.1:8001 --mode tpu \
//! --data-type transaction --generate-unique-transactions
//! --payer config/bootstrap-validator/identity.json \
//! --generate-valid-blockhash
//! ```
//!
#![allow(clippy::integer_arithmetic)]
use {
clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg},
clap::{crate_description, crate_name, crate_version, ArgEnum, Args, Parser},
log::*,
rand::{thread_rng, Rng},
serde::{Deserialize, Serialize},
solana_client::rpc_client::RpcClient,
solana_core::serve_repair::RepairProtocol,
solana_gossip::{contact_info::ContactInfo, gossip_service::discover},
solana_sdk::pubkey::Pubkey,
solana_sdk::{
hash::Hash,
instruction::{AccountMeta, CompiledInstruction, Instruction},
pubkey::Pubkey,
signature::{read_keypair_file, Keypair, Signature, Signer},
stake,
system_instruction::SystemInstruction,
system_program,
transaction::Transaction,
},
solana_streamer::socket::SocketAddrSpace,
std::{
net::{SocketAddr, UdpSocket},
@@ -23,38 +61,151 @@ fn get_repair_contact(nodes: &[ContactInfo]) -> ContactInfo {
contact
}
struct TransactionGenerator {
blockhash: Hash,
last_generated: Instant,
transaction_params: TransactionParams,
cached_transaction: Option<Transaction>,
}
impl TransactionGenerator {
fn new(transaction_params: TransactionParams) -> Self {
TransactionGenerator {
blockhash: Hash::default(),
last_generated: (Instant::now() - Duration::from_secs(100)),
transaction_params,
cached_transaction: None,
}
}
fn generate(&mut self, payer: Option<&Keypair>, rpc_client: &Option<RpcClient>) -> Transaction {
if !self.transaction_params.unique_transactions && self.cached_transaction.is_some() {
return self.cached_transaction.as_ref().unwrap().clone();
}
// generate a new blockhash every 1sec
if self.transaction_params.valid_blockhash
&& self.last_generated.elapsed().as_millis() > 1000
{
self.blockhash = rpc_client.as_ref().unwrap().get_latest_blockhash().unwrap();
self.last_generated = Instant::now();
}
// in order to evaluate the performance implications of the different transactions
// we create here transactions which are filtered out on different stages of processing pipeline
// create an arbitrary valid instruction
let lamports = 5;
let transfer_instruction = SystemInstruction::Transfer { lamports };
let program_ids = vec![system_program::id(), stake::program::id()];
// transaction with payer, in this case signatures are valid and num_signatures is irrelevant
// random payer will cause error "attempt to debit an account but found no record of a prior credit"
// if payer is correct, it will trigger error with not enough signatures
let transaction = if let Some(payer) = payer {
let instruction = Instruction::new_with_bincode(
program_ids[0],
&transfer_instruction,
vec![
AccountMeta::new(program_ids[0], false),
AccountMeta::new(program_ids[1], false),
],
);
Transaction::new_signed_with_payer(
&[instruction],
Some(&payer.pubkey()),
&[payer],
self.blockhash,
)
} else if self.transaction_params.valid_signatures {
// Since we don't provide a payer, this transaction will end up
// filtered at legacy.rs sanitize method (banking_stage) with error "a program cannot be payer"
let kpvals: Vec<Keypair> = (0..self.transaction_params.num_signatures)
.map(|_| Keypair::new())
.collect();
let keypairs: Vec<&Keypair> = kpvals.iter().collect();
let instructions = vec![CompiledInstruction::new(
0,
&transfer_instruction,
vec![0, 1],
)];
Transaction::new_with_compiled_instructions(
&keypairs,
&[],
self.blockhash,
program_ids,
instructions,
)
} else {
// Since we provided invalid signatures
// this transaction will end up filtered at legacy.rs (banking_stage) because
// num_required_signatures == 0
let instructions = vec![CompiledInstruction::new(
0,
&transfer_instruction,
vec![0, 1],
)];
let mut tx = Transaction::new_with_compiled_instructions(
&[] as &[&Keypair; 0],
&[],
self.blockhash,
program_ids,
instructions,
);
tx.signatures = vec![Signature::new_unique(); self.transaction_params.num_signatures];
tx
};
// if we need to generate only one transaction, we cache it to reuse later
if !self.transaction_params.unique_transactions {
self.cached_transaction = Some(transaction.clone());
}
transaction
}
}
fn run_dos(
nodes: &[ContactInfo],
iterations: usize,
entrypoint_addr: SocketAddr,
data_type: String,
data_size: usize,
mode: String,
data_input: Option<String>,
payer: Option<&Keypair>,
params: DosClientParameters,
) {
let mut target = None;
let mut rpc_client = None;
if nodes.is_empty() {
if mode == "rpc" {
rpc_client = Some(RpcClient::new_socket(entrypoint_addr));
if params.mode == Mode::Rpc {
rpc_client = Some(RpcClient::new_socket(params.entrypoint_addr));
}
target = Some(entrypoint_addr);
target = Some(params.entrypoint_addr);
} else {
info!("************ NODE ***********");
for node in nodes {
if node.gossip == entrypoint_addr {
target = match mode.as_str() {
"gossip" => Some(node.gossip),
"tvu" => Some(node.tvu),
"tvu_forwards" => Some(node.tvu_forwards),
"tpu" => Some(node.tpu),
"tpu_forwards" => Some(node.tpu_forwards),
"repair" => Some(node.repair),
"serve_repair" => Some(node.serve_repair),
"rpc" => {
info!("{:?}", node);
}
info!("ADDR = {}", params.entrypoint_addr);
for node in nodes {
if node.gossip == params.entrypoint_addr {
info!("{}", node.gossip);
target = match params.mode {
Mode::Gossip => Some(node.gossip),
Mode::Tvu => Some(node.tvu),
Mode::TvuForwards => Some(node.tvu_forwards),
Mode::Tpu => {
rpc_client = Some(RpcClient::new_socket(node.rpc));
Some(node.tpu)
}
Mode::TpuForwards => Some(node.tpu_forwards),
Mode::Repair => Some(node.repair),
Mode::ServeRepair => Some(node.serve_repair),
Mode::Rpc => {
rpc_client = Some(RpcClient::new_socket(node.rpc));
None
}
&_ => panic!("Unknown mode"),
};
break;
}
@@ -62,74 +213,83 @@ fn run_dos(
}
let target = target.expect("should have target");
info!("Targetting {}", target);
info!("Targeting {}", target);
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let mut data = Vec::new();
let mut transaction_generator = None;
match data_type.as_str() {
"repair_highest" => {
match params.data_type {
DataType::RepairHighest => {
let slot = 100;
let req = RepairProtocol::WindowIndexWithNonce(get_repair_contact(nodes), slot, 0, 0);
data = bincode::serialize(&req).unwrap();
}
"repair_shred" => {
DataType::RepairShred => {
let slot = 100;
let req =
RepairProtocol::HighestWindowIndexWithNonce(get_repair_contact(nodes), slot, 0, 0);
data = bincode::serialize(&req).unwrap();
}
"repair_orphan" => {
DataType::RepairOrphan => {
let slot = 100;
let req = RepairProtocol::OrphanWithNonce(get_repair_contact(nodes), slot, 0);
data = bincode::serialize(&req).unwrap();
}
"random" => {
data.resize(data_size, 0);
DataType::Random => {
data.resize(params.data_size, 0);
}
"transaction" => {
let tx = solana_perf::test_tx::test_tx();
DataType::Transaction => {
let tp = params.transaction_params;
info!("{:?}", tp);
transaction_generator = Some(TransactionGenerator::new(tp));
let tx = transaction_generator
.as_mut()
.unwrap()
.generate(payer, &rpc_client);
info!("{:?}", tx);
data = bincode::serialize(&tx).unwrap();
}
"get_account_info" => {}
"get_program_accounts" => {}
&_ => {
panic!("unknown data type");
}
DataType::GetAccountInfo => {}
DataType::GetProgramAccounts => {}
}
let mut last_log = Instant::now();
let mut count = 0;
let mut error_count = 0;
loop {
if mode == "rpc" {
match data_type.as_str() {
"get_account_info" => {
let res = rpc_client
.as_ref()
.unwrap()
.get_account(&Pubkey::from_str(data_input.as_ref().unwrap()).unwrap());
if res.is_err() {
error_count += 1;
}
}
"get_program_accounts" => {
let res = rpc_client.as_ref().unwrap().get_program_accounts(
&Pubkey::from_str(data_input.as_ref().unwrap()).unwrap(),
if params.mode == Mode::Rpc {
match params.data_type {
DataType::GetAccountInfo => {
let res = rpc_client.as_ref().unwrap().get_account(
&Pubkey::from_str(params.data_input.as_ref().unwrap()).unwrap(),
);
if res.is_err() {
error_count += 1;
}
}
&_ => {
DataType::GetProgramAccounts => {
let res = rpc_client.as_ref().unwrap().get_program_accounts(
&Pubkey::from_str(params.data_input.as_ref().unwrap()).unwrap(),
);
if res.is_err() {
error_count += 1;
}
}
_ => {
panic!("unsupported data type");
}
}
} else {
if data_type == "random" {
if params.data_type == DataType::Random {
thread_rng().fill(&mut data[..]);
}
if let Some(tg) = transaction_generator.as_mut() {
let tx = tg.generate(payer, &rpc_client);
info!("{:?}", tx);
data = bincode::serialize(&tx).unwrap();
}
let res = socket.send_to(&data, target);
if res.is_err() {
error_count += 1;
@@ -147,126 +307,173 @@ fn run_dos(
}
}
// command line parsing
#[derive(Parser)]
#[clap(name = crate_name!(),
version = crate_version!(),
about = crate_description!(),
rename_all = "kebab-case"
)]
struct DosClientParameters {
#[clap(long, arg_enum, help = "Interface to DoS")]
mode: Mode,
#[clap(long, arg_enum, help = "Type of data to send")]
data_type: DataType,
#[clap(
long = "entrypoint",
parse(try_from_str = addr_parser),
default_value = "127.0.0.1:8001",
help = "Gossip entrypoint address. Usually <ip>:8001"
)]
entrypoint_addr: SocketAddr,
#[clap(
long,
default_value = "128",
required_if_eq("data-type", "random"),
help = "Size of packet to DoS with, relevant only for data-type=random"
)]
data_size: usize,
#[clap(long, help = "Data to send [Optional]")]
data_input: Option<String>,
#[clap(long, help = "Just use entrypoint address directly")]
skip_gossip: bool,
#[clap(long, help = "Allow contacting private ip addresses")]
allow_private_addr: bool,
#[clap(flatten)]
transaction_params: TransactionParams,
}
#[derive(Args, Serialize, Deserialize, Debug, Default)]
#[clap(rename_all = "kebab-case")]
struct TransactionParams {
#[clap(
long,
default_value = "2",
help = "Number of signatures in transaction"
)]
num_signatures: usize,
#[clap(long, help = "Generate a valid blockhash for transaction")]
valid_blockhash: bool,
#[clap(long, help = "Generate valid signature(s) for transaction")]
valid_signatures: bool,
#[clap(long, help = "Generate unique transactions")]
unique_transactions: bool,
#[clap(
long = "payer",
help = "Payer's keypair file to fund transactions [Optional]"
)]
payer_filename: Option<String>,
}
#[derive(ArgEnum, Clone, Eq, PartialEq)]
enum Mode {
Gossip,
Tvu,
TvuForwards,
Tpu,
TpuForwards,
Repair,
ServeRepair,
Rpc,
}
#[derive(ArgEnum, Clone, Eq, PartialEq)]
enum DataType {
RepairHighest,
RepairShred,
RepairOrphan,
Random,
GetAccountInfo,
GetProgramAccounts,
Transaction,
}
fn addr_parser(addr: &str) -> Result<SocketAddr, &'static str> {
match solana_net_utils::parse_host_port(addr) {
Ok(v) => Ok(v),
Err(_) => Err("failed to parse entrypoint address"),
}
}
/// input checks which are not covered by Clap
fn validate_input(params: &DosClientParameters) {
if params.mode == Mode::Rpc
&& (params.data_type != DataType::GetAccountInfo
&& params.data_type != DataType::GetProgramAccounts)
{
panic!("unsupported data type");
}
if params.data_type != DataType::Transaction {
let tp = &params.transaction_params;
if tp.valid_blockhash
|| tp.valid_signatures
|| tp.unique_transactions
|| tp.payer_filename.is_some()
{
println!("Arguments valid-blockhash, valid-sign, unique-trans, payer are ignored if data-type != transaction");
}
}
if params.transaction_params.payer_filename.is_some()
&& params.transaction_params.valid_signatures
{
println!("Arguments valid-signatures is ignored if payer is provided");
}
}
fn main() {
solana_logger::setup_with_default("solana=info");
let matches = App::new(crate_name!())
.about(crate_description!())
.version(solana_version::version!())
.arg(
Arg::with_name("entrypoint")
.long("entrypoint")
.takes_value(true)
.value_name("HOST:PORT")
.help("Gossip entrypoint address. Usually <ip>:8001"),
)
.arg(
Arg::with_name("mode")
.long("mode")
.takes_value(true)
.value_name("MODE")
.possible_values(&[
"gossip",
"tvu",
"tvu_forwards",
"tpu",
"tpu_forwards",
"repair",
"serve_repair",
"rpc",
])
.help("Interface to DoS"),
)
.arg(
Arg::with_name("data_size")
.long("data-size")
.takes_value(true)
.value_name("BYTES")
.help("Size of packet to DoS with"),
)
.arg(
Arg::with_name("data_type")
.long("data-type")
.takes_value(true)
.value_name("TYPE")
.possible_values(&[
"repair_highest",
"repair_shred",
"repair_orphan",
"random",
"get_account_info",
"get_program_accounts",
"transaction",
])
.help("Type of data to send"),
)
.arg(
Arg::with_name("data_input")
.long("data-input")
.takes_value(true)
.value_name("TYPE")
.help("Data to send"),
)
.arg(
Arg::with_name("skip_gossip")
.long("skip-gossip")
.help("Just use entrypoint address directly"),
)
.arg(
Arg::with_name("allow_private_addr")
.long("allow-private-addr")
.takes_value(false)
.help("Allow contacting private ip addresses")
.hidden(true),
)
.get_matches();
let mut entrypoint_addr = SocketAddr::from(([127, 0, 0, 1], 8001));
if let Some(addr) = matches.value_of("entrypoint") {
entrypoint_addr = solana_net_utils::parse_host_port(addr).unwrap_or_else(|e| {
eprintln!("failed to parse entrypoint address: {}", e);
exit(1)
});
}
let data_size = value_t!(matches, "data_size", usize).unwrap_or(128);
let skip_gossip = matches.is_present("skip_gossip");
let mode = value_t_or_exit!(matches, "mode", String);
let data_type = value_t_or_exit!(matches, "data_type", String);
let data_input = value_t!(matches, "data_input", String).ok();
let cmd_params = DosClientParameters::parse();
validate_input(&cmd_params);
let mut nodes = vec![];
if !skip_gossip {
info!("Finding cluster entry: {:?}", entrypoint_addr);
let socket_addr_space = SocketAddrSpace::new(matches.is_present("allow_private_addr"));
if !cmd_params.skip_gossip {
info!("Finding cluster entry: {:?}", cmd_params.entrypoint_addr);
let socket_addr_space = SocketAddrSpace::new(cmd_params.allow_private_addr);
let (gossip_nodes, _validators) = discover(
None, // keypair
Some(&entrypoint_addr),
None, // num_nodes
Duration::from_secs(60), // timeout
None, // find_node_by_pubkey
Some(&entrypoint_addr), // find_node_by_gossip_addr
None, // my_gossip_addr
0, // my_shred_version
Some(&cmd_params.entrypoint_addr),
None, // num_nodes
Duration::from_secs(60), // timeout
None, // find_node_by_pubkey
Some(&cmd_params.entrypoint_addr), // find_node_by_gossip_addr
None, // my_gossip_addr
0, // my_shred_version
socket_addr_space,
)
.unwrap_or_else(|err| {
eprintln!("Failed to discover {} node: {:?}", entrypoint_addr, err);
eprintln!(
"Failed to discover {} node: {:?}",
cmd_params.entrypoint_addr, err
);
exit(1);
});
nodes = gossip_nodes;
}
info!("done found {} nodes", nodes.len());
let payer = cmd_params
.transaction_params
.payer_filename
.as_ref()
.map(|keypair_file_name| {
read_keypair_file(&keypair_file_name)
.unwrap_or_else(|_| panic!("bad keypair {:?}", keypair_file_name))
});
run_dos(
&nodes,
0,
entrypoint_addr,
data_type,
data_size,
mode,
data_input,
);
run_dos(&nodes, 0, payer.as_ref(), cmd_params);
}
#[cfg(test)]
@@ -284,34 +491,206 @@ pub mod test {
timestamp(),
)];
let entrypoint_addr = nodes[0].gossip;
run_dos(
&nodes,
1,
entrypoint_addr,
"random".to_string(),
10,
"tvu".to_string(),
None,
DosClientParameters {
entrypoint_addr,
mode: Mode::Tvu,
data_size: 10,
data_type: DataType::Random,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams::default(),
},
);
run_dos(
&nodes,
1,
entrypoint_addr,
"repair_highest".to_string(),
10,
"repair".to_string(),
None,
DosClientParameters {
entrypoint_addr,
mode: Mode::Repair,
data_size: 10,
data_type: DataType::RepairHighest,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams::default(),
},
);
run_dos(
&nodes,
1,
entrypoint_addr,
"repair_shred".to_string(),
10,
"serve_repair".to_string(),
None,
DosClientParameters {
entrypoint_addr,
mode: Mode::ServeRepair,
data_size: 10,
data_type: DataType::RepairShred,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams::default(),
},
);
}
#[test]
fn test_dos_local_cluster_transactions() {
let num_nodes = 1;
let cluster =
LocalCluster::new_with_equal_stakes(num_nodes, 100, 3, SocketAddrSpace::Unspecified);
assert_eq!(cluster.validators.len(), num_nodes);
let nodes = cluster.get_node_pubkeys();
let node = cluster.get_contact_info(&nodes[0]).unwrap().clone();
let nodes_slice = [node];
// send random transactions to TPU
// will be discarded on sigverify stage
run_dos(
&nodes_slice,
1,
None,
DosClientParameters {
entrypoint_addr: cluster.entry_point_info.gossip,
mode: Mode::Tpu,
data_size: 1024,
data_type: DataType::Random,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams::default(),
},
);
// send transactions to TPU with 2 random signatures
// will be filtered on dedup (because transactions are not unique)
run_dos(
&nodes_slice,
1,
None,
DosClientParameters {
entrypoint_addr: cluster.entry_point_info.gossip,
mode: Mode::Tpu,
data_size: 0, // irrelevant if not random
data_type: DataType::Transaction,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams {
num_signatures: 2,
valid_blockhash: false,
valid_signatures: false,
unique_transactions: false,
payer_filename: None,
},
},
);
// send *unique* transactions to TPU with 4 random signatures
// will be discarded on banking stage in legacy.rs
// ("there should be at least 1 RW fee-payer account")
run_dos(
&nodes_slice,
1,
None,
DosClientParameters {
entrypoint_addr: cluster.entry_point_info.gossip,
mode: Mode::Tpu,
data_size: 0, // irrelevant if not random
data_type: DataType::Transaction,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams {
num_signatures: 4,
valid_blockhash: false,
valid_signatures: false,
unique_transactions: true,
payer_filename: None,
},
},
);
// send unique transactions to TPU with 2 random signatures
// will be discarded on banking stage in legacy.rs (A program cannot be a payer)
// because we haven't provided a valid payer
run_dos(
&nodes_slice,
1,
None,
DosClientParameters {
entrypoint_addr: cluster.entry_point_info.gossip,
mode: Mode::Tpu,
data_size: 0, // irrelevant if not random
data_type: DataType::Transaction,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams {
num_signatures: 2,
valid_blockhash: false, // irrelevant without valid payer, because
// it will be filtered before blockhash validity checks
valid_signatures: true,
unique_transactions: true,
payer_filename: None,
},
},
);
// send unique transaction to TPU with valid blockhash
// will be discarded due to invalid hash
run_dos(
&nodes_slice,
1,
Some(&cluster.funding_keypair),
DosClientParameters {
entrypoint_addr: cluster.entry_point_info.gossip,
mode: Mode::Tpu,
data_size: 0, // irrelevant if not random
data_type: DataType::Transaction,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams {
num_signatures: 2,
valid_blockhash: false,
valid_signatures: true,
unique_transactions: true,
payer_filename: None,
},
},
);
// send unique transaction to TPU with valid blockhash
// will fail with error processing Instruction 0: missing required signature for instruction
run_dos(
&nodes_slice,
1,
Some(&cluster.funding_keypair),
DosClientParameters {
entrypoint_addr: cluster.entry_point_info.gossip,
mode: Mode::Tpu,
data_size: 0, // irrelevant if not random
data_type: DataType::Transaction,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams {
num_signatures: 2,
valid_blockhash: true,
valid_signatures: true,
unique_transactions: true,
payer_filename: None,
},
},
);
}
@@ -330,11 +709,23 @@ pub mod test {
run_dos(
&[node],
10_000_000,
cluster.entry_point_info.gossip,
"transaction".to_string(),
1000,
"tpu".to_string(),
None,
Some(&cluster.funding_keypair),
DosClientParameters {
entrypoint_addr: cluster.entry_point_info.gossip,
mode: Mode::Tpu,
data_size: 0, // irrelevant if not random
data_type: DataType::Transaction,
data_input: None,
skip_gossip: false,
allow_private_addr: false,
transaction_params: TransactionParams {
num_signatures: 2,
valid_blockhash: true,
valid_signatures: true,
unique_transactions: true,
payer_filename: None,
},
},
);
}
}

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-download-utils"
version = "1.10.3"
version = "1.10.6"
description = "Solana Download Utils"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -14,8 +14,8 @@ console = "0.15.0"
indicatif = "0.16.2"
log = "0.4.14"
reqwest = { version = "0.11.10", default-features = false, features = ["blocking", "rustls-tls", "json"] }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
[lib]
crate-type = ["lib"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-entry"
version = "1.10.3"
version = "1.10.6"
description = "Solana Entry"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -18,16 +18,16 @@ log = "0.4.11"
rand = "0.7.0"
rayon = "1.5.1"
serde = "1.0.136"
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-merkle-tree = { path = "../merkle-tree", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-merkle-tree = { path = "../merkle-tree", version = "=1.10.6" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-perf = { path = "../perf", version = "=1.10.6" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
[dev-dependencies]
matches = "0.1.9"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[lib]
crate-type = ["lib"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-faucet"
version = "1.10.3"
version = "1.10.6"
description = "Solana Faucet"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -17,12 +17,12 @@ crossbeam-channel = "0.5"
log = "0.4.14"
serde = "1.0.136"
serde_derive = "1.0.103"
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-cli-config = { path = "../cli-config", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-cli-config = { path = "../cli-config", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
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.10.3"
version = "1.10.6"
description = "Solana Frozen ABI"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -16,8 +16,9 @@ lazy_static = "1.4.0"
log = "0.4.14"
serde = "1.0.136"
serde_derive = "1.0.103"
serde_bytes = "0.11"
sha2 = "0.10.2"
solana-frozen-abi-macro = { path = "macro", version = "=1.10.3" }
solana-frozen-abi-macro = { path = "macro", version = "=1.10.6" }
thiserror = "1.0"
[target.'cfg(not(target_arch = "bpf"))'.dependencies]
@@ -26,7 +27,7 @@ im = { version = "15.0.0", features = ["rayon", "serde"] }
memmap2 = "0.5.3"
[target.'cfg(not(target_arch = "bpf"))'.dev-dependencies]
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[build-dependencies]
rustc_version = "0.4"

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-frozen-abi-macro"
version = "1.10.3"
version = "1.10.6"
description = "Solana Frozen ABI Macro"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"

View File

@@ -562,6 +562,17 @@ mod tests {
#[derive(Serialize, AbiExample)]
struct TestNewtypeStruct(i8);
#[frozen_abi(digest = "Hbs1X2X7TF2gFEfsspwfZ1JKr8ZGbLY3uidQBebqcMYt")]
#[derive(Serialize, AbiExample)]
struct Foo<'a> {
#[serde(with = "serde_bytes")]
data1: Vec<u8>,
#[serde(with = "serde_bytes")]
data2: &'a [u8],
#[serde(with = "serde_bytes")]
data3: &'a Vec<u8>,
}
#[frozen_abi(digest = "5qio5qYurHDv6fq5kcwP2ue2RBEazSZF8CPk2kUuwC2j")]
#[derive(Serialize, AbiExample)]
struct TestStructReversed {

View File

@@ -410,11 +410,18 @@ lazy_static! {
impl AbiExample for &Vec<u8> {
fn example() -> Self {
info!("AbiExample for (&Vec<T>): {}", type_name::<Self>());
info!("AbiExample for (&Vec<u8>): {}", type_name::<Self>());
&*VEC_U8
}
}
impl AbiExample for &[u8] {
fn example() -> Self {
info!("AbiExample for (&[u8]): {}", type_name::<Self>());
&VEC_U8[..]
}
}
impl<T: AbiExample> AbiExample for VecDeque<T> {
fn example() -> Self {
info!("AbiExample for (Vec<T>): {}", type_name::<Self>());

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-genesis-utils"
version = "1.10.3"
version = "1.10.6"
description = "Solana Genesis Utils"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -10,9 +10,9 @@ documentation = "https://docs.rs/solana-download-utils"
edition = "2021"
[dependencies]
solana-download-utils = { path = "../download-utils", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-download-utils = { path = "../download-utils", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
[lib]
crate-type = ["lib"]

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-genesis"
description = "Blockchain, Rebuilt for Scale"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -15,16 +15,16 @@ clap = "2.33.1"
serde = "1.0.136"
serde_json = "1.0.79"
serde_yaml = "0.8.23"
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-cli-config = { path = "../cli-config", version = "=1.10.3" }
solana-entry = { path = "../entry", version = "=1.10.3" }
solana-ledger = { path = "../ledger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-stake-program = { path = "../programs/stake", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-cli-config = { path = "../cli-config", version = "=1.10.6" }
solana-entry = { path = "../entry", version = "=1.10.6" }
solana-ledger = { path = "../ledger", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-stake-program = { path = "../programs/stake", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
tempfile = "3.3.0"
[[bin]]

View File

@@ -13,7 +13,7 @@ use {
},
solana_entry::poh::compute_hashes_per_tick,
solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account},
solana_ledger::{blockstore::create_new_ledger, blockstore_db::BlockstoreAdvancedOptions},
solana_ledger::{blockstore::create_new_ledger, blockstore_db::LedgerColumnOptions},
solana_runtime::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
solana_sdk::{
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
@@ -629,7 +629,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
&ledger_path,
&genesis_config,
max_genesis_archive_unpacked_size,
BlockstoreAdvancedOptions::default(),
LedgerColumnOptions::default(),
)?;
println!("{}", genesis_config);

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-geyser-plugin-interface"
description = "The Solana Geyser plugin interface."
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -11,8 +11,8 @@ documentation = "https://docs.rs/solana-geyser-plugin-interface"
[dependencies]
log = "0.4.11"
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
thiserror = "1.0.30"
[package.metadata.docs.rs]

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-geyser-plugin-manager"
description = "The Solana Geyser plugin manager."
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -16,13 +16,13 @@ json5 = "0.4.1"
libloading = "0.7.3"
log = "0.4.11"
serde_json = "1.0.79"
solana-geyser-plugin-interface = { path = "../geyser-plugin-interface", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-rpc = { path = "../rpc", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-geyser-plugin-interface = { path = "../geyser-plugin-interface", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-rpc = { path = "../rpc", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
thiserror = "1.0.30"
[package.metadata.docs.rs]

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-gossip"
description = "Blockchain, Rebuilt for Scale"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -27,24 +27,24 @@ rayon = "1.5.1"
serde = "1.0.136"
serde_bytes = "0.11"
serde_derive = "1.0.103"
solana-bloom = { path = "../bloom", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-client = { path = "../client", version = "=1.10.3" }
solana-entry = { path = "../entry", version = "=1.10.3" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.3" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.3" }
solana-ledger = { path = "../ledger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-net-utils = { path = "../net-utils", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-bloom = { path = "../bloom", version = "=1.10.6" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-client = { path = "../client", version = "=1.10.6" }
solana-entry = { path = "../entry", version = "=1.10.6" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.6" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.6" }
solana-ledger = { path = "../ledger", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-net-utils = { path = "../net-utils", version = "=1.10.6" }
solana-perf = { path = "../perf", version = "=1.10.6" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
thiserror = "1.0"
[dev-dependencies]

View File

@@ -32,8 +32,7 @@ fn bench_weighted_shuffle_new(bencher: &mut Bencher) {
let weights = make_weights(&mut rng);
bencher.iter(|| {
rng.fill(&mut seed[..]);
let shuffle = WeightedShuffle::new(&weights).unwrap();
shuffle
WeightedShuffle::new("", &weights)
.shuffle(&mut ChaChaRng::from_seed(seed))
.collect::<Vec<_>>()
});

View File

@@ -635,6 +635,10 @@ impl ClusterInfo {
self.my_contact_info.write().unwrap().id = id;
self.insert_self();
self.push_message(CrdsValue::new_signed(
CrdsData::Version(Version::new(self.id())),
&self.keypair(),
));
self.push_self(&HashMap::new(), None);
}
@@ -2011,7 +2015,7 @@ impl ClusterInfo {
return packet_batch;
}
let mut rng = rand::thread_rng();
let shuffle = WeightedShuffle::new(&scores).unwrap().shuffle(&mut rng);
let shuffle = WeightedShuffle::new("handle-pull-requests", &scores).shuffle(&mut rng);
let mut total_bytes = 0;
let mut sent = 0;
for (addr, response) in shuffle.map(|i| &responses[i]) {

View File

@@ -246,8 +246,7 @@ impl CrdsGossipPull {
return Err(CrdsGossipError::NoPeers);
}
let mut rng = rand::thread_rng();
let mut peers = WeightedShuffle::new(&weights)
.unwrap()
let mut peers = WeightedShuffle::new("pull-options", &weights)
.shuffle(&mut rng)
.map(|i| peers[i]);
let peer = {

View File

@@ -169,8 +169,7 @@ impl CrdsGossipPush {
.filter(|(_, stake)| *stake > 0)
.collect();
let weights: Vec<_> = peers.iter().map(|(_, stake)| *stake).collect();
WeightedShuffle::new(&weights)
.unwrap()
WeightedShuffle::new("prune-received-cache", &weights)
.shuffle(&mut rng)
.map(move |i| peers[i])
};
@@ -370,7 +369,7 @@ impl CrdsGossipPush {
return;
}
let num_bloom_items = MIN_NUM_BLOOM_ITEMS.max(network_size);
let shuffle = WeightedShuffle::new(&weights).unwrap().shuffle(&mut rng);
let shuffle = WeightedShuffle::new("push-options", &weights).shuffle(&mut rng);
let mut active_set = self.active_set.write().unwrap();
let need = Self::compute_need(self.num_active, active_set.len(), ratio);
for peer in shuffle.map(|i| peers[i]) {

View File

@@ -15,12 +15,6 @@ use {
},
};
#[derive(Debug)]
pub enum WeightedShuffleError<T> {
NegativeWeight(T),
SumOverflow,
}
/// Implements an iterator where indices are shuffled according to their
/// weights:
/// - Returned indices are unique in the range [0, weights.len()).
@@ -43,34 +37,48 @@ impl<T> WeightedShuffle<T>
where
T: Copy + Default + PartialOrd + AddAssign + CheckedAdd,
{
/// Returns error if:
/// - any of the weights are negative.
/// - sum of weights overflows.
pub fn new(weights: &[T]) -> Result<Self, WeightedShuffleError<T>> {
/// If weights are negative or overflow the total sum
/// they are treated as zero.
pub fn new(name: &'static str, weights: &[T]) -> Self {
let size = weights.len() + 1;
let zero = <T as Default>::default();
let mut arr = vec![zero; size];
let mut sum = zero;
let mut zeros = Vec::default();
let mut num_negative = 0;
let mut num_overflow = 0;
for (mut k, &weight) in (1usize..).zip(weights) {
#[allow(clippy::neg_cmp_op_on_partial_ord)]
// weight < zero does not work for NaNs.
if !(weight >= zero) {
return Err(WeightedShuffleError::NegativeWeight(weight));
zeros.push(k - 1);
num_negative += 1;
continue;
}
if weight == zero {
zeros.push(k - 1);
continue;
}
sum = sum
.checked_add(&weight)
.ok_or(WeightedShuffleError::SumOverflow)?;
sum = match sum.checked_add(&weight) {
Some(val) => val,
None => {
zeros.push(k - 1);
num_overflow += 1;
continue;
}
};
while k < size {
arr[k] += weight;
k += k & k.wrapping_neg();
}
}
Ok(Self { arr, sum, zeros })
if num_negative > 0 {
datapoint_error!("weighted-shuffle-negative", (name, num_negative, i64));
}
if num_overflow > 0 {
datapoint_error!("weighted-shuffle-overflow", (name, num_overflow, i64));
}
Self { arr, sum, zeros }
}
}
@@ -343,7 +351,7 @@ mod tests {
fn test_weighted_shuffle_empty_weights() {
let weights = Vec::<u64>::new();
let mut rng = rand::thread_rng();
let shuffle = WeightedShuffle::new(&weights).unwrap();
let shuffle = WeightedShuffle::new("", &weights);
assert!(shuffle.clone().shuffle(&mut rng).next().is_none());
assert!(shuffle.first(&mut rng).is_none());
}
@@ -354,7 +362,7 @@ mod tests {
let weights = vec![0u64; 5];
let seed = [37u8; 32];
let mut rng = ChaChaRng::from_seed(seed);
let shuffle = WeightedShuffle::new(&weights).unwrap();
let shuffle = WeightedShuffle::new("", &weights);
assert_eq!(
shuffle.clone().shuffle(&mut rng).collect::<Vec<_>>(),
[1, 4, 2, 3, 0]
@@ -372,14 +380,14 @@ mod tests {
let weights = [1, 0, 1000, 0, 0, 10, 100, 0];
let mut counts = [0; 8];
for _ in 0..100000 {
let mut shuffle = WeightedShuffle::new(&weights).unwrap().shuffle(&mut rng);
let mut shuffle = WeightedShuffle::new("", &weights).shuffle(&mut rng);
counts[shuffle.next().unwrap()] += 1;
let _ = shuffle.count(); // consume the rest.
}
assert_eq!(counts, [95, 0, 90069, 0, 0, 908, 8928, 0]);
let mut counts = [0; 8];
for _ in 0..100000 {
let mut shuffle = WeightedShuffle::new(&weights).unwrap();
let mut shuffle = WeightedShuffle::new("", &weights);
shuffle.remove_index(5);
shuffle.remove_index(3);
shuffle.remove_index(1);
@@ -390,6 +398,26 @@ mod tests {
assert_eq!(counts, [97, 0, 90862, 0, 0, 0, 9041, 0]);
}
#[test]
fn test_weighted_shuffle_negative_overflow() {
const SEED: [u8; 32] = [48u8; 32];
let weights = [19i64, 23, 7, 0, 0, 23, 3, 0, 5, 0, 19, 29];
let mut rng = ChaChaRng::from_seed(SEED);
let shuffle = WeightedShuffle::new("", &weights);
assert_eq!(
shuffle.shuffle(&mut rng).collect::<Vec<_>>(),
[8, 1, 5, 10, 11, 0, 2, 6, 9, 4, 3, 7]
);
// Negative weights and overflowing ones are treated as zero.
let weights = [19, 23, 7, -57, i64::MAX, 23, 3, i64::MAX, 5, -79, 19, 29];
let mut rng = ChaChaRng::from_seed(SEED);
let shuffle = WeightedShuffle::new("", &weights);
assert_eq!(
shuffle.shuffle(&mut rng).collect::<Vec<_>>(),
[8, 1, 5, 10, 11, 0, 2, 6, 9, 4, 3, 7]
);
}
#[test]
fn test_weighted_shuffle_hard_coded() {
let weights = [
@@ -397,7 +425,7 @@ mod tests {
];
let seed = [48u8; 32];
let mut rng = ChaChaRng::from_seed(seed);
let mut shuffle = WeightedShuffle::new(&weights).unwrap();
let mut shuffle = WeightedShuffle::new("", &weights);
assert_eq!(
shuffle.clone().shuffle(&mut rng).collect::<Vec<_>>(),
[2, 12, 18, 0, 14, 15, 17, 10, 1, 9, 7, 6, 13, 20, 4, 19, 3, 8, 11, 16, 5]
@@ -417,7 +445,7 @@ mod tests {
assert_eq!(shuffle.first(&mut rng), Some(4));
let seed = [37u8; 32];
let mut rng = ChaChaRng::from_seed(seed);
let mut shuffle = WeightedShuffle::new(&weights).unwrap();
let mut shuffle = WeightedShuffle::new("", &weights);
assert_eq!(
shuffle.clone().shuffle(&mut rng).collect::<Vec<_>>(),
[19, 3, 15, 14, 6, 10, 17, 18, 9, 2, 4, 1, 0, 7, 8, 20, 12, 13, 16, 5, 11]
@@ -447,13 +475,13 @@ mod tests {
let mut seed = [0u8; 32];
rng.fill(&mut seed[..]);
let mut rng = ChaChaRng::from_seed(seed);
let shuffle = WeightedShuffle::new(&weights).unwrap();
let shuffle = WeightedShuffle::new("", &weights);
let shuffle: Vec<_> = shuffle.shuffle(&mut rng).collect();
let mut rng = ChaChaRng::from_seed(seed);
let shuffle_slow = weighted_shuffle_slow(&mut rng, weights.clone());
assert_eq!(shuffle, shuffle_slow);
let mut rng = ChaChaRng::from_seed(seed);
let shuffle = WeightedShuffle::new(&weights).unwrap();
let shuffle = WeightedShuffle::new("", &weights);
assert_eq!(shuffle.first(&mut rng), Some(shuffle_slow[0]));
}
}

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-install"
description = "The solana cluster software installer"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -26,12 +26,12 @@ reqwest = { version = "0.11.10", default-features = false, features = ["blocking
semver = "1.0.6"
serde = { version = "1.0.136", features = ["derive"] }
serde_yaml = "0.8.23"
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-client = { path = "../client", version = "=1.10.3" }
solana-config-program = { path = "../programs/config", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-client = { path = "../client", version = "=1.10.6" }
solana-config-program = { path = "../programs/config", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
tar = "0.4.38"
tempfile = "3.3.0"
url = "2.2.2"

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-keygen"
version = "1.10.3"
version = "1.10.6"
description = "Solana key generation utility"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -14,11 +14,11 @@ bs58 = "0.4.0"
clap = "2.33"
dirs-next = "2.0.0"
num_cpus = "1.13.1"
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-cli-config = { path = "../cli-config", version = "=1.10.3" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-cli-config = { path = "../cli-config", version = "=1.10.6" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
tiny-bip39 = "0.8.2"
[[bin]]

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-ledger-tool"
description = "Blockchain, Rebuilt for Scale"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -21,20 +21,20 @@ log = { version = "0.4.14" }
regex = "1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.79"
solana-clap-utils = { path = "../clap-utils", version = "=1.10.3" }
solana-cli-output = { path = "../cli-output", version = "=1.10.3" }
solana-core = { path = "../core", version = "=1.10.3" }
solana-entry = { path = "../entry", version = "=1.10.3" }
solana-ledger = { path = "../ledger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-stake-program = { path = "../programs/stake", version = "=1.10.3" }
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-clap-utils = { path = "../clap-utils", version = "=1.10.6" }
solana-cli-output = { path = "../cli-output", version = "=1.10.6" }
solana-core = { path = "../core", version = "=1.10.6" }
solana-entry = { path = "../entry", version = "=1.10.6" }
solana-ledger = { path = "../ledger", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-stake-program = { path = "../programs/stake", version = "=1.10.6" }
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
tokio = { version = "1", features = ["full"] }
[target.'cfg(not(target_env = "msvc"))'.dependencies]

View File

@@ -25,8 +25,8 @@ use {
bank_forks_utils,
blockstore::{create_new_ledger, Blockstore, PurgeType},
blockstore_db::{
self, AccessType, BlockstoreAdvancedOptions, BlockstoreOptions, BlockstoreRecoveryMode,
Database,
self, AccessType, BlockstoreOptions, BlockstoreRecoveryMode, Database,
LedgerColumnOptions,
},
blockstore_processor::{BlockstoreProcessorError, ProcessOptions},
shred::Shred,
@@ -1719,7 +1719,7 @@ fn main() {
&output_directory,
&genesis_config,
solana_runtime::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
BlockstoreAdvancedOptions::default(),
LedgerColumnOptions::default(),
)
.unwrap_or_else(|err| {
eprintln!("Failed to write genesis config: {:?}", err);

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-ledger"
version = "1.10.3"
version = "1.10.6"
description = "Solana ledger"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -11,6 +11,7 @@ edition = "2021"
[dependencies]
bincode = "1.3.3"
bitflags = "1.3.1"
byteorder = "1.4.3"
chrono = { version = "0.4.11", features = ["serde"] }
chrono-humanize = "0.2.1"
@@ -21,6 +22,7 @@ itertools = "0.10.3"
lazy_static = "1.4.0"
libc = "0.2.120"
log = { version = "0.4.14" }
lru = "0.7.3"
num-derive = "0.3"
num-traits = "0.2"
num_cpus = "1.13.1"
@@ -32,21 +34,21 @@ reed-solomon-erasure = { version = "5.0.1", features = ["simd-accel"] }
serde = "1.0.136"
serde_bytes = "0.11.5"
sha2 = "0.10.2"
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.10.3" }
solana-entry = { path = "../entry", version = "=1.10.3" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.3" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.3" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.10.3" }
solana-storage-proto = { path = "../storage-proto", version = "=1.10.3" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.10.6" }
solana-entry = { path = "../entry", version = "=1.10.6" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.6" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-perf = { path = "../perf", version = "=1.10.6" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.6" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.10.6" }
solana-storage-proto = { path = "../storage-proto", version = "=1.10.6" }
solana-transaction-status = { path = "../transaction-status", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
tempfile = "3.3.0"
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }
@@ -63,8 +65,8 @@ features = ["lz4"]
[dev-dependencies]
assert_matches = "1.5.0"
matches = "0.1.9"
solana-account-decoder = { path = "../account-decoder", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-account-decoder = { path = "../account-decoder", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[build-dependencies]
rustc_version = "0.4"

View File

@@ -5,8 +5,8 @@ use {
crate::{
ancestor_iterator::AncestorIterator,
blockstore_db::{
columns as cf, AccessType, BlockstoreAdvancedOptions, BlockstoreOptions, Column,
ColumnName, Database, IteratorDirection, IteratorMode, LedgerColumn, Result,
columns as cf, AccessType, BlockstoreOptions, Column, ColumnName, Database,
IteratorDirection, IteratorMode, LedgerColumn, LedgerColumnOptions, Result,
ShredStorageType, WriteBatch,
},
blockstore_meta::*,
@@ -16,6 +16,7 @@ use {
max_ticks_per_n_shreds, ErasureSetId, Result as ShredResult, Shred, ShredId, ShredType,
Shredder, SHRED_PAYLOAD_SIZE,
},
slot_stats::{ShredSource, SlotsStats},
},
bincode::deserialize,
crossbeam_channel::{bounded, Receiver, Sender, TrySendError},
@@ -50,7 +51,7 @@ use {
borrow::Cow,
cell::RefCell,
cmp,
collections::{hash_map::Entry as HashMapEntry, BTreeMap, BTreeSet, HashMap, HashSet},
collections::{hash_map::Entry as HashMapEntry, BTreeSet, HashMap, HashSet},
convert::TryInto,
fs,
io::{Error as IoError, ErrorKind},
@@ -60,7 +61,6 @@ use {
atomic::{AtomicBool, Ordering},
Arc, Mutex, RwLock, RwLockWriteGuard,
},
time::Instant,
},
tempfile::{Builder, TempDir},
thiserror::Error,
@@ -171,34 +171,14 @@ pub struct Blockstore {
block_height_cf: LedgerColumn<cf::BlockHeight>,
program_costs_cf: LedgerColumn<cf::ProgramCosts>,
bank_hash_cf: LedgerColumn<cf::BankHash>,
last_root: Arc<RwLock<Slot>>,
insert_shreds_lock: Arc<Mutex<()>>,
last_root: RwLock<Slot>,
insert_shreds_lock: Mutex<()>,
pub new_shreds_signals: Vec<Sender<bool>>,
pub completed_slots_senders: Vec<CompletedSlotsSender>,
pub lowest_cleanup_slot: Arc<RwLock<Slot>>,
pub lowest_cleanup_slot: RwLock<Slot>,
no_compaction: bool,
slots_stats: Arc<Mutex<SlotsStats>>,
advanced_options: BlockstoreAdvancedOptions,
}
struct SlotsStats {
last_cleanup_ts: Instant,
stats: BTreeMap<Slot, SlotStats>,
}
impl Default for SlotsStats {
fn default() -> Self {
SlotsStats {
last_cleanup_ts: Instant::now(),
stats: BTreeMap::new(),
}
}
}
#[derive(Default)]
struct SlotStats {
num_repaired: usize,
num_recovered: usize,
slots_stats: Mutex<SlotsStats>,
column_options: LedgerColumnOptions,
}
pub struct IndexMetaWorkingSetEntry {
@@ -223,13 +203,6 @@ pub struct SlotMetaWorkingSetEntry {
did_insert_occur: bool,
}
#[derive(PartialEq, Debug, Clone)]
enum ShredSource {
Turbine,
Repaired,
Recovered,
}
#[derive(Default)]
pub struct BlockstoreInsertionMetrics {
pub num_shreds: usize,
@@ -521,8 +494,8 @@ impl BlockstoreRocksDbColumnFamilyMetrics {
}
macro_rules! rocksdb_metric_header {
($metric_name:literal, $cf_name:literal, $advanced_options:expr) => {
match $advanced_options.shred_storage_type {
($metric_name:literal, $cf_name:literal, $column_options:expr) => {
match $column_options.shred_storage_type {
ShredStorageType::RocksLevel =>
rocksdb_metric_header!(@all_fields $metric_name, $cf_name, "rocks_level"),
ShredStorageType::RocksFifo(_) =>
@@ -569,9 +542,9 @@ impl Blockstore {
fn do_open(ledger_path: &Path, options: BlockstoreOptions) -> Result<Blockstore> {
fs::create_dir_all(&ledger_path)?;
let blockstore_path = ledger_path.join(Self::blockstore_directory(
&options.advanced_options.shred_storage_type,
&options.column_options.shred_storage_type,
));
let advanced_options = options.advanced_options.clone();
let column_options = options.column_options.clone();
adjust_ulimit_nofile(options.enforce_ulimit_nofile)?;
@@ -615,7 +588,7 @@ impl Blockstore {
.next()
.map(|(slot, _)| slot)
.unwrap_or(0);
let last_root = Arc::new(RwLock::new(max_root));
let last_root = RwLock::new(max_root);
// Get active transaction-status index or 0
let active_transaction_status_index = db
@@ -659,12 +632,12 @@ impl Blockstore {
bank_hash_cf,
new_shreds_signals: vec![],
completed_slots_senders: vec![],
insert_shreds_lock: Arc::new(Mutex::new(())),
insert_shreds_lock: Mutex::<()>::default(),
last_root,
lowest_cleanup_slot: Arc::new(RwLock::new(0)),
lowest_cleanup_slot: RwLock::<Slot>::default(),
no_compaction: false,
slots_stats: Arc::new(Mutex::new(SlotsStats::default())),
advanced_options,
slots_stats: Mutex::<SlotsStats>::default(),
column_options,
};
if initialize_transaction_status_index {
blockstore.initialize_transaction_status_index()?;
@@ -961,101 +934,101 @@ impl Blockstore {
/// Collects and reports [`BlockstoreRocksDbColumnFamilyMetrics`] for the
/// all the column families.
pub fn submit_rocksdb_cf_metrics_for_all_cfs(&self) {
let advanced_options = &self.advanced_options;
let column_options = &self.column_options;
self.submit_rocksdb_cf_metrics::<cf::SlotMeta>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"slot_meta",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::DeadSlots>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"dead_slots",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::DuplicateSlots>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"duplicate_slots",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::ErasureMeta>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"erasure_meta",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::Orphans>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"orphans",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::BankHash>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"bank_hash",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::Root>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"root",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::Index>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"index",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::ShredData>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"shred_data",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::ShredCode>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"shred_code",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::TransactionStatus>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"transaction_status",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::AddressSignatures>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"address_signature",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::TransactionMemos>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"transaction_memos",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::TransactionStatusIndex>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"transaction_status_index",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::Rewards>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"rewards",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::Blocktime>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"blocktime",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::PerfSamples>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"perf_sample",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::BlockHeight>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"block_height",
advanced_options
column_options
));
self.submit_rocksdb_cf_metrics::<cf::ProgramCosts>(rocksdb_metric_header!(
"blockstore_rocksdb_cfs",
"program_costs",
advanced_options
column_options
));
}
@@ -1250,13 +1223,13 @@ impl Blockstore {
let mut newly_completed_data_sets: Vec<CompletedDataSetInfo> = vec![];
let mut inserted_indices = Vec::new();
for (i, (shred, is_repaired)) in shreds.into_iter().zip(is_repaired).enumerate() {
let shred_source = if is_repaired {
ShredSource::Repaired
} else {
ShredSource::Turbine
};
match shred.shred_type() {
ShredType::Data => {
let shred_source = if is_repaired {
ShredSource::Repaired
} else {
ShredSource::Turbine
};
match self.check_insert_data_shred(
shred,
&mut erasure_metas,
@@ -1295,7 +1268,7 @@ impl Blockstore {
&mut index_meta_time,
handle_duplicate,
is_trusted,
is_repaired,
shred_source,
metrics,
);
}
@@ -1464,10 +1437,9 @@ impl Blockstore {
}
fn erasure_mismatch(shred1: &Shred, shred2: &Shred) -> bool {
// TODO should also compare first-coding-index once position field is
// populated across cluster.
shred1.coding_header.num_coding_shreds != shred2.coding_header.num_coding_shreds
|| shred1.coding_header.num_data_shreds != shred2.coding_header.num_data_shreds
|| shred1.first_coding_index() != shred2.first_coding_index()
}
#[allow(clippy::too_many_arguments)]
@@ -1481,7 +1453,7 @@ impl Blockstore {
index_meta_time: &mut u64,
handle_duplicate: &F,
is_trusted: bool,
is_repaired: bool,
shred_source: ShredSource,
metrics: &mut BlockstoreInsertionMetrics,
) -> bool
where
@@ -1548,13 +1520,10 @@ impl Blockstore {
return false;
}
if is_repaired {
let mut slots_stats = self.slots_stats.lock().unwrap();
let mut e = slots_stats.stats.entry(slot).or_default();
e.num_repaired += 1;
}
self.slots_stats
.lock()
.unwrap()
.add_shred(slot, shred_source);
// insert coding shred into rocks
let result = self
.insert_coding_shred(index_meta, &shred, write_batch)
@@ -1700,7 +1669,7 @@ impl Blockstore {
just_inserted_shreds,
&self.last_root,
leader_schedule,
shred_source.clone(),
shred_source,
) {
return Err(InsertDataShredError::InvalidShred);
}
@@ -1972,49 +1941,12 @@ impl Blockstore {
end_index,
})
.collect();
if shred_source == ShredSource::Repaired || shred_source == ShredSource::Recovered {
{
let mut slots_stats = self.slots_stats.lock().unwrap();
let mut e = slots_stats.stats.entry(slot_meta.slot).or_default();
if shred_source == ShredSource::Repaired {
e.num_repaired += 1;
slots_stats.add_shred(slot_meta.slot, shred_source);
if slot_meta.is_full() {
slots_stats.set_full(slot_meta);
}
if shred_source == ShredSource::Recovered {
e.num_recovered += 1;
}
}
if slot_meta.is_full() {
let (num_repaired, num_recovered) = {
let mut slots_stats = self.slots_stats.lock().unwrap();
if let Some(e) = slots_stats.stats.remove(&slot_meta.slot) {
if slots_stats.last_cleanup_ts.elapsed().as_secs() > 30 {
let root = self.last_root();
slots_stats.stats = slots_stats.stats.split_off(&root);
slots_stats.last_cleanup_ts = Instant::now();
}
(e.num_repaired, e.num_recovered)
} else {
(0, 0)
}
};
datapoint_info!(
"shred_insert_is_full",
(
"total_time_ms",
solana_sdk::timing::timestamp() - slot_meta.first_shred_timestamp,
i64
),
("slot", slot_meta.slot, i64),
(
"last_index",
slot_meta
.last_index
.and_then(|ix| i64::try_from(ix).ok())
.unwrap_or(-1),
i64
),
("num_repaired", num_repaired, i64),
("num_recovered", num_recovered, i64),
);
}
trace!("inserted shred into slot {:?} and index {:?}", slot, index);
Ok(newly_completed_data_sets)
@@ -2109,7 +2041,7 @@ impl Blockstore {
ticks_per_slot: u64,
parent: Option<u64>,
is_full_slot: bool,
keypair: &Arc<Keypair>,
keypair: &Keypair,
entries: Vec<Entry>,
version: u16,
) -> Result<usize /*num of data shreds*/> {
@@ -3574,7 +3506,7 @@ impl Blockstore {
self.db.is_primary_access()
}
pub fn scan_and_fix_roots(&self, exit: &Arc<AtomicBool>) -> Result<()> {
pub fn scan_and_fix_roots(&self, exit: &AtomicBool) -> Result<()> {
let ancestor_iterator = AncestorIterator::new(self.last_root(), self)
.take_while(|&slot| slot >= self.lowest_cleanup_slot());
@@ -4150,20 +4082,20 @@ pub fn create_new_ledger(
ledger_path: &Path,
genesis_config: &GenesisConfig,
max_genesis_archive_unpacked_size: u64,
advanced_options: BlockstoreAdvancedOptions,
column_options: LedgerColumnOptions,
) -> Result<Hash> {
Blockstore::destroy(ledger_path)?;
genesis_config.write(ledger_path)?;
// Fill slot 0 with ticks that link back to the genesis_config to bootstrap the ledger.
let blockstore_dir = Blockstore::blockstore_directory(&advanced_options.shred_storage_type);
let blockstore_dir = Blockstore::blockstore_directory(&column_options.shred_storage_type);
let blockstore = Blockstore::open_with_options(
ledger_path,
BlockstoreOptions {
access_type: AccessType::PrimaryOnly,
recovery_mode: None,
enforce_ulimit_nofile: false,
advanced_options: advanced_options.clone(),
column_options: column_options.clone(),
},
)?;
let ticks_per_slot = genesis_config.ticks_per_slot;
@@ -4332,7 +4264,7 @@ macro_rules! create_new_tmp_ledger {
$crate::blockstore::create_new_ledger_from_name(
$crate::tmp_ledger_name!(),
$genesis_config,
$crate::blockstore_db::BlockstoreAdvancedOptions::default(),
$crate::blockstore_db::LedgerColumnOptions::default(),
)
};
}
@@ -4343,7 +4275,7 @@ macro_rules! create_new_tmp_ledger_auto_delete {
$crate::blockstore::create_new_ledger_from_name_auto_delete(
$crate::tmp_ledger_name!(),
$genesis_config,
$crate::blockstore_db::BlockstoreAdvancedOptions::default(),
$crate::blockstore_db::LedgerColumnOptions::default(),
)
};
}
@@ -4354,7 +4286,7 @@ macro_rules! create_new_tmp_ledger_fifo_auto_delete {
$crate::blockstore::create_new_ledger_from_name_auto_delete(
$crate::tmp_ledger_name!(),
$genesis_config,
$crate::blockstore_db::BlockstoreAdvancedOptions {
$crate::blockstore_db::LedgerColumnOptions {
shred_storage_type: $crate::blockstore_db::ShredStorageType::RocksFifo(
$crate::blockstore_db::BlockstoreRocksFifoOptions::default(),
),
@@ -4388,10 +4320,10 @@ pub fn verify_shred_slots(slot: Slot, parent_slot: Slot, last_root: Slot) -> boo
pub fn create_new_ledger_from_name(
name: &str,
genesis_config: &GenesisConfig,
advanced_options: BlockstoreAdvancedOptions,
column_options: LedgerColumnOptions,
) -> (PathBuf, Hash) {
let (ledger_path, blockhash) =
create_new_ledger_from_name_auto_delete(name, genesis_config, advanced_options);
create_new_ledger_from_name_auto_delete(name, genesis_config, column_options);
(ledger_path.into_path(), blockhash)
}
@@ -4402,14 +4334,14 @@ pub fn create_new_ledger_from_name(
pub fn create_new_ledger_from_name_auto_delete(
name: &str,
genesis_config: &GenesisConfig,
advanced_options: BlockstoreAdvancedOptions,
column_options: LedgerColumnOptions,
) -> (TempDir, Hash) {
let ledger_path = get_ledger_path_from_name_auto_delete(name);
let blockhash = create_new_ledger(
ledger_path.path(),
genesis_config,
MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
advanced_options,
column_options,
)
.unwrap();
(ledger_path, blockhash)
@@ -4718,7 +4650,7 @@ pub mod tests {
let blockstore = Blockstore::open_with_options(
ledger_path.path(),
BlockstoreOptions {
advanced_options: BlockstoreAdvancedOptions {
column_options: LedgerColumnOptions {
shred_storage_type: ShredStorageType::RocksFifo(
BlockstoreRocksFifoOptions::default(),
),
@@ -6355,7 +6287,7 @@ pub mod tests {
panic!("no dupes");
},
false,
false,
ShredSource::Turbine,
&mut BlockstoreInsertionMetrics::default(),
));
@@ -6373,7 +6305,7 @@ pub mod tests {
counter.fetch_add(1, Ordering::Relaxed);
},
false,
false,
ShredSource::Turbine,
&mut BlockstoreInsertionMetrics::default(),
));
assert_eq!(counter.load(Ordering::Relaxed), 1);
@@ -6487,7 +6419,7 @@ pub mod tests {
);
coding_shred.common_header.fec_set_index = std::u32::MAX - 1;
coding_shred.coding_header.num_data_shreds = 2;
coding_shred.coding_header.num_coding_shreds = 3;
coding_shred.coding_header.num_coding_shreds = 4;
coding_shred.coding_header.position = 1;
coding_shred.common_header.index = std::u32::MAX - 1;
assert!(!Blockstore::should_insert_coding_shred(

View File

@@ -991,16 +991,16 @@ impl Default for ShredStorageType {
}
}
/// Advanced options for blockstore.
/// The each advanced option might also be used as a tag that supports
/// group-by operation when reporting Blockstore metrics.
/// Options for LedgerColumn.
/// Each field might also be used as a tag that supports group-by operation when
/// reporting metrics.
#[derive(Clone)]
pub struct BlockstoreAdvancedOptions {
pub struct LedgerColumnOptions {
// Determine how to store both data and coding shreds. Default: RocksLevel.
pub shred_storage_type: ShredStorageType,
}
impl Default for BlockstoreAdvancedOptions {
impl Default for LedgerColumnOptions {
fn default() -> Self {
Self {
shred_storage_type: ShredStorageType::RocksLevel,
@@ -1015,7 +1015,7 @@ pub struct BlockstoreOptions {
pub recovery_mode: Option<BlockstoreRecoveryMode>,
// Whether to allow unlimited number of open files. Default: true.
pub enforce_ulimit_nofile: bool,
pub advanced_options: BlockstoreAdvancedOptions,
pub column_options: LedgerColumnOptions,
}
impl Default for BlockstoreOptions {
@@ -1025,7 +1025,7 @@ impl Default for BlockstoreOptions {
access_type: AccessType::PrimaryOnly,
recovery_mode: None,
enforce_ulimit_nofile: true,
advanced_options: BlockstoreAdvancedOptions::default(),
column_options: LedgerColumnOptions::default(),
}
}
}
@@ -1459,7 +1459,7 @@ fn new_cf_descriptor_pair_shreds<
options: &BlockstoreOptions,
oldest_slot: &OldestSlot,
) -> (ColumnFamilyDescriptor, ColumnFamilyDescriptor) {
match &options.advanced_options.shred_storage_type {
match &options.column_options.shred_storage_type {
ShredStorageType::RocksLevel => (
new_cf_descriptor::<D>(options, oldest_slot),
new_cf_descriptor::<C>(options, oldest_slot),

View File

@@ -257,10 +257,6 @@ impl ErasureMeta {
None => return false,
};
other.__unused_size = self.__unused_size;
// Ignore first_coding_index field for now to be backward compatible.
// TODO remove this once cluster is upgraded to always populate
// first_coding_index field.
other.first_coding_index = self.first_coding_index;
self == &other
}
@@ -275,16 +271,7 @@ impl ErasureMeta {
pub(crate) fn coding_shreds_indices(&self) -> Range<u64> {
let num_coding = self.config.num_coding() as u64;
// first_coding_index == 0 may imply that the field is not populated.
// self.set_index to be backward compatible.
// TODO remove this once cluster is upgraded to always populate
// first_coding_index field.
let first_coding_index = if self.first_coding_index == 0 {
self.set_index
} else {
self.first_coding_index
};
first_coding_index..first_coding_index + num_coding
self.first_coding_index..self.first_coding_index + num_coding
}
pub(crate) fn status(&self, index: &Index) -> ErasureMetaStatus {

View File

@@ -8,6 +8,7 @@ pub mod bigtable_delete;
pub mod bigtable_upload;
pub mod bigtable_upload_service;
pub mod block_error;
mod slot_stats;
#[macro_use]
pub mod blockstore;
pub mod ancestor_iterator;

View File

@@ -504,9 +504,10 @@ impl Shred {
pub(crate) fn first_coding_index(&self) -> Option<u32> {
match self.shred_type() {
ShredType::Data => None,
// TODO should be: self.index() - self.coding_header.position
// once position field is populated.
ShredType::Code => Some(self.fec_set_index()),
ShredType::Code => {
let position = u32::from(self.coding_header.position);
self.index().checked_sub(position)
}
}
}
@@ -536,25 +537,25 @@ impl Shred {
// Returns the block index within the erasure coding set.
fn erasure_block_index(&self) -> Option<usize> {
let index = self.index().checked_sub(self.fec_set_index())?;
let index = usize::try_from(index).ok()?;
match self.shred_type() {
ShredType::Data => Some(index),
ShredType::Data => {
let index = self.index().checked_sub(self.fec_set_index())?;
usize::try_from(index).ok()
}
ShredType::Code => {
// TODO should use first_coding_index once position field is
// populated.
// Assert that the last shred index in the erasure set does not
// overshoot u32.
self.fec_set_index().checked_add(u32::from(
self.coding_header
.num_data_shreds
.max(self.coding_header.num_coding_shreds)
.checked_sub(1)?,
self.coding_header.num_data_shreds.checked_sub(1)?,
))?;
self.first_coding_index()?.checked_add(u32::from(
self.coding_header.num_coding_shreds.checked_sub(1)?,
))?;
let num_data_shreds = usize::from(self.coding_header.num_data_shreds);
let num_coding_shreds = usize::from(self.coding_header.num_coding_shreds);
let position = usize::from(self.coding_header.position);
let fec_set_size = num_data_shreds.checked_add(num_coding_shreds)?;
let index = index.checked_add(num_data_shreds)?;
let index = position.checked_add(num_data_shreds)?;
(index < fec_set_size).then(|| index)
}
}

90
ledger/src/slot_stats.rs Normal file
View File

@@ -0,0 +1,90 @@
use {
crate::blockstore_meta::SlotMeta, bitflags::bitflags, lru::LruCache, solana_sdk::clock::Slot,
};
const SLOTS_STATS_CACHE_CAPACITY: usize = 300;
macro_rules! get_mut_entry (
($cache:expr, $key:expr) => (
match $cache.get_mut(&$key) {
Some(entry) => entry,
None => {
$cache.put($key, SlotStats::default());
$cache.get_mut(&$key).unwrap()
}
}
);
);
#[derive(Copy, Clone, Debug)]
pub(crate) enum ShredSource {
Turbine,
Repaired,
Recovered,
}
bitflags! {
#[derive(Default)]
struct SlotFlags: u8 {
const DEAD = 0b00000001;
const FULL = 0b00000010;
const ROOTED = 0b00000100;
}
}
#[derive(Default)]
struct SlotStats {
flags: SlotFlags,
num_repaired: usize,
num_recovered: usize,
}
pub(crate) struct SlotsStats(LruCache<Slot, SlotStats>);
impl Default for SlotsStats {
fn default() -> Self {
// LruCache::unbounded because capacity is enforced manually.
Self(LruCache::unbounded())
}
}
impl SlotsStats {
pub(crate) fn add_shred(&mut self, slot: Slot, source: ShredSource) {
let entry = get_mut_entry!(self.0, slot);
match source {
ShredSource::Turbine => (),
ShredSource::Repaired => entry.num_repaired += 1,
ShredSource::Recovered => entry.num_recovered += 1,
}
self.maybe_evict_cache();
}
pub(crate) fn set_full(&mut self, slot_meta: &SlotMeta) {
let total_time_ms =
solana_sdk::timing::timestamp().saturating_sub(slot_meta.first_shred_timestamp);
let last_index = slot_meta
.last_index
.and_then(|ix| i64::try_from(ix).ok())
.unwrap_or(-1);
let entry = get_mut_entry!(self.0, slot_meta.slot);
if !entry.flags.contains(SlotFlags::FULL) {
datapoint_info!(
"shred_insert_is_full",
("total_time_ms", total_time_ms, i64),
("slot", slot_meta.slot, i64),
("last_index", last_index, i64),
("num_repaired", entry.num_repaired, i64),
("num_recovered", entry.num_recovered, i64),
);
}
entry.flags |= SlotFlags::FULL;
self.maybe_evict_cache();
}
fn maybe_evict_cache(&mut self) {
while self.0.len() > SLOTS_STATS_CACHE_CAPACITY {
let (_slot, _entry) = self.0.pop_lru().unwrap();
// TODO: submit metrics for (slot, entry).
}
}
}

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-local-cluster"
description = "Blockchain, Rebuilt for Scale"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -16,25 +16,25 @@ itertools = "0.10.3"
log = "0.4.14"
rand = "0.7.0"
rayon = "1.5.1"
solana-client = { path = "../client", version = "=1.10.3" }
solana-config-program = { path = "../programs/config", version = "=1.10.3" }
solana-core = { path = "../core", version = "=1.10.3" }
solana-entry = { path = "../entry", version = "=1.10.3" }
solana-gossip = { path = "../gossip", version = "=1.10.3" }
solana-ledger = { path = "../ledger", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-stake-program = { path = "../programs/stake", version = "=1.10.3" }
solana-streamer = { path = "../streamer", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-client = { path = "../client", version = "=1.10.6" }
solana-config-program = { path = "../programs/config", version = "=1.10.6" }
solana-core = { path = "../core", version = "=1.10.6" }
solana-entry = { path = "../entry", version = "=1.10.6" }
solana-gossip = { path = "../gossip", version = "=1.10.6" }
solana-ledger = { path = "../ledger", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-stake-program = { path = "../programs/stake", version = "=1.10.6" }
solana-streamer = { path = "../streamer", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
tempfile = "3.3.0"
[dev-dependencies]
assert_matches = "1.5.0"
gag = "1.0.0"
serial_test = "0.6.0"
solana-download-utils = { path = "../download-utils", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-download-utils = { path = "../download-utils", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -63,7 +63,7 @@ pub fn safe_clone_config(config: &ValidatorConfig) -> ValidatorConfig {
accounts_shrink_ratio: config.accounts_shrink_ratio,
accounts_db_config: config.accounts_db_config.clone(),
wait_to_vote_slot: config.wait_to_vote_slot,
blockstore_advanced_options: config.blockstore_advanced_options.clone(),
ledger_column_options: config.ledger_column_options.clone(),
}
}

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
edition = "2021"
name = "solana-log-analyzer"
description = "The solana cluster network analysis tool"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -14,8 +14,8 @@ byte-unit = "4.0.14"
clap = "2.33.1"
serde = "1.0.136"
serde_json = "1.0.79"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
[[bin]]
name = "solana-log-analyzer"

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-logger"
version = "1.10.3"
version = "1.10.6"
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.10.3"
version = "1.10.6"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-measure"
readme = "../README.md"
@@ -12,7 +12,7 @@ edition = "2021"
[dependencies]
log = "0.4.14"
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-merkle-root-bench"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -11,11 +11,11 @@ publish = false
[dependencies]
clap = "2.33.1"
log = "0.4.14"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-merkle-tree"
version = "1.10.3"
version = "1.10.6"
description = "Solana Merkle Tree"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -11,7 +11,7 @@ edition = "2021"
[dependencies]
fast-math = "0.1"
solana-program = { path = "../sdk/program", version = "=1.10.3" }
solana-program = { path = "../sdk/program", version = "=1.10.6" }
# This can go once the BPF toolchain target Rust 1.42.0+
[target.bpfel-unknown-unknown.dependencies]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-metrics"
version = "1.10.3"
version = "1.10.6"
description = "Solana Metrics"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -15,7 +15,7 @@ gethostname = "0.2.3"
lazy_static = "1.4.0"
log = "0.4.14"
reqwest = { version = "0.11.10", default-features = false, features = ["blocking", "rustls-tls", "json"] }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
[dev-dependencies]
env_logger = "0.9.0"

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-net-shaper"
description = "The solana cluster network shaping tool"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -14,7 +14,7 @@ clap = "2.33.1"
rand = "0.7.0"
serde = "1.0.136"
serde_json = "1.0.79"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[[bin]]
name = "solana-net-shaper"

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-net-utils"
version = "1.10.3"
version = "1.10.6"
description = "Solana Network Utilities"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -19,9 +19,9 @@ rand = "0.7.0"
serde = "1.0.136"
serde_derive = "1.0.103"
socket2 = "0.4.4"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
tokio = { version = "1", features = ["full"] }
url = "2.2.2"

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-notifier"
version = "1.10.3"
version = "1.10.6"
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.10.3"
version = "1.10.6"
description = "Solana Performance APIs"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -22,10 +22,10 @@ log = "0.4.14"
rand = "0.7.0"
rayon = "1.5.1"
serde = "1.0.136"
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
[target."cfg(target_os = \"linux\")".dependencies]
caps = "0.5.3"
@@ -37,7 +37,7 @@ name = "solana_perf"
[dev-dependencies]
matches = "0.1.9"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[[bench]]
name = "sigverify"

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2021"
name = "solana-poh-bench"
version = "1.10.3"
version = "1.10.6"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -14,12 +14,12 @@ clap = "2.33.1"
log = "0.4.14"
rand = "0.7.0"
rayon = "1.5.1"
solana-entry = { path = "../entry", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-version = { path = "../version", version = "=1.10.3" }
solana-entry = { path = "../entry", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-perf = { path = "../perf", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-version = { path = "../version", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-poh"
version = "1.10.3"
version = "1.10.6"
description = "Solana PoH"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -13,21 +13,21 @@ edition = "2021"
core_affinity = "0.5.10"
crossbeam-channel = "0.5"
log = "0.4.14"
solana-entry = { path = "../entry", version = "=1.10.3" }
solana-ledger = { path = "../ledger", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-metrics = { path = "../metrics", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-sys-tuner = { path = "../sys-tuner", version = "=1.10.3" }
solana-entry = { path = "../entry", version = "=1.10.6" }
solana-ledger = { path = "../ledger", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-metrics = { path = "../metrics", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-sys-tuner = { path = "../sys-tuner", version = "=1.10.6" }
thiserror = "1.0"
[dev-dependencies]
bincode = "1.3.3"
matches = "0.1.9"
rand = "0.7.0"
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-perf = { path = "../perf", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-perf = { path = "../perf", version = "=1.10.6" }
[lib]
crate-type = ["lib"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-program-runtime"
version = "1.10.3"
version = "1.10.6"
description = "Solana program runtime"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -19,15 +19,15 @@ log = "0.4.14"
num-derive = { version = "0.3" }
num-traits = { version = "0.2" }
serde = { version = "1.0.129", features = ["derive", "rc"] }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.3" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.3" }
solana-measure = { path = "../measure", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.10.6" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.10.6" }
solana-measure = { path = "../measure", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
thiserror = "1.0"
enum-iterator = "0.7.0"
[dev-dependencies]
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.6" }
[lib]
crate-type = ["lib"]

View File

@@ -7,7 +7,8 @@ use solana_sdk::{
transaction::TransactionError,
};
const MAX_UNITS: u32 = 1_400_000;
pub const DEFAULT_UNITS: u32 = 200_000;
pub const MAX_UNITS: u32 = 1_400_000;
const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024;
#[cfg(RUSTC_WITH_SPECIALIZATION)]
@@ -67,19 +68,14 @@ pub struct ComputeBudget {
impl Default for ComputeBudget {
fn default() -> Self {
Self::new(true)
Self::new(MAX_UNITS)
}
}
impl ComputeBudget {
pub fn new(use_max_units_default: bool) -> Self {
let max_units = if use_max_units_default {
MAX_UNITS
} else {
200_000
} as u64;
pub fn new(max_units: u32) -> Self {
ComputeBudget {
max_units,
max_units: max_units as u64,
log_64_units: 100,
create_program_address_units: 1500,
invoke_units: 1000,

View File

@@ -1193,6 +1193,7 @@ pub fn visit_each_account_once<E>(
mod tests {
use {
super::*,
crate::compute_budget,
serde::{Deserialize, Serialize},
solana_sdk::account::{ReadableAccount, WritableAccount},
};
@@ -1674,12 +1675,12 @@ mod tests {
let mut transaction_context = TransactionContext::new(accounts, 1, 3);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.feature_set = Arc::new(feature_set);
invoke_context.compute_budget = ComputeBudget::new(false);
invoke_context.compute_budget = ComputeBudget::new(compute_budget::DEFAULT_UNITS);
invoke_context.push(&[], &[0], &[]).unwrap();
assert_eq!(
*invoke_context.get_compute_budget(),
ComputeBudget::new(false)
ComputeBudget::new(compute_budget::DEFAULT_UNITS)
);
invoke_context.pop().unwrap();
@@ -1687,7 +1688,7 @@ mod tests {
let expected_compute_budget = ComputeBudget {
max_units: 500_000,
heap_size: Some(256_usize.saturating_mul(1024)),
..ComputeBudget::new(false)
..ComputeBudget::new(compute_budget::DEFAULT_UNITS)
};
assert_eq!(
*invoke_context.get_compute_budget(),
@@ -1698,7 +1699,7 @@ mod tests {
invoke_context.push(&[], &[0], &[]).unwrap();
assert_eq!(
*invoke_context.get_compute_budget(),
ComputeBudget::new(false)
ComputeBudget::new(compute_budget::DEFAULT_UNITS)
);
invoke_context.pop().unwrap();
}

View File

@@ -5,7 +5,7 @@ edition = "2021"
license = "Apache-2.0"
name = "solana-program-test"
repository = "https://github.com/solana-labs/solana"
version = "1.10.3"
version = "1.10.6"
[dependencies]
async-trait = "0.1.52"
@@ -14,13 +14,13 @@ bincode = "1.3.3"
chrono-humanize = "0.2.1"
log = "0.4.14"
serde = "1.0.136"
solana-banks-client = { path = "../banks-client", version = "=1.10.3" }
solana-banks-server = { path = "../banks-server", version = "=1.10.3" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.10.3" }
solana-logger = { path = "../logger", version = "=1.10.3" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.3" }
solana-runtime = { path = "../runtime", version = "=1.10.3" }
solana-sdk = { path = "../sdk", version = "=1.10.3" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.3" }
solana-banks-client = { path = "../banks-client", version = "=1.10.6" }
solana-banks-server = { path = "../banks-server", version = "=1.10.6" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.10.6" }
solana-logger = { path = "../logger", version = "=1.10.6" }
solana-program-runtime = { path = "../program-runtime", version = "=1.10.6" }
solana-runtime = { path = "../runtime", version = "=1.10.6" }
solana-sdk = { path = "../sdk", version = "=1.10.6" }
solana-vote-program = { path = "../programs/vote", version = "=1.10.6" }
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }

View File

@@ -3,7 +3,7 @@
[package]
name = "solana-address-lookup-table-program-tests"
version = "1.10.3"
version = "1.10.6"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
@@ -14,9 +14,9 @@ publish = false
[dev-dependencies]
assert_matches = "1.5.0"
bincode = "1.3.3"
solana-address-lookup-table-program = { path = "../address-lookup-table", version = "=1.10.3" }
solana-program-test = { path = "../../program-test", version = "=1.10.3" }
solana-sdk = { path = "../../sdk", version = "=1.10.3" }
solana-address-lookup-table-program = { path = "../address-lookup-table", version = "=1.10.6" }
solana-program-test = { path = "../../program-test", version = "=1.10.6" }
solana-sdk = { path = "../../sdk", version = "=1.10.6" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

Some files were not shown because too many files have changed in this diff Show More