Compare commits

...

93 Commits

Author SHA1 Message Date
mergify[bot]
a4ad2925a2 Allow nodes to advertise a different rpc address over gossip (#13053) (#13078)
* Allow nodes to advertise a different rpc address over gossip

* Feedback

(cherry picked from commit 8b0242a5d8)

Co-authored-by: Justin Starry <justin@solana.com>
2020-10-22 07:06:27 +00:00
mergify[bot]
edfbd8d65a Add replacements for Pubkey::new_rand()/Hash::new_rand() (bp #12987) (#13076)
* Add pubkey_new_rand(), mark Pubkey::new_rand() deprecated

(cherry picked from commit 0e68ed6a8d)

* Add hash_new_rand(), mark Hash::new_rand() as deprecated

(cherry picked from commit 76f11c7dae)

* Run `codemod --extensions rs Pubkey::new_rand solana_sdk::pubkey::new_rand`

(cherry picked from commit 7bc073defe)

# Conflicts:
#	programs/bpf/benches/bpf_loader.rs
#	runtime/benches/accounts.rs
#	runtime/src/accounts.rs

* Run `codemod --extensions rs Hash::new_rand solana_sdk:#️⃣:new_rand`

(cherry picked from commit 17c391121a)

* Remove unused pubkey::Pubkey imports

(cherry picked from commit 959880db60)

# Conflicts:
#	runtime/src/accounts_index.rs

* Resolve conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-22 05:08:01 +00:00
mergify[bot]
e0ae54fd7e Add cargo-build-bpf (bp #13040) (#13075)
* Add cargo-build-bpf

(cherry picked from commit 07a853d6cc)

* Remove do.sh

(cherry picked from commit 61be155413)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-22 03:09:52 +00:00
mergify[bot]
60297951ec CLI: Print address ephemeral keypair seed phrase to stderr on deploy failure (bp #13046) (#13055)
* CLI: Print address ephemeral keypair seed phrase to stderr on deploy failure

(cherry picked from commit 2905ccc7ec)

# Conflicts:
#	cli/Cargo.toml

* Fix conflicts

Co-authored-by: Trent Nelson <trent@solana.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-10-21 15:29:56 -06:00
Tyera Eulberg
e0f9f72a2c RPC: Don't send base64 TXs to old clusters (#13072)
Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-21 20:25:36 +00:00
mergify[bot]
5236acf4b0 Add ledger-tool dead-slots and improve purge a lot (#13065) (#13071)
* Add ledger-tool dead-slots and improve purge a lot

* Reduce batch size...

* Add --dead-slots-only and fixed purge ordering

(cherry picked from commit 0776fa05c7)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-21 18:57:22 +00:00
mergify[bot]
5dd61b5db2 Port various rent fixes to runtime feature (#12842) (#13068)
* Port various rent fixes to runtime feature

* Fix CI

* Use more consistent naming...

(cherry picked from commit 608b81b412)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-21 14:47:48 +00:00
mergify[bot]
8752bf0826 Skip 'Stake by Feature Set' output when showing status of a single feature (#13052)
(cherry picked from commit ad65d4785e)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-21 07:14:49 +00:00
mergify[bot]
b1712e80ec Parse stake and system instructions (#13035) (#13045)
* Fix token account check

* Add helper to check num accounts

* Add parse_stake

* Add parse_system

* Fix AuthorizeNonce docs

* Remove jsonParsed unstable markers

* Clippy

(cherry picked from commit 46d0019955)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-21 04:35:05 +00:00
Trent Nelson
2fe1a4677c Ignore more paths in increment-cargo-version.sh
(cherry picked from commit c1c69ecc34)
2020-10-20 20:55:34 -07:00
mergify[bot]
f76c128f4f Various clean-ups before assert adjustment (#13006) (#13041)
* Various clean-ups before assert adjustment

* oops

(cherry picked from commit efdb560e97)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-21 02:41:20 +00:00
mergify[bot]
b143b9c3c2 Remove frozen ABI modules from solana-sdk (bp #13008) (#13036)
* Remove frozen ABI modules from solana-sdk

(cherry picked from commit 6858950f76)

# Conflicts:
#	Cargo.lock
#	core/Cargo.toml
#	frozen-abi/macro/Cargo.toml
#	programs/bpf/Cargo.lock
#	programs/stake/Cargo.toml
#	programs/vote/Cargo.toml
#	runtime/Cargo.toml
#	sdk/Cargo.toml
#	version/Cargo.toml

* rebase

* fix broken ci (#13039)

Co-authored-by: Michael Vines <mvines@gmail.com>
Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-21 02:00:45 +00:00
mergify[bot]
b4178b75e7 Add --eval flag to solana-install info (#13038)
(cherry picked from commit 6f930351d2)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-21 01:12:48 +00:00
Michael Vines
c54b751df7 Include sdk/bpf in the main release tarball
(cherry picked from commit f71677164f)
2020-10-20 16:25:04 -07:00
mergify[bot]
0fde9e893f Force unset CARGO to use correct version of cargo (#13027) (#13034)
(cherry picked from commit 81d0c8ae7f)

Co-authored-by: Jon Cinque <jon.cinque@gmail.com>
2020-10-20 23:06:57 +00:00
mergify[bot]
d24abbdac9 Fix secp256k1 instruction indexing and add tests (#13026) (#13032)
(cherry picked from commit 83c53ae4b5)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-10-20 22:25:59 +00:00
Michael Vines
3b03985f28 Remove unsupported metrics tarball from release artifacts
(cherry picked from commit 62f20bc170)
2020-10-20 13:16:35 -07:00
mergify[bot]
d05bfa08c7 improves threads' utilization in processing gossip packets (#12962) (#13023)
ClusterInfo::process_packets handles incoming packets in a thread_pool:
https://github.com/solana-labs/solana/blob/87311cce7/core/src/cluster_info.rs#L2118-L2134

However, profiling runtime shows that threads are not well utilized and
a lot of the processing is done sequentially.

This commit redistributes the work done in parallel. Testing on a gce
cluster shows 20%+ improvement in processing gossip packets with much
smaller variations.

(cherry picked from commit 75d62ca095)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-10-20 19:59:35 +00:00
mergify[bot]
9da2ac7a44 passes through feature-set to gossip requests handling (#12878) (#12991)
* passes through feature-set to down to gossip requests handling
* takes the feature-set from root_bank instead of working_bank

(cherry picked from commit 48283161c3)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-10-20 18:25:44 +00:00
mergify[bot]
9e95d0fb58 Add more info for --limit-ledger-size (#13021)
(cherry picked from commit de04a208c7)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-20 17:50:11 +00:00
mergify[bot]
94cad9873c Support Debug Bank (#13017) (#13019)
(cherry picked from commit c0675968b1)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-20 17:20:40 +00:00
Tyera Eulberg
f33171b32f Remove errant print 2020-10-20 09:02:51 -06:00
mergify[bot]
aa6406f263 implements DataBudget using atomics (#12856) (#12990)
(cherry picked from commit 05cf15a382)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-10-20 12:51:42 +00:00
mergify[bot]
77864a6bee Parse bpf loader instructions (#12998) (#13005)
* Add parsing for BpfLoader2 instructions

* Skip info if null

* Return account address in info map

(cherry picked from commit 942e4273ba)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-20 06:25:56 +00:00
mergify[bot]
b51715d33c validator: Activate RPC before halting on slot (#13002)
(cherry picked from commit 3b3f7341fa)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-20 03:31:04 +00:00
mergify[bot]
7d395177d4 Add everything feature (#12999)
(cherry picked from commit c5e16383b0)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-20 01:52:21 +00:00
mergify[bot]
77ba6d6784 sdk: Add SyscallStubs to enable syscall interception when building programs for non-BPF (bp #12984) (#12993)
* Add SyscallStubs to enable syscall interception when building programs for non-BPF

(cherry picked from commit 9c53e1dfb2)

* Remove program_stubs!()

(cherry picked from commit 6d5889bdb5)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-19 22:28:44 +00:00
Tyera Eulberg
4bf0a54ed7 Revert "CLI: Put deploy ephemeral keypair behind a flag (#12942)" (#12982)
This reverts commit 8cac6835c0.
2020-10-19 17:41:10 +00:00
mergify[bot]
8a526f2f53 Follow up to persistent tower with tests and API cleaning (#12350) (#12972)
* Follow up to persistent tower

* Ignore for now...

* Hard-code validator identities for easy reasoning

* Add a test for opt. conf violation without tower

* Fix compile with rust < 1.47

* Remove unused method

* More move of assert tweak to the asser pr

* Add comments

* Clean up

* Clean the test addressing various review comments

* Clean up a bit

(cherry picked from commit 54517ea454)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-19 08:47:58 +00:00
mergify[bot]
43f99bdb31 Improve vote-account "Recent Timestamp" output (#12971)
(cherry picked from commit 2cc3d7511a)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-19 07:30:29 +00:00
mergify[bot]
0008dc62e4 Fix zero-lamport accounts preventing slot cleanup (#12606) (#12969)
Co-authored-by: Carl Lin <carl@solana.com>
(cherry picked from commit 16d45b8480)

Co-authored-by: carllin <wumu727@gmail.com>
2020-10-19 07:07:08 +00:00
mergify[bot]
7e8174fb79 Minor doc typo (#12966)
(cherry picked from commit 6123d71489)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-19 03:23:24 +00:00
mergify[bot]
4ad2ebcde9 Mention monitoring and updating for exchanges (#12953) (#12959)
* Mention monitoring and updating for exchanges

* Fix link syntax...

* Apply suggestions from code review

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Trent Nelson <trent.a.b.nelson@gmail.com>

* Apply suggestions from code review

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* More review comments and word-wrapping

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Trent Nelson <trent.a.b.nelson@gmail.com>
(cherry picked from commit 87311cce7f)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-17 06:49:59 +00:00
mergify[bot]
da183d655a keygen: add more mnemonic language support (#12944) (#12957)
(cherry picked from commit 4451042c76)

Co-authored-by: guanqun <guanqun.lu@gmail.com>
2020-10-17 04:00:29 +00:00
mergify[bot]
2e449276be Check payer balance for program account rent as needed (#12952) (#12955)
(cherry picked from commit b6bfed64cb)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-16 19:14:26 +00:00
mergify[bot]
8cac6835c0 CLI: Put deploy ephemeral keypair behind a flag (#12942)
(cherry picked from commit 5a5b7f39c1)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-16 16:56:50 +00:00
mergify[bot]
677c184e47 Another some tower logging improvements (#12940) (#12943)
(cherry picked from commit fd8ec27fe8)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-16 07:00:27 +00:00
mergify[bot]
f36cfb92f7 Convert Blockstore Rewards cf to protobuf (bp #12860) (#12935)
* Convert Blockstore Rewards cf to protobuf (#12860)

* Add Blockstore protobuf cf type

* Add Rewards message to proto and make generated pub

* Convert Rewards cf to ProtobufColumn

* Add bench

* Adjust tags

* Move solana proto definitions and conversion methods to new crate

(cherry picked from commit 359707c85e)

# Conflicts:
#	Cargo.lock
#	ledger/Cargo.toml
#	storage-bigtable/Cargo.toml

* v1.4-ify

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-10-16 01:27:37 +00:00
mergify[bot]
e7062de05f Report compute budget usage (#12931) (#12934)
(cherry picked from commit b510474dcb)

Co-authored-by: Jack May <jack@solana.com>
2020-10-16 00:05:18 +00:00
mergify[bot]
a443e2e773 Update get-block method in get_confirmed_transaction (#12923) (#12930)
* Update get-block method in get_confirmed_transaction

* Remove superfluous into()

(cherry picked from commit 42943ab86d)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-15 21:38:38 +00:00
mergify[bot]
3a6db787e2 Support arbitrary toolchains with cargo wrapper script (#12926)
(cherry picked from commit 99aecdaf65)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-15 20:26:35 +00:00
Trent Nelson
f3c986385f Bump version to 1.4.2 2020-10-15 20:26:29 +00:00
mergify[bot]
3df811348f program log pubkey as base58 (bp #12901) (#12911)
* program log pubkey as base58 (#12901)

(cherry picked from commit 3f9e6a600b)

# Conflicts:
#	programs/bpf/benches/bpf_loader.rs
#	programs/bpf/c/src/tuner/tuner.c

* resolve conflicts

* fix bench conflict

Co-authored-by: Jack May <jack@solana.com>
2020-10-15 19:40:20 +00:00
mergify[bot]
e8c86ed3e5 Drop 'Pubkey' in 'solana validators' header (#12919)
(cherry picked from commit 3073dc9801)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-15 19:02:10 +00:00
Tyera Eulberg
489a7bb576 Bump spl-memo and spl-token versions (#12914) 2020-10-15 18:05:41 +00:00
mergify[bot]
688dd85e61 Release: Use pinned cargo version to install spl-token-cli (#12916)
(cherry picked from commit bb2f0df9e1)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-15 17:59:24 +00:00
mergify[bot]
fe54a30084 Docs: Clarify validator disk requirements (#12921)
(cherry picked from commit cc0781e0ac)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-15 17:56:46 +00:00
mergify[bot]
80942841a2 Surface 'Program account allocation failed' error details (#12904)
(cherry picked from commit eec3d25ab9)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-15 16:22:12 +00:00
mergify[bot]
d2808a8e29 docs: Rework JSON RPC curl examples to be more readable (bp #12893) (#12899)
* Rework curl examples to be more readable

(cherry picked from commit f0d0bdc572)

# Conflicts:
#	docs/src/apps/jsonrpc-api.md

* rebase

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-15 15:47:49 +00:00
mergify[bot]
f8413a28b5 Better tower logs for SwitchForkDecision and etc (#12875) (#12905)
* Better tower logs for SwitchForkDecision and etc

* nits

* Update comment

(cherry picked from commit a44e4d386f)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-15 10:41:03 +00:00
mergify[bot]
bc96332899 Respect RefCell when calling invoke (#12858) (#12891)
* Respect RefCell when calling invoke

* nudge

(cherry picked from commit 969f7b015b)

Co-authored-by: Jack May <jack@solana.com>
2020-10-15 02:15:36 +00:00
mergify[bot]
ceeeb3c9dd Change developer CTA (#12857) (#12892)
* change `index.js`

(cherry picked from commit 9e7fad1fd2)

Co-authored-by: R. M. Shea <8948187+rmshea@users.noreply.github.com>
2020-10-15 01:45:06 +00:00
mergify[bot]
bd058ec8f1 Release: Include SPL Token in release tarballs (#12889)
(cherry picked from commit f70762913c)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-15 01:32:34 +00:00
mergify[bot]
4b5ac44fc8 RPC: Add metrics for TX encoding (#12880)
(cherry picked from commit c26512255d)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-14 19:39:08 +00:00
mergify[bot]
fef979f0e5 Don't report RewardType::Fee when none was awarded (#12877)
(cherry picked from commit 4b04ed86b6)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-14 17:15:41 +00:00
mergify[bot]
cca2cdf39b Expose program error constants (#12861) (#12871)
(cherry picked from commit d4e953277e)

Co-authored-by: Jack May <jack@solana.com>
2020-10-14 08:48:50 +00:00
Trent Nelson
6e91996606 Bump version to 1.4.1 2020-10-14 03:05:04 +00:00
mergify[bot]
99be00d61f Add separate push queue to reduce push lock contention (#12713) (#12867)
(cherry picked from commit 1f1eb9f26e)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-10-14 02:46:13 +00:00
mergify[bot]
68f808026e Add log_messages to proto file (#12859) (#12863)
(cherry picked from commit 67ed44c007)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-14 01:50:55 +00:00
mergify[bot]
0c7ab0a1bb Update programming-faq.md (#12864) (#12865)
Fix typo

(cherry picked from commit b8f03c9b0f)

Co-authored-by: kemargrant <kemargrant@gmail.com>
2020-10-14 01:15:52 +00:00
mergify[bot]
3d8ccbc079 terminology update, nonce to bump seed (#12840) (#12851)
(cherry picked from commit 56211378d3)

Co-authored-by: Jack May <jack@solana.com>
2020-10-13 18:31:48 +00:00
mergify[bot]
275d096a46 solana vote-account/solana stake-account now works with RPC servers without --enable-rpc-transaction-history (bp #12826) (#12849)
* Implementation-defined RPC server errors are now accessible to client/ users

(cherry picked from commit 247228ee61)

* Cleanly handle RPC servers that don't have --enable-rpc-transaction-history enabled

(cherry picked from commit 14d793b22c)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-13 18:28:15 +00:00
mergify[bot]
6d70a06b23 Add nop feature set for upcoming ported rent fixes (#12841) (#12847)
(cherry picked from commit 7de7efe96c)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-13 17:47:59 +00:00
mergify[bot]
7e68b2e1bd Add transaction log messages to |solana confirm -v| output (#12836)
(cherry picked from commit e9dbbdeb81)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-13 06:57:21 +00:00
mergify[bot]
f0d761630e get_vote_accounts: access HashMap directly instead of turning it into an iterator (#12829)
(cherry picked from commit 649fe6d3b6)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-13 05:25:31 +00:00
mergify[bot]
1986927eb6 Check ELF file for errors before deploy (bp #12741) (#12801)
* Check ELF file for errors before deploy (#12741)

* Check ELF file for errors before deploy

* Update cli/src/cli.rs

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

* Fix formatting

* Bump solana_rbpf

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

# Conflicts:
#	cli/Cargo.toml

* rebase

Co-authored-by: Alexandre Esteves <2335822+alexfmpe@users.noreply.github.com>
Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-13 04:41:51 +00:00
mergify[bot]
9a0ea61007 Add docs on vote account key rotation (bp #12815) (#12831)
* Add docs on vote account key rotation

(cherry picked from commit 253114ca20)

* Update docs/src/running-validator/vote-accounts.md

Co-authored-by: Trent Nelson <trent.a.b.nelson@gmail.com>
(cherry picked from commit d83027c0cd)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-13 04:32:03 +00:00
mergify[bot]
51a70e52f2 CI: Fix crate publication (#12825)
(cherry picked from commit c38021502e)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-12 23:15:46 +00:00
mergify[bot]
9797c93db3 fix native_loader behavior for invalid accounts (#12814) (#12819)
(cherry picked from commit c24da1ee16)

Co-authored-by: Jack May <jack@solana.com>
2020-10-12 22:14:56 +00:00
mergify[bot]
9598114658 Use latest stable channel release if there's no beta release (#12823)
(cherry picked from commit 65213a1782)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-12 22:12:16 +00:00
mergify[bot]
d3ef061044 RpcClient: Encode TXs as base64 by default (#12817)
(cherry picked from commit efbe37ba20)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-12 21:56:18 +00:00
mergify[bot]
1f102d2617 Move no-0-rent rent dist. behavior under feature (#12804) (#12811)
(cherry picked from commit 2f5bb7e507)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-12 09:57:32 +00:00
mergify[bot]
5e97bd3d8a simulate_transaction_with_config() now passes full config to server (#12803)
(cherry picked from commit b3c2752bb0)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-12 05:58:30 +00:00
mergify[bot]
ed06e8b85d Pacify cargo audit (bp #12797) (#12799)
* Bump reqwest/rayon to get past `cargo audit`

(cherry picked from commit 8a119c1483)

# Conflicts:
#	dos/Cargo.toml
#	download-utils/Cargo.toml
#	metrics/Cargo.toml

* Switch to tempfile

(cherry picked from commit d3b0f87a49)

* Rework cargo audit ignores

(cherry picked from commit 2301dcf973)

* Cargo.lock

(cherry picked from commit 859eb606da)

* rebase

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-12 04:29:55 +00:00
mergify[bot]
10b9225edb Don't bother paying 0 rent (#12793)
(cherry picked from commit 1fc7c1ecee)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-10 18:12:14 +00:00
Michael Vines
b1b5ddd2b9 Update gossip entrypoints 2020-10-10 08:39:38 -07:00
mergify[bot]
6b9b107ead Fix various ledger-tool error due to no builtins (bp #12759) (#12766)
* Fix various ledger-tool error due to no builtins (#12759)

* Fix various ledger-tool error due to no builtins

* Add missing file...

(cherry picked from commit 1f4bcf70b0)

# Conflicts:
#	core/Cargo.toml
#	ledger/Cargo.toml

* Rebase

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-10 07:10:38 +00:00
mergify[bot]
3fef98fd1e Expose all rewards (fees, rent, voting and staking) in RPC getConfirmedBlock and the cli (bp #12768) (#12790)
* Expose all rewards (fees, rent, voting and staking) in RPC getConfirmedBlock and the cli

(cherry picked from commit c5c8da1ac0)

# Conflicts:
#	Cargo.lock
#	transaction-status/Cargo.toml

* fix: surface full block rewards type

(cherry picked from commit 1b16790325)

* resolve conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-10 06:11:42 +00:00
Jack May
e999823b4b document program address collisions (#12774)
(cherry picked from commit 9ac8db3533)
2020-10-09 22:35:47 -07:00
mergify[bot]
1e46a5b147 Fix typo (#12780) (#12784)
(cherry picked from commit 5800217998)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-10 02:09:09 +00:00
mergify[bot]
567a1cb944 Correct Bank timestamp drift every slot (#12737) (#12777)
* Move timestamp helper to sdk

* Add Bank method for getting timestamp estimate

* Return sysvar info from Bank::clock

* Add feature-gated timestamp correction

* Rename unix_timestamp method to be more descriptive

* Review comments

* Add timestamp metric

(cherry picked from commit b028c47d2b)

# Conflicts:
#	runtime/src/feature_set.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-10 00:42:44 +00:00
mergify[bot]
2996cebfaa Add convenience script for working in stability branches (#12765) (#12773)
* Add convenience script for working in stability branches

* Update scripts/curgo.sh

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

* re{locate,name} to /cargo

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

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-09 23:02:21 +00:00
mergify[bot]
7a1889aaf9 Add adjustable stack size and call depth (bp #12728) (#12770)
* Add adjustable stack size and call depth (#12728)

(cherry picked from commit c3907be623)

# Conflicts:
#	programs/bpf/Cargo.toml
#	programs/bpf_loader/Cargo.toml

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
2020-10-09 22:08:01 +00:00
mergify[bot]
9188153b7d Fix fee mismatch on snapshot deserialize (#12697) (#12754)
Co-authored-by: Carl Lin <carl@solana.com>
(cherry picked from commit c879e7c1ad)

Co-authored-by: carllin <wumu727@gmail.com>
2020-10-09 20:21:50 +00:00
mergify[bot]
4b9f2e987a Bump max invoke depth to 4 (#12742) (#12764)
(cherry picked from commit 2cd7cd3149)

Co-authored-by: Jack May <jack@solana.com>
2020-10-09 18:49:44 +00:00
mergify[bot]
bb5c76483a Advise setting --wal-recovery-mode, and using --private-rpc for mainnet-beta (#12761)
(cherry picked from commit 3fedcdc6bc)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-09 15:56:56 +00:00
mergify[bot]
aafbb251b9 Only fetch snapshot if it's newer than local (#12663) (#12752)
* Only fetch snapshot if it's newer than local

* Prefer as_ref over clone

* More nits

* Don't wait forwever for newer snapshot

(cherry picked from commit 81489ccb76)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-09 07:15:34 +00:00
mergify[bot]
dd32540ceb Add inflation_kill_switch feature (#12749)
(cherry picked from commit c8807d227a)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-09 05:55:51 +00:00
mergify[bot]
e1a9cbaf3c Add new internal accounts (#12740) (#12747)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit 2c5f83c264)

Co-authored-by: Dan Albert <dan@solana.com>
2020-10-09 02:19:55 +00:00
mergify[bot]
83740246fc Minor variable name cleanup (#12745)
(cherry picked from commit 3a04026599)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-09 02:12:28 +00:00
mergify[bot]
7a53ca18a6 Store program logs in blockstore / bigtable (TransactionWithStatusMeta) (#12678) (#12735)
* introduce store program logs in blockstore / bigtable

* fix test, transaction logs created for successful transactions

* fix test for legacy bincode implementation around log_messages

* only api nodes should record logs

* truncate transaction logs to 100KB

* refactor log truncate for improved coverage

(cherry picked from commit 8f5431551e)

Co-authored-by: Josh <josh.hundley@gmail.com>
2020-10-08 20:19:26 +00:00
mergify[bot]
c1a8637cb5 Support multiple connected HW wallets configured with the same seed phrase (bp #12716) (#12720)
* remote-wallet: Select hardware wallets based on host device path

(cherry picked from commit 8e3353d9ef)

* remote-wallet: Append wallet "name" to entries in selector UI

(cherry picked from commit f1a2ad1b7d)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-08 05:32:48 +00:00
mergify[bot]
d6831309cd Revert "Restore --expected-shred-version argument for mainnet-beta" (#12723)
This reverts commit 9410eab2af.

(cherry picked from commit dadc84fa8c)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-08 05:00:44 +00:00
364 changed files with 10601 additions and 4091 deletions

701
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -16,6 +16,7 @@ members = [
"dos",
"download-utils",
"faucet",
"frozen-abi",
"perf",
"validator",
"genesis",
@@ -30,6 +31,7 @@ members = [
"merkle-tree",
"stake-o-matic",
"storage-bigtable",
"storage-proto",
"streamer",
"measure",
"metrics",
@@ -51,6 +53,7 @@ members = [
"ramp-tps",
"runtime",
"sdk",
"sdk/cargo-build-bpf",
"scripts",
"stake-accounts",
"stake-monitor",

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-account-decoder"
version = "1.4.0"
version = "1.4.2"
description = "Solana account decoder"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -18,11 +18,11 @@ lazy_static = "1.4.0"
serde = "1.0.112"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-config-program = { path = "../programs/config", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
spl-token-v2-0 = { package = "spl-token", version = "=2.0.6", features = ["skip-no-mangle"] }
solana-config-program = { path = "../programs/config", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-stake-program = { path = "../programs/stake", version = "1.4.2" }
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
spl-token-v2-0 = { package = "spl-token", version = "=2.0.8" }
thiserror = "1.0"
[package.metadata.docs.rs]

View File

@@ -111,8 +111,8 @@ mod test {
#[test]
fn test_parse_account_data() {
let account_pubkey = Pubkey::new_rand();
let other_program = Pubkey::new_rand();
let account_pubkey = solana_sdk::pubkey::new_rand();
let other_program = solana_sdk::pubkey::new_rand();
let data = vec![0; 4];
assert!(parse_account_data(&account_pubkey, &other_program, &data, None).is_err());

View File

@@ -117,7 +117,7 @@ mod test {
}))
.unwrap(),
};
let info_pubkey = Pubkey::new_rand();
let info_pubkey = solana_sdk::pubkey::new_rand();
let validator_info_config_account = create_config_account(
vec![(validator_info::id(), false), (info_pubkey, true)],
&validator_info,

View File

@@ -134,7 +134,6 @@ impl From<Delegation> for UiDelegation {
mod test {
use super::*;
use bincode::serialize;
use solana_sdk::pubkey::Pubkey;
#[test]
fn test_parse_stake() {
@@ -145,8 +144,8 @@ mod test {
StakeAccountType::Uninitialized
);
let pubkey = Pubkey::new_rand();
let custodian = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let custodian = solana_sdk::pubkey::new_rand();
let authorized = Authorized::auto(&pubkey);
let lockup = Lockup {
unix_timestamp: 0,
@@ -180,7 +179,7 @@ mod test {
})
);
let voter_pubkey = Pubkey::new_rand();
let voter_pubkey = solana_sdk::pubkey::new_rand();
let stake = Stake {
delegation: Delegation {
voter_pubkey,

View File

@@ -319,7 +319,7 @@ mod test {
}]),
);
let bad_pubkey = Pubkey::new_rand();
let bad_pubkey = solana_sdk::pubkey::new_rand();
assert!(parse_sysvar(&stake_history_sysvar.data, &bad_pubkey).is_err());
let bad_data = vec![0; 4];

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-accounts-bench"
version = "1.4.0"
version = "1.4.2"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -11,11 +11,11 @@ publish = false
[dependencies]
log = "0.4.6"
rayon = "1.4.0"
solana-logger = { path = "../logger", version = "1.4.0" }
solana-runtime = { path = "../runtime", version = "1.4.0" }
solana-measure = { path = "../measure", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-version = { path = "../version", version = "1.4.0" }
solana-logger = { path = "../logger", version = "1.4.2" }
solana-runtime = { path = "../runtime", version = "1.4.2" }
solana-measure = { path = "../measure", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-version = { path = "../version", version = "1.4.2" }
rand = "0.7.0"
clap = "2.33.1"
crossbeam-channel = "0.4"

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-banking-bench"
version = "1.4.0"
version = "1.4.2"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -14,16 +14,16 @@ crossbeam-channel = "0.4"
log = "0.4.6"
rand = "0.7.0"
rayon = "1.4.0"
solana-core = { path = "../core", version = "1.4.0" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
solana-streamer = { path = "../streamer", version = "1.4.0" }
solana-perf = { path = "../perf", version = "1.4.0" }
solana-ledger = { path = "../ledger", version = "1.4.0" }
solana-logger = { path = "../logger", version = "1.4.0" }
solana-runtime = { path = "../runtime", version = "1.4.0" }
solana-measure = { path = "../measure", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-version = { path = "../version", version = "1.4.0" }
solana-core = { path = "../core", version = "1.4.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
solana-streamer = { path = "../streamer", version = "1.4.2" }
solana-perf = { path = "../perf", version = "1.4.2" }
solana-ledger = { path = "../ledger", version = "1.4.2" }
solana-logger = { path = "../logger", version = "1.4.2" }
solana-runtime = { path = "../runtime", version = "1.4.2" }
solana-measure = { path = "../measure", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-version = { path = "../version", version = "1.4.2" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -20,7 +20,6 @@ use solana_perf::packet::to_packets_chunked;
use solana_runtime::{bank::Bank, bank_forks::BankForks};
use solana_sdk::{
hash::Hash,
pubkey::Pubkey,
signature::Keypair,
signature::Signature,
system_transaction,
@@ -69,7 +68,7 @@ fn make_accounts_txs(
hash: Hash,
same_payer: bool,
) -> Vec<Transaction> {
let to_pubkey = Pubkey::new_rand();
let to_pubkey = solana_sdk::pubkey::new_rand();
let payer_key = Keypair::new();
let dummy = system_transaction::transfer(&payer_key, &to_pubkey, 1, hash);
(0..total_num_transactions)
@@ -78,9 +77,9 @@ fn make_accounts_txs(
let mut new = dummy.clone();
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
if !same_payer {
new.message.account_keys[0] = Pubkey::new_rand();
new.message.account_keys[0] = solana_sdk::pubkey::new_rand();
}
new.message.account_keys[1] = Pubkey::new_rand();
new.message.account_keys[1] = solana_sdk::pubkey::new_rand();
new.signatures = vec![Signature::new(&sig[0..64])];
new
})
@@ -241,7 +240,7 @@ fn main() {
let base_tx_count = bank.transaction_count();
let mut txs_processed = 0;
let mut root = 1;
let collector = Pubkey::new_rand();
let collector = solana_sdk::pubkey::new_rand();
let config = Config {
packets_per_batch: packets_per_chunk,
chunk_len,

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-banks-client"
version = "1.4.0"
version = "1.4.2"
description = "Solana banks client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -12,15 +12,15 @@ edition = "2018"
async-trait = "0.1.36"
bincode = "1.3.1"
futures = "0.3"
solana-banks-interface = { path = "../banks-interface", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-banks-interface = { path = "../banks-interface", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
tarpc = { version = "0.22.0", features = ["full"] }
tokio = "0.2"
tokio-serde = { version = "0.6", features = ["bincode"] }
[dev-dependencies]
solana-runtime = { path = "../runtime", version = "1.4.0" }
solana-banks-server = { path = "../banks-server", version = "1.4.0" }
solana-runtime = { path = "../runtime", version = "1.4.2" }
solana-banks-server = { path = "../banks-server", version = "1.4.2" }
[lib]
crate-type = ["lib"]

View File

@@ -213,7 +213,7 @@ mod tests {
use super::*;
use solana_banks_server::banks_server::start_local_server;
use solana_runtime::{bank::Bank, bank_forks::BankForks, genesis_utils::create_genesis_config};
use solana_sdk::{message::Message, pubkey::Pubkey, signature::Signer, system_instruction};
use solana_sdk::{message::Message, signature::Signer, system_instruction};
use std::sync::{Arc, RwLock};
use tarpc::transport;
use tokio::{runtime::Runtime, time::delay_for};
@@ -235,7 +235,7 @@ mod tests {
&genesis.genesis_config,
))));
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let mint_pubkey = genesis.mint_keypair.pubkey();
let instruction = system_instruction::transfer(&mint_pubkey, &bob_pubkey, 1);
let message = Message::new(&[instruction], Some(&mint_pubkey));
@@ -265,7 +265,7 @@ mod tests {
))));
let mint_pubkey = &genesis.mint_keypair.pubkey();
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let instruction = system_instruction::transfer(&mint_pubkey, &bob_pubkey, 1);
let message = Message::new(&[instruction], Some(&mint_pubkey));

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-banks-interface"
version = "1.4.0"
version = "1.4.2"
description = "Solana banks RPC interface"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -10,7 +10,7 @@ edition = "2018"
[dependencies]
serde = { version = "1.0.112", features = ["derive"] }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
tarpc = { version = "0.22.0", features = ["full"] }
[lib]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-banks-server"
version = "1.4.0"
version = "1.4.2"
description = "Solana banks server"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -12,10 +12,10 @@ edition = "2018"
bincode = "1.3.1"
futures = "0.3"
log = "0.4.8"
solana-banks-interface = { path = "../banks-interface", version = "1.4.0" }
solana-runtime = { path = "../runtime", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-metrics = { path = "../metrics", version = "1.4.0" }
solana-banks-interface = { path = "../banks-interface", version = "1.4.2" }
solana-runtime = { path = "../runtime", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-metrics = { path = "../metrics", version = "1.4.2" }
tarpc = { version = "0.22.0", features = ["full"] }
tokio = "0.2"
tokio-serde = { version = "0.6", features = ["bincode"] }

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-bench-exchange"
version = "1.4.0"
version = "1.4.2"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -18,21 +18,21 @@ rand = "0.7.0"
rayon = "1.4.0"
serde_json = "1.0.56"
serde_yaml = "0.8.13"
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
solana-core = { path = "../core", version = "1.4.0" }
solana-genesis = { path = "../genesis", version = "1.4.0" }
solana-client = { path = "../client", version = "1.4.0" }
solana-faucet = { path = "../faucet", version = "1.4.0" }
solana-exchange-program = { path = "../programs/exchange", version = "1.4.0" }
solana-logger = { path = "../logger", version = "1.4.0" }
solana-metrics = { path = "../metrics", version = "1.4.0" }
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
solana-runtime = { path = "../runtime", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-version = { path = "../version", version = "1.4.0" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
solana-core = { path = "../core", version = "1.4.2" }
solana-genesis = { path = "../genesis", version = "1.4.2" }
solana-client = { path = "../client", version = "1.4.2" }
solana-faucet = { path = "../faucet", version = "1.4.2" }
solana-exchange-program = { path = "../programs/exchange", version = "1.4.2" }
solana-logger = { path = "../logger", version = "1.4.2" }
solana-metrics = { path = "../metrics", version = "1.4.2" }
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
solana-runtime = { path = "../runtime", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-version = { path = "../version", version = "1.4.2" }
[dev-dependencies]
solana-local-cluster = { path = "../local-cluster", version = "1.4.0" }
solana-local-cluster = { path = "../local-cluster", version = "1.4.2" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

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

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-bench-tps"
version = "1.4.0"
version = "1.4.2"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -15,23 +15,23 @@ log = "0.4.8"
rayon = "1.4.0"
serde_json = "1.0.56"
serde_yaml = "0.8.13"
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
solana-core = { path = "../core", version = "1.4.0" }
solana-genesis = { path = "../genesis", version = "1.4.0" }
solana-client = { path = "../client", version = "1.4.0" }
solana-faucet = { path = "../faucet", version = "1.4.0" }
solana-logger = { path = "../logger", version = "1.4.0" }
solana-metrics = { path = "../metrics", version = "1.4.0" }
solana-measure = { path = "../measure", version = "1.4.0" }
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
solana-runtime = { path = "../runtime", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-version = { path = "../version", version = "1.4.0" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
solana-core = { path = "../core", version = "1.4.2" }
solana-genesis = { path = "../genesis", version = "1.4.2" }
solana-client = { path = "../client", version = "1.4.2" }
solana-faucet = { path = "../faucet", version = "1.4.2" }
solana-logger = { path = "../logger", version = "1.4.2" }
solana-metrics = { path = "../metrics", version = "1.4.2" }
solana-measure = { path = "../measure", version = "1.4.2" }
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
solana-runtime = { path = "../runtime", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-version = { path = "../version", version = "1.4.2" }
[dev-dependencies]
serial_test = "0.4.0"
serial_test_derive = "0.4.0"
solana-local-cluster = { path = "../local-cluster", version = "1.4.0" }
solana-local-cluster = { path = "../local-cluster", version = "1.4.2" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

31
cargo Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# shellcheck source=ci/rust-version.sh
here=$(dirname "$0")
source "${here}"/ci/rust-version.sh all
toolchain=
case "$1" in
stable)
# shellcheck disable=SC2054 # rust_stable is sourced from rust-version.sh
toolchain="$rust_stable"
shift
;;
nightly)
# shellcheck disable=SC2054 # rust_nightly is sourced from rust-version.sh
toolchain="$rust_nightly"
shift
;;
+*)
toolchain="${1#+}"
shift
;;
*)
# shellcheck disable=SC2054 # rust_stable is sourced from rust-version.sh
toolchain="$rust_stable"
;;
esac
set -x
exec cargo "+${toolchain}" "${@}"

5
cargo-build-bpf Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
here=$(dirname "$0")
set -x
exec cargo run --manifest-path $here/sdk/cargo-build-bpf/Cargo.toml -- --bpf-sdk $here/sdk/bpf "$@"

View File

@@ -26,6 +26,7 @@ declare print_free_tree=(
':runtime/src/**.rs'
':sdk/bpf/rust/rust-utils/**.rs'
':sdk/**.rs'
':^sdk/cargo-build-bpf/**.rs'
':^sdk/src/program_option.rs'
':^sdk/src/program_stubs.rs'
':programs/**.rs'

View File

@@ -42,10 +42,10 @@ def get_packages():
sys.exit(1)
# Order dependencies
deleted_dependencies = []
sorted_dependency_graph = []
max_iterations = pow(len(dependency_graph),2)
while len(deleted_dependencies) < len(dependency_graph):
while dependency_graph:
deleted_packages = []
if max_iterations == 0:
# One day be more helpful and find the actual cycle for the user...
sys.exit('Error: Circular dependency suspected between these packages: \n {}\n'.format('\n '.join(dependency_graph.keys())))
@@ -53,13 +53,17 @@ def get_packages():
max_iterations -= 1
for package, dependencies in dependency_graph.items():
if package in deleted_packages:
continue
for dependency in dependencies:
if dependency in dependency_graph:
break
else:
deleted_dependencies.append(package)
deleted_packages.append(package)
sorted_dependency_graph.append((package, manifest_path[package]))
dependency_graph = {p: d for p, d in dependency_graph.items() if not p in deleted_packages }
return sorted_dependency_graph

View File

@@ -85,23 +85,24 @@ echo --- Creating release tarball
source ci/rust-version.sh stable
scripts/cargo-install-all.sh +"$rust_stable" "${RELEASE_BASENAME}"
mkdir -p "${RELEASE_BASENAME}"/bin/sdk/bpf
cp -a sdk/bpf/* "${RELEASE_BASENAME}"/bin/sdk/bpf
tar cvf "${TARBALL_BASENAME}"-$TARGET.tar "${RELEASE_BASENAME}"
bzip2 "${TARBALL_BASENAME}"-$TARGET.tar
cp "${RELEASE_BASENAME}"/bin/solana-install-init solana-install-init-$TARGET
cp "${RELEASE_BASENAME}"/version.yml "${TARBALL_BASENAME}"-$TARGET.yml
)
# Metrics tarball is platform agnostic, only publish it from Linux
# Maybe tarballs are platform agnostic, only publish them from the Linux build
MAYBE_TARBALLS=
if [[ "$CI_OS_NAME" = linux ]]; then
metrics/create-metrics-tarball.sh
(
set -x
sdk/bpf/scripts/package.sh
[[ -f bpf-sdk.tar.bz2 ]]
)
MAYBE_TARBALLS="bpf-sdk.tar.bz2 solana-metrics.tar.bz2"
MAYBE_TARBALLS="bpf-sdk.tar.bz2"
fi
source ci/upload-ci-artifact.sh

View File

@@ -41,7 +41,7 @@ if [[ $CI_BASE_BRANCH = "$EDGE_CHANNEL" ]]; then
echo "$0: [tree (for outdated Cargo.lock sync)|check (for compilation error)|update -p foo --precise x.y.z (for your Cargo.toml update)] ..." >&2
exit "$check_status"
fi
# Ensure nightly and --benches
_ scripts/cargo-for-all-lock-files.sh +"$rust_nightly" check --locked --all-targets
else
@@ -57,7 +57,18 @@ _ cargo +"$rust_nightly" clippy \
-Zunstable-options --workspace --all-targets \
-- --deny=warnings --allow=clippy::stable_sort_primitive
_ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit --ignore RUSTSEC-2020-0002 --ignore RUSTSEC-2020-0008
cargo_audit_ignores=(
# failure is officially deprecated/unmaintained
#
# Blocked on multiple upstream crates removing their `failure` dependency.
--ignore RUSTSEC-2020-0036
# `net2` crate has been deprecated; use `socket2` instead
#
# Blocked on https://github.com/paritytech/jsonrpc/issues/575
--ignore RUSTSEC-2020-0016
)
_ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit "${cargo_audit_ignores[@]}"
{
cd programs/bpf
@@ -68,7 +79,9 @@ _ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit --ignore RUSTSEC-202
cd "$project"
_ cargo +"$rust_stable" fmt -- --check
_ cargo +"$rust_nightly" test
_ cargo +"$rust_nightly" clippy -- --deny=warnings --allow=clippy::missing_safety_doc
_ cargo +"$rust_nightly" clippy -- --deny=warnings \
--allow=clippy::missing_safety_doc \
--allow=clippy::stable_sort_primitive
)
done
}

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-clap-utils"
version = "1.4.0"
version = "1.4.2"
description = "Solana utilities for the clap"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -11,8 +11,8 @@ edition = "2018"
[dependencies]
clap = "2.33.0"
rpassword = "4.0"
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
thiserror = "1.0.20"
tiny-bip39 = "0.7.0"
url = "2.1.0"

View File

@@ -228,8 +228,8 @@ mod tests {
assert_eq!(values_of(&matches, "multiple"), Some(vec![50, 39]));
assert_eq!(values_of::<u64>(&matches, "single"), None);
let pubkey0 = Pubkey::new_rand();
let pubkey1 = Pubkey::new_rand();
let pubkey0 = solana_sdk::pubkey::new_rand();
let pubkey1 = solana_sdk::pubkey::new_rand();
let matches = app().clone().get_matches_from(vec![
"test",
"--multiple",
@@ -251,7 +251,7 @@ mod tests {
assert_eq!(value_of(&matches, "single"), Some(50));
assert_eq!(value_of::<u64>(&matches, "multiple"), None);
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let matches = app()
.clone()
.get_matches_from(vec!["test", "--single", &pubkey.to_string()]);
@@ -331,8 +331,8 @@ mod tests {
#[test]
fn test_pubkeys_sigs_of() {
let key1 = Pubkey::new_rand();
let key2 = Pubkey::new_rand();
let key1 = solana_sdk::pubkey::new_rand();
let key2 = solana_sdk::pubkey::new_rand();
let sig1 = Keypair::new().sign_message(&[0u8]);
let sig2 = Keypair::new().sign_message(&[1u8]);
let signer1 = format!("{}={}", key1, sig1);

View File

@@ -298,7 +298,24 @@ pub fn keypair_from_seed_phrase(
keypair_from_seed_phrase_and_passphrase(&seed_phrase, &passphrase)?
} else {
let sanitized = sanitize_seed_phrase(seed_phrase);
let mnemonic = Mnemonic::from_phrase(&sanitized, Language::English)?;
let parse_language_fn = || {
for language in &[
Language::English,
Language::ChineseSimplified,
Language::ChineseTraditional,
Language::Japanese,
Language::Spanish,
Language::Korean,
Language::French,
Language::Italian,
] {
if let Ok(mnemonic) = Mnemonic::from_phrase(&sanitized, *language) {
return Ok(mnemonic);
}
}
Err("Can't get mnemonic from seed phrases")
};
let mnemonic = parse_language_fn()?;
let passphrase = prompt_passphrase(&passphrase_prompt)?;
let seed = Seed::new(&mnemonic, &passphrase);
keypair_from_seed(seed.as_bytes())?

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-cli-config"
description = "Blockchain, Rebuilt for Scale"
version = "1.4.0"
version = "1.4.2"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-cli-output"
description = "Blockchain, Rebuilt for Scale"
version = "1.4.0"
version = "1.4.2"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -17,13 +17,13 @@ indicatif = "0.15.0"
serde = "1.0.112"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "1.4.0" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
solana-client = { path = "../client", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.0" }
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
solana-account-decoder = { path = "../account-decoder", version = "1.4.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
solana-client = { path = "../client", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-stake-program = { path = "../programs/stake", version = "1.4.2" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.2" }
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -132,7 +132,7 @@ impl fmt::Display for CliBlockProduction {
"{}",
style(format!(
" {:<44} {:>15} {:>15} {:>15} {:>23}",
"Identity Pubkey",
"Identity",
"Leader Slots",
"Blocks Produced",
"Skipped Slots",
@@ -301,7 +301,7 @@ pub struct CliValidatorsStakeByVersion {
pub struct CliValidators {
pub total_active_stake: u64,
pub total_current_stake: u64,
pub total_deliquent_stake: u64,
pub total_delinquent_stake: u64,
pub current_validators: Vec<CliValidator>,
pub delinquent_validators: Vec<CliValidator>,
pub stake_by_version: BTreeMap<String, CliValidatorsStakeByVersion>,
@@ -360,7 +360,7 @@ impl fmt::Display for CliValidators {
"Active Stake:",
&build_balance_message(self.total_active_stake, self.use_lamports_unit, true),
)?;
if self.total_deliquent_stake > 0 {
if self.total_delinquent_stake > 0 {
writeln_name_value(
f,
"Current Stake:",
@@ -376,11 +376,11 @@ impl fmt::Display for CliValidators {
&format!(
"{} ({:0.2}%)",
&build_balance_message(
self.total_deliquent_stake,
self.total_delinquent_stake,
self.use_lamports_unit,
true
),
100. * self.total_deliquent_stake as f64 / self.total_active_stake as f64
100. * self.total_delinquent_stake as f64 / self.total_active_stake as f64
),
)?;
}
@@ -412,8 +412,8 @@ impl fmt::Display for CliValidators {
"{}",
style(format!(
" {:<44} {:<38} {} {} {} {:>10} {:^8} {}",
"Identity Pubkey",
"Vote Account Pubkey",
"Identity",
"Vote Account",
"Commission",
"Last Vote",
"Root Block",
@@ -661,13 +661,8 @@ impl fmt::Display for CliStakeState {
if lockup.unix_timestamp != UnixTimestamp::default() {
writeln!(
f,
"Lockup Timestamp: {} (UnixTimestamp: {})",
DateTime::<Utc>::from_utc(
NaiveDateTime::from_timestamp(lockup.unix_timestamp, 0),
Utc
)
.to_rfc3339_opts(SecondsFormat::Secs, true),
lockup.unix_timestamp
"Lockup Timestamp: {}",
unix_timestamp_to_string(lockup.unix_timestamp)
)?;
}
if lockup.epoch != Epoch::default() {
@@ -952,8 +947,8 @@ impl VerboseDisplay for CliValidatorInfo {}
impl fmt::Display for CliValidatorInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln_name_value(f, "Validator Identity Pubkey:", &self.identity_pubkey)?;
writeln_name_value(f, " Info Pubkey:", &self.info_pubkey)?;
writeln_name_value(f, "Validator Identity:", &self.identity_pubkey)?;
writeln_name_value(f, " Info Address:", &self.info_pubkey)?;
for (key, value) in self.info.iter() {
writeln_name_value(
f,
@@ -1008,7 +1003,12 @@ impl fmt::Display for CliVoteAccount {
None => "~".to_string(),
}
)?;
writeln!(f, "Recent Timestamp: {:?}", self.recent_timestamp)?;
writeln!(
f,
"Recent Timestamp: {} from slot {}",
unix_timestamp_to_string(self.recent_timestamp.timestamp),
self.recent_timestamp.slot
)?;
if !self.votes.is_empty() {
writeln!(f, "Recent Votes:")?;
for vote in &self.votes {
@@ -1093,19 +1093,22 @@ pub struct CliBlockTime {
impl QuietDisplay for CliBlockTime {}
impl VerboseDisplay for CliBlockTime {}
fn unix_timestamp_to_string(unix_timestamp: UnixTimestamp) -> String {
format!(
"{} (UnixTimestamp: {})",
match NaiveDateTime::from_timestamp_opt(unix_timestamp, 0) {
Some(ndt) =>
DateTime::<Utc>::from_utc(ndt, Utc).to_rfc3339_opts(SecondsFormat::Secs, true),
None => "unknown".to_string(),
},
unix_timestamp,
)
}
impl fmt::Display for CliBlockTime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln_name_value(f, "Block:", &self.slot.to_string())?;
writeln_name_value(
f,
"Date:",
&format!(
"{} (UnixTimestamp: {})",
DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(self.timestamp, 0), Utc)
.to_rfc3339_opts(SecondsFormat::Secs, true),
self.timestamp
),
)
writeln_name_value(f, "Date:", &unix_timestamp_to_string(self.timestamp))
}
}

View File

@@ -197,6 +197,15 @@ pub fn write_transaction<W: io::Write>(
)?;
}
}
if let Some(log_messages) = &transaction_status.log_messages {
if !log_messages.is_empty() {
writeln!(w, "{}Log Messages:", prefix,)?;
for log_message in log_messages {
writeln!(w, "{} {}", prefix, log_message,)?;
}
}
}
} else {
writeln!(w, "{}Status: Unavailable", prefix)?;
}

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-cli"
description = "Blockchain, Rebuilt for Scale"
version = "1.4.0"
version = "1.4.2"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -23,32 +23,35 @@ indicatif = "0.15.0"
humantime = "2.0.1"
num-traits = "0.2"
pretty-hex = "0.1.1"
reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] }
reqwest = { version = "0.10.8", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde = "1.0.112"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "1.4.0" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
solana-cli-config = { path = "../cli-config", version = "1.4.0" }
solana-cli-output = { path = "../cli-output", version = "1.4.0" }
solana-client = { path = "../client", version = "1.4.0" }
solana-config-program = { path = "../programs/config", version = "1.4.0" }
solana-faucet = { path = "../faucet", version = "1.4.0" }
solana-logger = { path = "../logger", version = "1.4.0" }
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.0" }
solana-runtime = { path = "../runtime", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.0" }
solana-version = { path = "../version", version = "1.4.0" }
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
solana-vote-signer = { path = "../vote-signer", version = "1.4.0" }
solana-account-decoder = { path = "../account-decoder", version = "1.4.2" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.4.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
solana-cli-config = { path = "../cli-config", version = "1.4.2" }
solana-cli-output = { path = "../cli-output", version = "1.4.2" }
solana-client = { path = "../client", version = "1.4.2" }
solana-config-program = { path = "../programs/config", version = "1.4.2" }
solana-faucet = { path = "../faucet", version = "1.4.2" }
solana-logger = { path = "../logger", version = "1.4.2" }
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
solana_rbpf = "=0.1.32"
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.2" }
solana-runtime = { path = "../runtime", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-stake-program = { path = "../programs/stake", version = "1.4.2" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.2" }
solana-version = { path = "../version", version = "1.4.2" }
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
solana-vote-signer = { path = "../vote-signer", version = "1.4.2" }
thiserror = "1.0.20"
tiny-bip39 = "0.7.0"
url = "2.1.1"
[dev-dependencies]
solana-core = { path = "../core", version = "1.4.0" }
solana-core = { path = "../core", version = "1.4.2" }
tempfile = "3.1.0"
[[bin]]

View File

@@ -54,12 +54,42 @@ pub fn check_account_for_multiple_fees_with_commitment(
fee_calculator: &FeeCalculator,
messages: &[&Message],
commitment: CommitmentConfig,
) -> Result<(), CliError> {
check_account_for_spend_multiple_fees_with_commitment(
rpc_client,
account_pubkey,
0,
fee_calculator,
messages,
commitment,
)
}
pub fn check_account_for_spend_multiple_fees_with_commitment(
rpc_client: &RpcClient,
account_pubkey: &Pubkey,
balance: u64,
fee_calculator: &FeeCalculator,
messages: &[&Message],
commitment: CommitmentConfig,
) -> Result<(), CliError> {
let fee = calculate_fee(fee_calculator, messages);
if !check_account_for_balance_with_commitment(rpc_client, account_pubkey, fee, commitment)
.map_err(Into::<ClientError>::into)?
if !check_account_for_balance_with_commitment(
rpc_client,
account_pubkey,
balance + fee,
commitment,
)
.map_err(Into::<ClientError>::into)?
{
return Err(CliError::InsufficientFundsForFee(lamports_to_sol(fee)));
if balance > 0 {
return Err(CliError::InsufficientFundsForSpendAndFee(
lamports_to_sol(balance),
lamports_to_sol(fee),
));
} else {
return Err(CliError::InsufficientFundsForFee(lamports_to_sol(fee)));
}
}
Ok(())
}
@@ -131,7 +161,7 @@ mod tests {
context: RpcResponseContext { slot: 1 },
value: json!(account_balance),
});
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let fee_calculator = FeeCalculator::new(1);
let pubkey0 = Pubkey::new(&[0; 32]);
@@ -191,7 +221,7 @@ mod tests {
context: RpcResponseContext { slot: 1 },
value: json!(account_balance),
});
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let mut mocks = HashMap::new();
mocks.insert(RpcRequest::GetBalance, account_balance_response);
@@ -237,9 +267,9 @@ mod tests {
#[test]
fn test_check_unique_pubkeys() {
let pubkey0 = Pubkey::new_rand();
let pubkey0 = solana_sdk::pubkey::new_rand();
let pubkey_clone = pubkey0;
let pubkey1 = Pubkey::new_rand();
let pubkey1 = solana_sdk::pubkey::new_rand();
check_unique_pubkeys((&pubkey0, "foo".to_string()), (&pubkey1, "bar".to_string()))
.expect("unexpected result");

View File

@@ -2,11 +2,13 @@ use crate::{
checks::*, cluster_query::*, feature::*, inflation::*, nonce::*, spend_utils::*, stake::*,
validator_info::*, vote::*,
};
use bip39::{Language, Mnemonic, MnemonicType, Seed};
use clap::{value_t_or_exit, App, AppSettings, Arg, ArgMatches, SubCommand};
use log::*;
use num_traits::FromPrimitive;
use serde_json::{self, json, Value};
use solana_account_decoder::{UiAccount, UiAccountEncoding};
use solana_bpf_loader_program::bpf_verifier;
use solana_clap_utils::{
self,
commitment::commitment_arg_with_default,
@@ -36,6 +38,7 @@ use solana_client::{
use solana_faucet::faucet::request_airdrop_transaction;
#[cfg(test)]
use solana_faucet::faucet_mock::request_airdrop_transaction;
use solana_rbpf::vm::EbpfVm;
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
bpf_loader, bpf_loader_deprecated,
@@ -47,7 +50,7 @@ use solana_sdk::{
loader_instruction,
message::Message,
pubkey::{Pubkey, MAX_SEED_LEN},
signature::{Keypair, Signature, Signer, SignerError},
signature::{keypair_from_seed, Keypair, Signature, Signer, SignerError},
signers::Signers,
system_instruction::{self, SystemError},
system_program,
@@ -98,7 +101,7 @@ pub enum CliCommand {
Fees,
FirstAvailableBlock,
GetBlock {
slot: Slot,
slot: Option<Slot>,
},
GetBlockTime {
slot: Option<Slot>,
@@ -1130,7 +1133,48 @@ fn process_deploy(
address: Option<SignerIndex>,
use_deprecated_loader: bool,
) -> ProcessResult {
let new_keypair = Keypair::new(); // Create ephemeral keypair to use for program address, if not provided
const WORDS: usize = 12;
// Create ephemeral keypair to use for program address, if not provided
let mnemonic = Mnemonic::new(MnemonicType::for_word_count(WORDS)?, Language::English);
let seed = Seed::new(&mnemonic, "");
let new_keypair = keypair_from_seed(seed.as_bytes())?;
let result = do_process_deploy(
rpc_client,
config,
program_location,
address,
use_deprecated_loader,
new_keypair,
);
if result.is_err() && address.is_none() {
let phrase: &str = mnemonic.phrase();
let divider = String::from_utf8(vec![b'='; phrase.len()]).unwrap();
eprintln!(
"{}\nTo reuse this address, recover the ephemeral keypair file with",
divider
);
eprintln!(
"`solana-keygen recover` and the following {}-word seed phrase,",
WORDS
);
eprintln!(
"then pass it as the [ADDRESS_SIGNER] argument to `solana deploy ...`\n{}\n{}\n{}",
divider, phrase, divider
);
}
result
}
fn do_process_deploy(
rpc_client: &RpcClient,
config: &CliConfig,
program_location: &str,
address: Option<SignerIndex>,
use_deprecated_loader: bool,
new_keypair: Keypair,
) -> ProcessResult {
let program_id = if let Some(i) = address {
config.signers[i]
} else {
@@ -1144,6 +1188,9 @@ fn process_deploy(
CliError::DynamicProgramError(format!("Unable to read program file: {}", err))
})?;
EbpfVm::create_executable_from_elf(&program_data, Some(|x| bpf_verifier::check(x, true)))
.map_err(|err| CliError::DynamicProgramError(format!("ELF error: {}", err)))?;
let loader_id = if use_deprecated_loader {
bpf_loader_deprecated::id()
} else {
@@ -1154,11 +1201,12 @@ fn process_deploy(
let signers = [config.signers[0], program_id];
// Check program account to see if partial initialization has occurred
let initial_instructions = if let Some(account) = rpc_client
let (initial_instructions, balance_needed) = if let Some(account) = rpc_client
.get_account_with_commitment(&program_id.pubkey(), config.commitment)?
.value
{
let mut instructions: Vec<Instruction> = vec![];
let mut balance_needed = 0;
if account.executable {
return Err(CliError::DynamicProgramError(
"Program account is already executable".to_string(),
@@ -1182,21 +1230,26 @@ fn process_deploy(
}
}
if account.lamports < minimum_balance {
let balance = minimum_balance - account.lamports;
instructions.push(system_instruction::transfer(
&config.signers[0].pubkey(),
&program_id.pubkey(),
minimum_balance - account.lamports,
balance,
));
balance_needed = balance;
}
instructions
(instructions, balance_needed)
} else {
vec![system_instruction::create_account(
&config.signers[0].pubkey(),
&program_id.pubkey(),
(
vec![system_instruction::create_account(
&config.signers[0].pubkey(),
&program_id.pubkey(),
minimum_balance,
program_data.len() as u64,
&loader_id,
)],
minimum_balance,
program_data.len() as u64,
&loader_id,
)]
)
};
let initial_message = if !initial_instructions.is_empty() {
Some(Message::new(
@@ -1239,9 +1292,10 @@ fn process_deploy(
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
check_account_for_multiple_fees_with_commitment(
check_account_for_spend_multiple_fees_with_commitment(
rpc_client,
&config.signers[0].pubkey(),
balance_needed,
&fee_calculator,
&messages,
config.commitment,
@@ -1266,8 +1320,8 @@ fn process_deploy(
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<SystemError>(result, &config).map_err(|_| {
CliError::DynamicProgramError("Program account allocation failed".to_string())
log_instruction_custom_error::<SystemError>(result, &config).map_err(|err| {
CliError::DynamicProgramError(format!("Program account allocation failed: {}", err))
})?;
}
@@ -2187,7 +2241,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
.arg(
Arg::with_name("address_signer")
.index(2)
.value_name("SIGNER_KEYPAIR")
.value_name("ADDRESS_SIGNER")
.takes_value(true)
.validator(is_valid_signer)
.help("The signer for the desired address of the program [default: new random address]")
@@ -2355,7 +2409,10 @@ mod tests {
.unwrap();
assert_eq!(signer_info.signers.len(), 1);
assert_eq!(signer_info.index_of(None), Some(0));
assert_eq!(signer_info.index_of(Some(Pubkey::new_rand())), None);
assert_eq!(
signer_info.index_of(Some(solana_sdk::pubkey::new_rand())),
None
);
let keypair0 = keypair_from_seed(&[1u8; 32]).unwrap();
let keypair0_pubkey = keypair0.pubkey();
@@ -2411,7 +2468,7 @@ mod tests {
fn test_cli_parse_command() {
let test_commands = app("test", "desc", "version");
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let pubkey_string = format!("{}", pubkey);
let default_keypair = Keypair::new();
@@ -2507,7 +2564,7 @@ mod tests {
assert!(parse_command(&test_bad_signature, &default_signer, &mut None).is_err());
// Test CreateAddressWithSeed
let from_pubkey = Some(Pubkey::new_rand());
let from_pubkey = Some(solana_sdk::pubkey::new_rand());
let from_str = from_pubkey.unwrap().to_string();
for (name, program_id) in &[
("STAKE", solana_stake_program::id()),
@@ -2664,7 +2721,7 @@ mod tests {
let result = process_command(&config);
assert!(result.is_ok());
let new_authorized_pubkey = Pubkey::new_rand();
let new_authorized_pubkey = solana_sdk::pubkey::new_rand();
config.signers = vec![&bob_keypair];
config.command = CliCommand::VoteAuthorize {
vote_account_pubkey: bob_pubkey,
@@ -2686,7 +2743,7 @@ mod tests {
let bob_keypair = Keypair::new();
let bob_pubkey = bob_keypair.pubkey();
let custodian = Pubkey::new_rand();
let custodian = solana_sdk::pubkey::new_rand();
config.command = CliCommand::CreateStakeAccount {
stake_account: 1,
seed: None,
@@ -2709,8 +2766,8 @@ mod tests {
let result = process_command(&config);
assert!(result.is_ok());
let stake_account_pubkey = Pubkey::new_rand();
let to_pubkey = Pubkey::new_rand();
let stake_account_pubkey = solana_sdk::pubkey::new_rand();
let to_pubkey = solana_sdk::pubkey::new_rand();
config.command = CliCommand::WithdrawStake {
stake_account_pubkey,
destination_account_pubkey: to_pubkey,
@@ -2727,7 +2784,7 @@ mod tests {
let result = process_command(&config);
assert!(result.is_ok());
let stake_account_pubkey = Pubkey::new_rand();
let stake_account_pubkey = solana_sdk::pubkey::new_rand();
config.command = CliCommand::DeactivateStake {
stake_account_pubkey,
stake_authority: 0,
@@ -2740,7 +2797,7 @@ mod tests {
let result = process_command(&config);
assert!(result.is_ok());
let stake_account_pubkey = Pubkey::new_rand();
let stake_account_pubkey = solana_sdk::pubkey::new_rand();
let split_stake_account = Keypair::new();
config.command = CliCommand::SplitStake {
stake_account_pubkey,
@@ -2758,8 +2815,8 @@ mod tests {
let result = process_command(&config);
assert!(result.is_ok());
let stake_account_pubkey = Pubkey::new_rand();
let source_stake_account_pubkey = Pubkey::new_rand();
let stake_account_pubkey = solana_sdk::pubkey::new_rand();
let source_stake_account_pubkey = solana_sdk::pubkey::new_rand();
let merge_stake_account = Keypair::new();
config.command = CliCommand::MergeStake {
stake_account_pubkey,
@@ -2782,7 +2839,7 @@ mod tests {
assert_eq!(process_command(&config).unwrap(), "1234");
// CreateAddressWithSeed
let from_pubkey = Pubkey::new_rand();
let from_pubkey = solana_sdk::pubkey::new_rand();
config.signers = vec![];
config.command = CliCommand::CreateAddressWithSeed {
from_pubkey: Some(from_pubkey),
@@ -2795,7 +2852,7 @@ mod tests {
assert_eq!(address.unwrap(), expected_address.to_string());
// Need airdrop cases
let to = Pubkey::new_rand();
let to = solana_sdk::pubkey::new_rand();
config.signers = vec![&keypair];
config.command = CliCommand::Airdrop {
faucet_host: None,

View File

@@ -73,8 +73,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
.validator(is_slot)
.value_name("SLOT")
.takes_value(true)
.index(1)
.required(true),
.index(1),
),
)
.subcommand(
@@ -363,7 +362,7 @@ pub fn parse_cluster_ping(
}
pub fn parse_get_block(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let slot = value_t_or_exit!(matches, "slot", Slot);
let slot = value_of(matches, "slot");
Ok(CliCommandInfo {
command: CliCommand::GetBlock { slot },
signers: vec![],
@@ -700,7 +699,17 @@ pub fn process_leader_schedule(rpc_client: &RpcClient) -> ProcessResult {
Ok("".to_string())
}
pub fn process_get_block(rpc_client: &RpcClient, _config: &CliConfig, slot: Slot) -> ProcessResult {
pub fn process_get_block(
rpc_client: &RpcClient,
_config: &CliConfig,
slot: Option<Slot>,
) -> ProcessResult {
let slot = if let Some(slot) = slot {
slot
} else {
rpc_client.get_slot()?
};
let mut block =
rpc_client.get_confirmed_block_with_encoding(slot, UiTransactionEncoding::Base64)?;
@@ -716,18 +725,23 @@ pub fn process_get_block(rpc_client: &RpcClient, _config: &CliConfig, slot: Slot
let mut total_rewards = 0;
println!("Rewards:",);
println!(
" {:<44} {:<15} {:<13} {:>14}",
"Address", "Amount", "New Balance", "Percent Change"
" {:<44} {:^15} {:<15} {:<20} {:>14}",
"Address", "Type", "Amount", "New Balance", "Percent Change"
);
for reward in block.rewards {
let sign = if reward.lamports < 0 { "-" } else { "" };
total_rewards += reward.lamports;
println!(
" {:<44} {:>15} {}",
" {:<44} {:^15} {:>15} {}",
reward.pubkey,
if let Some(reward_type) = reward.reward_type {
format!("{}", reward_type)
} else {
"-".to_string()
},
format!(
"{}{:<14.4}",
"{}{:<14.9}",
sign,
lamports_to_sol(reward.lamports.abs() as u64)
),
@@ -735,7 +749,7 @@ pub fn process_get_block(rpc_client: &RpcClient, _config: &CliConfig, slot: Slot
" - -".to_string()
} else {
format!(
"{:<12.4} {:>13.4}%",
"{:<19.9} {:>13.9}%",
lamports_to_sol(reward.post_balance),
reward.lamports.abs() as f64
/ (reward.post_balance as f64 - reward.lamports as f64)
@@ -746,7 +760,7 @@ pub fn process_get_block(rpc_client: &RpcClient, _config: &CliConfig, slot: Slot
let sign = if total_rewards < 0 { "-" } else { "" };
println!(
"Total Rewards: {}{:12.9}",
"Total Rewards: {}{:<12.9}",
sign,
lamports_to_sol(total_rewards.abs() as u64)
);
@@ -1253,14 +1267,16 @@ pub fn process_show_gossip(rpc_client: &RpcClient, config: &CliConfig) -> Proces
.into_iter()
.map(|node| {
format!(
"{:15} | {:44} | {:6} | {:5} | {:5} | {}",
"{:15} | {:44} | {:6} | {:5} | {:21} | {}",
node.gossip
.map(|addr| addr.ip().to_string())
.unwrap_or_else(|| "none".to_string()),
format_labeled_address(&node.pubkey, &config.address_labels),
format_port(node.gossip),
format_port(node.tpu),
format_port(node.rpc),
node.rpc
.map(|addr| addr.to_string())
.unwrap_or_else(|| "none".to_string()),
node.version.unwrap_or_else(|| "unknown".to_string()),
)
})
@@ -1268,9 +1284,9 @@ pub fn process_show_gossip(rpc_client: &RpcClient, config: &CliConfig) -> Proces
Ok(format!(
"IP Address | Node identifier \
| Gossip | TPU | RPC | Version\n\
| Gossip | TPU | RPC Address | Version\n\
----------------+----------------------------------------------+\
--------+-------+-------+----------------\n\
--------+-------+-----------------------+----------------\n\
{}\n\
Nodes: {}",
s.join("\n"),
@@ -1405,12 +1421,12 @@ pub fn process_show_validators(
.map(|vote_account| vote_account.activated_stake)
.sum();
let total_deliquent_stake = vote_accounts
let total_delinquent_stake = vote_accounts
.delinquent
.iter()
.map(|vote_account| vote_account.activated_stake)
.sum();
let total_current_stake = total_active_stake - total_deliquent_stake;
let total_current_stake = total_active_stake - total_delinquent_stake;
let mut current = vote_accounts.current;
current.sort_by(|a, b| b.activated_stake.cmp(&a.activated_stake));
@@ -1464,7 +1480,7 @@ pub fn process_show_validators(
let cli_validators = CliValidators {
total_active_stake,
total_current_stake,
total_deliquent_stake,
total_delinquent_stake,
current_validators,
delinquent_validators,
stake_by_version,

View File

@@ -230,7 +230,7 @@ fn active_stake_by_feature_set(rpc_client: &RpcClient) -> Result<HashMap<u32, u6
}
// Feature activation is only allowed when 95% of the active stake is on the current feature set
fn feature_activation_allowed(rpc_client: &RpcClient) -> Result<bool, ClientError> {
fn feature_activation_allowed(rpc_client: &RpcClient, quiet: bool) -> Result<bool, ClientError> {
let my_feature_set = solana_version::Version::default().feature_set;
let active_stake_by_feature_set = active_stake_by_feature_set(rpc_client)?;
@@ -240,8 +240,8 @@ fn feature_activation_allowed(rpc_client: &RpcClient) -> Result<bool, ClientErro
.map(|percentage| *percentage >= 95)
.unwrap_or(false);
if !feature_activation_allowed {
println!("\n{}", style("Stake By Feature Set:").bold());
if !feature_activation_allowed && !quiet {
println!("{}", style("Stake By Feature Set:").bold());
for (feature_set, percentage) in active_stake_by_feature_set.iter() {
if *feature_set == 0 {
println!("unknown - {}%", percentage);
@@ -258,6 +258,7 @@ fn feature_activation_allowed(rpc_client: &RpcClient) -> Result<bool, ClientErro
);
}
}
println!();
}
Ok(feature_activation_allowed)
@@ -299,9 +300,10 @@ fn process_status(
});
}
let feature_activation_allowed = feature_activation_allowed(rpc_client, features.len() <= 1)?;
let feature_set = CliFeatures {
features,
feature_activation_allowed: feature_activation_allowed(rpc_client)?,
feature_activation_allowed,
inactive,
};
Ok(config.output_format.formatted_string(&feature_set))
@@ -323,7 +325,7 @@ fn process_activate(
}
}
if !feature_activation_allowed(rpc_client)? {
if !feature_activation_allowed(rpc_client, false)? {
return Err("Feature activation is not allowed at this time".into());
}

View File

@@ -833,7 +833,7 @@ mod tests {
#[test]
fn test_check_nonce_account() {
let blockhash = Hash::default();
let nonce_pubkey = Pubkey::new_rand();
let nonce_pubkey = solana_sdk::pubkey::new_rand();
let data = Versions::new_current(State::Initialized(nonce::state::Data {
authority: nonce_pubkey,
blockhash,
@@ -869,7 +869,7 @@ mod tests {
}
let data = Versions::new_current(State::Initialized(nonce::state::Data {
authority: Pubkey::new_rand(),
authority: solana_sdk::pubkey::new_rand(),
blockhash,
fee_calculator: FeeCalculator::default(),
}));

View File

@@ -23,13 +23,17 @@ use solana_cli_output::{
CliStakeType,
};
use solana_client::{
blockhash_query::BlockhashQuery, nonce_utils, rpc_client::RpcClient,
rpc_request::DELINQUENT_VALIDATOR_SLOT_DISTANCE,
blockhash_query::BlockhashQuery,
client_error::{ClientError, ClientErrorKind},
nonce_utils,
rpc_client::RpcClient,
rpc_custom_error,
rpc_request::{self, DELINQUENT_VALIDATOR_SLOT_DISTANCE},
};
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
account_utils::StateMut,
clock::{Clock, Epoch, Slot, UnixTimestamp},
clock::{Clock, Epoch, Slot, UnixTimestamp, SECONDS_PER_DAY},
message::Message,
pubkey::Pubkey,
system_instruction::SystemError,
@@ -1605,10 +1609,26 @@ pub(crate) fn fetch_epoch_rewards(
.get(0)
.ok_or_else(|| format!("Unable to fetch first confirmed block for epoch {}", epoch))?;
let first_confirmed_block = rpc_client.get_confirmed_block_with_encoding(
let first_confirmed_block = match rpc_client.get_confirmed_block_with_encoding(
first_confirmed_block_in_epoch,
solana_transaction_status::UiTransactionEncoding::Base64,
)?;
) {
Ok(first_confirmed_block) => first_confirmed_block,
Err(ClientError {
kind:
ClientErrorKind::RpcError(rpc_request::RpcError::RpcResponseError {
code: rpc_custom_error::JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE,
message: _,
}),
request: _,
}) => {
// RPC node doesn't have this block
break;
}
Err(err) => {
return Err(err.into());
}
};
let epoch_start_time = if let Some(block_time) = first_confirmed_block.block_time {
block_time
@@ -1620,13 +1640,13 @@ pub(crate) fn fetch_epoch_rewards(
let previous_epoch_rewards = first_confirmed_block.rewards;
if let Some((effective_slot, epoch_end_time, epoch_rewards)) = epoch_info {
let wall_clock_epoch_duration =
let wallclock_epoch_duration =
{ Local.timestamp(epoch_end_time, 0) - Local.timestamp(epoch_start_time, 0) }
.to_std()?
.as_secs_f64();
const SECONDS_PER_YEAR: f64 = (24 * 60 * 60 * 356) as f64;
let percent_of_year = SECONDS_PER_YEAR / wall_clock_epoch_duration;
let wallclock_epochs_per_year =
(SECONDS_PER_DAY * 356) as f64 / wallclock_epoch_duration;
if let Some(reward) = epoch_rewards
.into_iter()
@@ -1642,7 +1662,7 @@ pub(crate) fn fetch_epoch_rewards(
amount: reward.lamports.abs() as u64,
post_balance: reward.post_balance,
percent_change: balance_increase_percent,
apr: balance_increase_percent * percent_of_year,
apr: balance_increase_percent * wallclock_epochs_per_year,
});
}
}
@@ -2406,9 +2426,9 @@ mod tests {
);
// Test CreateStakeAccount SubCommand
let custodian = Pubkey::new_rand();
let custodian = solana_sdk::pubkey::new_rand();
let custodian_string = format!("{}", custodian);
let authorized = Pubkey::new_rand();
let authorized = solana_sdk::pubkey::new_rand();
let authorized_string = format!("{}", authorized);
let test_create_stake_account = test_commands.clone().get_matches_from(vec![
"test",
@@ -2546,7 +2566,7 @@ mod tests {
);
// Test DelegateStake Subcommand
let vote_account_pubkey = Pubkey::new_rand();
let vote_account_pubkey = solana_sdk::pubkey::new_rand();
let vote_account_string = vote_account_pubkey.to_string();
let test_delegate_stake = test_commands.clone().get_matches_from(vec![
"test",
@@ -2573,7 +2593,7 @@ mod tests {
);
// Test DelegateStake Subcommand w/ authority
let vote_account_pubkey = Pubkey::new_rand();
let vote_account_pubkey = solana_sdk::pubkey::new_rand();
let vote_account_string = vote_account_pubkey.to_string();
let test_delegate_stake = test_commands.clone().get_matches_from(vec![
"test",
@@ -2692,7 +2712,7 @@ mod tests {
);
// Test Delegate Subcommand w/ absent fee payer
let key1 = Pubkey::new_rand();
let key1 = solana_sdk::pubkey::new_rand();
let sig1 = Keypair::new().sign_message(&[0u8]);
let signer1 = format!("{}={}", key1, sig1);
let test_delegate_stake = test_commands.clone().get_matches_from(vec![
@@ -2732,7 +2752,7 @@ mod tests {
);
// Test Delegate Subcommand w/ absent fee payer and absent nonce authority
let key2 = Pubkey::new_rand();
let key2 = solana_sdk::pubkey::new_rand();
let sig2 = Keypair::new().sign_message(&[0u8]);
let signer2 = format!("{}={}", key2, sig2);
let test_delegate_stake = test_commands.clone().get_matches_from(vec![
@@ -3060,7 +3080,7 @@ mod tests {
);
// Test Deactivate Subcommand w/ absent fee payer
let key1 = Pubkey::new_rand();
let key1 = solana_sdk::pubkey::new_rand();
let sig1 = Keypair::new().sign_message(&[0u8]);
let signer1 = format!("{}={}", key1, sig1);
let test_deactivate_stake = test_commands.clone().get_matches_from(vec![
@@ -3097,7 +3117,7 @@ mod tests {
);
// Test Deactivate Subcommand w/ absent fee payer and nonce authority
let key2 = Pubkey::new_rand();
let key2 = solana_sdk::pubkey::new_rand();
let sig2 = Keypair::new().sign_message(&[0u8]);
let signer2 = format!("{}={}", key2, sig2);
let test_deactivate_stake = test_commands.clone().get_matches_from(vec![
@@ -3276,7 +3296,7 @@ mod tests {
let stake_account_keypair = Keypair::new();
write_keypair(&stake_account_keypair, tmp_file.as_file_mut()).unwrap();
let source_stake_account_pubkey = Pubkey::new_rand();
let source_stake_account_pubkey = solana_sdk::pubkey::new_rand();
let test_merge_stake_account = test_commands.clone().get_matches_from(vec![
"test",
"merge-stake",

View File

@@ -486,7 +486,7 @@ mod tests {
#[test]
fn test_parse_validator_info() {
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let keys = vec![(validator_info::id(), false), (pubkey, true)];
let config = ConfigKeys { keys };

View File

@@ -915,7 +915,7 @@ mod tests {
);
// test init with an authed voter
let authed = Pubkey::new_rand();
let authed = solana_sdk::pubkey::new_rand();
let (keypair_file, mut tmp_file) = make_tmp_file();
let keypair = Keypair::new();
write_keypair(&keypair, tmp_file.as_file_mut()).unwrap();

View File

@@ -172,7 +172,7 @@ fn full_battery_tests(
assert_ne!(first_nonce, third_nonce);
// Withdraw from nonce account
let payee_pubkey = Pubkey::new_rand();
let payee_pubkey = solana_sdk::pubkey::new_rand();
config_payer.signers = authorized_signers;
config_payer.command = CliCommand::WithdrawFromNonceAccount {
nonce_account,

View File

@@ -12,7 +12,6 @@ use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
account_utils::StateMut,
commitment_config::CommitmentConfig,
pubkey::Pubkey,
signature::{Keypair, Signer},
};
use solana_vote_program::vote_state::{VoteAuthorize, VoteState, VoteStateVersions};
@@ -110,7 +109,7 @@ fn test_vote_authorize_and_withdraw() {
assert_eq!(authorized_withdrawer, withdraw_authority.pubkey());
// Withdraw from vote account
let destination_account = Pubkey::new_rand(); // Send withdrawal to new account to make balance check easy
let destination_account = solana_sdk::pubkey::new_rand(); // Send withdrawal to new account to make balance check easy
config.signers = vec![&default_signer, &withdraw_authority];
config.command = CliCommand::WithdrawFromVoteAccount {
vote_account_pubkey,

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-client"
version = "1.4.0"
version = "1.4.2"
description = "Solana Client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -17,16 +17,18 @@ indicatif = "0.15.0"
jsonrpc-core = "15.0.0"
log = "0.4.8"
rayon = "1.4.0"
reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] }
reqwest = { version = "0.10.8", default-features = false, features = ["blocking", "rustls-tls", "json"] }
semver = "0.11.0"
serde = "1.0.112"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "1.4.0" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.0" }
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
solana-account-decoder = { path = "../account-decoder", version = "1.4.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.2" }
solana-version = { path = "../version", version = "1.4.2" }
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
thiserror = "1.0"
tungstenite = "0.10.1"
url = "2.1.1"
@@ -35,7 +37,7 @@ url = "2.1.1"
assert_matches = "1.3.0"
jsonrpc-core = "15.0.0"
jsonrpc-http-server = "15.0.0"
solana-logger = { path = "../logger", version = "1.4.0" }
solana-logger = { path = "../logger", version = "1.4.2" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -50,10 +50,10 @@ impl Into<TransportError> for ClientErrorKind {
#[derive(Error, Debug)]
#[error("{kind}")]
pub struct ClientError {
request: Option<rpc_request::RpcRequest>,
pub request: Option<rpc_request::RpcRequest>,
#[source]
kind: ClientErrorKind,
pub kind: ClientErrorKind,
}
impl ClientError {

View File

@@ -27,6 +27,13 @@ impl HttpSender {
}
}
#[derive(Deserialize, Debug)]
struct RpcErrorObject {
code: i64,
message: String,
/*data field omitted*/
}
impl RpcSender for HttpSender {
fn send(&self, request: RpcRequest, params: serde_json::Value) -> Result<serde_json::Value> {
// Concurrent requests are not supported so reuse the same request id for all requests
@@ -63,11 +70,20 @@ impl RpcSender for HttpSender {
let json: serde_json::Value = serde_json::from_str(&response.text()?)?;
if json["error"].is_object() {
return Err(RpcError::RpcRequestError(format!(
"RPC Error response: {}",
serde_json::to_string(&json["error"]).unwrap()
))
.into());
return match serde_json::from_value::<RpcErrorObject>(json["error"].clone())
{
Ok(rpc_error_object) => Err(RpcError::RpcResponseError {
code: rpc_error_object.code,
message: rpc_error_object.message,
}
.into()),
Err(err) => Err(RpcError::RpcRequestError(format!(
"Failed to deserialize RPC error response: {} [{}]",
serde_json::to_string(&json["error"]).unwrap(),
err
))
.into()),
};
}
return Ok(json["result"].clone());
}

View File

@@ -10,6 +10,7 @@ pub mod perf_utils;
pub mod pubsub_client;
pub mod rpc_client;
pub mod rpc_config;
pub mod rpc_custom_error;
pub mod rpc_filter;
pub mod rpc_request;
pub mod rpc_response;

View File

@@ -1,10 +1,10 @@
use crate::{
client_error::Result,
rpc_request::RpcRequest,
rpc_response::{Response, RpcResponseContext},
rpc_response::{Response, RpcResponseContext, RpcVersionInfo},
rpc_sender::RpcSender,
};
use serde_json::{Number, Value};
use serde_json::{json, Number, Value};
use solana_sdk::{
fee_calculator::{FeeCalculator, FeeRateGovernor},
instruction::InstructionError,
@@ -12,6 +12,7 @@ use solana_sdk::{
transaction::{self, Transaction, TransactionError},
};
use solana_transaction_status::TransactionStatus;
use solana_version::Version;
use std::{collections::HashMap, sync::RwLock};
pub const PUBKEY: &str = "7RoSF9fUmdphVCpabEoefH81WwrW7orsWonXWqTXkKV8";
@@ -112,13 +113,20 @@ impl RpcSender for MockSender {
Signature::new(&[8; 64]).to_string()
} else {
let tx_str = params.as_array().unwrap()[0].as_str().unwrap().to_string();
let data = bs58::decode(tx_str).into_vec().unwrap();
let data = base64::decode(tx_str).unwrap();
let tx: Transaction = bincode::deserialize(&data).unwrap();
tx.signatures[0].to_string()
};
Value::String(signature)
}
RpcRequest::GetMinimumBalanceForRentExemption => Value::Number(Number::from(20)),
RpcRequest::GetVersion => {
let version = Version::default();
json!(RpcVersionInfo {
solana_core: version.to_string(),
feature_set: Some(version.feature_set),
})
}
_ => Value::Null,
};
Ok(val)

View File

@@ -41,12 +41,14 @@ use solana_transaction_status::{
use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY;
use std::{
net::SocketAddr,
sync::RwLock,
thread::sleep,
time::{Duration, Instant},
};
pub struct RpcClient {
sender: Box<dyn RpcSender + Send + Sync + 'static>,
default_cluster_transaction_encoding: RwLock<Option<UiTransactionEncoding>>,
}
fn serialize_encode_transaction(
@@ -73,6 +75,7 @@ impl RpcClient {
pub fn new_sender<T: RpcSender + Send + Sync + 'static>(sender: T) -> Self {
Self {
sender: Box::new(sender),
default_cluster_transaction_encoding: RwLock::new(None),
}
}
@@ -128,12 +131,45 @@ impl RpcClient {
self.send_transaction_with_config(transaction, RpcSendTransactionConfig::default())
}
fn default_cluster_transaction_encoding(&self) -> Result<UiTransactionEncoding, RpcError> {
let default_cluster_transaction_encoding =
self.default_cluster_transaction_encoding.read().unwrap();
if let Some(encoding) = *default_cluster_transaction_encoding {
Ok(encoding)
} else {
drop(default_cluster_transaction_encoding);
let cluster_version = self.get_version().map_err(|e| {
RpcError::RpcRequestError(format!("cluster version query failed: {}", e))
})?;
let cluster_version =
semver::Version::parse(&cluster_version.solana_core).map_err(|e| {
RpcError::RpcRequestError(format!("failed to parse cluster version: {}", e))
})?;
// Prefer base64 since 1.3.16
let encoding = if cluster_version < semver::Version::new(1, 3, 16) {
UiTransactionEncoding::Base58
} else {
UiTransactionEncoding::Base64
};
*self.default_cluster_transaction_encoding.write().unwrap() = Some(encoding);
Ok(encoding)
}
}
pub fn send_transaction_with_config(
&self,
transaction: &Transaction,
config: RpcSendTransactionConfig,
) -> ClientResult<Signature> {
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
let encoding = if let Some(encoding) = config.encoding {
encoding
} else {
self.default_cluster_transaction_encoding()?
};
let config = RpcSendTransactionConfig {
encoding: Some(encoding),
..config
};
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?;
let signature_base58_str: String = self.send(
RpcRequest::SendTransaction,
@@ -161,26 +197,28 @@ impl RpcClient {
pub fn simulate_transaction(
&self,
transaction: &Transaction,
sig_verify: bool,
) -> RpcResult<RpcSimulateTransactionResult> {
self.simulate_transaction_with_config(
transaction,
sig_verify,
RpcSimulateTransactionConfig::default(),
)
self.simulate_transaction_with_config(transaction, RpcSimulateTransactionConfig::default())
}
pub fn simulate_transaction_with_config(
&self,
transaction: &Transaction,
sig_verify: bool,
config: RpcSimulateTransactionConfig,
) -> RpcResult<RpcSimulateTransactionResult> {
let encoding = config.encoding.unwrap_or(UiTransactionEncoding::Base58);
let encoding = if let Some(encoding) = config.encoding {
encoding
} else {
self.default_cluster_transaction_encoding()?
};
let config = RpcSimulateTransactionConfig {
encoding: Some(encoding),
..config
};
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?;
self.send(
RpcRequest::SimulateTransaction,
json!([serialized_encoded, { "sigVerify": sig_verify }]),
json!([serialized_encoded, config]),
)
}
@@ -1418,7 +1456,7 @@ mod tests {
let rpc_client = RpcClient::new_mock("succeeds".to_string());
let key = Keypair::new();
let to = Pubkey::new_rand();
let to = solana_sdk::pubkey::new_rand();
let blockhash = Hash::default();
let tx = system_transaction::transfer(&key, &to, 50, blockhash);
@@ -1471,7 +1509,7 @@ mod tests {
let rpc_client = RpcClient::new_mock("succeeds".to_string());
let key = Keypair::new();
let to = Pubkey::new_rand();
let to = solana_sdk::pubkey::new_rand();
let blockhash = Hash::default();
let tx = system_transaction::transfer(&key, &to, 50, blockhash);
let result = rpc_client.send_and_confirm_transaction(&tx);

View File

@@ -1,13 +1,15 @@
//! Implementation defined RPC server errors
use crate::rpc_response::RpcSimulateTransactionResult;
use jsonrpc_core::{Error, ErrorCode};
use solana_client::rpc_response::RpcSimulateTransactionResult;
use solana_sdk::clock::Slot;
const JSON_RPC_SERVER_ERROR_1: i64 = -32001;
const JSON_RPC_SERVER_ERROR_2: i64 = -32002;
const JSON_RPC_SERVER_ERROR_3: i64 = -32003;
const JSON_RPC_SERVER_ERROR_4: i64 = -32004;
const JSON_RPC_SERVER_ERROR_5: i64 = -32005;
const JSON_RPC_SERVER_ERROR_6: i64 = -32006;
pub const JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP: i64 = -32001;
pub const JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE: i64 = -32002;
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE: i64 = -32003;
pub const JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE: i64 = -32004;
pub const JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY: i64 = -32005;
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64 = -32006;
pub enum RpcCustomError {
BlockCleanedUp {
@@ -33,7 +35,7 @@ impl From<RpcCustomError> for Error {
slot,
first_available_block,
} => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_1),
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP),
message: format!(
"Block {} cleaned up, does not exist on node. First available block: {}",
slot, first_available_block,
@@ -41,27 +43,33 @@ impl From<RpcCustomError> for Error {
data: None,
},
RpcCustomError::SendTransactionPreflightFailure { message, result } => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_2),
code: ErrorCode::ServerError(
JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
),
message,
data: Some(serde_json::json!(result)),
},
RpcCustomError::TransactionSignatureVerificationFailure => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_3),
code: ErrorCode::ServerError(
JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE,
),
message: "Transaction signature verification failure".to_string(),
data: None,
},
RpcCustomError::BlockNotAvailable { slot } => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_4),
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE),
message: format!("Block not available for slot {}", slot),
data: None,
},
RpcCustomError::RpcNodeUnhealthy => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_5),
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY),
message: "RPC node is unhealthy".to_string(),
data: None,
},
RpcCustomError::TransactionPrecompileVerificationFailure(e) => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_6),
code: ErrorCode::ServerError(
JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE,
),
message: format!("Transaction precompile verification failure {:?}", e),
data: None,
},

View File

@@ -140,8 +140,10 @@ impl RpcRequest {
#[derive(Debug, Error)]
pub enum RpcError {
#[error("rpc request error: {0}")]
#[error("RPC request error: {0}")]
RpcRequestError(String),
#[error("RPC response error {code}: {message}")]
RpcResponseError { code: i64, message: String },
#[error("parse error: expected {0}")]
ParseError(String), /* "expected" */
// Anything in a `ForUser` needs to die. The caller should be
@@ -226,7 +228,7 @@ mod tests {
// Test request with CommitmentConfig and params
let test_request = RpcRequest::GetTokenAccountsByOwner;
let mint = Pubkey::new_rand();
let mint = solana_sdk::pubkey::new_rand();
let token_account_filter = RpcTokenAccountsFilter::Mint(mint.to_string());
let request = test_request
.build_request_json(1, json!([addr, token_account_filter, commitment_config]));

View File

@@ -1,7 +1,7 @@
[package]
name = "solana-core"
description = "Blockchain, Rebuilt for Scale"
version = "1.4.0"
version = "1.4.2"
documentation = "https://docs.rs/solana"
homepage = "https://solana.com/"
readme = "../README.md"
@@ -39,48 +39,48 @@ num-traits = "0.2"
rand = "0.7.0"
rand_chacha = "0.2.2"
raptorq = "1.4.2"
rayon = "1.4.0"
rayon = "1.4.1"
regex = "1.3.9"
serde = "1.0.112"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "1.4.0" }
solana-banks-server = { path = "../banks-server", version = "1.4.0" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.4.0" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.0" }
solana-client = { path = "../client", version = "1.4.0" }
solana-faucet = { path = "../faucet", version = "1.4.0" }
solana-ledger = { path = "../ledger", version = "1.4.0" }
solana-logger = { path = "../logger", version = "1.4.0" }
solana-merkle-tree = { path = "../merkle-tree", version = "1.4.0" }
solana-metrics = { path = "../metrics", version = "1.4.0" }
solana-measure = { path = "../measure", version = "1.4.0" }
solana-net-utils = { path = "../net-utils", version = "1.4.0" }
solana-perf = { path = "../perf", version = "1.4.0" }
solana-runtime = { path = "../runtime", version = "1.4.0" }
solana-sdk = { path = "../sdk", version = "1.4.0" }
solana-sdk-macro-frozen-abi = { path = "../sdk/macro-frozen-abi", version = "1.4.0" }
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
solana-storage-bigtable = { path = "../storage-bigtable", version = "1.4.0" }
solana-streamer = { path = "../streamer", version = "1.4.0" }
solana-sys-tuner = { path = "../sys-tuner", version = "1.4.0" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.0" }
solana-version = { path = "../version", version = "1.4.0" }
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
solana-vote-signer = { path = "../vote-signer", version = "1.4.0" }
spl-token-v2-0 = { package = "spl-token", version = "=2.0.6", features = ["skip-no-mangle"] }
solana-account-decoder = { path = "../account-decoder", version = "1.4.2" }
solana-banks-server = { path = "../banks-server", version = "1.4.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.2" }
solana-client = { path = "../client", version = "1.4.2" }
solana-faucet = { path = "../faucet", version = "1.4.2" }
solana-frozen-abi = { path = "../frozen-abi", version = "1.4.2" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "1.4.2" }
solana-ledger = { path = "../ledger", version = "1.4.2" }
solana-logger = { path = "../logger", version = "1.4.2" }
solana-merkle-tree = { path = "../merkle-tree", version = "1.4.2" }
solana-metrics = { path = "../metrics", version = "1.4.2" }
solana-measure = { path = "../measure", version = "1.4.2" }
solana-net-utils = { path = "../net-utils", version = "1.4.2" }
solana-perf = { path = "../perf", version = "1.4.2" }
solana-runtime = { path = "../runtime", version = "1.4.2" }
solana-sdk = { path = "../sdk", version = "1.4.2" }
solana-stake-program = { path = "../programs/stake", version = "1.4.2" }
solana-storage-bigtable = { path = "../storage-bigtable", version = "1.4.2" }
solana-streamer = { path = "../streamer", version = "1.4.2" }
solana-sys-tuner = { path = "../sys-tuner", version = "1.4.2" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.2" }
solana-version = { path = "../version", version = "1.4.2" }
solana-vote-program = { path = "../programs/vote", version = "1.4.2" }
solana-vote-signer = { path = "../vote-signer", version = "1.4.2" }
spl-token-v2-0 = { package = "spl-token", version = "=2.0.8" }
tempfile = "3.1.0"
thiserror = "1.0"
tokio = { version = "0.2.22", features = ["full"] }
tokio_01 = { version = "0.1", package = "tokio" }
tokio_fs_01 = { version = "0.1", package = "tokio-fs" }
tokio_io_01 = { version = "0.1", package = "tokio-io" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.4.0" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.4.2" }
trees = "0.2.1"
[dev-dependencies]
matches = "0.1.6"
reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] }
reqwest = { version = "0.10.8", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serial_test = "0.4.0"
serial_test_derive = "0.4.0"
systemstat = "0.1.5"

View File

@@ -20,7 +20,7 @@ use solana_runtime::bank::Bank;
use solana_sdk::genesis_config::GenesisConfig;
use solana_sdk::hash::Hash;
use solana_sdk::message::Message;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::pubkey;
use solana_sdk::signature::Keypair;
use solana_sdk::signature::Signature;
use solana_sdk::signature::Signer;
@@ -56,7 +56,7 @@ fn bench_consume_buffered(bencher: &mut Bencher) {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100_000);
let bank = Arc::new(Bank::new(&genesis_config));
let ledger_path = get_tmp_ledger_path!();
let my_pubkey = Pubkey::new_rand();
let my_pubkey = pubkey::new_rand();
{
let blockstore = Arc::new(
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
@@ -94,15 +94,15 @@ fn bench_consume_buffered(bencher: &mut Bencher) {
}
fn make_accounts_txs(txes: usize, mint_keypair: &Keypair, hash: Hash) -> Vec<Transaction> {
let to_pubkey = Pubkey::new_rand();
let to_pubkey = pubkey::new_rand();
let dummy = system_transaction::transfer(mint_keypair, &to_pubkey, 1, hash);
(0..txes)
.into_par_iter()
.map(|_| {
let mut new = dummy.clone();
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
new.message.account_keys[0] = Pubkey::new_rand();
new.message.account_keys[1] = Pubkey::new_rand();
new.message.account_keys[0] = pubkey::new_rand();
new.message.account_keys[1] = pubkey::new_rand();
new.signatures = vec![Signature::new(&sig[0..64])];
new
})
@@ -117,7 +117,7 @@ fn make_programs_txs(txes: usize, hash: Hash) -> Vec<Transaction> {
let mut instructions = vec![];
let from_key = Keypair::new();
for _ in 1..progs {
let to_key = Pubkey::new_rand();
let to_key = pubkey::new_rand();
instructions.push(system_instruction::transfer(&from_key.pubkey(), &to_key, 1));
}
let message = Message::new(&instructions, Some(&from_key.pubkey()));

View File

@@ -8,7 +8,7 @@ use solana_core::broadcast_stage::{broadcast_shreds, get_broadcast_peers};
use solana_core::cluster_info::{ClusterInfo, Node};
use solana_core::contact_info::ContactInfo;
use solana_ledger::shred::Shred;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::pubkey;
use solana_sdk::timing::timestamp;
use std::{
collections::HashMap,
@@ -20,7 +20,7 @@ use test::Bencher;
#[bench]
fn broadcast_shreds_bench(bencher: &mut Bencher) {
solana_logger::setup();
let leader_pubkey = Pubkey::new_rand();
let leader_pubkey = pubkey::new_rand();
let leader_info = Node::new_localhost_with_pubkey(&leader_pubkey);
let cluster_info = ClusterInfo::new_with_invalid_keypair(leader_info.info);
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
@@ -30,7 +30,7 @@ fn broadcast_shreds_bench(bencher: &mut Bencher) {
let mut stakes = HashMap::new();
const NUM_PEERS: usize = 200;
for _ in 0..NUM_PEERS {
let id = Pubkey::new_rand();
let id = pubkey::new_rand();
let contact_info = ContactInfo::new_localhost(&id, timestamp());
cluster_info.insert_info(contact_info);
stakes.insert(id, thread_rng().gen_range(1, NUM_PEERS) as u64);

View File

@@ -8,13 +8,13 @@ use solana_core::cluster_info::MAX_BLOOM_SIZE;
use solana_core::crds::Crds;
use solana_core::crds_gossip_pull::{CrdsFilter, CrdsGossipPull};
use solana_core::crds_value::CrdsValue;
use solana_sdk::hash::Hash;
use solana_sdk::hash;
use test::Bencher;
#[bench]
fn bench_hash_as_u64(bencher: &mut Bencher) {
let mut rng = thread_rng();
let hashes: Vec<_> = std::iter::repeat_with(|| Hash::new_rand(&mut rng))
let hashes: Vec<_> = std::iter::repeat_with(|| hash::new_rand(&mut rng))
.take(1000)
.collect();
bencher.iter(|| {
@@ -34,7 +34,7 @@ fn bench_build_crds_filters(bencher: &mut Bencher) {
for _ in 0..50_000 {
crds_gossip_pull
.purged_values
.push_back((Hash::new_rand(&mut rng), rng.gen()));
.push_back((solana_sdk::hash::new_rand(&mut rng), rng.gen()));
}
let mut num_inserts = 0;
for _ in 0..90_000 {

View File

@@ -7,14 +7,14 @@ use solana_core::contact_info::ContactInfo;
use solana_core::crds::VersionedCrdsValue;
use solana_core::crds_shards::CrdsShards;
use solana_core::crds_value::{CrdsData, CrdsValue};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::pubkey;
use solana_sdk::timing::timestamp;
use test::Bencher;
const CRDS_SHARDS_BITS: u32 = 8;
fn new_test_crds_value() -> VersionedCrdsValue {
let data = CrdsData::ContactInfo(ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp()));
let data = CrdsData::ContactInfo(ContactInfo::new_localhost(&pubkey::new_rand(), timestamp()));
VersionedCrdsValue::new(timestamp(), CrdsValue::new_unsigned(data))
}

View File

@@ -14,7 +14,7 @@ use solana_perf::packet::to_packets_chunked;
use solana_perf::test_tx::test_tx;
use solana_runtime::bank::Bank;
use solana_runtime::bank_forks::BankForks;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::pubkey;
use solana_sdk::timing::timestamp;
use std::net::UdpSocket;
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -34,7 +34,7 @@ fn bench_retransmitter(bencher: &mut Bencher) {
const NUM_PEERS: usize = 4;
let mut peer_sockets = Vec::new();
for _ in 0..NUM_PEERS {
let id = Pubkey::new_rand();
let id = pubkey::new_rand();
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let mut contact_info = ContactInfo::new_localhost(&id, timestamp());
contact_info.tvu = socket.local_addr().unwrap();

View File

@@ -1 +1 @@
../sdk/build.rs
../frozen-abi/build.rs

View File

@@ -204,6 +204,7 @@ mod tests {
{
let message = make_accounts_hashes_message(&validator1, vec![(0, hash1)]).unwrap();
cluster_info.push_message(message);
cluster_info.flush_push_queue();
}
slot_to_hash.insert(0, hash2);
trusted_validators.insert(validator1.pubkey());
@@ -254,6 +255,7 @@ mod tests {
100,
);
}
cluster_info.flush_push_queue();
let cluster_hashes = cluster_info
.get_accounts_hash_for_node(&keypair.pubkey(), |c| c.clone())
.unwrap();

View File

@@ -60,7 +60,7 @@ impl ForkChoice for BankWeightForkChoice {
trace!("frozen_banks {}", frozen_banks.len());
let num_old_banks = frozen_banks
.iter()
.filter(|b| b.slot() < tower.root().unwrap_or(0))
.filter(|b| b.slot() < tower.root())
.count();
let last_voted_slot = tower.last_voted_slot();

View File

@@ -534,13 +534,14 @@ impl BankingStage {
mut loaded_accounts,
results,
inner_instructions,
transaction_logs,
mut retryable_txs,
tx_count,
signature_count,
) = bank.load_and_execute_transactions(
batch,
MAX_PROCESSING_AGE,
None,
transaction_status_sender.is_some(),
transaction_status_sender.is_some(),
);
load_execute_time.stop();
@@ -580,6 +581,7 @@ impl BankingStage {
tx_results.processing_results,
TransactionBalancesSet::new(pre_balances, post_balances),
inner_instructions,
transaction_logs,
sender,
);
}
@@ -1244,16 +1246,16 @@ mod tests {
bank.process_transaction(&fund_tx).unwrap();
// good tx
let to = Pubkey::new_rand();
let to = solana_sdk::pubkey::new_rand();
let tx = system_transaction::transfer(&mint_keypair, &to, 1, start_hash);
// good tx, but no verify
let to2 = Pubkey::new_rand();
let to2 = solana_sdk::pubkey::new_rand();
let tx_no_ver = system_transaction::transfer(&keypair, &to2, 2, start_hash);
// bad tx, AccountNotFound
let keypair = Keypair::new();
let to3 = Pubkey::new_rand();
let to3 = solana_sdk::pubkey::new_rand();
let tx_anf = system_transaction::transfer(&keypair, &to3, 1, start_hash);
// send 'em over
@@ -1446,9 +1448,9 @@ mod tests {
let poh_recorder = Arc::new(Mutex::new(poh_recorder));
poh_recorder.lock().unwrap().set_working_bank(working_bank);
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let keypair2 = Keypair::new();
let pubkey2 = Pubkey::new_rand();
let pubkey2 = solana_sdk::pubkey::new_rand();
let transactions = vec![
system_transaction::transfer(&mint_keypair, &pubkey, 1, genesis_config.hash()),
@@ -1526,7 +1528,7 @@ mod tests {
mint_keypair,
..
} = create_genesis_config(10_000);
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let transactions = vec![
None,
@@ -1607,7 +1609,7 @@ mod tests {
mint_keypair,
..
} = create_genesis_config(10_000);
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let transactions = vec![
system_transaction::transfer(&mint_keypair, &pubkey, 1, genesis_config.hash()),
@@ -1678,8 +1680,8 @@ mod tests {
#[test]
fn test_should_process_or_forward_packets() {
let my_pubkey = Pubkey::new_rand();
let my_pubkey1 = Pubkey::new_rand();
let my_pubkey = solana_sdk::pubkey::new_rand();
let my_pubkey1 = solana_sdk::pubkey::new_rand();
assert_eq!(
BankingStage::consume_or_forward_packets(&my_pubkey, None, true, false,),
@@ -1725,7 +1727,7 @@ mod tests {
..
} = create_genesis_config(10_000);
let bank = Arc::new(Bank::new(&genesis_config));
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let transactions = vec![system_transaction::transfer(
&mint_keypair,
@@ -1822,8 +1824,8 @@ mod tests {
..
} = create_genesis_config(10_000);
let bank = Arc::new(Bank::new(&genesis_config));
let pubkey = Pubkey::new_rand();
let pubkey1 = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let pubkey1 = solana_sdk::pubkey::new_rand();
let transactions = vec![
system_transaction::transfer(&mint_keypair, &pubkey, 1, genesis_config.hash()),
@@ -1918,7 +1920,7 @@ mod tests {
} = create_genesis_config(10_000);
let bank = Arc::new(Bank::new(&genesis_config));
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let transactions =
vec![
@@ -1936,7 +1938,7 @@ mod tests {
bank.slot(),
Some((4, 4)),
bank.ticks_per_slot(),
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
&Arc::new(blockstore),
&Arc::new(LeaderScheduleCache::new_from_bank(&bank)),
&Arc::new(PohConfig::default()),
@@ -1976,8 +1978,8 @@ mod tests {
..
} = create_genesis_config(10_000);
let bank = Arc::new(Bank::new(&genesis_config));
let pubkey = Pubkey::new_rand();
let pubkey1 = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let pubkey1 = solana_sdk::pubkey::new_rand();
let keypair1 = Keypair::new();
let success_tx =

View File

@@ -140,13 +140,12 @@ impl BroadcastRun for BroadcastFakeShredsRun {
mod tests {
use super::*;
use crate::contact_info::ContactInfo;
use solana_sdk::pubkey::Pubkey;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
#[test]
fn test_tvu_peers_ordering() {
let cluster = ClusterInfo::new_with_invalid_keypair(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
));
cluster.insert_info(ContactInfo::new_with_socketaddr(&SocketAddr::new(

View File

@@ -92,7 +92,7 @@ mod tests {
let bank0 = Arc::new(Bank::new(&genesis_config));
let tx = system_transaction::transfer(
&mint_keypair,
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
1,
genesis_config.hash(),
);

View File

@@ -21,6 +21,7 @@ use crate::{
self, CrdsData, CrdsValue, CrdsValueLabel, EpochSlotsIndex, LowestSlot, SnapshotHash,
Version, Vote, MAX_WALLCLOCK,
},
data_budget::DataBudget,
epoch_slots::EpochSlots,
result::{Error, Result},
weighted_shuffle::weighted_shuffle,
@@ -51,6 +52,7 @@ use solana_perf::packet::{
};
use solana_rayon_threadlimit::get_thread_count;
use solana_runtime::bank_forks::BankForks;
use solana_runtime::feature_set::{self, FeatureSet};
use solana_sdk::hash::Hash;
use solana_sdk::{
clock::{Slot, DEFAULT_MS_PER_SLOT, DEFAULT_SLOTS_PER_EPOCH},
@@ -103,12 +105,6 @@ pub enum ClusterInfoError {
BadContactInfo,
BadGossipAddress,
}
#[derive(Clone)]
pub struct DataBudget {
bytes: usize, // amount of bytes we have in the budget to send
last_timestamp_ms: u64, // Last time that we upped the bytes count,
// used to detect when to up the bytes budget again
}
struct GossipWriteLock<'a> {
gossip: RwLockWriteGuard<'a, CrdsGossip>,
@@ -215,6 +211,7 @@ struct GossipStats {
new_push_requests2: Counter,
new_push_requests_num: Counter,
filter_pull_response: Counter,
process_gossip_packets_time: Counter,
process_pull_response: Counter,
process_pull_response_count: Counter,
process_pull_response_len: Counter,
@@ -252,11 +249,12 @@ pub struct ClusterInfo {
pub(crate) keypair: Arc<Keypair>,
/// The network entrypoint
entrypoint: RwLock<Option<ContactInfo>>,
outbound_budget: RwLock<DataBudget>,
outbound_budget: DataBudget,
my_contact_info: RwLock<ContactInfo>,
id: Pubkey,
stats: GossipStats,
socket: UdpSocket,
local_message_pending_push_queue: RwLock<Vec<(CrdsValue, u64)>>,
}
impl Default for ClusterInfo {
@@ -369,6 +367,59 @@ enum Protocol {
PruneMessage(Pubkey, PruneData),
}
impl Protocol {
fn par_verify(self) -> Option<Self> {
match self {
Protocol::PullRequest(_, ref caller) => {
if caller.verify() {
Some(self)
} else {
inc_new_counter_info!("cluster_info-gossip_pull_request_verify_fail", 1);
None
}
}
Protocol::PullResponse(from, data) => {
let size = data.len();
let data: Vec<_> = data.into_par_iter().filter(Signable::verify).collect();
if size != data.len() {
inc_new_counter_info!(
"cluster_info-gossip_pull_response_verify_fail",
size - data.len()
);
}
if data.is_empty() {
None
} else {
Some(Protocol::PullResponse(from, data))
}
}
Protocol::PushMessage(from, data) => {
let size = data.len();
let data: Vec<_> = data.into_par_iter().filter(Signable::verify).collect();
if size != data.len() {
inc_new_counter_info!(
"cluster_info-gossip_push_msg_verify_fail",
size - data.len()
);
}
if data.is_empty() {
None
} else {
Some(Protocol::PushMessage(from, data))
}
}
Protocol::PruneMessage(_, ref data) => {
if data.verify() {
Some(self)
} else {
inc_new_counter_debug!("cluster_info-gossip_prune_msg_verify_fail", 1);
None
}
}
}
}
}
impl Sanitize for Protocol {
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
match self {
@@ -406,14 +457,12 @@ impl ClusterInfo {
gossip: RwLock::new(CrdsGossip::default()),
keypair,
entrypoint: RwLock::new(None),
outbound_budget: RwLock::new(DataBudget {
bytes: 0,
last_timestamp_ms: 0,
}),
outbound_budget: DataBudget::default(),
my_contact_info: RwLock::new(contact_info),
id,
stats: GossipStats::default(),
socket: UdpSocket::bind("0.0.0.0:0").unwrap(),
local_message_pending_push_queue: RwLock::new(vec![]),
};
{
let mut gossip = me.gossip.write().unwrap();
@@ -435,11 +484,17 @@ impl ClusterInfo {
gossip: RwLock::new(gossip),
keypair: self.keypair.clone(),
entrypoint: RwLock::new(self.entrypoint.read().unwrap().clone()),
outbound_budget: RwLock::new(self.outbound_budget.read().unwrap().clone()),
outbound_budget: self.outbound_budget.clone_non_atomic(),
my_contact_info: RwLock::new(my_contact_info),
id: *new_id,
stats: GossipStats::default(),
socket: UdpSocket::bind("0.0.0.0:0").unwrap(),
local_message_pending_push_queue: RwLock::new(
self.local_message_pending_push_queue
.read()
.unwrap()
.clone(),
),
}
}
@@ -462,9 +517,14 @@ impl ClusterInfo {
self.my_contact_info.write().unwrap().wallclock = now;
let entry =
CrdsValue::new_signed(CrdsData::ContactInfo(self.my_contact_info()), &self.keypair);
let mut w_gossip = self.gossip.write().unwrap();
w_gossip.refresh_push_active_set(stakes, gossip_validators);
w_gossip.process_push_message(&self.id(), vec![entry], now);
self.gossip
.write()
.unwrap()
.refresh_push_active_set(stakes, gossip_validators);
self.local_message_pending_push_queue
.write()
.unwrap()
.push((entry, now));
}
// TODO kill insert_info, only used by tests
@@ -530,6 +590,70 @@ impl ClusterInfo {
.unwrap_or_else(|| EpochSlots::new(self.id(), timestamp()))
}
pub fn rpc_info_trace(&self) -> String {
let now = timestamp();
let my_pubkey = self.id();
let my_shred_version = self.my_shred_version();
let nodes: Vec<_> = self
.all_peers()
.into_iter()
.filter_map(|(node, last_updated)| {
if !ContactInfo::is_valid_address(&node.rpc) {
info!("invalid rpc: {}", node.rpc.to_string());
return None;
}
let node_version = self.get_node_version(&node.id);
if my_shred_version != 0
&& (node.shred_version != 0 && node.shred_version != my_shred_version)
{
return None;
}
fn addr_to_string(default_ip: &IpAddr, addr: &SocketAddr) -> String {
if ContactInfo::is_valid_address(addr) {
if &addr.ip() == default_ip {
addr.port().to_string()
} else {
addr.to_string()
}
} else {
"none".to_string()
}
}
let rpc_addr = node.rpc.ip();
Some(format!(
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {}\n",
rpc_addr.to_string(),
if node.id == my_pubkey { "me" } else { "" }.to_string(),
now.saturating_sub(last_updated),
node.id.to_string(),
if let Some(node_version) = node_version {
node_version.to_string()
} else {
"-".to_string()
},
addr_to_string(&rpc_addr, &node.rpc),
addr_to_string(&rpc_addr, &node.rpc_pubsub),
addr_to_string(&rpc_addr, &node.rpc_banks),
node.shred_version,
))
})
.collect();
format!(
"RPC Address |Age(ms)| Node identifier \
| Version | RPC |PubSub| Banks|ShredVer\n\
------------------+-------+----------------------------------------------+---------+\
------+------+------+--------\n\
{}\
RPC Enabled Nodes: {}",
nodes.join(""),
nodes.len(),
)
}
pub fn contact_info_trace(&self) -> String {
let now = timestamp();
let mut spy_nodes = 0;
@@ -562,7 +686,7 @@ impl ClusterInfo {
}
let ip_addr = node.gossip.ip();
Some(format!(
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
if ContactInfo::is_valid_address(&node.gossip) {
ip_addr.to_string()
} else {
@@ -583,9 +707,6 @@ impl ClusterInfo {
addr_to_string(&ip_addr, &node.tvu_forwards),
addr_to_string(&ip_addr, &node.repair),
addr_to_string(&ip_addr, &node.serve_repair),
addr_to_string(&ip_addr, &node.rpc),
addr_to_string(&ip_addr, &node.rpc_pubsub),
addr_to_string(&ip_addr, &node.rpc_banks),
node.shred_version,
))
}
@@ -594,9 +715,9 @@ impl ClusterInfo {
format!(
"IP Address |Age(ms)| Node identifier \
| Version |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR| RPC |PubSub|ShredVer\n\
| Version |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR|ShredVer\n\
------------------+-------+----------------------------------------------+---------+\
------+------+------+------+------+------+------+------+------+--------\n\
------+------+------+------+------+------+------+--------\n\
{}\
Nodes: {}{}{}",
nodes.join(""),
@@ -633,10 +754,10 @@ impl ClusterInfo {
CrdsData::LowestSlot(0, LowestSlot::new(id, min, now)),
&self.keypair,
);
self.gossip
self.local_message_pending_push_queue
.write()
.unwrap()
.process_push_message(&self.id(), vec![entry], now);
.push((entry, now));
}
}
@@ -689,8 +810,10 @@ impl ClusterInfo {
let n = slots.fill(&update[num..], now);
if n > 0 {
let entry = CrdsValue::new_signed(CrdsData::EpochSlots(ix, slots), &self.keypair);
self.time_gossip_write_lock("epcoh_slots_push", &self.stats.epoch_slots_push)
.process_push_message(&self.id(), vec![entry], now);
self.local_message_pending_push_queue
.write()
.unwrap()
.push((entry, now));
}
num += n;
if num < update.len() {
@@ -718,9 +841,10 @@ impl ClusterInfo {
pub fn push_message(&self, message: CrdsValue) {
let now = message.wallclock();
let id = message.pubkey();
self.time_gossip_write_lock("process_push_message", &self.stats.push_message)
.process_push_message(&id, vec![message], now);
self.local_message_pending_push_queue
.write()
.unwrap()
.push((message, now));
}
pub fn push_accounts_hashes(&self, accounts_hashes: Vec<(Slot, Hash)>) {
@@ -761,8 +885,10 @@ impl ClusterInfo {
CrdsValue::compute_vote_index(tower_index, current_votes)
};
let entry = CrdsValue::new_signed(CrdsData::Vote(vote_ix, vote), &self.keypair);
self.time_gossip_write_lock("push_vote_process_push", &self.stats.vote_process_push)
.process_push_message(&self.id(), vec![entry], now);
self.local_message_pending_push_queue
.write()
.unwrap()
.push((entry, now));
}
pub fn send_vote(&self, vote: &Transaction) -> Result<()> {
@@ -1425,11 +1551,21 @@ impl ClusterInfo {
})
.collect()
}
fn drain_push_queue(&self) -> Vec<(CrdsValue, u64)> {
let mut push_queue = self.local_message_pending_push_queue.write().unwrap();
std::mem::take(&mut *push_queue)
}
#[cfg(test)]
pub fn flush_push_queue(&self) {
let pending_push_messages = self.drain_push_queue();
let mut gossip = self.gossip.write().unwrap();
gossip.process_push_messages(pending_push_messages);
}
fn new_push_requests(&self) -> Vec<(SocketAddr, Protocol)> {
let self_id = self.id();
let (_, push_messages) = self
.time_gossip_write_lock("new_push_requests", &self.stats.new_push_requests)
.new_push_messages(timestamp());
.new_push_messages(self.drain_push_queue(), timestamp());
let messages: Vec<_> = push_messages
.into_iter()
.filter_map(|(peer, messages)| {
@@ -1580,7 +1716,11 @@ impl ClusterInfo {
thread_mem_usage::datapoint("solana-gossip");
if start - last_contact_info_trace > 10000 {
// Log contact info every 10 seconds
info!("\n{}", self.contact_info_trace());
info!(
"\n{}\n\n{}",
self.contact_info_trace(),
self.rpc_info_trace()
);
last_contact_info_trace = start;
}
@@ -1629,8 +1769,9 @@ impl ClusterInfo {
&self,
recycler: &PacketsRecycler,
stakes: &HashMap<Pubkey, u64>,
packets: Packets,
packets: Vec<(SocketAddr, Protocol)>,
response_sender: &PacketSender,
feature_set: Option<&FeatureSet>,
epoch_time_ms: u64,
) {
// iter over the packets, collect pulls separately and process everything else
@@ -1642,115 +1783,82 @@ impl ClusterInfo {
.unwrap()
.make_timeouts(&stakes, epoch_time_ms);
let mut pull_responses = HashMap::new();
packets.packets.iter().for_each(|packet| {
let from_addr = packet.meta.addr();
limited_deserialize(&packet.data[..packet.meta.size])
.into_iter()
.filter(|r: &Protocol| r.sanitize().is_ok())
.for_each(|request| match request {
Protocol::PullRequest(filter, caller) => {
let start = allocated.get();
if !caller.verify() {
inc_new_counter_info!(
"cluster_info-gossip_pull_request_verify_fail",
1
);
} else if let Some(contact_info) = caller.contact_info() {
if contact_info.id == self.id() {
warn!("PullRequest ignored, I'm talking to myself");
inc_new_counter_debug!("cluster_info-window-request-loopback", 1);
} else if contact_info.shred_version == 0
|| contact_info.shred_version == self.my_shred_version()
|| self.my_shred_version() == 0
{
gossip_pull_data.push(PullData {
from_addr,
caller,
filter,
});
} else {
self.stats.skip_pull_shred_version.add_relaxed(1);
}
}
datapoint_debug!(
"solana-gossip-listen-memory",
("pull_request", (allocated.get() - start) as i64, i64),
);
}
Protocol::PullResponse(from, mut data) => {
let start = allocated.get();
data.retain(|v| {
let ret = v.verify();
if !ret {
inc_new_counter_info!(
"cluster_info-gossip_pull_response_verify_fail",
1
);
}
ret
});
let pull_entry = pull_responses.entry(from).or_insert_with(Vec::new);
pull_entry.extend(data);
datapoint_debug!(
"solana-gossip-listen-memory",
("pull_response", (allocated.get() - start) as i64, i64),
);
}
Protocol::PushMessage(from, mut data) => {
let start = allocated.get();
data.retain(|v| {
let ret = v.verify();
if !ret {
inc_new_counter_info!(
"cluster_info-gossip_push_msg_verify_fail",
1
);
}
ret
});
let rsp = self.handle_push_message(recycler, &from, data, stakes);
if let Some(rsp) = rsp {
let _ignore_disconnect = response_sender.send(rsp);
}
datapoint_debug!(
"solana-gossip-listen-memory",
("push_message", (allocated.get() - start) as i64, i64),
);
}
Protocol::PruneMessage(from, data) => {
let start = allocated.get();
if data.verify() {
self.stats.prune_message_count.add_relaxed(1);
self.stats
.prune_message_len
.add_relaxed(data.prunes.len() as u64);
match self
.time_gossip_write_lock("process_prune", &self.stats.process_prune)
.process_prune_msg(
&from,
&data.destination,
&data.prunes,
data.wallclock,
timestamp(),
) {
Err(CrdsGossipError::PruneMessageTimeout) => {
inc_new_counter_debug!("cluster_info-prune_message_timeout", 1)
}
Err(CrdsGossipError::BadPruneDestination) => {
inc_new_counter_debug!("cluster_info-bad_prune_destination", 1)
}
_ => (),
}
for (from_addr, packet) in packets {
match packet {
Protocol::PullRequest(filter, caller) => {
let start = allocated.get();
if let Some(contact_info) = caller.contact_info() {
if contact_info.id == self.id() {
warn!("PullRequest ignored, I'm talking to myself");
inc_new_counter_debug!("cluster_info-window-request-loopback", 1);
} else if contact_info.shred_version == 0
|| contact_info.shred_version == self.my_shred_version()
|| self.my_shred_version() == 0
{
gossip_pull_data.push(PullData {
from_addr,
caller,
filter,
});
} else {
inc_new_counter_debug!("cluster_info-gossip_prune_msg_verify_fail", 1);
self.stats.skip_pull_shred_version.add_relaxed(1);
}
datapoint_debug!(
"solana-gossip-listen-memory",
("prune_message", (allocated.get() - start) as i64, i64),
);
}
})
});
datapoint_debug!(
"solana-gossip-listen-memory",
("pull_request", (allocated.get() - start) as i64, i64),
);
}
Protocol::PullResponse(from, data) => {
let start = allocated.get();
let pull_entry = pull_responses.entry(from).or_insert_with(Vec::new);
pull_entry.extend(data);
datapoint_debug!(
"solana-gossip-listen-memory",
("pull_response", (allocated.get() - start) as i64, i64),
);
}
Protocol::PushMessage(from, data) => {
let start = allocated.get();
let rsp = self.handle_push_message(recycler, &from, data, stakes);
if let Some(rsp) = rsp {
let _ignore_disconnect = response_sender.send(rsp);
}
datapoint_debug!(
"solana-gossip-listen-memory",
("push_message", (allocated.get() - start) as i64, i64),
);
}
Protocol::PruneMessage(from, data) => {
let start = allocated.get();
self.stats.prune_message_count.add_relaxed(1);
self.stats
.prune_message_len
.add_relaxed(data.prunes.len() as u64);
match self
.time_gossip_write_lock("process_prune", &self.stats.process_prune)
.process_prune_msg(
&from,
&data.destination,
&data.prunes,
data.wallclock,
timestamp(),
) {
Err(CrdsGossipError::PruneMessageTimeout) => {
inc_new_counter_debug!("cluster_info-prune_message_timeout", 1)
}
Err(CrdsGossipError::BadPruneDestination) => {
inc_new_counter_debug!("cluster_info-bad_prune_destination", 1)
}
_ => (),
}
datapoint_debug!(
"solana-gossip-listen-memory",
("prune_message", (allocated.get() - start) as i64, i64),
);
}
}
}
for (from, data) in pull_responses {
self.handle_pull_response(&from, data, &timeouts);
@@ -1761,31 +1869,25 @@ impl ClusterInfo {
self.stats
.pull_requests_count
.add_relaxed(gossip_pull_data.len() as u64);
let rsp = self.handle_pull_requests(recycler, gossip_pull_data, stakes);
let rsp = self.handle_pull_requests(recycler, gossip_pull_data, stakes, feature_set);
if let Some(rsp) = rsp {
let _ignore_disconnect = response_sender.send(rsp);
}
}
}
fn update_data_budget(&self, stakes: &HashMap<Pubkey, u64>) {
let mut w_outbound_budget = self.outbound_budget.write().unwrap();
let now = timestamp();
fn update_data_budget(&self, num_staked: usize) {
const INTERVAL_MS: u64 = 100;
// allow 50kBps per staked validator, epoch slots + votes ~= 1.5kB/slot ~= 4kB/s
const BYTES_PER_INTERVAL: usize = 5000;
const MAX_BUDGET_MULTIPLE: usize = 5; // allow budget build-up to 5x the interval default
if now - w_outbound_budget.last_timestamp_ms > INTERVAL_MS {
let len = std::cmp::max(stakes.len(), 2);
w_outbound_budget.bytes += len * BYTES_PER_INTERVAL;
w_outbound_budget.bytes = std::cmp::min(
w_outbound_budget.bytes,
MAX_BUDGET_MULTIPLE * len * BYTES_PER_INTERVAL,
);
w_outbound_budget.last_timestamp_ms = now;
}
let num_staked = num_staked.max(2);
self.outbound_budget.update(INTERVAL_MS, |bytes| {
std::cmp::min(
bytes + num_staked * BYTES_PER_INTERVAL,
MAX_BUDGET_MULTIPLE * num_staked * BYTES_PER_INTERVAL,
)
});
}
// Pull requests take an incoming bloom filter of contained entries from a node
@@ -1795,12 +1897,18 @@ impl ClusterInfo {
recycler: &PacketsRecycler,
requests: Vec<PullData>,
stakes: &HashMap<Pubkey, u64>,
feature_set: Option<&FeatureSet>,
) -> Option<Packets> {
if matches!(feature_set, Some(feature_set) if
feature_set.is_active(&feature_set::pull_request_ping_pong_check::id()))
{
// TODO: add ping-pong check on pull-request addresses.
}
// split the requests into addrs and filters
let mut caller_and_filters = vec![];
let mut addrs = vec![];
let mut time = Measure::start("handle_pull_requests");
self.update_data_budget(stakes);
self.update_data_budget(stakes.len());
for pull_data in requests {
caller_and_filters.push((pull_data.caller, pull_data.filter));
addrs.push(pull_data.from_addr);
@@ -1880,17 +1988,13 @@ impl ClusterInfo {
let response = pull_responses[stat.to].0[stat.responses_index].clone();
let protocol = Protocol::PullResponse(self_id, vec![response]);
let new_packet = Packet::from_data(&from_addr, protocol);
{
let mut w_outbound_budget = self.outbound_budget.write().unwrap();
if w_outbound_budget.bytes > new_packet.meta.size {
sent.insert(index);
w_outbound_budget.bytes -= new_packet.meta.size;
total_bytes += new_packet.meta.size;
packets.packets.push(new_packet)
} else {
inc_new_counter_info!("gossip_pull_request-no_budget", 1);
break;
}
if self.outbound_budget.take(new_packet.meta.size) {
sent.insert(index);
total_bytes += new_packet.meta.size;
packets.packets.push(new_packet)
} else {
inc_new_counter_info!("gossip_pull_request-no_budget", 1);
break;
}
}
time.stop();
@@ -2104,14 +2208,34 @@ impl ClusterInfo {
recycler: &PacketsRecycler,
response_sender: &PacketSender,
stakes: HashMap<Pubkey, u64>,
feature_set: Option<&FeatureSet>,
epoch_time_ms: u64,
) {
let sender = response_sender.clone();
thread_pool.install(|| {
requests.into_par_iter().for_each_with(sender, |s, reqs| {
self.handle_packets(&recycler, &stakes, reqs, s, epoch_time_ms)
});
let mut timer = Measure::start("process_gossip_packets_time");
let packets: Vec<_> = thread_pool.install(|| {
requests
.into_par_iter()
.flat_map(|request| request.packets.into_par_iter())
.filter_map(|packet| {
let protocol: Protocol =
limited_deserialize(&packet.data[..packet.meta.size]).ok()?;
protocol.sanitize().ok()?;
let protocol = protocol.par_verify()?;
Some((packet.meta.addr(), protocol))
})
.collect()
});
self.handle_packets(
recycler,
&stakes,
packets,
response_sender,
feature_set,
epoch_time_ms,
);
self.stats
.process_gossip_packets_time
.add_measure(&mut timer);
}
/// Process messages from the network
@@ -2143,13 +2267,25 @@ impl ClusterInfo {
}
let (stakes, epoch_time_ms) = Self::get_stakes_and_epoch_time(bank_forks);
// Using root_bank instead of working_bank here so that an enbaled
// feature does not roll back (if the feature happens to get enabled in
// a minority fork).
let feature_set = bank_forks.map(|bank_forks| {
bank_forks
.read()
.unwrap()
.root_bank()
.deref()
.feature_set
.clone()
});
self.process_packets(
requests,
thread_pool,
recycler,
response_sender,
stakes,
feature_set.as_deref(),
epoch_time_ms,
);
@@ -2210,6 +2346,11 @@ impl ClusterInfo {
i64
),
("purge", self.stats.purge.clear(), i64),
(
"process_gossip_packets_time",
self.stats.process_gossip_packets_time.clear(),
i64
),
(
"process_pull_resp",
self.stats.process_pull_response.clear(),
@@ -2494,7 +2635,7 @@ pub struct Node {
impl Node {
pub fn new_localhost() -> Self {
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
Self::new_localhost_with_pubkey(&pubkey)
}
pub fn new_localhost_with_pubkey(pubkey: &Pubkey) -> Self {
@@ -2658,10 +2799,13 @@ mod tests {
#[test]
fn test_gossip_node() {
//check that a gossip nodes always show up as spies
let (node, _, _) = ClusterInfo::spy_node(&Pubkey::new_rand(), 0);
let (node, _, _) = ClusterInfo::spy_node(&solana_sdk::pubkey::new_rand(), 0);
assert!(ClusterInfo::is_spy_node(&node));
let (node, _, _) =
ClusterInfo::gossip_node(&Pubkey::new_rand(), &"1.1.1.1:1111".parse().unwrap(), 0);
let (node, _, _) = ClusterInfo::gossip_node(
&solana_sdk::pubkey::new_rand(),
&"1.1.1.1:1111".parse().unwrap(),
0,
);
assert!(ClusterInfo::is_spy_node(&node));
}
@@ -2671,7 +2815,7 @@ mod tests {
let node = Node::new_localhost();
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(node.info));
let entrypoint_pubkey = Pubkey::new_rand();
let entrypoint_pubkey = solana_sdk::pubkey::new_rand();
let data = test_crds_values(entrypoint_pubkey);
let timeouts = HashMap::new();
assert_eq!(
@@ -2684,7 +2828,7 @@ mod tests {
)
);
let entrypoint_pubkey2 = Pubkey::new_rand();
let entrypoint_pubkey2 = solana_sdk::pubkey::new_rand();
assert_eq!(
(1, 0, 0),
ClusterInfo::handle_pull_response(&cluster_info, &entrypoint_pubkey2, data, &timeouts)
@@ -2699,7 +2843,7 @@ mod tests {
#[test]
fn test_filter_shred_version() {
let from = Pubkey::new_rand();
let from = solana_sdk::pubkey::new_rand();
let my_shred_version = 1;
let other_shred_version = 1;
@@ -2734,7 +2878,7 @@ mod tests {
assert_eq!(values.len(), 1);
let snapshot_hash_data = CrdsValue::new_unsigned(CrdsData::SnapshotHashes(SnapshotHash {
from: Pubkey::new_rand(),
from: solana_sdk::pubkey::new_rand(),
hashes: vec![],
wallclock: 0,
}));
@@ -2755,7 +2899,7 @@ mod tests {
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
//check that gossip doesn't try to push to invalid addresses
let node = Node::new_localhost();
let (spy, _, _) = ClusterInfo::spy_node(&Pubkey::new_rand(), 0);
let (spy, _, _) = ClusterInfo::spy_node(&solana_sdk::pubkey::new_rand(), 0);
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(node.info));
cluster_info.insert_info(spy);
cluster_info
@@ -2775,16 +2919,16 @@ mod tests {
#[test]
fn test_cluster_info_new() {
let d = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
let d = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
let cluster_info = ClusterInfo::new_with_invalid_keypair(d.clone());
assert_eq!(d.id, cluster_info.id());
}
#[test]
fn insert_info_test() {
let d = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
let d = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
let cluster_info = ClusterInfo::new_with_invalid_keypair(d);
let d = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
let d = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
let label = CrdsValueLabel::ContactInfo(d.id);
cluster_info.insert_info(d);
assert!(cluster_info
@@ -2798,7 +2942,7 @@ mod tests {
#[test]
#[should_panic]
fn test_update_contact_info() {
let d = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
let d = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
let cluster_info = ClusterInfo::new_with_invalid_keypair(d);
let entry_label = CrdsValueLabel::ContactInfo(cluster_info.id());
assert!(cluster_info
@@ -2827,7 +2971,7 @@ mod tests {
// Inserting Contactinfo with different pubkey should panic,
// and update should fail
cluster_info.update_contact_info(|ci| ci.id = Pubkey::new_rand())
cluster_info.update_contact_info(|ci| ci.id = solana_sdk::pubkey::new_rand())
}
fn assert_in_range(x: u16, range: (u16, u16)) {
@@ -2862,7 +3006,7 @@ mod tests {
fn new_with_external_ip_test_random() {
let ip = Ipv4Addr::from(0);
let node = Node::new_with_external_ip(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
&socketaddr!(ip, 0),
VALIDATOR_PORT_RANGE,
IpAddr::V4(ip),
@@ -2879,8 +3023,12 @@ mod tests {
let ip = IpAddr::V4(Ipv4Addr::from(0));
let port = bind_in_range(ip, port_range).expect("Failed to bind").0;
let node =
Node::new_with_external_ip(&Pubkey::new_rand(), &socketaddr!(0, port), port_range, ip);
let node = Node::new_with_external_ip(
&solana_sdk::pubkey::new_rand(),
&socketaddr!(0, port),
port_range,
ip,
);
check_node_sockets(&node, ip, port_range);
@@ -2909,7 +3057,7 @@ mod tests {
.gossip
.write()
.unwrap()
.new_push_messages(timestamp());
.new_push_messages(cluster_info.drain_push_queue(), timestamp());
// there should be some pushes ready
assert_eq!(push_messages.is_empty(), false);
push_messages
@@ -3092,6 +3240,7 @@ mod tests {
let tx = test_tx();
let index = 1;
cluster_info.push_vote(index, tx.clone());
cluster_info.flush_push_queue();
// -1 to make sure that the clock is strictly lower then when insert occurred
let (labels, votes, max_ts) = cluster_info.get_votes(now - 1);
@@ -3121,6 +3270,7 @@ mod tests {
assert!(slots.is_empty());
assert!(since.is_none());
cluster_info.push_epoch_slots(&[0]);
cluster_info.flush_push_queue();
let (slots, since) = cluster_info.get_epoch_slots_since(Some(std::u64::MAX));
assert!(slots.is_empty());
@@ -3143,7 +3293,7 @@ mod tests {
ContactInfo::new_localhost(&node_keypair.pubkey(), timestamp()),
node_keypair,
);
let entrypoint_pubkey = Pubkey::new_rand();
let entrypoint_pubkey = solana_sdk::pubkey::new_rand();
let entrypoint = ContactInfo::new_localhost(&entrypoint_pubkey, timestamp());
cluster_info.set_entrypoint(entrypoint.clone());
let pulls = cluster_info.new_pull_requests(&thread_pool, None, &HashMap::new());
@@ -3302,14 +3452,14 @@ mod tests {
ContactInfo::new_localhost(&node_keypair.pubkey(), timestamp()),
node_keypair,
);
let entrypoint_pubkey = Pubkey::new_rand();
let entrypoint_pubkey = solana_sdk::pubkey::new_rand();
let mut entrypoint = ContactInfo::new_localhost(&entrypoint_pubkey, timestamp());
entrypoint.gossip = socketaddr!("127.0.0.2:1234");
cluster_info.set_entrypoint(entrypoint.clone());
let mut stakes = HashMap::new();
let other_node_pubkey = Pubkey::new_rand();
let other_node_pubkey = solana_sdk::pubkey::new_rand();
let other_node = ContactInfo::new_localhost(&other_node_pubkey, timestamp());
assert_ne!(other_node.gossip, entrypoint.gossip);
cluster_info.insert_info(other_node.clone());
@@ -3352,7 +3502,7 @@ mod tests {
for i in 0..10 {
// make these invalid for the upcoming repair request
let peer_lowest = if i >= 5 { 10 } else { 0 };
let other_node_pubkey = Pubkey::new_rand();
let other_node_pubkey = solana_sdk::pubkey::new_rand();
let other_node = ContactInfo::new_localhost(&other_node_pubkey, timestamp());
cluster_info.insert_info(other_node.clone());
let value = CrdsValue::new_unsigned(CrdsData::LowestSlot(
@@ -3449,7 +3599,9 @@ mod tests {
range.push(last + rand::thread_rng().gen_range(1, 32));
}
cluster_info.push_epoch_slots(&range[..16000]);
cluster_info.flush_push_queue();
cluster_info.push_epoch_slots(&range[16000..]);
cluster_info.flush_push_queue();
let (slots, since) = cluster_info.get_epoch_slots_since(None);
let slots: Vec<_> = slots.iter().flat_map(|x| x.to_slots(0)).collect();
assert_eq!(slots, range);
@@ -3501,7 +3653,7 @@ mod tests {
// Simulate getting entrypoint ContactInfo from gossip
let mut gossiped_entrypoint_info =
ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
gossiped_entrypoint_info.gossip = entrypoint_gossip_addr;
gossiped_entrypoint_info.shred_version = 1;
cluster_info.insert_info(gossiped_entrypoint_info.clone());

View File

@@ -898,7 +898,7 @@ mod tests {
let (vote_tracker, bank, _, _) = setup();
// Check outdated slots are purged with new root
let new_voter = Arc::new(Pubkey::new_rand());
let new_voter = Arc::new(solana_sdk::pubkey::new_rand());
// Make separate copy so the original doesn't count toward
// the ref count, which would prevent cleanup
let new_voter_ = Arc::new(*new_voter);
@@ -1681,7 +1681,7 @@ mod tests {
fn run_test_verify_votes_1_pass(hash: Option<Hash>) {
let vote_tx = test_vote_tx(hash);
let votes = vec![vote_tx];
let labels = vec![CrdsValueLabel::Vote(0, Pubkey::new_rand())];
let labels = vec![CrdsValueLabel::Vote(0, solana_sdk::pubkey::new_rand())];
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels);
assert_eq!(vote_txs.len(), 1);
verify_packets_len(&packets, 1);
@@ -1698,7 +1698,7 @@ mod tests {
let mut bad_vote = vote_tx.clone();
bad_vote.signatures[0] = Signature::default();
let votes = vec![vote_tx.clone(), bad_vote, vote_tx];
let label = CrdsValueLabel::Vote(0, Pubkey::new_rand());
let label = CrdsValueLabel::Vote(0, solana_sdk::pubkey::new_rand());
let labels: Vec<_> = (0..votes.len()).map(|_| label.clone()).collect();
let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, labels);
assert_eq!(vote_txs.len(), 2);

View File

@@ -237,8 +237,8 @@ mod tests {
let mut c1 = ContactInfo::default();
let mut c2 = ContactInfo::default();
let mut map = HashMap::new();
let k1 = Pubkey::new_rand();
let k2 = Pubkey::new_rand();
let k1 = solana_sdk::pubkey::new_rand();
let k2 = solana_sdk::pubkey::new_rand();
map.insert(Arc::new(k1), std::u64::MAX / 2);
map.insert(Arc::new(k2), 0);
cs.cluster_slots
@@ -259,8 +259,8 @@ mod tests {
let mut c1 = ContactInfo::default();
let mut c2 = ContactInfo::default();
let mut map = HashMap::new();
let k1 = Pubkey::new_rand();
let k2 = Pubkey::new_rand();
let k1 = solana_sdk::pubkey::new_rand();
let k2 = solana_sdk::pubkey::new_rand();
map.insert(Arc::new(k2), 0);
cs.cluster_slots
.write()
@@ -290,7 +290,7 @@ mod tests {
let cs = ClusterSlots::default();
let mut contact_infos = vec![ContactInfo::default(); 2];
for ci in contact_infos.iter_mut() {
ci.id = Pubkey::new_rand();
ci.id = solana_sdk::pubkey::new_rand();
}
let slot = 9;
@@ -359,7 +359,7 @@ mod tests {
let mut epoch_slot = EpochSlots::default();
epoch_slot.fill(&[1], 0);
cs.update_internal(0, (vec![epoch_slot], None));
let self_id = Pubkey::new_rand();
let self_id = solana_sdk::pubkey::new_rand();
assert_eq!(
cs.generate_repairs_for_missing_slots(&self_id, 0),
vec![RepairType::HighestShred(1, 0)]

View File

@@ -181,6 +181,7 @@ mod test {
let node_info = Node::new_localhost_with_pubkey(&Pubkey::default());
let cluster_info = ClusterInfo::new_with_invalid_keypair(node_info.info);
ClusterSlotsService::update_lowest_slot(&Pubkey::default(), 5, &cluster_info);
cluster_info.flush_push_queue();
let lowest = cluster_info
.get_lowest_slot_for_node(&Pubkey::default(), None, |lowest_slot, _| {
lowest_slot.clone()

View File

@@ -375,19 +375,22 @@ mod tests {
let rooted_stake_amount = 40;
let sk1 = Pubkey::new_rand();
let pk1 = Pubkey::new_rand();
let mut vote_account1 = vote_state::create_account(&pk1, &Pubkey::new_rand(), 0, 100);
let sk1 = solana_sdk::pubkey::new_rand();
let pk1 = solana_sdk::pubkey::new_rand();
let mut vote_account1 =
vote_state::create_account(&pk1, &solana_sdk::pubkey::new_rand(), 0, 100);
let stake_account1 =
stake_state::create_account(&sk1, &pk1, &vote_account1, &genesis_config.rent, 100);
let sk2 = Pubkey::new_rand();
let pk2 = Pubkey::new_rand();
let mut vote_account2 = vote_state::create_account(&pk2, &Pubkey::new_rand(), 0, 50);
let sk2 = solana_sdk::pubkey::new_rand();
let pk2 = solana_sdk::pubkey::new_rand();
let mut vote_account2 =
vote_state::create_account(&pk2, &solana_sdk::pubkey::new_rand(), 0, 50);
let stake_account2 =
stake_state::create_account(&sk2, &pk2, &vote_account2, &genesis_config.rent, 50);
let sk3 = Pubkey::new_rand();
let pk3 = Pubkey::new_rand();
let mut vote_account3 = vote_state::create_account(&pk3, &Pubkey::new_rand(), 0, 1);
let sk3 = solana_sdk::pubkey::new_rand();
let pk3 = solana_sdk::pubkey::new_rand();
let mut vote_account3 =
vote_state::create_account(&pk3, &solana_sdk::pubkey::new_rand(), 0, 1);
let stake_account3 = stake_state::create_account(
&sk3,
&pk3,
@@ -395,9 +398,10 @@ mod tests {
&genesis_config.rent,
rooted_stake_amount,
);
let sk4 = Pubkey::new_rand();
let pk4 = Pubkey::new_rand();
let mut vote_account4 = vote_state::create_account(&pk4, &Pubkey::new_rand(), 0, 1);
let sk4 = solana_sdk::pubkey::new_rand();
let pk4 = solana_sdk::pubkey::new_rand();
let mut vote_account4 =
vote_state::create_account(&pk4, &solana_sdk::pubkey::new_rand(), 0, 1);
let stake_account4 = stake_state::create_account(
&sk4,
&pk4,

View File

@@ -30,11 +30,11 @@ use std::{
};
use thiserror::Error;
#[derive(PartialEq, Clone, Debug)]
#[derive(PartialEq, Clone, Debug, AbiExample)]
pub enum SwitchForkDecision {
SwitchProof(Hash),
NoSwitch,
FailedSwitchThreshold,
SameFork,
FailedSwitchThreshold(u64, u64),
}
impl SwitchForkDecision {
@@ -45,8 +45,11 @@ impl SwitchForkDecision {
authorized_voter_pubkey: &Pubkey,
) -> Option<Instruction> {
match self {
SwitchForkDecision::FailedSwitchThreshold => None,
SwitchForkDecision::NoSwitch => Some(vote_instruction::vote(
SwitchForkDecision::FailedSwitchThreshold(_, total_stake) => {
assert_ne!(*total_stake, 0);
None
}
SwitchForkDecision::SameFork => Some(vote_instruction::vote(
vote_account_pubkey,
authorized_voter_pubkey,
vote,
@@ -61,6 +64,10 @@ impl SwitchForkDecision {
}
}
}
pub fn can_vote(&self) -> bool {
!matches!(self, SwitchForkDecision::FailedSwitchThreshold(_, _))
}
}
pub const VOTE_THRESHOLD_DEPTH: usize = 8;
@@ -100,7 +107,11 @@ pub struct Tower {
// (This is a special field for slashing-free validator restart with edge cases).
// This could be emptied after some time; but left intact indefinitely for easier
// implementation
// Further, stray slot can be stale or not. `Stale` here means whether given
// bank_forks (=~ ledger) lacks the slot or not.
stray_restored_slot: Option<Slot>,
#[serde(skip)]
pub last_switch_threshold_check: Option<(Slot, SwitchForkDecision)>,
}
impl Default for Tower {
@@ -115,6 +126,7 @@ impl Default for Tower {
path: PathBuf::default(),
tmp_path: PathBuf::default(),
stray_restored_slot: Option::default(),
last_switch_threshold_check: Option::default(),
};
// VoteState::root_slot is ensured to be Some in Tower
tower.lockouts.root_slot = Some(Slot::default());
@@ -377,17 +389,14 @@ impl Tower {
pub fn record_bank_vote(&mut self, vote: Vote) -> Option<Slot> {
let slot = vote.last_voted_slot().unwrap_or(0);
trace!("{} record_vote for {}", self.node_pubkey, slot);
let root_slot = self.lockouts.root_slot;
let old_root = self.root();
self.lockouts.process_vote_unchecked(&vote);
self.last_vote = vote;
let new_root = self.root();
datapoint_info!(
"tower-vote",
("latest", slot, i64),
("root", self.lockouts.root_slot.unwrap_or(0), i64)
);
if root_slot != self.lockouts.root_slot {
Some(self.lockouts.root_slot.unwrap())
datapoint_info!("tower-vote", ("latest", slot, i64), ("root", new_root, i64));
if old_root != new_root {
Some(new_root)
} else {
None
}
@@ -431,13 +440,13 @@ impl Tower {
// root may be forcibly set by arbitrary replay root slot, for example from a root
// after replaying a snapshot.
// Also, tower.root() couldn't be None; do_initialize_lockouts() ensures that.
// Also, tower.root() couldn't be None; initialize_lockouts() ensures that.
// Conceptually, every tower must have been constructed from a concrete starting point,
// which establishes the origin of trust (i.e. root) whether booting from genesis (slot 0) or
// snapshot (slot N). In other words, there should be no possibility a Tower doesn't have
// root, unlike young vote accounts.
pub fn root(&self) -> Option<Slot> {
self.lockouts.root_slot
pub fn root(&self) -> Slot {
self.lockouts.root_slot.unwrap()
}
// a slot is recent if it's newer than the last vote we have
@@ -493,7 +502,7 @@ impl Tower {
false
}
pub(crate) fn check_switch_threshold(
fn make_check_switch_threshold_decision(
&self,
switch_slot: u64,
ancestors: &HashMap<Slot, HashSet<u64>>,
@@ -504,13 +513,13 @@ impl Tower {
) -> SwitchForkDecision {
self.last_voted_slot()
.map(|last_voted_slot| {
let root = self.lockouts.root_slot.unwrap_or(0);
let root = self.root();
let empty_ancestors = HashSet::default();
let last_vote_ancestors =
ancestors.get(&last_voted_slot).unwrap_or_else(|| {
if !self.is_stray_last_vote() {
// Unless last vote is stray, ancestors.get(last_voted_slot) must
// Unless last vote is stray and stale, ancestors.get(last_voted_slot) must
// return Some(_), justifying to panic! here.
// Also, adjust_lockouts_after_replay() correctly makes last_voted_slot None,
// if all saved votes are ancestors of replayed_root_slot. So this code shouldn't be
@@ -520,9 +529,34 @@ impl Tower {
// all of them.
panic!("no ancestors found with slot: {}", last_voted_slot);
} else {
// bank_forks doesn't have corresponding data for the stray restored last vote,
// meaning some inconsistency between saved tower and ledger.
// (newer snapshot, or only a saved tower is moved over to new setup?)
// This condition (stale stray last vote) shouldn't occur under normal validator
// operation, indicating something unusual happened.
// Possible causes include: OS/HW crash, validator process crash, only saved tower
// is moved over to a new setup, etc...
// However, returning empty ancestors as a fallback here shouldn't result in
// slashing by itself (Note that we couldn't fully preclude any kind of slashing if
// the failure was OS or HW level).
// Firstly, lockout is ensured elsewhere.
// Also, there is no risk of optimistic conf. violation. Although empty ancestors
// could result in incorrect (= more than actual) locked_out_stake and
// false-positive SwitchProof later in this function, there should be no such a
// heavier fork candidate, first of all, if the last vote (or any of its
// unavailable ancestors) were already optimistically confirmed.
// The only exception is that other validator is already violating it...
if self.is_first_switch_check() && switch_slot < last_voted_slot {
// `switch < last` is needed not to warn! this message just because of using
// newer snapshots on validator restart
let message = format!(
"bank_forks doesn't have corresponding data for the stray restored \
last vote({}), meaning some inconsistency between saved tower and ledger.",
last_voted_slot
);
warn!("{}", message);
datapoint_warn!("tower_warn", ("warn", message, String));
}
&empty_ancestors
}
});
@@ -532,12 +566,16 @@ impl Tower {
if switch_slot == last_voted_slot || switch_slot_ancestors.contains(&last_voted_slot) {
// If the `switch_slot is a descendant of the last vote,
// no switching proof is necessary
return SwitchForkDecision::NoSwitch;
return SwitchForkDecision::SameFork;
}
// Should never consider switching to an ancestor
// of your last vote
assert!(!last_vote_ancestors.contains(&switch_slot));
assert!(
!last_vote_ancestors.contains(&switch_slot),
"Should never consider switching to slot ({}), which is ancestors({:?}) of last vote: {}",
switch_slot,
last_vote_ancestors,
last_voted_slot
);
// By this point, we know the `switch_slot` is on a different fork
// (is neither an ancestor nor descendant of `last_vote`), so a
@@ -598,7 +636,7 @@ impl Tower {
}
// Only count lockouts on slots that are:
// 1) Not ancestors of `last_vote`
// 1) Not ancestors of `last_vote`, meaning being on different fork
// 2) Not from before the current root as we can't determine if
// anything before the root was an ancestor of `last_vote` or not
if !last_vote_ancestors.contains(lockout_interval_start)
@@ -622,10 +660,43 @@ impl Tower {
if (locked_out_stake as f64 / total_stake as f64) > SWITCH_FORK_THRESHOLD {
SwitchForkDecision::SwitchProof(switch_proof)
} else {
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(locked_out_stake, total_stake)
}
})
.unwrap_or(SwitchForkDecision::NoSwitch)
.unwrap_or(SwitchForkDecision::SameFork)
}
pub(crate) fn check_switch_threshold(
&mut self,
switch_slot: u64,
ancestors: &HashMap<Slot, HashSet<u64>>,
descendants: &HashMap<Slot, HashSet<u64>>,
progress: &ProgressMap,
total_stake: u64,
epoch_vote_accounts: &HashMap<Pubkey, (u64, Account)>,
) -> SwitchForkDecision {
let decision = self.make_check_switch_threshold_decision(
switch_slot,
ancestors,
descendants,
progress,
total_stake,
epoch_vote_accounts,
);
let new_check = Some((switch_slot, decision.clone()));
if new_check != self.last_switch_threshold_check {
trace!(
"new switch threshold check: slot {}: {:?}",
switch_slot,
decision,
);
self.last_switch_threshold_check = new_check;
}
decision
}
fn is_first_switch_check(&self) -> bool {
self.last_switch_threshold_check.is_none()
}
pub fn check_vote_stake_threshold(
@@ -760,20 +831,21 @@ impl Tower {
// The tower root can be older/newer if the validator booted from a newer/older snapshot, so
// tower lockouts may need adjustment
pub fn adjust_lockouts_after_replay(
self,
mut self,
replayed_root: Slot,
slot_history: &SlotHistory,
) -> Result<Self> {
info!(
"adjusting lockouts (after replay up to {}): {:?}",
replayed_root,
self.voted_slots()
);
// sanity assertions for roots
let tower_root = self.root();
info!(
"adjusting lockouts (after replay up to {}): {:?} tower root: {} replayed root: {}",
replayed_root,
self.voted_slots(),
tower_root,
replayed_root,
);
assert_eq!(slot_history.check(replayed_root), Check::Found);
assert!(self.root().is_some());
let tower_root = self.root().unwrap();
// reconcile_blockstore_roots_with_tower() should already have aligned these.
assert!(
tower_root <= replayed_root,
@@ -791,30 +863,24 @@ impl Tower {
)
);
// return immediately if votes are empty...
if self.lockouts.votes.is_empty() {
return Ok(self);
if let Some(last_voted_slot) = self.last_voted_slot() {
if slot_history.check(last_voted_slot) == Check::TooOld {
// We could try hard to anchor with other older votes, but opt to simplify the
// following logic
return Err(TowerError::TooOldTower(
last_voted_slot,
slot_history.oldest(),
));
}
self.adjust_lockouts_with_slot_history(slot_history)?;
self.initialize_root(replayed_root);
}
let last_voted_slot = self.last_voted_slot().unwrap();
if slot_history.check(last_voted_slot) == Check::TooOld {
// We could try hard to anchor with other older votes, but opt to simplify the
// following logic
return Err(TowerError::TooOldTower(
last_voted_slot,
slot_history.oldest(),
));
}
self.do_adjust_lockouts_after_replay(tower_root, replayed_root, slot_history)
Ok(self)
}
fn do_adjust_lockouts_after_replay(
mut self,
tower_root: Slot,
replayed_root: Slot,
slot_history: &SlotHistory,
) -> Result<Self> {
fn adjust_lockouts_with_slot_history(&mut self, slot_history: &SlotHistory) -> Result<()> {
let tower_root = self.root();
// retained slots will be consisted only from divergent slots
let mut retain_flags_for_each_vote_in_reverse: Vec<_> =
Vec::with_capacity(self.lockouts.votes.len());
@@ -862,7 +928,12 @@ impl Tower {
if !voting_from_genesis {
// Unless we're voting since genesis, slots_in_tower must always be older than last checked_slot
// including all vote slot and the root slot.
assert!(*slot_in_tower < checked_slot)
assert!(
*slot_in_tower < checked_slot,
"slot_in_tower({}) < checked_slot({})",
*slot_in_tower,
checked_slot
);
}
}
@@ -890,15 +961,10 @@ impl Tower {
retain_flags_for_each_vote_in_reverse.into_iter().rev();
let original_votes_len = self.lockouts.votes.len();
self.do_initialize_lockouts(replayed_root, move |_| {
retain_flags_for_each_vote.next().unwrap()
});
self.initialize_lockouts(move |_| retain_flags_for_each_vote.next().unwrap());
if self.lockouts.votes.is_empty() {
info!(
"All restored votes were behind replayed_root({}); resetting root_slot and last_vote in tower!",
replayed_root
);
info!("All restored votes were behind; resetting root_slot and last_vote in tower!");
// we might not have banks for those votes so just reset.
// That's because the votes may well past replayed_root
self.last_vote = Vote::default();
@@ -917,7 +983,7 @@ impl Tower {
self.stray_restored_slot = Some(self.last_vote.last_voted_slot().unwrap());
}
Ok(self)
Ok(())
}
fn initialize_lockouts_from_bank(
@@ -930,18 +996,19 @@ impl Tower {
let vote_state = VoteState::deserialize(&vote_account.data)
.expect("vote_account isn't a VoteState?");
self.lockouts = vote_state;
self.do_initialize_lockouts(root, |v| v.slot > root);
self.initialize_root(root);
self.initialize_lockouts(|v| v.slot > root);
trace!(
"{} lockouts initialized to {:?}",
"Lockouts in tower for {} is initialized using bank {}",
self.node_pubkey,
self.lockouts
bank.slot(),
);
assert_eq!(
self.lockouts.node_pubkey, self.node_pubkey,
"vote account's node_pubkey doesn't match",
);
} else {
self.do_initialize_lockouts(root, |_| true);
self.initialize_root(root);
info!(
"vote account({}) not found in bank (slot={})",
vote_account_pubkey,
@@ -950,13 +1017,16 @@ impl Tower {
}
}
fn do_initialize_lockouts<F: FnMut(&Lockout) -> bool>(&mut self, root: Slot, should_retain: F) {
// Updating root is needed to correctly restore from newly-saved tower for the next
// boot
self.lockouts.root_slot = Some(root);
fn initialize_lockouts<F: FnMut(&Lockout) -> bool>(&mut self, should_retain: F) {
self.lockouts.votes.retain(should_retain);
}
// Updating root is needed to correctly restore from newly-saved tower for the next
// boot
fn initialize_root(&mut self, root: Slot) {
self.lockouts.root_slot = Some(root);
}
pub fn get_filename(path: &Path, node_pubkey: &Pubkey) -> PathBuf {
path.join(format!("tower-{}", node_pubkey))
.with_extension("bin")
@@ -986,6 +1056,7 @@ impl Tower {
bincode::serialize_into(&mut file, &saved_tower)?;
// file.sync_all() hurts performance; pipeline sync-ing and submitting votes to the cluster!
}
trace!("persisted votes: {:?}", self.voted_slots());
fs::rename(&new_filename, &filename)?;
// self.path.parent().sync_all() hurts performance same as the above sync
@@ -1047,6 +1118,16 @@ pub enum TowerError {
FatallyInconsistent(&'static str),
}
impl TowerError {
pub fn is_file_missing(&self) -> bool {
if let TowerError::IOError(io_err) = &self {
io_err.kind() == std::io::ErrorKind::NotFound
} else {
false
}
}
}
#[frozen_abi(digest = "Gaxfwvx5MArn52mKZQgzHmDCyn5YfCuTHvp5Et3rFfpp")]
#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq, AbiExample)]
pub struct SavedTower {
@@ -1076,28 +1157,27 @@ pub fn reconcile_blockstore_roots_with_tower(
tower: &Tower,
blockstore: &Blockstore,
) -> blockstore_db::Result<()> {
if let Some(tower_root) = tower.root() {
let last_blockstore_root = blockstore.last_root();
if last_blockstore_root < tower_root {
// Ensure tower_root itself to exist and be marked as rooted in the blockstore
// in addition to its ancestors.
let new_roots: Vec<_> = AncestorIterator::new_inclusive(tower_root, &blockstore)
.take_while(|current| match current.cmp(&last_blockstore_root) {
Ordering::Greater => true,
Ordering::Equal => false,
Ordering::Less => panic!(
"couldn't find a last_blockstore_root upwards from: {}!?",
tower_root
),
})
.collect();
assert!(
!new_roots.is_empty(),
"at least 1 parent slot must be found"
);
let tower_root = tower.root();
let last_blockstore_root = blockstore.last_root();
if last_blockstore_root < tower_root {
// Ensure tower_root itself to exist and be marked as rooted in the blockstore
// in addition to its ancestors.
let new_roots: Vec<_> = AncestorIterator::new_inclusive(tower_root, &blockstore)
.take_while(|current| match current.cmp(&last_blockstore_root) {
Ordering::Greater => true,
Ordering::Equal => false,
Ordering::Less => panic!(
"couldn't find a last_blockstore_root upwards from: {}!?",
tower_root
),
})
.collect();
assert!(
!new_roots.is_empty(),
"at least 1 parent slot must be found"
);
blockstore.set_roots(&new_roots)?
}
blockstore.set_roots(&new_roots)?;
}
Ok(())
}
@@ -1267,7 +1347,7 @@ pub mod test {
&ancestors,
&descendants,
&self.progress,
&tower,
tower,
);
// Make sure this slot isn't locked out or failing threshold
@@ -1456,7 +1536,7 @@ pub mod test {
&mut account.data,
)
.expect("serialize state");
stakes.push((Pubkey::new_rand(), (*lamports, account)));
stakes.push((solana_sdk::pubkey::new_rand(), (*lamports, account)));
}
stakes
}
@@ -1464,11 +1544,11 @@ pub mod test {
#[test]
fn test_to_vote_instruction() {
let vote = Vote::default();
let mut decision = SwitchForkDecision::FailedSwitchThreshold;
let mut decision = SwitchForkDecision::FailedSwitchThreshold(0, 1);
assert!(decision
.to_vote_instruction(vote.clone(), &Pubkey::default(), &Pubkey::default())
.is_none());
decision = SwitchForkDecision::NoSwitch;
decision = SwitchForkDecision::SameFork;
assert_eq!(
decision.to_vote_instruction(vote.clone(), &Pubkey::default(), &Pubkey::default()),
Some(vote_instruction::vote(
@@ -1571,7 +1651,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::NoSwitch
SwitchForkDecision::SameFork
);
// Trying to switch to another fork at 110 should fail
@@ -1584,7 +1664,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
// Adding another validator lockout on a descendant of last vote should
@@ -1599,7 +1679,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
// Adding another validator lockout on an ancestor of last vote should
@@ -1614,7 +1694,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
// Adding another validator lockout on a different fork, but the lockout
@@ -1629,7 +1709,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
// Adding another validator lockout on a different fork, and the lockout
@@ -1646,7 +1726,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
// Adding another validator lockout on a different fork, and the lockout
@@ -1697,7 +1777,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
}
@@ -2365,7 +2445,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::NoSwitch
SwitchForkDecision::SameFork
);
// Trying to switch to another fork at 110 should fail
@@ -2378,7 +2458,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
vote_simulator.simulate_lockout_interval(111, (10, 49), &other_vote_account);
@@ -2456,7 +2536,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
// Add lockout_interval which should be excluded
@@ -2470,7 +2550,7 @@ pub mod test {
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
),
SwitchForkDecision::FailedSwitchThreshold
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
// Add lockout_interval which should not be excluded
@@ -2660,13 +2740,13 @@ pub mod test {
.unwrap();
assert_eq!(tower.voted_slots(), vec![2, 3]);
assert_eq!(tower.root(), Some(replayed_root_slot));
assert_eq!(tower.root(), replayed_root_slot);
tower = tower
.adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
.unwrap();
assert_eq!(tower.voted_slots(), vec![2, 3]);
assert_eq!(tower.root(), Some(replayed_root_slot));
assert_eq!(tower.root(), replayed_root_slot);
}
#[test]
@@ -2688,7 +2768,7 @@ pub mod test {
.unwrap();
assert_eq!(tower.voted_slots(), vec![2, 3]);
assert_eq!(tower.root(), Some(replayed_root_slot));
assert_eq!(tower.root(), replayed_root_slot);
}
#[test]
@@ -2712,12 +2792,12 @@ pub mod test {
.unwrap();
assert_eq!(tower.voted_slots(), vec![] as Vec<Slot>);
assert_eq!(tower.root(), Some(replayed_root_slot));
assert_eq!(tower.root(), replayed_root_slot);
assert_eq!(tower.stray_restored_slot, None);
}
#[test]
fn test_adjust_lockouts_after_relay_all_rooted_with_too_old() {
fn test_adjust_lockouts_after_replay_all_rooted_with_too_old() {
use solana_sdk::slot_history::MAX_ENTRIES;
let mut tower = Tower::new_for_tests(10, 0.9);
@@ -2735,7 +2815,7 @@ pub mod test {
.adjust_lockouts_after_replay(MAX_ENTRIES, &slot_history)
.unwrap();
assert_eq!(tower.voted_slots(), vec![] as Vec<Slot>);
assert_eq!(tower.root(), Some(MAX_ENTRIES));
assert_eq!(tower.root(), MAX_ENTRIES);
}
#[test]
@@ -2758,7 +2838,7 @@ pub mod test {
.unwrap();
assert_eq!(tower.voted_slots(), vec![3, 4]);
assert_eq!(tower.root(), Some(replayed_root_slot));
assert_eq!(tower.root(), replayed_root_slot);
}
#[test]
@@ -2779,7 +2859,7 @@ pub mod test {
.unwrap();
assert_eq!(tower.voted_slots(), vec![5, 6]);
assert_eq!(tower.root(), Some(replayed_root_slot));
assert_eq!(tower.root(), replayed_root_slot);
}
#[test]
@@ -2823,7 +2903,7 @@ pub mod test {
.unwrap();
assert_eq!(tower.voted_slots(), vec![3, 4, 5]);
assert_eq!(tower.root(), Some(replayed_root_slot));
assert_eq!(tower.root(), replayed_root_slot);
}
#[test]
@@ -2839,7 +2919,7 @@ pub mod test {
.unwrap();
assert_eq!(tower.voted_slots(), vec![] as Vec<Slot>);
assert_eq!(tower.root(), Some(replayed_root_slot));
assert_eq!(tower.root(), replayed_root_slot);
}
#[test]
@@ -2920,4 +3000,54 @@ pub mod test {
"The tower is fatally inconsistent with blockstore: not too old once after got too old?"
);
}
#[test]
#[should_panic(expected = "slot_in_tower(2) < checked_slot(1)")]
fn test_adjust_lockouts_after_replay_reversed_votes() {
let mut tower = Tower::new_for_tests(10, 0.9);
tower.lockouts.votes.push_back(Lockout::new(2));
tower.lockouts.votes.push_back(Lockout::new(1));
let vote = Vote::new(vec![1], Hash::default());
tower.last_vote = vote;
let mut slot_history = SlotHistory::default();
slot_history.add(0);
slot_history.add(2);
tower
.adjust_lockouts_after_replay(2, &slot_history)
.unwrap();
}
#[test]
#[should_panic(expected = "slot_in_tower(3) < checked_slot(3)")]
fn test_adjust_lockouts_after_replay_repeated_non_root_votes() {
let mut tower = Tower::new_for_tests(10, 0.9);
tower.lockouts.votes.push_back(Lockout::new(2));
tower.lockouts.votes.push_back(Lockout::new(3));
tower.lockouts.votes.push_back(Lockout::new(3));
let vote = Vote::new(vec![3], Hash::default());
tower.last_vote = vote;
let mut slot_history = SlotHistory::default();
slot_history.add(0);
slot_history.add(2);
tower
.adjust_lockouts_after_replay(2, &slot_history)
.unwrap();
}
#[test]
fn test_adjust_lockouts_after_replay_vote_on_genesis() {
let mut tower = Tower::new_for_tests(10, 0.9);
tower.lockouts.votes.push_back(Lockout::new(0));
let vote = Vote::new(vec![0], Hash::default());
tower.last_vote = vote;
let mut slot_history = SlotHistory::default();
slot_history.add(0);
assert!(tower.adjust_lockouts_after_replay(0, &slot_history).is_ok());
}
}

View File

@@ -130,7 +130,7 @@ impl ContactInfo {
let addr = socketaddr!("224.0.1.255:1000");
assert!(addr.ip().is_multicast());
Self {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
gossip: addr,
tvu: addr,
tvu_forwards: addr,

View File

@@ -361,7 +361,9 @@ mod test {
}
let mut crds = Crds::default();
let pubkeys: Vec<_> = std::iter::repeat_with(Pubkey::new_rand).take(256).collect();
let pubkeys: Vec<_> = std::iter::repeat_with(solana_sdk::pubkey::new_rand)
.take(256)
.collect();
let mut rng = thread_rng();
let mut num_inserts = 0;
for _ in 0..4096 {
@@ -484,14 +486,14 @@ mod test {
let v1 = VersionedCrdsValue::new(
1,
CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
))),
);
let v2 = VersionedCrdsValue::new(
1,
CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
))),
);

View File

@@ -88,7 +88,20 @@ impl CrdsGossip {
prune_map
}
pub fn new_push_messages(&mut self, now: u64) -> (Pubkey, HashMap<Pubkey, Vec<CrdsValue>>) {
pub fn process_push_messages(&mut self, pending_push_messages: Vec<(CrdsValue, u64)>) {
for (push_message, timestamp) in pending_push_messages {
let _ =
self.push
.process_push_message(&mut self.crds, &self.id, push_message, timestamp);
}
}
pub fn new_push_messages(
&mut self,
pending_push_messages: Vec<(CrdsValue, u64)>,
now: u64,
) -> (Pubkey, HashMap<Pubkey, Vec<CrdsValue>>) {
self.process_push_messages(pending_push_messages);
let push_messages = self.push.new_push_messages(&self.crds, now);
(self.id, push_messages)
}

View File

@@ -626,7 +626,7 @@ mod test {
}
let mut rng = thread_rng();
for _ in 0..100 {
let hash = Hash::new_rand(&mut rng);
let hash = solana_sdk::hash::new_rand(&mut rng);
assert_eq!(CrdsFilter::hash_as_u64(&hash), hash_as_u64_bitops(&hash));
}
}
@@ -638,7 +638,7 @@ mod test {
assert_eq!(filter.mask, mask);
let mut rng = thread_rng();
for _ in 0..10 {
let hash = Hash::new_rand(&mut rng);
let hash = solana_sdk::hash::new_rand(&mut rng);
assert!(filter.test_mask(&hash));
}
}
@@ -649,13 +649,13 @@ mod test {
let mut stakes = HashMap::new();
let node = CrdsGossipPull::default();
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
crds.insert(me.clone(), 0).unwrap();
for i in 1..=30 {
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let id = entry.label().pubkey();
@@ -682,25 +682,25 @@ mod test {
let gossip = socketaddr!("127.0.0.1:1234");
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
shred_version: 123,
gossip,
..ContactInfo::default()
}));
let spy = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
shred_version: 0,
gossip,
..ContactInfo::default()
}));
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
shred_version: 123,
gossip,
..ContactInfo::default()
}));
let node_456 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
shred_version: 456,
gossip,
..ContactInfo::default()
@@ -741,12 +741,12 @@ mod test {
let gossip = socketaddr!("127.0.0.1:1234");
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
gossip,
..ContactInfo::default()
}));
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
gossip,
..ContactInfo::default()
}));
@@ -767,7 +767,7 @@ mod test {
assert!(options.is_empty());
// Unknown pubkey in gossip_validators -- will pull from nobody
gossip_validators.insert(Pubkey::new_rand());
gossip_validators.insert(solana_sdk::pubkey::new_rand());
let options = node.pull_options(
&crds,
&me.label().pubkey(),
@@ -797,7 +797,7 @@ mod test {
let mut rng = thread_rng();
let crds_filter_set =
CrdsFilterSet::new(/*num_items=*/ 9672788, /*max_bytes=*/ 8196);
let hash_values: Vec<_> = std::iter::repeat_with(|| Hash::new_rand(&mut rng))
let hash_values: Vec<_> = std::iter::repeat_with(|| solana_sdk::hash::new_rand(&mut rng))
.take(1024)
.collect();
for hash_value in &hash_values {
@@ -849,7 +849,7 @@ mod test {
for _ in 0..10_000 {
crds_gossip_pull
.purged_values
.push_back((Hash::new_rand(&mut rng), rng.gen()));
.push_back((solana_sdk::hash::new_rand(&mut rng), rng.gen()));
}
let mut num_inserts = 0;
for _ in 0..20_000 {
@@ -898,7 +898,7 @@ mod test {
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
let mut crds = Crds::default();
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let id = entry.label().pubkey();
@@ -933,7 +933,7 @@ mod test {
);
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
crds.insert(new.clone(), 0).unwrap();
@@ -957,19 +957,19 @@ mod test {
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
let mut crds = Crds::default();
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let node_pubkey = entry.label().pubkey();
let mut node = CrdsGossipPull::default();
crds.insert(entry.clone(), 0).unwrap();
let old = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
crds.insert(old.clone(), 0).unwrap();
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
crds.insert(new.clone(), 0).unwrap();
@@ -1000,14 +1000,14 @@ mod test {
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
let mut node_crds = Crds::default();
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let node_pubkey = entry.label().pubkey();
let node = CrdsGossipPull::default();
node_crds.insert(entry, 0).unwrap();
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
node_crds.insert(new, 0).unwrap();
@@ -1031,7 +1031,7 @@ mod test {
assert_eq!(rsp[0].len(), 0);
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS,
)));
dest_crds
@@ -1047,7 +1047,7 @@ mod test {
filters.push(filters[0].clone());
//should return new value since caller is new
filters[1].0 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS + 1,
)));
@@ -1063,14 +1063,14 @@ mod test {
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
let mut node_crds = Crds::default();
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let node_pubkey = entry.label().pubkey();
let node = CrdsGossipPull::default();
node_crds.insert(entry, 0).unwrap();
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
node_crds.insert(new, 0).unwrap();
@@ -1113,7 +1113,7 @@ mod test {
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
let mut node_crds = Crds::default();
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
1,
)));
let node_pubkey = entry.label().pubkey();
@@ -1121,14 +1121,14 @@ mod test {
node_crds.insert(entry, 0).unwrap();
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
1,
)));
node_crds.insert(new, 0).unwrap();
let mut dest = CrdsGossipPull::default();
let mut dest_crds = Crds::default();
let new_id = Pubkey::new_rand();
let new_id = solana_sdk::pubkey::new_rand();
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&new_id, 1,
)));
@@ -1210,7 +1210,7 @@ mod test {
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
let mut node_crds = Crds::default();
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let node_label = entry.label();
@@ -1218,7 +1218,7 @@ mod test {
let mut node = CrdsGossipPull::default();
node_crds.insert(entry, 0).unwrap();
let old = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
node_crds.insert(old.clone(), 0).unwrap();
@@ -1330,7 +1330,7 @@ mod test {
let mut node_crds = Crds::default();
let mut node = CrdsGossipPull::default();
let peer_pubkey = Pubkey::new_rand();
let peer_pubkey = solana_sdk::pubkey::new_rand();
let peer_entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(
ContactInfo::new_localhost(&peer_pubkey, 0),
));

View File

@@ -438,15 +438,15 @@ mod test {
let mut push = CrdsGossipPush::default();
let mut stakes = HashMap::new();
let self_id = Pubkey::new_rand();
let origin = Pubkey::new_rand();
let self_id = solana_sdk::pubkey::new_rand();
let origin = solana_sdk::pubkey::new_rand();
stakes.insert(self_id, 100);
stakes.insert(origin, 100);
let value = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&origin, 0,
)));
let low_staked_peers = (0..10).map(|_| Pubkey::new_rand());
let low_staked_peers = (0..10).map(|_| solana_sdk::pubkey::new_rand());
let mut low_staked_set = HashSet::new();
low_staked_peers.for_each(|p| {
let _ = push.process_push_message(&mut crds, &p, value.clone(), 0);
@@ -460,7 +460,7 @@ mod test {
"should not prune if min threshold has not been reached"
);
let high_staked_peer = Pubkey::new_rand();
let high_staked_peer = solana_sdk::pubkey::new_rand();
let high_stake = CrdsGossipPush::prune_stake_threshold(100, 100) + 10;
stakes.insert(high_staked_peer, high_stake);
let _ = push.process_push_message(&mut crds, &high_staked_peer, value, 0);
@@ -483,7 +483,7 @@ mod test {
let mut crds = Crds::default();
let mut push = CrdsGossipPush::default();
let value = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let label = value.label();
@@ -504,7 +504,7 @@ mod test {
fn test_process_push_old_version() {
let mut crds = Crds::default();
let mut push = CrdsGossipPush::default();
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
ci.wallclock = 1;
let value = CrdsValue::new_unsigned(CrdsData::ContactInfo(ci.clone()));
@@ -527,7 +527,7 @@ mod test {
let mut crds = Crds::default();
let mut push = CrdsGossipPush::default();
let timeout = push.msg_timeout;
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
// push a version to far in the future
ci.wallclock = timeout + 1;
@@ -549,7 +549,7 @@ mod test {
fn test_process_push_update() {
let mut crds = Crds::default();
let mut push = CrdsGossipPush::default();
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
ci.wallclock = 0;
let value_old = CrdsValue::new_unsigned(CrdsData::ContactInfo(ci.clone()));
@@ -584,7 +584,7 @@ mod test {
let mut crds = Crds::default();
let mut push = CrdsGossipPush::default();
let value1 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
@@ -593,7 +593,7 @@ mod test {
assert!(push.active_set.get(&value1.label().pubkey()).is_some());
let value2 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
assert!(push.active_set.get(&value2.label().pubkey()).is_none());
@@ -608,7 +608,7 @@ mod test {
for _ in 0..push.num_active {
let value2 = CrdsValue::new_unsigned(CrdsData::ContactInfo(
ContactInfo::new_localhost(&Pubkey::new_rand(), 0),
ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0),
));
assert_eq!(crds.insert(value2.clone(), now), Ok(None));
}
@@ -624,7 +624,7 @@ mod test {
let mut stakes = HashMap::new();
for i in 1..=100 {
let peer = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
time,
)));
let id = peer.label().pubkey();
@@ -652,25 +652,25 @@ mod test {
let gossip = socketaddr!("127.0.0.1:1234");
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
shred_version: 123,
gossip,
..ContactInfo::default()
}));
let spy = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
shred_version: 0,
gossip,
..ContactInfo::default()
}));
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
shred_version: 123,
gossip,
..ContactInfo::default()
}));
let node_456 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
shred_version: 456,
gossip,
..ContactInfo::default()
@@ -709,12 +709,12 @@ mod test {
let gossip = socketaddr!("127.0.0.1:1234");
let me = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
gossip,
..ContactInfo::default()
}));
let node_123 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
gossip,
..ContactInfo::default()
}));
@@ -735,7 +735,7 @@ mod test {
assert!(options.is_empty());
// Unknown pubkey in gossip_validators -- will push to nobody
gossip_validators.insert(Pubkey::new_rand());
gossip_validators.insert(solana_sdk::pubkey::new_rand());
let options = node.push_options(
&crds,
&me.label().pubkey(),
@@ -765,14 +765,14 @@ mod test {
let mut crds = Crds::default();
let mut push = CrdsGossipPush::default();
let peer = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
assert_eq!(crds.insert(peer.clone(), now), Ok(None));
push.refresh_push_active_set(&crds, &HashMap::new(), None, &Pubkey::default(), 0, 1, 1);
let new_msg = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let mut expected = HashMap::new();
@@ -790,17 +790,17 @@ mod test {
let mut crds = Crds::default();
let mut push = CrdsGossipPush::default();
let peer_1 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
assert_eq!(crds.insert(peer_1.clone(), now), Ok(None));
let peer_2 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
assert_eq!(crds.insert(peer_2.clone(), now), Ok(None));
let peer_3 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
now,
)));
assert_eq!(
@@ -823,17 +823,17 @@ mod test {
#[test]
fn test_process_prune() {
let mut crds = Crds::default();
let self_id = Pubkey::new_rand();
let self_id = solana_sdk::pubkey::new_rand();
let mut push = CrdsGossipPush::default();
let peer = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
assert_eq!(crds.insert(peer.clone(), 0), Ok(None));
push.refresh_push_active_set(&crds, &HashMap::new(), None, &Pubkey::default(), 0, 1, 1);
let new_msg = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let expected = HashMap::new();
@@ -853,13 +853,13 @@ mod test {
let mut crds = Crds::default();
let mut push = CrdsGossipPush::default();
let peer = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
assert_eq!(crds.insert(peer, 0), Ok(None));
push.refresh_push_active_set(&crds, &HashMap::new(), None, &Pubkey::default(), 0, 1, 1);
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
ci.wallclock = 1;
let new_msg = CrdsValue::new_unsigned(CrdsData::ContactInfo(ci));
let expected = HashMap::new();
@@ -875,7 +875,7 @@ mod test {
fn test_purge_old_received_cache() {
let mut crds = Crds::default();
let mut push = CrdsGossipPush::default();
let mut ci = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
let mut ci = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
ci.wallclock = 0;
let value = CrdsValue::new_unsigned(CrdsData::ContactInfo(ci));
let label = value.label();

View File

@@ -135,14 +135,15 @@ mod test {
use crate::contact_info::ContactInfo;
use crate::crds_value::{CrdsData, CrdsValue};
use rand::{thread_rng, Rng};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::timing::timestamp;
use std::collections::HashSet;
use std::ops::Index;
fn new_test_crds_value() -> VersionedCrdsValue {
let data =
CrdsData::ContactInfo(ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp()));
let data = CrdsData::ContactInfo(ContactInfo::new_localhost(
&solana_sdk::pubkey::new_rand(),
timestamp(),
));
VersionedCrdsValue::new(timestamp(), CrdsValue::new_unsigned(data))
}

View File

@@ -318,7 +318,7 @@ impl CrdsValue {
R: rand::Rng,
{
let now = rng.gen();
let contact_info = ContactInfo::new_localhost(&Pubkey::new_rand(), now);
let contact_info = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), now);
Self::new_signed(CrdsData::ContactInfo(contact_info), &Keypair::new())
}

112
core/src/data_budget.rs Normal file
View File

@@ -0,0 +1,112 @@
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
#[derive(Default)]
pub struct DataBudget {
// Amount of bytes we have in the budget to send.
bytes: AtomicUsize,
// Last time that we upped the bytes count, used
// to detect when to up the bytes budget again
last_timestamp_ms: AtomicU64,
}
impl DataBudget {
// If there are enough bytes in the budget, consumes from
// the budget and returns true. Otherwise returns false.
#[must_use]
pub fn take(&self, size: usize) -> bool {
let mut budget = self.bytes.load(Ordering::Acquire);
loop {
if budget < size {
return false;
}
match self.bytes.compare_exchange_weak(
budget,
budget - size,
Ordering::AcqRel,
Ordering::Acquire,
) {
Ok(_) => return true,
Err(bytes) => budget = bytes,
}
}
}
// Updates timestamp and returns true, if at least given milliseconds
// has passed since last update. Otherwise returns false.
fn can_update(&self, duration_millis: u64) -> bool {
let now = solana_sdk::timing::timestamp();
let mut last_timestamp = self.last_timestamp_ms.load(Ordering::Acquire);
loop {
if now < last_timestamp + duration_millis {
return false;
}
match self.last_timestamp_ms.compare_exchange_weak(
last_timestamp,
now,
Ordering::AcqRel,
Ordering::Acquire,
) {
Ok(_) => return true,
Err(ts) => last_timestamp = ts,
}
}
}
// Updates the budget if at least given milliseconds has passed since last
// update. Updater function maps current value of bytes to the new one.
pub fn update<F>(&self, duration_millis: u64, updater: F)
where
F: Fn(usize) -> usize,
{
if !self.can_update(duration_millis) {
return;
}
let mut bytes = self.bytes.load(Ordering::Acquire);
loop {
match self.bytes.compare_exchange_weak(
bytes,
updater(bytes),
Ordering::AcqRel,
Ordering::Acquire,
) {
Ok(_) => break,
Err(b) => bytes = b,
}
}
}
// Non-atomic clone only for tests and simulations.
pub fn clone_non_atomic(&self) -> Self {
Self {
bytes: AtomicUsize::new(self.bytes.load(Ordering::Acquire)),
last_timestamp_ms: AtomicU64::new(self.last_timestamp_ms.load(Ordering::Acquire)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_data_budget() {
let budget = DataBudget::default();
assert!(!budget.take(1)); // budget = 0.
budget.update(1000, |bytes| bytes + 5); // budget updates to 5.
assert!(budget.take(1));
assert!(budget.take(2));
assert!(!budget.take(3)); // budget = 2, out of budget.
budget.update(30, |_| 10); // no update, budget = 2.
assert!(!budget.take(3)); // budget = 2, out of budget.
std::thread::sleep(Duration::from_millis(50));
budget.update(30, |bytes| bytes * 2); // budget updates to 4.
assert!(budget.take(3));
assert!(budget.take(1));
assert!(!budget.take(1)); // budget = 0.
}
}

View File

@@ -306,8 +306,8 @@ mod tests {
#[test]
fn test_gossip_services_spy() {
let keypair = Keypair::new();
let peer0 = Pubkey::new_rand();
let peer1 = Pubkey::new_rand();
let peer0 = solana_sdk::pubkey::new_rand();
let peer1 = solana_sdk::pubkey::new_rand();
let contact_info = ContactInfo::new_localhost(&keypair.pubkey(), 0);
let peer0_info = ContactInfo::new_localhost(&peer0, 0);
let peer1_info = ContactInfo::new_localhost(&peer1, 0);
@@ -335,7 +335,7 @@ mod tests {
spy_ref.clone(),
None,
Some(0),
Some(Pubkey::new_rand()),
Some(solana_sdk::pubkey::new_rand()),
None,
);
assert_eq!(met_criteria, false);
@@ -349,7 +349,7 @@ mod tests {
spy_ref.clone(),
Some(1),
Some(0),
Some(Pubkey::new_rand()),
Some(solana_sdk::pubkey::new_rand()),
None,
);
assert_eq!(met_criteria, false);

View File

@@ -498,7 +498,7 @@ impl HeaviestSubtreeForkChoice {
let heaviest_slot_on_same_voted_fork = self.best_slot(last_voted_slot);
if heaviest_slot_on_same_voted_fork.is_none() {
if !tower.is_stray_last_vote() {
// Unless last vote is stray, self.bast_slot(last_voted_slot) must return
// Unless last vote is stray and stale, self.bast_slot(last_voted_slot) must return
// Some(_), justifying to panic! here.
// Also, adjust_lockouts_after_replay() correctly makes last_voted_slot None,
// if all saved votes are ancestors of replayed_root_slot. So this code shouldn't be
@@ -507,12 +507,12 @@ impl HeaviestSubtreeForkChoice {
// validator has been running, so we must be able to fetch best_slots for all of
// them.
panic!(
"a bank at last_voted_slot({}) is a frozen bank so must have been\
"a bank at last_voted_slot({}) is a frozen bank so must have been \
added to heaviest_subtree_fork_choice at time of freezing",
last_voted_slot,
)
} else {
// fork_infos doesn't have corresponding data for the stray restored last vote,
// fork_infos doesn't have corresponding data for the stale stray last vote,
// meaning some inconsistency between saved tower and ledger.
// (newer snapshot, or only a saved tower is moved over to new setup?)
return None;

View File

@@ -6,14 +6,10 @@
//! command-line tools to spin up validators and a Rust library
//!
#[macro_use]
extern crate solana_bpf_loader_program;
pub mod accounts_hash_verifier;
pub mod banking_stage;
pub mod bigtable_upload_service;
pub mod broadcast_stage;
mod builtins;
pub mod cache_block_time_service;
pub mod cluster_info_vote_listener;
pub mod commitment_service;
@@ -35,6 +31,7 @@ pub mod crds_gossip_pull;
pub mod crds_gossip_push;
pub mod crds_shards;
pub mod crds_value;
pub mod data_budget;
pub mod epoch_slots;
pub mod fetch_stage;
pub mod fork_choice;
@@ -59,7 +56,6 @@ mod result;
pub mod retransmit_stage;
pub mod rewards_recorder_service;
pub mod rpc;
pub mod rpc_error;
pub mod rpc_health;
pub mod rpc_pubsub;
pub mod rpc_pubsub_service;
@@ -97,7 +93,7 @@ extern crate serde_json;
extern crate solana_metrics;
#[macro_use]
extern crate solana_sdk_macro_frozen_abi;
extern crate solana_frozen_abi_macro;
#[cfg(test)]
#[macro_use]

View File

@@ -79,6 +79,26 @@ solana_sdk::pubkeys!(
"GumSE5HsMV5HCwBTv2D2D81yy9x17aDkvobkqAfTRgmo",
"AzVV9ZZDxTgW4wWfJmsG6ytaHpQGSe1yz76Nyy84VbQF",
"8CUUMKYNGxdgYio5CLHRHyzMEhhVRMcqefgE6dLqnVRK",
"CQDYc4ET2mbFhVpgj41gXahL6Exn5ZoPcGAzSHuYxwmE",
"5PLJZLJiRR9vf7d1JCCg7UuWjtyN9nkab9uok6TqSyuP",
"7xJ9CLtEAcEShw9kW2gSoZkRWL566Dg12cvgzANJwbTr",
"BuCEvc9ze8UoAQwwsQLy8d447C8sA4zeVtVpc6m5wQeS",
"8ndGYFjav6NDXvzYcxs449Aub3AxYv4vYpk89zRDwgj7",
"8W58E8JVJjH1jCy5CeHJQgvwFXTyAVyesuXRZGbcSUGG",
"GNiz4Mq886bTNDT3pijGsu2gbw6it7sqrwncro45USeB",
"GhsotwFMH6XUrRLJCxcx62h7748N2Uq8mf87hUGkmPhg",
"Fgyh8EeYGZtbW8sS33YmNQnzx54WXPrJ5KWNPkCfWPot",
"8UVjvYyoqP6sqcctTso3xpCdCfgTMiv3VRh7vraC2eJk",
"BhvLngiqqKeZ8rpxch2uGjeCiC88zzewoWPRuoxpp1aS",
"63DtkW7zuARcd185EmHAkfF44bDcC2SiTSEj2spLP3iA",
"GvpCiTgq9dmEeojCDBivoLoZqc4AkbUDACpqPMwYLWKh",
"7Y8smnoUrYKGGuDq2uaFKVxJYhojgg7DVixHyAtGTYEV",
"DUS1KxwUhUyDKB4A81E8vdnTe3hSahd92Abtn9CXsEcj",
"F9MWFw8cnYVwsRq8Am1PGfFL3cQUZV37mbGoxZftzLjN",
"8vqrX3H2BYLaXVintse3gorPEM4TgTwTFZNN1Fm9TdYs",
"CUageMFi49kzoDqtdU8NvQ4Bq3sbtJygjKDAXJ45nmAi",
"5smrYwb1Hr2T8XMnvsqccTgXxuqQs14iuE8RbHFYf2Cf",
"xQadXQiUTCCFhfHjvQx1hyJK6KVWr1w2fD6DT3cdwj7",
]
);
@@ -115,7 +135,7 @@ mod tests {
let num_genesis_accounts = 10;
for _ in 0..num_genesis_accounts {
accounts.insert(
Pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
Account::new(balance, 0, &Pubkey::default()),
);
}
@@ -127,7 +147,7 @@ mod tests {
let num_stake_accounts = 3;
for _ in 0..num_stake_accounts {
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let meta = Meta {
authorized: Authorized::auto(&pubkey),
lockup: Lockup {

View File

@@ -401,7 +401,7 @@ mod test {
fn test_add_vote_pubkey() {
let mut stats = PropagatedStats::default();
let mut all_pubkeys = PubkeyReferences::default();
let mut vote_pubkey = Pubkey::new_rand();
let mut vote_pubkey = solana_sdk::pubkey::new_rand();
all_pubkeys.get_or_insert(&vote_pubkey);
// Add a vote pubkey, the number of references in all_pubkeys
@@ -420,7 +420,7 @@ mod test {
assert_eq!(stats.propagated_validators_stake, 1);
// Adding another pubkey should succeed
vote_pubkey = Pubkey::new_rand();
vote_pubkey = solana_sdk::pubkey::new_rand();
stats.add_vote_pubkey(&vote_pubkey, &mut all_pubkeys, 2);
assert!(stats.propagated_validators.contains(&vote_pubkey));
assert_eq!(stats.propagated_validators_stake, 3);
@@ -434,7 +434,7 @@ mod test {
fn test_add_node_pubkey_internal() {
let num_vote_accounts = 10;
let staked_vote_accounts = 5;
let vote_account_pubkeys: Vec<_> = std::iter::repeat_with(Pubkey::new_rand)
let vote_account_pubkeys: Vec<_> = std::iter::repeat_with(solana_sdk::pubkey::new_rand)
.take(num_vote_accounts)
.collect();
let epoch_vote_accounts: HashMap<_, _> = vote_account_pubkeys
@@ -445,7 +445,7 @@ mod test {
let mut stats = PropagatedStats::default();
let mut all_pubkeys = PubkeyReferences::default();
let mut node_pubkey = Pubkey::new_rand();
let mut node_pubkey = solana_sdk::pubkey::new_rand();
all_pubkeys.get_or_insert(&node_pubkey);
// Add a vote pubkey, the number of references in all_pubkeys
@@ -481,7 +481,7 @@ mod test {
// Adding another pubkey with same vote accounts should succeed, but stake
// shouldn't increase
node_pubkey = Pubkey::new_rand();
node_pubkey = solana_sdk::pubkey::new_rand();
stats.add_node_pubkey_internal(
&node_pubkey,
&mut all_pubkeys,
@@ -500,8 +500,8 @@ mod test {
// Adding another pubkey with different vote accounts should succeed
// and increase stake
node_pubkey = Pubkey::new_rand();
let vote_account_pubkeys: Vec<_> = std::iter::repeat_with(Pubkey::new_rand)
node_pubkey = solana_sdk::pubkey::new_rand();
let vote_account_pubkeys: Vec<_> = std::iter::repeat_with(solana_sdk::pubkey::new_rand)
.take(num_vote_accounts)
.collect();
let epoch_vote_accounts: HashMap<_, _> = vote_account_pubkeys

View File

@@ -291,7 +291,6 @@ impl ReplayStage {
&bank_forks,
&leader_schedule_cache,
&subscriptions,
rewards_recorder_sender.clone(),
&mut progress,
&mut all_pubkeys,
);
@@ -313,6 +312,7 @@ impl ReplayStage {
&mut heaviest_subtree_fork_choice,
&replay_vote_sender,
&bank_notification_sender,
&rewards_recorder_sender,
);
replay_active_banks_time.stop();
Self::report_memory(&allocated, "replay_active_banks", start);
@@ -408,7 +408,7 @@ impl ReplayStage {
&ancestors,
&descendants,
&progress,
&tower,
&mut tower,
);
select_vote_and_reset_forks_time.stop();
@@ -554,7 +554,6 @@ impl ReplayStage {
&poh_recorder,
&leader_schedule_cache,
&subscriptions,
rewards_recorder_sender.clone(),
&progress,
&retransmit_slots_sender,
&mut skipped_slots_info,
@@ -854,7 +853,6 @@ impl ReplayStage {
poh_recorder: &Arc<Mutex<PohRecorder>>,
leader_schedule_cache: &Arc<LeaderScheduleCache>,
subscriptions: &Arc<RpcSubscriptions>,
rewards_recorder_sender: Option<RewardsRecorderSender>,
progress_map: &ProgressMap,
retransmit_slots_sender: &RetransmitSlotsSender,
skipped_slots_info: &mut SkippedSlotsInfo,
@@ -953,7 +951,6 @@ impl ReplayStage {
poh_slot,
root_slot,
my_pubkey,
&rewards_recorder_sender,
subscriptions,
);
@@ -1265,6 +1262,7 @@ impl ReplayStage {
heaviest_subtree_fork_choice: &mut HeaviestSubtreeForkChoice,
replay_vote_sender: &ReplayVoteSender,
bank_notification_sender: &Option<BankNotificationSender>,
rewards_recorder_sender: &Option<RewardsRecorderSender>,
) -> bool {
let mut did_complete_bank = false;
let mut tx_count = 0;
@@ -1340,6 +1338,8 @@ impl ReplayStage {
.send(BankNotification::Frozen(bank.clone()))
.unwrap_or_else(|err| warn!("bank_notification_sender failed: {:?}", err));
}
Self::record_rewards(&bank, &rewards_recorder_sender);
} else {
trace!(
"bank {} not completed tick_height: {}, max_tick_height: {}",
@@ -1525,7 +1525,7 @@ impl ReplayStage {
ancestors: &HashMap<u64, HashSet<u64>>,
descendants: &HashMap<u64, HashSet<u64>>,
progress: &ProgressMap,
tower: &Tower,
tower: &mut Tower,
) -> SelectVoteAndResetForkResult {
// Try to vote on the actual heaviest fork. If the heaviest bank is
// locked out or fails the threshold check, the validator will:
@@ -1552,7 +1552,7 @@ impl ReplayStage {
.epoch_vote_accounts(heaviest_bank.epoch())
.expect("Bank epoch vote accounts must contain entry for the bank's own epoch"),
);
if switch_fork_decision == SwitchForkDecision::FailedSwitchThreshold {
if let SwitchForkDecision::FailedSwitchThreshold(_, _) = switch_fork_decision {
// If we can't switch, then reset to the the next votable
// bank on the same fork as our last vote, but don't vote
info!(
@@ -1601,7 +1601,7 @@ impl ReplayStage {
if !is_locked_out
&& vote_threshold
&& propagation_confirmed
&& switch_fork_decision != SwitchForkDecision::FailedSwitchThreshold
&& switch_fork_decision.can_vote()
{
info!("voting: {} {}", bank.slot(), fork_weight);
SelectVoteAndResetForkResult {
@@ -1817,7 +1817,6 @@ impl ReplayStage {
bank_forks: &RwLock<BankForks>,
leader_schedule_cache: &Arc<LeaderScheduleCache>,
subscriptions: &Arc<RpcSubscriptions>,
rewards_recorder_sender: Option<RewardsRecorderSender>,
progress: &mut ProgressMap,
all_pubkeys: &mut PubkeyReferences,
) {
@@ -1863,7 +1862,6 @@ impl ReplayStage {
child_slot,
forks.root(),
&leader,
&rewards_recorder_sender,
subscriptions,
);
let empty: Vec<&Pubkey> = vec![];
@@ -1891,21 +1889,18 @@ impl ReplayStage {
slot: u64,
root_slot: u64,
leader: &Pubkey,
rewards_recorder_sender: &Option<RewardsRecorderSender>,
subscriptions: &Arc<RpcSubscriptions>,
) -> Bank {
subscriptions.notify_slot(slot, parent.slot(), root_slot);
let child_bank = Bank::new_from_parent(parent, leader, slot);
Self::record_rewards(&child_bank, &rewards_recorder_sender);
child_bank
Bank::new_from_parent(parent, leader, slot)
}
fn record_rewards(bank: &Bank, rewards_recorder_sender: &Option<RewardsRecorderSender>) {
if let Some(rewards_recorder_sender) = rewards_recorder_sender {
if let Some(ref rewards) = bank.rewards {
let rewards = bank.rewards.read().unwrap();
if !rewards.is_empty() {
rewards_recorder_sender
.send((bank.slot(), rewards.iter().copied().collect()))
.send((bank.slot(), rewards.clone()))
.unwrap_or_else(|err| warn!("rewards_recorder_sender failed: {:?}", err));
}
}
@@ -2155,7 +2150,6 @@ pub(crate) mod tests {
&bank_forks,
&leader_schedule_cache,
&rpc_subscriptions,
None,
&mut progress,
&mut PubkeyReferences::default(),
);
@@ -2179,7 +2173,6 @@ pub(crate) mod tests {
&bank_forks,
&leader_schedule_cache,
&rpc_subscriptions,
None,
&mut progress,
&mut PubkeyReferences::default(),
);
@@ -2561,7 +2554,7 @@ pub(crate) mod tests {
bank.store_account(&pubkey, &leader_vote_account);
}
let leader_pubkey = Pubkey::new_rand();
let leader_pubkey = solana_sdk::pubkey::new_rand();
let leader_lamports = 3;
let genesis_config_info =
create_genesis_config_with_leader(50, &leader_pubkey, leader_lamports);
@@ -2603,7 +2596,11 @@ pub(crate) mod tests {
.is_none());
let bank1 = Bank::new_from_parent(&arc_bank0, &Pubkey::default(), arc_bank0.slot() + 1);
let _res = bank1.transfer(10, &genesis_config_info.mint_keypair, &Pubkey::new_rand());
let _res = bank1.transfer(
10,
&genesis_config_info.mint_keypair,
&solana_sdk::pubkey::new_rand(),
);
for _ in 0..genesis_config.ticks_per_slot {
bank1.register_tick(&Hash::default());
}
@@ -2619,7 +2616,11 @@ pub(crate) mod tests {
);
let bank2 = Bank::new_from_parent(&arc_bank1, &Pubkey::default(), arc_bank1.slot() + 1);
let _res = bank2.transfer(10, &genesis_config_info.mint_keypair, &Pubkey::new_rand());
let _res = bank2.transfer(
10,
&genesis_config_info.mint_keypair,
&solana_sdk::pubkey::new_rand(),
);
for _ in 0..genesis_config.ticks_per_slot {
bank2.register_tick(&Hash::default());
}

View File

@@ -504,7 +504,6 @@ mod tests {
use solana_ledger::genesis_utils::{create_genesis_config, GenesisConfigInfo};
use solana_net_utils::find_available_port_in_range;
use solana_perf::packet::{Meta, Packet, Packets};
use solana_sdk::pubkey::Pubkey;
use std::net::{IpAddr, Ipv4Addr};
#[test]
@@ -521,7 +520,7 @@ mod tests {
let leader_schedule_cache = Arc::new(cached_leader_schedule);
let bank_forks = Arc::new(RwLock::new(bank_forks));
let mut me = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
let mut me = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
let port = find_available_port_in_range(ip_addr, (8000, 10000)).unwrap();
let me_retransmit = UdpSocket::bind(format!("127.0.0.1:{}", port)).unwrap();
@@ -533,7 +532,7 @@ mod tests {
.local_addr()
.unwrap();
let other = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
let other = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
let cluster_info = ClusterInfo::new_with_invalid_keypair(other);
cluster_info.insert_info(me);

View File

@@ -54,6 +54,7 @@ impl RewardsRecorderService {
pubkey: pubkey.to_string(),
lamports: reward_info.lamports,
post_balance: reward_info.post_balance,
reward_type: Some(reward_info.reward_type),
})
.collect();

View File

@@ -5,7 +5,6 @@ use crate::{
contact_info::ContactInfo,
non_circulating_supply::calculate_non_circulating_supply,
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
rpc_error::RpcCustomError,
rpc_health::*,
send_transaction_service::{SendTransactionService, TransactionInfo},
validator::ValidatorExit,
@@ -23,6 +22,7 @@ use solana_account_decoder::{
};
use solana_client::{
rpc_config::*,
rpc_custom_error::RpcCustomError,
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
rpc_request::{
TokenAccountsFilter, DELINQUENT_VALIDATOR_SLOT_DISTANCE, MAX_GET_CONFIRMED_BLOCKS_RANGE,
@@ -35,6 +35,7 @@ use solana_client::{
};
use solana_faucet::faucet::request_airdrop_transaction;
use solana_ledger::{blockstore::Blockstore, blockstore_db::BlockstoreError, get_tmp_ledger_path};
use solana_metrics::inc_new_counter_info;
use solana_perf::packet::PACKET_DATA_SIZE;
use solana_runtime::{
accounts::AccountAddressFilter,
@@ -548,9 +549,6 @@ impl JsonRpcRequestProcessor {
} else {
0
};
let epoch_vote_account = epoch_vote_accounts
.iter()
.any(|(epoch_vote_pubkey, _)| epoch_vote_pubkey == pubkey);
RpcVoteAccountInfo {
vote_pubkey: (pubkey).to_string(),
node_pubkey: vote_state.node_pubkey.to_string(),
@@ -558,7 +556,7 @@ impl JsonRpcRequestProcessor {
commission: vote_state.commission,
root_slot: vote_state.root_slot.unwrap_or(0),
epoch_credits: vote_state.epoch_credits().clone(),
epoch_vote_account,
epoch_vote_account: epoch_vote_accounts.contains_key(pubkey),
last_vote,
}
})
@@ -2609,6 +2607,7 @@ fn deserialize_transaction(
) -> Result<(Vec<u8>, Transaction)> {
let wire_transaction = match encoding {
UiTransactionEncoding::Base58 => {
inc_new_counter_info!("rpc-base58_encoded_tx", 1);
if encoded_transaction.len() > WORST_CASE_BASE58_TX {
return Err(Error::invalid_params(format!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
@@ -2622,6 +2621,7 @@ fn deserialize_transaction(
.map_err(|e| Error::invalid_params(format!("{:?}", e)))?
}
UiTransactionEncoding::Base64 => {
inc_new_counter_info!("rpc-base64_encoded_tx", 1);
if encoded_transaction.len() > WORST_CASE_BASE64_TX {
return Err(Error::invalid_params(format!(
"encoded transaction too large: {} bytes (max: encoded/raw {}/{})",
@@ -2904,7 +2904,7 @@ pub mod tests {
#[test]
fn test_rpc_request_processor_new() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let genesis = create_genesis_config(100);
let bank = Arc::new(Bank::new(&genesis.genesis_config));
bank.transfer(20, &genesis.mint_keypair, &bob_pubkey)
@@ -2964,7 +2964,7 @@ pub mod tests {
#[test]
fn test_rpc_get_cluster_nodes() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -2991,7 +2991,7 @@ pub mod tests {
#[test]
fn test_rpc_get_recent_performance_samples() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getRecentPerformanceSamples"}"#;
@@ -3020,7 +3020,7 @@ pub mod tests {
#[test]
fn test_rpc_get_recent_performance_samples_invalid_limit() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req =
@@ -3046,7 +3046,7 @@ pub mod tests {
#[test]
fn test_rpc_get_slot_leader() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -3066,7 +3066,7 @@ pub mod tests {
#[test]
fn test_rpc_get_tx_count() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let genesis = create_genesis_config(10);
let bank = Arc::new(Bank::new(&genesis.genesis_config));
// Add 4 transactions
@@ -3096,7 +3096,7 @@ pub mod tests {
#[test]
fn test_rpc_minimum_ledger_slot() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"minimumLedgerSlot"}"#;
@@ -3111,7 +3111,7 @@ pub mod tests {
#[test]
fn test_rpc_get_total_supply() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getTotalSupply"}"#;
@@ -3136,7 +3136,7 @@ pub mod tests {
#[test]
fn test_get_supply() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getSupply"}"#;
let res = io.handle_request_sync(&req, meta);
@@ -3161,7 +3161,7 @@ pub mod tests {
#[test]
fn test_get_largest_accounts() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io, meta, alice, ..
} = start_rpc_handler_with_tx(&bob_pubkey);
@@ -3220,7 +3220,7 @@ pub mod tests {
#[test]
fn test_rpc_get_minimum_balance_for_rent_exemption() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let data_len = 50;
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
@@ -3252,7 +3252,7 @@ pub mod tests {
#[test]
fn test_rpc_get_inflation() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getInflationGovernor"}"#;
@@ -3299,7 +3299,7 @@ pub mod tests {
#[test]
fn test_rpc_get_epoch_schedule() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getEpochSchedule"}"#;
@@ -3321,7 +3321,7 @@ pub mod tests {
#[test]
fn test_rpc_get_leader_schedule() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
for req in [
@@ -3377,7 +3377,7 @@ pub mod tests {
#[test]
fn test_rpc_get_account_info() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = format!(
@@ -3405,7 +3405,7 @@ pub mod tests {
.expect("actual response deserialization");
assert_eq!(expected, result);
let address = Pubkey::new_rand();
let address = solana_sdk::pubkey::new_rand();
let data = vec![1, 2, 3, 4, 5];
let mut account = Account::new(42, 5, &Pubkey::default());
account.data = data.clone();
@@ -3459,7 +3459,7 @@ pub mod tests {
#[test]
fn test_rpc_get_multiple_accounts() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let address = Pubkey::new(&[9; 32]);
@@ -3586,7 +3586,7 @@ pub mod tests {
..
} = start_rpc_handler_with_tx(&bob.pubkey());
let new_program_id = Pubkey::new_rand();
let new_program_id = solana_sdk::pubkey::new_rand();
let tx = system_transaction::assign(&bob, blockhash, &new_program_id);
bank.process_transaction(&tx).unwrap();
let req = format!(
@@ -3633,7 +3633,7 @@ pub mod tests {
bank.process_transaction(&tx).unwrap();
let nonce_keypair1 = Keypair::new();
let authority = Pubkey::new_rand();
let authority = solana_sdk::pubkey::new_rand();
let instruction = system_instruction::create_nonce_account(
&alice.pubkey(),
&nonce_keypair1.pubkey(),
@@ -3776,7 +3776,7 @@ pub mod tests {
#[test]
fn test_rpc_simulate_transaction() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -3877,7 +3877,7 @@ pub mod tests {
#[test]
#[should_panic]
fn test_rpc_simulate_transaction_panic_on_unfrozen_bank() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -3903,7 +3903,7 @@ pub mod tests {
#[test]
fn test_rpc_confirm_tx() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -3935,7 +3935,7 @@ pub mod tests {
#[test]
fn test_rpc_get_signature_status() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -4005,7 +4005,7 @@ pub mod tests {
#[test]
fn test_rpc_get_signature_statuses() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -4061,7 +4061,7 @@ pub mod tests {
#[test]
fn test_rpc_get_recent_blockhash() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -4092,7 +4092,7 @@ pub mod tests {
#[test]
fn test_rpc_get_fees() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -4124,7 +4124,7 @@ pub mod tests {
#[test]
fn test_rpc_get_fee_calculator_for_blockhash() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let (blockhash, fee_calculator) = bank.last_blockhash_with_fee_calculator();
@@ -4172,7 +4172,7 @@ pub mod tests {
#[test]
fn test_rpc_get_fee_rate_governor() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getFeeRateGovernor"}"#;
@@ -4201,7 +4201,7 @@ pub mod tests {
#[test]
fn test_rpc_fail_request_airdrop() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
// Expect internal error because no faucet is available
@@ -4271,8 +4271,12 @@ pub mod tests {
);
SendTransactionService::new(tpu_address, &bank_forks, None, receiver);
let mut bad_transaction =
system_transaction::transfer(&mint_keypair, &Pubkey::new_rand(), 42, Hash::default());
let mut bad_transaction = system_transaction::transfer(
&mint_keypair,
&solana_sdk::pubkey::new_rand(),
42,
Hash::default(),
);
// sendTransaction will fail because the blockhash is invalid
let req = format!(
@@ -4302,8 +4306,12 @@ pub mod tests {
r#"{"jsonrpc":"2.0","error":{"code":-32002,"message":"Transaction simulation failed: Transaction failed to sanitize accounts offsets correctly","data":{"err":"SanitizeFailure","logs":[]}},"id":1}"#.to_string(),
)
);
let mut bad_transaction =
system_transaction::transfer(&mint_keypair, &Pubkey::new_rand(), 42, recent_blockhash);
let mut bad_transaction = system_transaction::transfer(
&mint_keypair,
&solana_sdk::pubkey::new_rand(),
42,
recent_blockhash,
);
// sendTransaction will fail due to poor node health
health.stub_set_health_status(Some(RpcHealthStatus::Behind));
@@ -4386,7 +4394,7 @@ pub mod tests {
#[test]
fn test_rpc_verify_pubkey() {
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
assert_eq!(verify_pubkey(pubkey.to_string()).unwrap(), pubkey);
let bad_pubkey = "a1b2c3d4";
assert_eq!(
@@ -4397,7 +4405,12 @@ pub mod tests {
#[test]
fn test_rpc_verify_signature() {
let tx = system_transaction::transfer(&Keypair::new(), &Pubkey::new_rand(), 20, hash(&[0]));
let tx = system_transaction::transfer(
&Keypair::new(),
&solana_sdk::pubkey::new_rand(),
20,
hash(&[0]),
);
assert_eq!(
verify_signature(&tx.signatures[0].to_string()).unwrap(),
tx.signatures[0]
@@ -4489,7 +4502,7 @@ pub mod tests {
#[test]
fn test_rpc_get_identity() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getIdentity"}"#;
@@ -4510,7 +4523,7 @@ pub mod tests {
#[test]
fn test_rpc_get_version() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getVersion"}"#;
@@ -4597,7 +4610,7 @@ pub mod tests {
#[test]
fn test_rpc_get_block_commitment() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -4651,7 +4664,7 @@ pub mod tests {
#[test]
fn test_get_confirmed_block() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let RpcHandler {
io,
meta,
@@ -4749,7 +4762,7 @@ pub mod tests {
#[test]
fn test_get_confirmed_blocks() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let roots = vec![0, 1, 3, 4, 8];
let RpcHandler {
io,
@@ -4826,7 +4839,7 @@ pub mod tests {
#[test]
fn test_get_confirmed_blocks_with_limit() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let roots = vec![0, 1, 3, 4, 8];
let RpcHandler {
io,
@@ -4889,7 +4902,7 @@ pub mod tests {
#[test]
fn test_get_block_time() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let base_timestamp = 1_576_183_541;
let RpcHandler {
io,
@@ -4976,7 +4989,7 @@ pub mod tests {
leader_vote_keypair,
block_commitment_cache,
..
} = start_rpc_handler_with_tx(&Pubkey::new_rand());
} = start_rpc_handler_with_tx(&solana_sdk::pubkey::new_rand());
assert_eq!(bank.vote_accounts().len(), 1);
@@ -5192,7 +5205,8 @@ pub mod tests {
#[test]
fn test_token_rpcs() {
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand());
let RpcHandler { io, meta, bank, .. } =
start_rpc_handler_with_tx(&solana_sdk::pubkey::new_rand());
let mut account_data = vec![0; TokenAccount::get_packed_len()];
let mint = SplTokenPubkey::new(&[2; 32]);
@@ -5215,7 +5229,7 @@ pub mod tests {
owner: spl_token_id_v2_0(),
..Account::default()
};
let token_account_pubkey = Pubkey::new_rand();
let token_account_pubkey = solana_sdk::pubkey::new_rand();
bank.store_account(&token_account_pubkey, &token_account);
// Add the mint
@@ -5253,7 +5267,7 @@ pub mod tests {
// Test non-existent token account
let req = format!(
r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenAccountBalance","params":["{}"]}}"#,
Pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
@@ -5278,7 +5292,7 @@ pub mod tests {
// Test non-existent mint address
let req = format!(
r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenSupply","params":["{}"]}}"#,
Pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
@@ -5286,7 +5300,7 @@ pub mod tests {
assert!(result.get("error").is_some());
// Add another token account with the same owner, delegate, and mint
let other_token_account_pubkey = Pubkey::new_rand();
let other_token_account_pubkey = solana_sdk::pubkey::new_rand();
bank.store_account(&other_token_account_pubkey, &token_account);
// Add another token account with the same owner and delegate but different mint
@@ -5309,7 +5323,7 @@ pub mod tests {
owner: spl_token_id_v2_0(),
..Account::default()
};
let token_with_different_mint_pubkey = Pubkey::new_rand();
let token_with_different_mint_pubkey = solana_sdk::pubkey::new_rand();
bank.store_account(&token_with_different_mint_pubkey, &token_account);
// Test getTokenAccountsByOwner with Token program id returns all accounts, regardless of Mint address
@@ -5390,7 +5404,7 @@ pub mod tests {
"params":["{}", {{"programId": "{}"}}]
}}"#,
owner,
Pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
@@ -5404,7 +5418,7 @@ pub mod tests {
"params":["{}", {{"mint": "{}"}}]
}}"#,
owner,
Pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
@@ -5419,7 +5433,7 @@ pub mod tests {
"method":"getTokenAccountsByOwner",
"params":["{}", {{"programId": "{}"}}]
}}"#,
Pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
spl_token_id_v2_0(),
);
let res = io.handle_request_sync(&req, meta.clone());
@@ -5473,7 +5487,7 @@ pub mod tests {
"params":["{}", {{"programId": "{}"}}]
}}"#,
delegate,
Pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
@@ -5487,7 +5501,7 @@ pub mod tests {
"params":["{}", {{"mint": "{}"}}]
}}"#,
delegate,
Pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
@@ -5502,7 +5516,7 @@ pub mod tests {
"method":"getTokenAccountsByDelegate",
"params":["{}", {{"programId": "{}"}}]
}}"#,
Pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
spl_token_id_v2_0(),
);
let res = io.handle_request_sync(&req, meta.clone());
@@ -5550,7 +5564,7 @@ pub mod tests {
owner: spl_token_id_v2_0(),
..Account::default()
};
let token_with_smaller_balance = Pubkey::new_rand();
let token_with_smaller_balance = solana_sdk::pubkey::new_rand();
bank.store_account(&token_with_smaller_balance, &token_account);
// Test largest token accounts
@@ -5588,7 +5602,8 @@ pub mod tests {
#[test]
fn test_token_parsing() {
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand());
let RpcHandler { io, meta, bank, .. } =
start_rpc_handler_with_tx(&solana_sdk::pubkey::new_rand());
let mut account_data = vec![0; TokenAccount::get_packed_len()];
let mint = SplTokenPubkey::new(&[2; 32]);
@@ -5611,7 +5626,7 @@ pub mod tests {
owner: spl_token_id_v2_0(),
..Account::default()
};
let token_account_pubkey = Pubkey::new_rand();
let token_account_pubkey = solana_sdk::pubkey::new_rand();
bank.store_account(&token_account_pubkey, &token_account);
// Add the mint

View File

@@ -505,7 +505,7 @@ mod tests {
mint_keypair: alice,
..
} = create_genesis_config(10_000);
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let bank = Bank::new(&genesis_config);
let blockhash = bank.last_blockhash();
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
@@ -551,7 +551,7 @@ mod tests {
..
} = create_genesis_config(10_000);
let new_stake_authority = Pubkey::new_rand();
let new_stake_authority = solana_sdk::pubkey::new_rand();
let stake_authority = Keypair::new();
let from = Keypair::new();
let stake_account = Keypair::new();
@@ -748,7 +748,7 @@ mod tests {
#[test]
#[serial]
fn test_account_unsubscribe() {
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let session = create_session();
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config))));

View File

@@ -550,7 +550,11 @@ mod tests {
let cluster_info = Arc::new(ClusterInfo::default());
let health_check_slot_distance = 123;
let override_health_check = Arc::new(AtomicBool::new(false));
let trusted_validators = vec![Pubkey::new_rand(), Pubkey::new_rand(), Pubkey::new_rand()];
let trusted_validators = vec![
solana_sdk::pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
];
let health = Arc::new(RpcHealth::new(
cluster_info.clone(),
@@ -566,6 +570,7 @@ mod tests {
// No account hashes for any trusted validators == "behind"
cluster_info.push_accounts_hashes(vec![(1000, Hash::default()), (900, Hash::default())]);
cluster_info.flush_push_queue();
assert_eq!(rm.health_check(), "behind");
override_health_check.store(true, Ordering::Relaxed);
assert_eq!(rm.health_check(), "ok");

View File

@@ -1249,8 +1249,11 @@ pub(crate) mod tests {
.process_transaction(&past_bank_tx)
.unwrap();
let next_bank =
Bank::new_from_parent(&bank_forks.banks[&0].clone(), &Pubkey::new_rand(), 1);
let next_bank = Bank::new_from_parent(
&bank_forks.banks[&0].clone(),
&solana_sdk::pubkey::new_rand(),
1,
);
bank_forks.insert(next_bank);
bank_forks

View File

@@ -396,7 +396,7 @@ impl ServeRepair {
cache.insert(slot, (repair_peers, weights));
}
let (repair_peers, weights) = cache.get(&slot).unwrap();
let n = weighted_best(&weights, Pubkey::new_rand().to_bytes());
let n = weighted_best(&weights, solana_sdk::pubkey::new_rand().to_bytes());
let addr = repair_peers[n].serve_repair; // send the request to the peer's serve_repair port
let repair_peer_id = repair_peers[n].id;
let out = self.map_repair_request(
@@ -419,7 +419,7 @@ impl ServeRepair {
return Err(ClusterInfoError::NoPeers.into());
}
let weights = cluster_slots.compute_weights_exclude_noncomplete(slot, &repair_peers);
let n = weighted_best(&weights, Pubkey::new_rand().to_bytes());
let n = weighted_best(&weights, solana_sdk::pubkey::new_rand().to_bytes());
Ok((repair_peers[n].id, repair_peers[n].serve_repair))
}
@@ -678,7 +678,7 @@ mod tests {
{
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let me = ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
gossip: socketaddr!("127.0.0.1:1234"),
tvu: socketaddr!("127.0.0.1:1235"),
tvu_forwards: socketaddr!("127.0.0.1:1236"),
@@ -748,7 +748,7 @@ mod tests {
#[test]
fn window_index_request() {
let cluster_slots = ClusterSlots::default();
let me = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
let me = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(me));
let serve_repair = ServeRepair::new(cluster_info.clone());
let rv = serve_repair.repair_request(
@@ -762,7 +762,7 @@ mod tests {
let serve_repair_addr = socketaddr!([127, 0, 0, 1], 1243);
let nxt = ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
gossip: socketaddr!([127, 0, 0, 1], 1234),
tvu: socketaddr!([127, 0, 0, 1], 1235),
tvu_forwards: socketaddr!([127, 0, 0, 1], 1236),
@@ -791,7 +791,7 @@ mod tests {
let serve_repair_addr2 = socketaddr!([127, 0, 0, 2], 1243);
let nxt = ContactInfo {
id: Pubkey::new_rand(),
id: solana_sdk::pubkey::new_rand(),
gossip: socketaddr!([127, 0, 0, 1], 1234),
tvu: socketaddr!([127, 0, 0, 1], 1235),
tvu_forwards: socketaddr!([127, 0, 0, 1], 1236),
@@ -967,12 +967,14 @@ mod tests {
#[test]
fn test_repair_with_repair_validators() {
let cluster_slots = ClusterSlots::default();
let me = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
let me = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(me.clone()));
// Insert two peers on the network
let contact_info2 = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
let contact_info3 = ContactInfo::new_localhost(&Pubkey::new_rand(), timestamp());
let contact_info2 =
ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
let contact_info3 =
ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), timestamp());
cluster_info.insert_info(contact_info2.clone());
cluster_info.insert_info(contact_info3.clone());
let serve_repair = ServeRepair::new(cluster_info);
@@ -981,7 +983,7 @@ mod tests {
// 1) repair validator set doesn't exist in gossip
// 2) repair validator set only includes our own id
// then no repairs should be generated
for pubkey in &[Pubkey::new_rand(), me.id] {
for pubkey in &[solana_sdk::pubkey::new_rand(), me.id] {
let trusted_validators = Some(vec![*pubkey].into_iter().collect());
assert!(serve_repair.repair_peers(&trusted_validators, 1).is_empty());
assert!(serve_repair

View File

@@ -66,7 +66,7 @@ impl TestValidator {
mint_lamports,
&contact_info.id,
&Keypair::new(),
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
42,
bootstrap_validator_lamports,
solana_sdk::genesis_config::ClusterType::Development,

View File

@@ -56,6 +56,7 @@ impl TransactionStatusService {
statuses,
balances,
inner_instructions,
transaction_logs,
} = write_transaction_status_receiver.recv_timeout(Duration::from_secs(1))?;
let slot = bank.slot();
@@ -65,12 +66,14 @@ impl TransactionStatusService {
pre_balances,
post_balances,
inner_instructions,
log_messages,
) in izip!(
OrderedIterator::new(&transactions, iteration_order.as_deref()),
statuses,
balances.pre_balances,
balances.post_balances,
inner_instructions
inner_instructions,
transaction_logs
) {
if Bank::can_commit(&status) && !transaction.signatures.is_empty() {
let fee_calculator = match hash_age_kind {
@@ -96,6 +99,8 @@ impl TransactionStatusService {
.collect()
});
let log_messages = Some(log_messages);
blockstore
.write_transaction_status(
slot,
@@ -108,6 +113,7 @@ impl TransactionStatusService {
pre_balances,
post_balances,
inner_instructions,
log_messages,
},
)
.expect("Expect database write to succeed");

View File

@@ -2,12 +2,11 @@
use crate::{
broadcast_stage::BroadcastStageType,
builtins,
cache_block_time_service::{CacheBlockTimeSender, CacheBlockTimeService},
cluster_info::{ClusterInfo, Node},
cluster_info_vote_listener::VoteTracker,
completed_data_sets_service::CompletedDataSetsService,
consensus::{reconcile_blockstore_roots_with_tower, Tower, TowerError},
consensus::{reconcile_blockstore_roots_with_tower, Tower},
contact_info::ContactInfo,
gossip_service::GossipService,
optimistically_confirmed_bank_tracker::{
@@ -369,19 +368,6 @@ impl Validator {
leader_schedule_cache.slot_leader_at(bank.slot(), Some(&bank))
);
if config.dev_halt_at_slot.is_some() {
// Simulate a confirmed root to avoid RPC errors with CommitmentConfig::max() and
// to ensure RPC endpoints like getConfirmedBlock, which require a confirmed root, work
block_commitment_cache
.write()
.unwrap()
.set_highest_confirmed_root(bank_forks.read().unwrap().root());
// Park with the RPC service running, ready for inspection!
warn!("Validator halted");
std::thread::park();
}
let poh_config = Arc::new(genesis_config.poh_config.clone());
let (mut poh_recorder, entry_receiver) = PohRecorder::new_with_clear_signal(
bank.tick_height(),
@@ -411,11 +397,10 @@ impl Validator {
if let Some((rpc_addr, rpc_pubsub_addr, rpc_banks_addr)) = config.rpc_addrs {
if ContactInfo::is_valid_address(&node.info.rpc) {
assert!(ContactInfo::is_valid_address(&node.info.rpc_pubsub));
assert_eq!(rpc_addr.port(), node.info.rpc.port());
assert_eq!(rpc_pubsub_addr.port(), node.info.rpc_pubsub.port());
assert_eq!(rpc_banks_addr.port(), node.info.rpc_banks.port());
assert!(ContactInfo::is_valid_address(&node.info.rpc_banks));
} else {
assert!(!ContactInfo::is_valid_address(&node.info.rpc_pubsub));
assert!(!ContactInfo::is_valid_address(&node.info.rpc_banks));
}
let tpu_address = cluster_info.my_contact_info().tpu;
let (bank_notification_sender, bank_notification_receiver) = unbounded();
@@ -465,6 +450,19 @@ impl Validator {
(None, None)
};
if config.dev_halt_at_slot.is_some() {
// Simulate a confirmed root to avoid RPC errors with CommitmentConfig::max() and
// to ensure RPC endpoints like getConfirmedBlock, which require a confirmed root, work
block_commitment_cache
.write()
.unwrap()
.set_highest_confirmed_root(bank_forks.read().unwrap().root());
// Park with the RPC service running, ready for inspection!
warn!("Validator halted");
std::thread::park();
}
let ip_echo_server = solana_net_utils::ip_echo_server(node.sockets.ip_echo.unwrap());
let gossip_service = GossipService::new(
@@ -731,12 +729,7 @@ fn post_process_restored_tower(
.unwrap_or_else(|err| {
let voting_has_been_active =
active_vote_account_exists_in_bank(&bank_forks.working_bank(), &vote_account);
let saved_tower_is_missing = if let TowerError::IOError(io_err) = &err {
io_err.kind() == std::io::ErrorKind::NotFound
} else {
false
};
if !saved_tower_is_missing {
if !err.is_file_missing() {
datapoint_error!(
"tower_error",
(
@@ -750,11 +743,11 @@ fn post_process_restored_tower(
error!("Requested mandatory tower restore failed: {}", err);
error!(
"And there is an existing vote_account containing actual votes. \
Aborting due to possible conflicting duplicate votes"
Aborting due to possible conflicting duplicate votes",
);
process::exit(1);
}
if saved_tower_is_missing && !voting_has_been_active {
if err.is_file_missing() && !voting_has_been_active {
// Currently, don't protect against spoofed snapshots with no tower at all
info!(
"Ignoring expected failed tower restore because this is the initial \
@@ -839,7 +832,6 @@ fn new_banks_from_ledger(
new_hard_forks: config.new_hard_forks.clone(),
frozen_accounts: config.frozen_accounts.clone(),
debug_keys: config.debug_keys.clone(),
additional_builtins: Some(builtins::get(genesis_config.cluster_type)),
..blockstore_processor::ProcessOptions::default()
};
@@ -941,8 +933,8 @@ fn backup_and_clear_blockstore(ledger_path: &Path, start_slot: Slot, shred_versi
let end_slot = last_slot.unwrap();
info!("Purging slots {} to {}", start_slot, end_slot);
blockstore.purge_slots(start_slot, end_slot, PurgeType::Exact);
blockstore.purge_from_next_slots(start_slot, end_slot);
blockstore.purge_slots(start_slot, end_slot, PurgeType::Exact);
info!("Purging done, compacting db..");
if let Err(e) = blockstore.compact_storage(start_slot, end_slot) {
warn!(

View File

@@ -59,11 +59,10 @@ mod tests {
use crate::result::Error;
use crossbeam_channel::{unbounded, RecvTimeoutError};
use solana_perf::packet::{Meta, Packet};
use solana_sdk::pubkey::Pubkey;
#[test]
fn test_get_latest_votes() {
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let label1 = CrdsValueLabel::Vote(0 as u8, pubkey);
let label2 = CrdsValueLabel::Vote(1 as u8, pubkey);
let mut verified_vote_packets = VerifiedVotePackets(HashMap::new());
@@ -107,7 +106,7 @@ mod tests {
#[test]
fn test_get_and_process_vote_packets() {
let (s, r) = unbounded();
let pubkey = Pubkey::new_rand();
let pubkey = solana_sdk::pubkey::new_rand();
let label1 = CrdsValueLabel::Vote(0 as u8, pubkey);
let label2 = CrdsValueLabel::Vote(1 as u8, pubkey);
let mut update_version = 0;

View File

@@ -52,7 +52,7 @@ mod test {
let total_epoch_stake = 10;
let mut vote_stake_tracker = VoteStakeTracker::default();
for i in 0..10 {
let pubkey = Arc::new(Pubkey::new_rand());
let pubkey = Arc::new(solana_sdk::pubkey::new_rand());
let (is_confirmed, is_new) =
vote_stake_tracker.add_vote_pubkey(pubkey.clone(), 1, total_epoch_stake);
let stake = vote_stake_tracker.stake();

View File

@@ -594,7 +594,7 @@ mod test {
#[test]
fn test_should_retransmit_and_persist() {
let me_id = Pubkey::new_rand();
let me_id = solana_sdk::pubkey::new_rand();
let leader_keypair = Arc::new(Keypair::new());
let leader_pubkey = leader_keypair.pubkey();
let bank = Arc::new(Bank::new(

View File

@@ -12,8 +12,7 @@ use solana_runtime::{
genesis_utils::{create_genesis_config, GenesisConfigInfo},
};
use solana_sdk::{
commitment_config::CommitmentConfig, pubkey::Pubkey, rpc_port, signature::Signer,
system_transaction,
commitment_config::CommitmentConfig, rpc_port, signature::Signer, system_transaction,
};
use std::{
fs::remove_dir_all,
@@ -38,7 +37,7 @@ fn test_rpc_client() {
ledger_path,
..
} = TestValidator::run();
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let client = RpcClient::new_socket(leader_data.rpc);

View File

@@ -72,7 +72,7 @@ fn run_simulation(stakes: &[u64], fanout: usize) {
let timeout = 60 * 5;
// describe the leader
let leader_info = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
let leader_info = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
let cluster_info = ClusterInfo::new_with_invalid_keypair(leader_info.clone());
// setup staked nodes
@@ -95,7 +95,7 @@ fn run_simulation(stakes: &[u64], fanout: usize) {
chunk.iter().for_each(|i| {
//distribute neighbors across threads to maximize parallel compute
let batch_ix = *i as usize % batches.len();
let node = ContactInfo::new_localhost(&Pubkey::new_rand(), 0);
let node = ContactInfo::new_localhost(&solana_sdk::pubkey::new_rand(), 0);
staked_nodes.insert(node.id, stakes[*i - 1]);
cluster_info.insert_info(node.clone());
let (s, r) = channel();

View File

@@ -77,13 +77,13 @@ fn stakes(network: &Network) -> HashMap<Pubkey, u64> {
fn star_network_create(num: usize) -> Network {
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let mut network: HashMap<_, _> = (1..num)
.map(|_| {
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let id = new.label().pubkey();
@@ -104,7 +104,7 @@ fn star_network_create(num: usize) -> Network {
fn rstar_network_create(num: usize) -> Network {
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let mut origin = CrdsGossip::default();
@@ -114,7 +114,7 @@ fn rstar_network_create(num: usize) -> Network {
let mut network: HashMap<_, _> = (1..num)
.map(|_| {
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let id = new.label().pubkey();
@@ -133,7 +133,7 @@ fn ring_network_create(num: usize) -> Network {
let mut network: HashMap<_, _> = (0..num)
.map(|_| {
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let id = new.label().pubkey();
@@ -171,7 +171,7 @@ fn connected_staked_network_create(stakes: &[u64]) -> Network {
let mut network: HashMap<_, _> = (0..num)
.map(|n| {
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
&Pubkey::new_rand(),
&solana_sdk::pubkey::new_rand(),
0,
)));
let id = new.label().pubkey();
@@ -293,9 +293,10 @@ fn network_run_push(network: &mut Network, start: usize, end: usize) -> (usize,
let requests: Vec<_> = network_values
.par_iter()
.map(|node| {
let timeouts = node.lock().unwrap().make_timeouts_test();
node.lock().unwrap().purge(now, &timeouts);
node.lock().unwrap().new_push_messages(now)
let mut node_lock = node.lock().unwrap();
let timeouts = node_lock.make_timeouts_test();
node_lock.purge(now, &timeouts);
node_lock.new_push_messages(vec![], now)
})
.collect();
let transfered: Vec<_> = requests

View File

@@ -15,8 +15,8 @@ use solana_client::{
use solana_core::contact_info::ContactInfo;
use solana_core::{rpc_pubsub::gen_client::Client as PubsubClient, test_validator::TestValidator};
use solana_sdk::{
commitment_config::CommitmentConfig, hash::Hash, pubkey::Pubkey, signature::Signer,
system_transaction, transaction::Transaction,
commitment_config::CommitmentConfig, hash::Hash, signature::Signer, system_transaction,
transaction::Transaction,
};
use std::{
collections::HashSet,
@@ -63,7 +63,7 @@ fn test_rpc_send_tx() {
ledger_path,
..
} = TestValidator::run();
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let req = json_req!("getRecentBlockhash", json!([]));
let json = post_rpc(req, &leader_data);
@@ -128,7 +128,7 @@ fn test_rpc_invalid_requests() {
ledger_path,
..
} = TestValidator::run();
let bob_pubkey = Pubkey::new_rand();
let bob_pubkey = solana_sdk::pubkey::new_rand();
// test invalid get_balance request
let req = json_req!("getBalance", json!(["invalid9999"]));
@@ -173,7 +173,9 @@ fn test_rpc_subscriptions() {
// Create transaction signatures to subscribe to
let transactions: Vec<Transaction> = (0..1000)
.map(|_| system_transaction::transfer(&alice, &Pubkey::new_rand(), 1, genesis_hash))
.map(|_| {
system_transaction::transfer(&alice, &solana_sdk::pubkey::new_rand(), 1, genesis_hash)
})
.collect();
let mut signature_set: HashSet<String> = transactions
.iter()

View File

@@ -156,7 +156,7 @@ mod tests {
.get(&deserialized_bank.slot())
.unwrap()
.clone();
bank.compare_bank(&deserialized_bank);
assert_eq!(*bank, deserialized_bank);
let slot_snapshot_paths = snapshot_utils::get_snapshot_paths(&snapshot_path);

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-crate-features"
version = "1.4.0"
version = "1.4.2"
description = "Solana Crate Features"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -14,12 +14,11 @@ bytes = { version = "0.4.12", features = ["either"] }
cc = { version = "1.0.45", features = ["jobserver", "num_cpus", "parallel"]}
curve25519-dalek = { version = "2" }
either= { version = "1.5.2" }
failure = { version = "0.1.5" }
lazy_static = { version = "1.4.0", features = ["spin", "spin_no_std"] }
libc = { version = "0.2.62", features = ["extra_traits"] }
rand_chacha = { version = "0.2.2" }
regex-syntax = { version = "0.6.12" }
reqwest = { version = "0.10.1", default-features = false, features = ["blocking", "rustls-tls", "json"] }
reqwest = { version = "0.10.8", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde = { version = "1.0.100", features = ["rc"] }
ed25519-dalek = { version = "=1.0.0-pre.4", features = ["serde"] }
syn_0_15 = { package = "syn", version = "0.15.42", features = ["extra-traits", "fold", "full"] }

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