Compare commits

..

230 Commits

Author SHA1 Message Date
mergify[bot]
437c356626 Discard pre hard fork persisted tower if hard-forking (#13536) (#13550)
* Discard pre hard fork persisted tower if hard-forking

* Relax config.require_tower

* Add cluster test

* nits

* Remove unnecessary check

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
Co-authored-by: Carl Lin <carl@solana.com>
(cherry picked from commit 9821a7754c)

Co-authored-by: carllin <wumu727@gmail.com>
2020-11-12 15:43:43 +00:00
Michael Vines
fd68f8ba2e program-test now generates new blockhashes for test usage 2020-11-11 20:29:20 -08:00
Jack May
2374664e95 Custom heap is BPF only (#13537) 2020-11-11 16:37:18 -08:00
mergify[bot]
2cb9ca5966 Fix slow/stuck unstaking due to toggling in epoch (#13501) (#13535)
* Fix slow/stuck unstaking due to toggling in epoch

* nits

* nits

* Add stake_program_v2 feature status check to cli

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

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-11-11 22:27:10 +00:00
mergify[bot]
4f247a232f Validator: Periodically log what we're waiting for during --wait-for-supermajority (#13531)
(cherry picked from commit 38f15e41b5)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-11-11 21:29:50 +00:00
mergify[bot]
15a2c73826 Use a non-zero fee_calculator for a more realistic test environment (#13525)
(cherry picked from commit 58724cb687)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-11 09:59:57 +00:00
Josh
d23f1436c5 docs: add log messages to json-rpc docs (#13317) 2020-11-11 00:43:32 -08:00
mergify[bot]
70c87d1a23 Add stubs and heap region definitions (#13521) (#13523)
* Add stubs and heap region definitions

* nudge

(cherry picked from commit e390c8cb7f)

Co-authored-by: Jack May <jack@solana.com>
2020-11-11 06:48:02 +00:00
mergify[bot]
053ce10ce5 Refactor function (#13294) (#13520)
Co-authored-by: Carl Lin <carl@solana.com>
(cherry picked from commit 2c2432fddc)

Co-authored-by: carllin <wumu727@gmail.com>
2020-11-11 04:07:51 +00:00
mergify[bot]
055eb360c2 Add printf declaration (#13514) (#13518)
(cherry picked from commit 9ca8e98525)

Co-authored-by: Jack May <jack@solana.com>
2020-11-11 01:50:42 +00:00
mergify[bot]
25cd1ceeeb Fix parsing CreateAccountWithSeed instructions (#13513) (#13517)
* Reduce required num_system_accounts and handle 2-account instructions properly

* Update CreateAccountWithSeed account docs to be correct

* Add CreateAccountWithSeed test

(cherry picked from commit 91f4e99b4c)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-11-11 01:13:12 +00:00
mergify[bot]
52ee3b1cee watchtower: Fix all clear duration message (#13510)
(cherry picked from commit 2a96e722b4)

Co-authored-by: Justin Starry <justin@solana.com>
2020-11-10 19:11:51 +00:00
mergify[bot]
bbadcca414 Bump token version fetched for localnet (#13490) (#13506)
(cherry picked from commit 3282334741)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-11-10 18:04:15 +00:00
mergify[bot]
e9eba97299 Fix signature access (#13491) (#13503)
(cherry picked from commit 70c4626efe)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-11-10 17:53:43 +00:00
mergify[bot]
920b63944e Make testnet section less ambiguous (#13504) (#13508)
(cherry picked from commit 599dae8f09)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-11-10 17:12:57 +00:00
mergify[bot]
8104895a07 Send RPC notification when account is deleted (#13440) (#13496)
* Send RPC notification when account is deleted

* Remove unwrap

(cherry picked from commit a97c04b400)

Co-authored-by: Justin Starry <justin@solana.com>
2020-11-10 13:07:51 +00:00
Tyera Eulberg
c9e646b86b Bump version to v1.4.7 (#13488) 2020-11-10 05:55:26 +00:00
mergify[bot]
7c47db1e3d align cluster and sim logging as hex (#13484) (#13486)
(cherry picked from commit c280d40b40)

Co-authored-by: Jack May <jack@solana.com>
2020-11-10 03:58:19 +00:00
mergify[bot]
c619e9b560 Docs update rpc getaccountinfo (bp #13483) (#13487)
* docs: Wrap RPC `getAccountInfo` at 80 char

(cherry picked from commit 1d7c00c915)

* docs: Consistently use "jsonParsed" param for RPC `getAccountInfo`

(cherry picked from commit 87924c7111)

* docs: Consistent used of "jsonParsed" throughout RPC reference

(cherry picked from commit fb815294b3)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-11-10 03:41:26 +00:00
Tyera Eulberg
ccd48923a0 Fix Bank accounts hash mismatch related to Clock::unix_timestamp (#13477) (#13485)
* Test for different ancestors with mismatch bank hash

* Test cleanup

* Remove nondeterministic ancestor check

* Update timestamp bounding feature key

* Update design doc

* Filter recent_timestamps to nodes voting within the last epoch

Co-authored-by: Stephen Akridge <sakridge@gmail.com>

Co-authored-by: Stephen Akridge <sakridge@gmail.com>
2020-11-10 03:35:22 +00:00
mergify[bot]
4e797cc867 Clean up Delegation::stake_activating_and_deactivating (#13471) (#13473)
(cherry picked from commit 5306eb93cc)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-11-09 09:57:32 +00:00
mergify[bot]
9627bfced3 propagates errors out of Packet::from_data (#13445) (#13470)
Packet::from_data is ignoring serialization errors:
https://github.com/solana-labs/solana/blob/d08c3232e/sdk/src/packet.rs#L42-L48
This is likely never useful as the packet will be sent over the wire
taking bandwidth but at the receiving end will either fail to
deserialize or it will be invalid.
This commit will propagate the errors out of the function to the
call-site, allowing the call-site to handle the error.

(cherry picked from commit 73ac104df2)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-11-08 16:25:36 +00:00
mergify[bot]
f823b10597 Clean up Delegation::stake_and_activating (#13460) (#13469)
(cherry picked from commit 737d3e376d)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-11-08 09:47:47 +00:00
mergify[bot]
c9e56c9749 Output more inflation calc details in ledger-tool (#13345) (#13467)
* Output more inflation calc details in ledger-tool

* Fix broken ci...

* Rename confusing variables

* Fix panic by wrapping PointValue with Opiton...

* Minor modifications

* Remove explict needless flush; Drop already does

* Yet another csv field adjustments

* Add data_size and rename epochs to earned_epochs

* Introduce null_tracer

* Unwrap Option in new_from_parent_with_tracer

* Don't shorten identifiers

* Allow irrefutable_let_patterns temporalily

* More null_tracer

* More field adjustments

(cherry picked from commit a81e7e7749)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-11-08 09:01:36 +00:00
Michael Vines
da7482d631 Add PATH to GNU readlink 2020-11-07 11:28:28 -08:00
Michael Vines
97650c7f37 Install coreutils on osx for 'readlink -f' support 2020-11-06 23:01:32 -08:00
Michael Vines
e738bf1c9a Bump version to v1.4.6 2020-11-07 02:49:14 +00:00
Trent Nelson
afebb2a8a5 CLI: Make clear that nonce account 'Nonce' field is a blockhash
(cherry picked from commit b4790120cb)
2020-11-06 17:19:52 -08:00
mergify[bot]
4e4fd03b65 Add builtin mem tests (bp #13429) (#13437)
* Add builtin mem tests (#13429)


(cherry picked from commit 84b139cc94)

* resolve crate version

* nudge

Co-authored-by: Jack May <jack@solana.com>
2020-11-07 01:15:35 +00:00
mergify[bot]
049ca18dc5 Fix stake split rent-exempt adjustment (#13357) (#13453)
* Add failing tests

* Fix stake split

* Calculate split rent-exempt-reserve and use

* Add comment in rent.rs

* Add tests for edge cases when splitting to larger accounts, and reject overflow splits

* Reframe InsufficientFunds checks in terms of lamports var

* Test hardening review comments

(cherry picked from commit 4c5f345798)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-11-06 22:05:57 +00:00
mergify[bot]
495c64556e cargo-build-bpf/cargo-test-bpf now support --workspace/--all (#13451)
(cherry picked from commit 0ea795caa8)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-06 21:43:12 +00:00
mergify[bot]
747e91d434 Fix stake redelegate (bp #13358) (#13450)
* stake: Add redelegation failing test

(cherry picked from commit 491ad59d2e)

* stake: Consider withdraws we redelegating

(cherry picked from commit fe1e08b9ad)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-11-06 20:07:46 +00:00
mergify[bot]
6d4f6e79b0 cargo-test-bpf now sets the "test-bpf" feature for crate tests (#13447)
The feature allows for tests to distinguish between `cargo test` and
`cargo test-bpf` primarily for the purpose of excluding CPI tests that
require the system program under `cargo test`, as the path to enabling
CPI in `cargo test`-based testing is unclear

(cherry picked from commit 1a70a2a25b)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-06 19:39:18 +00:00
mergify[bot]
98e9f34704 Feature-gate stake program (#13394) (#13439)
* Add legacy stake-program handling

* Strip out duplicative legacy code

* Add feature for stake-program-fix

* Feature-deploy new stake program

* Expand comment

(cherry picked from commit 1b1d9f6b0c)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-11-06 09:25:34 +00:00
mergify[bot]
70f74174e8 program-test: Remove special case for Rent sysvar (bp #13434) (#13435)
* Revert "Include Rent in ProgramTest::start() output"

This reverts commit c3d2d2134c.

(cherry picked from commit 920cd5285a)

* Add get_rent()

(cherry picked from commit 9a1c1fbab8)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-06 05:24:44 +00:00
mergify[bot]
70985f82f1 CI: Check monorepo for consistent crate versions (bp #13431) (#13433)
* increment-cargo-version.sh: Add check subcommand

(cherry picked from commit 5d4015358a)

* CI: Check monorepo for consistent crate versions

(cherry picked from commit 7a4e293b3b)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-11-06 02:29:26 +00:00
mergify[bot]
3b2bdd9f8a Fix duplicate records of inner instructions (#13380) (#13413)
* Fix duplicate records of inner instructions

* fix tests

* fix clippy

* Remove bad_inner_instructions

(cherry picked from commit c24fbb6f8b)

Co-authored-by: Justin Starry <justin@solana.com>
2020-11-06 01:30:24 +00:00
mergify[bot]
d33ae59fbf SPL Associated Token Account plumbing (bp #13398) (#13430)
* Fetch associated-program-account

(cherry picked from commit 4d553f4879)

* Add SPL Associated Token Account Program label to explorer

(cherry picked from commit 2d24160376)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-06 00:01:31 +00:00
Michael Vines
9ead7ca11a Define BPF_OUT_DIR for program-test, also handle -- arguments better 2020-11-05 22:42:35 +00:00
Michael Vines
dbcef35f7d Search BPF_OUT_DIR for programs 2020-11-05 22:42:35 +00:00
Michael Vines
9e733d7d9b Check file modification times before strip and dump 2020-11-05 22:42:35 +00:00
Michael Vines
39f1240ec2 Cargo.lock 2020-11-05 22:42:35 +00:00
Michael Vines
fa249721fa Search for program files in 'target/deploy' 2020-11-05 22:42:35 +00:00
Michael Vines
137793cd4c Add cargo-test-bpf 2020-11-05 22:42:35 +00:00
Michael Vines
47d8608aee Remove unneeded .gitignore 2020-11-05 22:42:35 +00:00
mergify[bot]
ed410aea10 adds the missing slash in cargo path (#13424) (#13427)
(cherry picked from commit 44b12a1594)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-11-05 22:10:06 +00:00
Jon Cinque
957dfa8f73 docs: Clarify the commitment levels based on questions (#13387)
* Clarify the commitment levels based on questions

Many people have asked about what commitment levels mean, and which to
choose.  This update includes some of the language at
`sdk/src/commitment_config.rs` and a recommendation for different use
cases.

Additionally, the preflight commitment documentation was out of date,
specifying that "max" was always used, and this is no longer the case.

* Update docs/src/developing/clients/jsonrpc-api.md

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

* Update docs/src/developing/clients/jsonrpc-api.md

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

* Update docs/src/developing/clients/jsonrpc-api.md

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

* Fix typo

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
(cherry picked from commit ede891a6c6)
2020-11-05 13:25:23 -08:00
mergify[bot]
98095b6f8d drops older gossip packets when load shedding (#13364) (#13423)
Gossip drops incoming packets when overloaded:
https://github.com/solana-labs/solana/blob/f6a73098a/core/src/cluster_info.rs#L2462-L2475
However newer packets are dropped in favor of the older ones.
This is probably not ideal as newer packets are more likely to contain
more recent data, so dropping them will keep the validator state
lagging.

(cherry picked from commit 7f4debdad5)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-11-05 18:30:00 +00:00
mergify[bot]
a2c32d7d0e shares the lock on gossip when processing prune messages (#13339) (#13422)
Processing prune messages acquires an exclusive lock on gossip:
https://github.com/solana-labs/solana/blob/55b0428ff/core/src/cluster_info.rs#L1824-L1825
This can be reduced to a shared lock if active-sets are changed to use
atomic bloom filters:
https://github.com/solana-labs/solana/blob/55b0428ff/core/src/crds_gossip_push.rs#L50

(cherry picked from commit 8f0796436a)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-11-05 17:18:22 +00:00
mergify[bot]
b15d826476 Allow feature builtins to overwrite existing builtins (#13403) (#13420)
* Allow feature builtins to overwrite existing builtins

* Add feature_builtin ActivationType

* Correctly retain idempotent for replacing case

* Fix test

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
(cherry picked from commit bc62313c66)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-11-05 16:51:25 +00:00
mergify[bot]
ed97a2578d measures processing time of each kind of gossip packets (#13366) (#13418)
(cherry picked from commit 118ce47b97)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-11-05 16:46:25 +00:00
Justin Starry
89f61f0b41 Bump low end validator RAM requirement (#13406) (#13408) 2020-11-05 15:24:16 +08:00
mergify[bot]
04cc9c1148 CI: Use branch-versioned cargo throughout (#13411)
(cherry picked from commit 66c3c6c2b3)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-11-05 06:25:11 +00:00
mergify[bot]
8314ab4508 Improve invoke_signed() docs (#13405)
(cherry picked from commit 8c4995b22b)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-05 01:07:24 +00:00
mergify[bot]
3a98042753 Final program ELF is now placed in ./target/deploy/ instead of . (#13404)
(cherry picked from commit 661a935075)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-05 00:19:19 +00:00
mergify[bot]
60d316c9fd Bump spl-token and spl-memo crate versions (#13400)
Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-04 23:16:41 +00:00
mergify[bot]
e324c221a6 uses thread-pool when handling push messages (#13338) (#13395)
From runtime profiles, the majority time of solana-listen thread:
https://github.com/solana-labs/solana/blob/55b0428ff/core/src/cluster_info.rs#L2720
is spent handling push messages. The code here:
https://github.com/solana-labs/solana/blob/55b0428ff/core/src/cluster_info.rs#L2272-L2364
may utilize the idle gossip thread-pool.

(cherry picked from commit 10fa4f45ab)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-11-04 20:28:56 +00:00
mergify[bot]
61246999ac Update SPL Token exchange documentation to include associated-token-account workflow (#13397)
(cherry picked from commit 97284adabb)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-04 19:57:02 +00:00
mergify[bot]
e476dc4eaa Comment Stakes::clone_with_epoch (#13388) (#13390)
(cherry picked from commit b0d1ae1d8b)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-11-04 12:29:13 +00:00
mergify[bot]
ee18e7668b Refine transaction log count message (#13378)
(cherry picked from commit b5ef319038)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-04 06:44:49 +00:00
mergify[bot]
62db7f6562 Surface transaction logs in rpc client (#13376)
(cherry picked from commit 6d9ca0ae15)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-04 02:12:46 +00:00
mergify[bot]
2e9b501355 more informative feature error message (#13373) (#13375)
(cherry picked from commit 04c5e6cc48)

Co-authored-by: Jack May <jack@solana.com>
2020-11-04 01:35:22 +00:00
mergify[bot]
089a99f1e3 docs: Mainnet-beta totally has smart contract enabled (#13369)
(cherry picked from commit fefa297877)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-11-03 19:21:18 +00:00
mergify[bot]
57961b1d17 Update sol_log_compute_units (#13360) (#13363)
(cherry picked from commit f6a73098a4)

Co-authored-by: Jack May <jack@solana.com>
2020-11-03 17:28:44 +00:00
mergify[bot]
fe8b2b7850 Include Rent in ProgramTest::start() output (#13356)
(cherry picked from commit c3d2d2134c)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-03 03:12:17 +00:00
mergify[bot]
0bf45cbab6 Small code cleanup and typo fixes (#13325) (#13341)
* Small code cleanup and typo fixes

* Clean up calculate_points_and_credits

(cherry picked from commit 0e4509c497)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-11-02 02:42:38 +00:00
Michael Vines
5877427389 Bump version to v1.4.5 2020-11-01 17:05:45 +00:00
mergify[bot]
25141288f4 Fix typos (#13334) (#13335)
(cherry picked from commit af9a3f004e)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-11-01 07:06:46 +00:00
mergify[bot]
b28d10d46f Add bank timestamp bounding (bp #13120) (#13331)
* Add bounding feature

(cherry picked from commit 96b8aa8bd1)

* Repurpose unused as Clock::epoch_start_timestamp; add gated update

(cherry picked from commit 0049ab69fb)

* Add bounded timestamp-estimation method

(cherry picked from commit 80db6c0980)

* Use bounded timestamp-correction when feature enabled

(cherry picked from commit 90778615f6)

* Prevent block times from ever going backward

(cherry picked from commit eb2560e782)

* Sample votes from ancestors back to root

(cherry picked from commit 4260b3b416)

* Add Clock sysvar details, update struct docs

(cherry picked from commit 3a1e125ce3)

* Add design proposal and update validator-timestamp-oracle

(cherry picked from commit a3912bc084)

* Adapt to feature::create_account

Co-authored-by: Tyera Eulberg <tyera@solana.com>
Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-01 06:02:34 +00:00
mergify[bot]
b6dc48da75 Add solana-program-test crate (bp #13324) (#13329)
* MockInvokeContext::get_programs() implementation

(cherry picked from commit 8acc47ee1b)

* start_local_server() now works with Banks > 0

(cherry picked from commit fa4bab4608)

* Add solana-program-test crate

(cherry picked from commit 52a292a75b)

* rebase

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-11-01 05:43:43 +00:00
mergify[bot]
f2d929c12d Move Feature struct to solana-program (#13321)
(cherry picked from commit 4b65e32f22)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-31 20:33:35 +00:00
Michael Vines
c49b89091a cargo update -p futures-task / cargo update -p futures-util 2020-10-31 18:50:51 +00:00
Michael Vines
23fe3a86d9 Switch to dirs-next 2020-10-31 18:50:51 +00:00
Michael Vines
2f778725d6 Ignore stdweb 2020-10-31 18:50:51 +00:00
mergify[bot]
93a119a51e Print the entry type as well when checking archive (#13312) (#13314)
(cherry picked from commit bc7133d752)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-30 17:48:23 +00:00
Jack May
65a7b536c9 Update AccountInfo comments (#13302)
(cherry picked from commit 72d41e5801)
2020-10-30 08:09:37 -07:00
mergify[bot]
1281483a8c Fix tower/blockstore unsync due to external causes (#12671) (#13310)
* Fix tower/blockstore unsync due to external causes

* Add and clean up long comments

* Clean up test

* Comment about warped_slot_history

* Run test_future_tower with master-only/master-slave

* Update comments about false leader condition

(cherry picked from commit 1df15d85c3)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-30 11:47:22 +00:00
mergify[bot]
4312841433 de-mut some InvokeContext methods (bp #13301) (#13309)
* de-mut some InvokeContext methods

(cherry picked from commit da9548fd12)

* Simplify CPI interface into MessageProcessor

(cherry picked from commit 9263ae1c60)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-30 10:35:59 +00:00
mergify[bot]
b859acbfea Upgrade tarpc and tokio (bp #13293) (#13300)
* Upgrade tarpc and tokio (#13293)

(cherry picked from commit ca00197009)

# Conflicts:
#	banks-client/Cargo.toml
#	banks-interface/Cargo.toml
#	banks-server/Cargo.toml

* rebase

Co-authored-by: Greg Fitzgerald <greg@solana.com>
Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-30 08:05:27 +00:00
mergify[bot]
40a3885d3b Native/builtin programs now receive an InvokeContext (bp #13286) (#13298)
* Native/builtin programs now receive an InvokeContext

(cherry picked from commit df8dab9d2b)

* Remove MessageProcessor::loaders

(cherry picked from commit 2664a1f7ef)

* Remove Entrypoint type

(cherry picked from commit 225bed11c7)

* Remove programs clone()

(cherry picked from commit 33884d847a)

* Add sol_log_compute_units syscall

(cherry picked from commit 66e51a7363)

* Add Bank::set_bpf_compute_budget()

(cherry picked from commit 7d686b72a0)

* Rebase

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-30 07:47:17 +00:00
Alexander Meißner
36b7c2ea97 Refactors the common code of test and bench targets into the solana_runtime::bpf_test_utils module. (#13203)
(cherry picked from commit 65ee3a6bdd)
2020-10-29 22:03:09 -07:00
mergify[bot]
24bd4ff6d4 clarify comment (#13289) (#13292)
(cherry picked from commit b5c8b86e7c)

Co-authored-by: Jack May <jack@solana.com>
2020-10-29 22:38:26 +00:00
mergify[bot]
69b3f10207 move Account to solana-sdk (bp #13198) (#13269)
* move Account to solana-sdk (#13198)

(cherry picked from commit c458d4b213)

# Conflicts:
#	programs/bpf/benches/bpf_loader.rs

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
2020-10-29 19:16:52 +00:00
mergify[bot]
9922f09a1d adds more parallel processing to gossip packets handling (#12988) (#13282)
(cherry picked from commit 3738611f5c)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-10-29 16:47:37 +00:00
mergify[bot]
38a99c0c25 Disable eager rent collection for less noise (#13275) (#13280)
(cherry picked from commit 363c148dbe)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-29 15:49:02 +00:00
mergify[bot]
7031235714 excludes origin from prune set (#13204) (#13276)
On the receiving end, prune messages are ignored if the origin points to
the node itself:
https://github.com/solana-labs/solana/blob/631f029fe/core/src/crds_gossip_push.rs#L285-L295
So to avoid sending these over the wire, the requester can exclude
origin from the prune set.

(cherry picked from commit be80f6d5c5)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-10-29 14:19:06 +00:00
mergify[bot]
dfb2356a9a Update FeatureSet::active to include slot-activated (#13256) (#13263)
* Update FeatureSet::active to include slot-activated

* Clippy suggestion

(cherry picked from commit c2dbf53d76)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-29 03:42:42 +00:00
mergify[bot]
010794806a Finer grained AccountsIndex locking (#12787) (#13240)
Co-authored-by: Carl Lin <carl@solana.com>

Co-authored-by: carllin <wumu727@gmail.com>
Co-authored-by: Carl Lin <carl@solana.com>
2020-10-28 23:46:54 +00:00
mergify[bot]
6f95d5f72a Update links from sdk to program (#13248) (#13249)
(cherry picked from commit db9ddc7e5b)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-28 21:32:12 +00:00
mergify[bot]
2720b939fd Calculate accounts hash async in accounts background service (#12852) (#13244)
(cherry picked from commit 456eae6ccb)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-10-28 21:20:07 +00:00
mergify[bot]
a25c3fcf7d Add doc page on sysvar accounts (#13237) (#13246)
* Add doc page on sysvar accounts

* Update with suggestions

(cherry picked from commit 664b6125b6)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-28 21:16:10 +00:00
mergify[bot]
7cc4810174 docs: Metrics update (bp #13239) (#13241)
* docs: Remove stale metrics steps

(cherry picked from commit 4dc4fefee2)

* docs: Reference metrics envvars for each cluster

(cherry picked from commit eb597cd60f)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-28 19:46:59 +00:00
mergify[bot]
c1a55bf249 Improve final report of ledger-tool capitalization (#13232) (#13236)
(cherry picked from commit 4698ee5e4a)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-28 18:45:19 +00:00
mergify[bot]
f19778b7d9 implements ping-pong packets between nodes (#12794) (#13234)
https://hackerone.com/reports/991106

> It’s possible to use UDP gossip protocol to amplify DDoS attacks. An attacker
> can spoof IP address in UDP packet when sending PullRequest to the node.
> There's no any validation if provided source IP address is not spoofed and
> the node can send much larger PullResponse to victim's IP. As I checked,
> PullRequest is about 290 bytes, while PullResponse is about 10 kB. It means
> that amplification is about 34x. This way an attacker can easily perform DDoS
> attack both on Solana node and third-party server.
>
> To prevent it, need for example to implement ping-pong mechanism similar as
> in Ethereum: Before accepting requests from remote client needs to validate
> his IP. Local node sends Ping packet to the remote node and it needs to reply
> with Pong packet that contains hash of matching Ping packet. Content of Ping
> packet is unpredictable. If hash from Pong packet matches, local node can
> remember IP where Ping packet was sent as correct and allow further
> communication.
>
> More info:
> https://github.com/ethereum/devp2p/blob/master/discv4.md#endpoint-proof
> https://github.com/ethereum/devp2p/blob/master/discv4.md#wire-protocol

The commit adds a PingCache, which maintains records of remote nodes
which have returned a valid response to a ping message, and on-the-fly
ping messages pending a pong response from the remote node.

When handling pull-requests, those from addresses which have not passed
the ping-pong check are filtered out, and additionally ping packets are
added for addresses which need to be (re)verified.

(cherry picked from commit ae91270961)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-10-28 18:36:28 +00:00
mergify[bot]
eecdacac42 Don't hold dashmap write lock in store create (#13007) (#13230)
Co-authored-by: Carl Lin <carl@solana.com>
(cherry picked from commit c8fc0a6ba1)

Co-authored-by: carllin <wumu727@gmail.com>
2020-10-28 11:36:28 +00:00
mergify[bot]
429f130532 Switch accounts storage lock to DashMap (#12126) (#13223)
Co-authored-by: Carl Lin <carl@solana.com>
(cherry picked from commit f8d338c9cb)

Co-authored-by: carllin <wumu727@gmail.com>
2020-10-28 08:07:28 +00:00
mergify[bot]
19b9839dfc Use pico inflation for ledger-tool capitalization --enable-inflation (#13215) (#13222)
* Use pico inflation for ledger-tool capitalization --enable-inflation

* rust fmt

(cherry picked from commit 7d2962135d)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-28 07:40:21 +00:00
mergify[bot]
ad2bf3afa6 more portable install.sh (#13114) (#13220)
(cherry picked from commit 4e0d1b1d4a)

Co-authored-by: Jack May <jack@solana.com>
2020-10-28 06:45:32 +00:00
mergify[bot]
5c739ba236 Use zstd for create-snapshot (#13214) (#13218)
(cherry picked from commit 6d4c69b7c3)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-28 06:38:20 +00:00
mergify[bot]
9fac507606 Fix log (#13207) (#13211)
Co-authored-by: Carl Lin <carl@solana.com>
(cherry picked from commit f96ab5a818)

Co-authored-by: carllin <wumu727@gmail.com>
2020-10-28 03:21:01 +00:00
mergify[bot]
d5a37cb06e Parse vote instructions (#13202) (#13209)
(cherry picked from commit c4962af9eb)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-28 01:19:29 +00:00
mergify[bot]
86eb0157c0 Account for forward delay in transaction simulation (#13199) (#13201)
(cherry picked from commit 631f029fe9)

Co-authored-by: Justin Starry <justin@solana.com>
2020-10-27 18:35:43 +00:00
mergify[bot]
072dab0948 Fix pr crossing for sysvar keyed-accounts (#13189) (#13191)
(cherry picked from commit 26eba5ac7d)

Co-authored-by: Jack May <jack@solana.com>
2020-10-27 08:33:13 +00:00
mergify[bot]
e20e79f412 ignore .so files (#13188) (#13192)
(cherry picked from commit bb6ab3a62d)

Co-authored-by: Jack May <jack@solana.com>
2020-10-27 07:23:50 +00:00
mergify[bot]
f118db81ce check sysvar id for AccountInfo (#13175) (#13185)
(cherry picked from commit 322c667655)

Co-authored-by: Jack May <jack@solana.com>
2020-10-27 00:22:27 -07:00
mergify[bot]
4ecb78d303 Move KeyedAccount out of solana-program. Native programs are not supported by solana-program (bp #13159) (#13181)
* Move KeyedAccount out of solana-program.  Native programs are not supported by solana-program

(cherry picked from commit 1b343665a1)

# Conflicts:
#	programs/bpf/benches/bpf_loader.rs

* rebase

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-27 05:43:14 +00:00
mergify[bot]
0a28e40606 fix .gitignore (#13177) (#13190)
(cherry picked from commit e3c0cc980b)

Co-authored-by: Jack May <jack@solana.com>
2020-10-27 05:26:59 +00:00
mergify[bot]
4d7a5a9daf macos portable rust-bpf (#13176) (#13187)
(cherry picked from commit fc83a666fc)

Co-authored-by: Jack May <jack@solana.com>
2020-10-27 04:51:14 +00:00
mergify[bot]
64cf6b4388 Add SSH key for buildkite-agent on achille (#13183)
(cherry picked from commit ff4b34202c)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-27 03:19:32 +00:00
mergify[bot]
f334c3b895 Add Bank::get_signature_status_with_blockhash() (#13167) (#13178)
Get the signature status in O(1) time, instead of O(n) where
n is the number of blockhashes in the StatusCache.

(cherry picked from commit f58bc8589d)

Co-authored-by: Greg Fitzgerald <greg@solana.com>
2020-10-27 01:29:16 +00:00
Michael Vines
15a7bcd4fe Delete .lib.rs.swo 2020-10-26 16:01:43 -07:00
mergify[bot]
8d6636d02a CLI: Surface deploy transaction errors (#13170)
(cherry picked from commit a82971879f)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-26 22:43:32 +00:00
mergify[bot]
cf896dbeee Use bank timestamp to populate Blockstore::blocktime_cf when correction active (#13158) (#13160)
(cherry picked from commit 39686ef098)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-26 20:34:15 +00:00
mergify[bot]
e5b60b75f8 Docs: Testnet has a faucet now (#13165)
(cherry picked from commit 8b1638f026)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-10-26 20:28:59 +00:00
mergify[bot]
0e155fdbd9 update call depth docs (#13155) (#13162)
(cherry picked from commit 35f77ccc73)

Co-authored-by: Jack May <jack@solana.com>
2020-10-26 19:58:55 +00:00
Michael Vines
b79a337ddd Don't reuse BPF target build artifacts
(cherry picked from commit 41a56e14fc)
2020-10-26 12:01:38 -07:00
Michael Vines
c4050f541d Fix reward type encoding
(cherry picked from commit 0a89bb4d3c)
2020-10-26 12:01:38 -07:00
mergify[bot]
f0b74a4ecf marks pull request creation time only once per peer (#13113) (#13156)
mark_pull_request_creation time requires an exclusive lock on gossip:
https://github.com/solana-labs/solana/blob/16944e218/core/src/cluster_info.rs#L1547-L1548
Current code is redundantly marking each peer once for each request.
There are at most only 2 unique peers, whereas there are hundreds of
requests per each. So the lock is acquired hundreds of time longer than
necessary.

(cherry picked from commit 4bfda3e766)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-10-26 18:27:26 +00:00
mergify[bot]
f7979378fd Fix test_optimistic_confirmation_violation_without_tower() (#13043) (#13145)
Co-authored-by: Carl Lin <carl@solana.com>
(cherry picked from commit dd6cccaf7e)

Co-authored-by: carllin <wumu727@gmail.com>
2020-10-26 06:33:20 +00:00
mergify[bot]
d7c5607982 Hide noisy specialization warnings for frozen abi (#13141) (#13144)
(cherry picked from commit 5caf81dbf8)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-26 06:19:58 +00:00
Michael Vines
91ab5ae990 Remove program feature from SPL builds 2020-10-25 21:08:53 -07:00
mergify[bot]
605e767259 Allow existence of vote on root in saved tower (#13135) (#13139)
(cherry picked from commit 66c7a98009)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-26 12:34:58 +09:00
Michael Vines
597618846b Bump version to v1.4.4 2020-10-24 22:10:32 +00:00
Michael Vines
712267bf51 Rename "everything" feature to "full"
(cherry picked from commit 0cc9c94c43)
2020-10-24 13:21:11 -07:00
mergify[bot]
eb9cef0cd4 Separate the "program" feature of solana-sdk into a new crate called solana-program (bp #12989) (#13131)
* Add solana-program-sdk boilerplate

(cherry picked from commit 3718771ffb)

# Conflicts:
#	sdk/Cargo.toml

* Initial population of solana-program-sdk

(cherry picked from commit 63db324204)

# Conflicts:
#	Cargo.lock

* Port programs to solana-program-sdk

(cherry picked from commit fe68f7f786)

# Conflicts:
#	programs/bpf/Cargo.lock
#	programs/bpf/rust/128bit/Cargo.toml
#	programs/bpf/rust/128bit_dep/Cargo.toml
#	programs/bpf/rust/alloc/Cargo.toml
#	programs/bpf/rust/call_depth/Cargo.toml
#	programs/bpf/rust/custom_heap/Cargo.toml
#	programs/bpf/rust/dep_crate/Cargo.toml
#	programs/bpf/rust/deprecated_loader/Cargo.toml
#	programs/bpf/rust/dup_accounts/Cargo.toml
#	programs/bpf/rust/error_handling/Cargo.toml
#	programs/bpf/rust/external_spend/Cargo.toml
#	programs/bpf/rust/instruction_introspection/Cargo.toml
#	programs/bpf/rust/invoke/Cargo.toml
#	programs/bpf/rust/invoked/Cargo.toml
#	programs/bpf/rust/iter/Cargo.toml
#	programs/bpf/rust/many_args/Cargo.toml
#	programs/bpf/rust/many_args_dep/Cargo.toml
#	programs/bpf/rust/noop/Cargo.toml
#	programs/bpf/rust/panic/Cargo.toml
#	programs/bpf/rust/param_passing/Cargo.toml
#	programs/bpf/rust/param_passing_dep/Cargo.toml
#	programs/bpf/rust/rand/Cargo.toml
#	programs/bpf/rust/ristretto/Cargo.toml
#	programs/bpf/rust/sanity/Cargo.toml
#	programs/bpf/rust/sha256/Cargo.toml
#	programs/bpf/rust/sysval/Cargo.toml

* Only activate legacy program feature for the solana-sdk crate

(cherry picked from commit 85c51f5787)

* Run serum-dex unit tests

(cherry picked from commit 92ce381d60)

* Rename solana-program-sdk to solana-program

(cherry picked from commit dd711ab5fb)

# Conflicts:
#	programs/bpf/rust/128bit/Cargo.toml
#	programs/bpf/rust/128bit_dep/Cargo.toml
#	programs/bpf/rust/alloc/Cargo.toml
#	programs/bpf/rust/call_depth/Cargo.toml
#	programs/bpf/rust/custom_heap/Cargo.toml
#	programs/bpf/rust/dep_crate/Cargo.toml
#	programs/bpf/rust/deprecated_loader/Cargo.toml
#	programs/bpf/rust/dup_accounts/Cargo.toml
#	programs/bpf/rust/error_handling/Cargo.toml
#	programs/bpf/rust/external_spend/Cargo.toml
#	programs/bpf/rust/instruction_introspection/Cargo.toml
#	programs/bpf/rust/invoke/Cargo.toml
#	programs/bpf/rust/invoked/Cargo.toml
#	programs/bpf/rust/iter/Cargo.toml
#	programs/bpf/rust/many_args/Cargo.toml
#	programs/bpf/rust/many_args_dep/Cargo.toml
#	programs/bpf/rust/noop/Cargo.toml
#	programs/bpf/rust/panic/Cargo.toml
#	programs/bpf/rust/param_passing/Cargo.toml
#	programs/bpf/rust/param_passing_dep/Cargo.toml
#	programs/bpf/rust/rand/Cargo.toml
#	programs/bpf/rust/ristretto/Cargo.toml
#	programs/bpf/rust/sanity/Cargo.toml
#	programs/bpf/rust/sha256/Cargo.toml
#	programs/bpf/rust/sysval/Cargo.toml

* Update frozen_abi hashes

The movement of files in sdk/ caused ABI hashes to change

(cherry picked from commit a4956844bd)

* Resolve merge conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-24 17:25:22 +00:00
mergify[bot]
62e0e19961 add precompile verification to simulate_transaction (#13080) (#13126)
(cherry picked from commit 766406fd23)

Co-authored-by: Josh <josh.hundley@gmail.com>
2020-10-24 05:02:41 +00:00
mergify[bot]
9aee9cb867 Clean up opt conf verifier and vote state tracker (#13081) (#13124)
* Clean up opt conf verifier and vote state tracker

* Update test to follow new message and some knob

* Rename

(cherry picked from commit 0264147d42)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-10-24 04:12:02 +00:00
mergify[bot]
2b11558b36 Shorten magic install URL (#13122)
(cherry picked from commit b5170b993e)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-23 23:28:19 +00:00
mergify[bot]
18c4e1b023 ci: Add downstream project build testing (bp #13112) (#13119)
* Use local cargo for CI

(cherry picked from commit c7c50bd32c)

* Add downstream project build testing

(cherry picked from commit c7f4f15e60)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-23 22:13:51 +00:00
mergify[bot]
6bac44ed92 Move bpf sdk packaging from publish-tarball to cargo-install-all (#13117)
(cherry picked from commit 965ea97b56)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-23 21:39:41 +00:00
mergify[bot]
8cb622084f Cli: deploy programs via TPU (#13090) (#13111)
* Deploy: send write transactions to leader tpu

* Less apparent stalling during confirmation

* Add EpochInfo mock

* Only get cluster nodes once

* Send deploy writes to next leader

(cherry picked from commit 16944e218f)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-23 17:29:41 +00:00
mergify[bot]
38f7e9a979 shrink debug (#13089) (#13109)
(cherry picked from commit 7d2729f6bd)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-10-23 17:02:00 +00:00
mergify[bot]
a536f779ee scans crds table in parallel for finding old labels (#13073) (#13107)
From runtime profiles, the majority time of ClusterInfo::handle_purge
https://github.com/solana-labs/solana/blob/0776fa05c/core/src/cluster_info.rs#L1605-L1626
is spent scanning crds table finding old labels:
https://github.com/solana-labs/solana/blob/0776fa05c/core/src/crds.rs#L175-L197

This can be done in parallel given that gossip thread-pool:
https://github.com/solana-labs/solana/blob/0776fa05c/core/src/cluster_info.rs#L1637-L1641
is idle when handle_purge is invoked:
https://github.com/solana-labs/solana/blob/0776fa05c/core/src/cluster_info.rs#L1681

(cherry picked from commit 37c8842bcb)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-10-23 15:36:06 +00:00
mergify[bot]
84a5e5ec97 Remove spammy invalid rpc log (#13100) (#13102)
(cherry picked from commit c95f6c4b83)

Co-authored-by: Justin Starry <justin@solana.com>
2020-10-23 08:32:46 +00:00
mergify[bot]
dd33aae3cf Add --bpf-out-dir argument to control where the final build products land (#13099)
(cherry picked from commit b169d9cfbe)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-10-23 07:56:35 +00:00
mergify[bot]
be2ace47e3 Add deploy err if program-account balance is too high (#13091) (#13098)
* Add deploy err if program-account balance is too high

* Review comments

* Add system-program check

* Rename and unhide flag

(cherry picked from commit 4669fa0f98)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-10-23 07:02:16 +00:00
Trent Nelson
53b074aa35 Bump version to 1.4.3 2020-10-23 04:20:28 +00:00
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
1144 changed files with 59418 additions and 163787 deletions

6
.gitignore vendored
View File

@@ -1,3 +1,7 @@
/docs/html/
/docs/src/tests.ok
/docs/src/cli/usage.md
/docs/src/.gitbook/assets/*.svg
/farf/
/solana-release/
/solana-release.tar.bz2
@@ -10,8 +14,6 @@
/config/
.cache
# log files
*.log
log-*.txt

View File

@@ -50,6 +50,22 @@ pull_request_rules:
label:
add:
- automerge
- name: v1.2 backport
conditions:
- label=v1.2
actions:
backport:
ignore_conflicts: true
branches:
- v1.2
- name: v1.3 backport
conditions:
- label=v1.3
actions:
backport:
ignore_conflicts: true
branches:
- v1.3
- name: v1.4 backport
conditions:
- label=v1.4
@@ -58,27 +74,3 @@ pull_request_rules:
ignore_conflicts: true
branches:
- v1.4
- name: v1.5 backport
conditions:
- label=v1.5
actions:
backport:
ignore_conflicts: true
branches:
- v1.5
- name: v1.6 backport
conditions:
- label=v1.6
actions:
backport:
ignore_conflicts: true
branches:
- v1.6
- name: v1.7 backport
conditions:
- label=v1.7
actions:
backport:
ignore_conflicts: true
branches:
- v1.7

2376
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
[workspace]
members = [
"accounts-cluster-bench",
"bench-exchange",
"bench-streamer",
"bench-tps",
@@ -29,7 +28,6 @@ members = [
"local-cluster",
"logger",
"log-analyzer",
"merkle-root-bench",
"merkle-tree",
"stake-o-matic",
"storage-bigtable",
@@ -55,7 +53,6 @@ members = [
"remote-wallet",
"ramp-tps",
"runtime",
"runtime/store-tool",
"sdk",
"sdk/cargo-build-bpf",
"sdk/cargo-test-bpf",
@@ -69,6 +66,7 @@ members = [
"upload-perf",
"net-utils",
"version",
"vote-signer",
"cli",
"rayon-threadlimit",
"watchtower",

View File

@@ -29,7 +29,7 @@ On Linux systems you may need to install libssl-dev, pkg-config, zlib1g-dev, etc
```bash
$ sudo apt-get update
$ sudo apt-get install libssl-dev libudev-dev pkg-config zlib1g-dev llvm clang make
$ sudo apt-get install libssl-dev libudev-dev pkg-config zlib1g-dev llvm clang
```
## **2. Download the source code.**
@@ -107,41 +107,4 @@ send us that patch!
# Disclaimer
All claims, content, designs, algorithms, estimates, roadmaps,
specifications, and performance measurements described in this project
are done with the Solana Foundation's ("SF") best efforts. It is up to
the reader to check and validate their accuracy and truthfulness.
Furthermore nothing in this project constitutes a solicitation for
investment.
Any content produced by SF or developer resources that SF provides, are
for educational and inspiration purposes only. SF does not encourage,
induce or sanction the deployment, integration or use of any such
applications (including the code comprising the Solana blockchain
protocol) in violation of applicable laws or regulations and hereby
prohibits any such deployment, integration or use. This includes use of
any such applications by the reader (a) in violation of export control
or sanctions laws of the United States or any other applicable
jurisdiction, (b) if the reader is located in or ordinarily resident in
a country or territory subject to comprehensive sanctions administered
by the U.S. Office of Foreign Assets Control (OFAC), or (c) if the
reader is or is working on behalf of a Specially Designated National
(SDN) or a person subject to similar blocking or denied party
prohibitions.
The reader should be aware that U.S. export control and sanctions laws
prohibit U.S. persons (and other persons that are subject to such laws)
from transacting with persons in certain countries and territories or
that are on the SDN list. As a project based primarily on open-source
software, it is possible that such sanctioned persons may nevertheless
bypass prohibitions, obtain the code comprising the Solana blockchain
protocol (or other project code or applications) and deploy, integrate,
or otherwise use it. Accordingly, there is a risk to individuals that
other persons using the Solana blockchain protocol may be sanctioned
persons and that transactions with such persons would be a violation of
U.S. export controls and sanctions law. This risk applies to
individuals, organizations, and other ecosystem participants that
deploy, integrate, or use the Solana blockchain protocol code directly
(e.g., as a node operator), and individuals that transact on the Solana
blockchain through light clients, third party interfaces, and/or wallet
software.
All claims, content, designs, algorithms, estimates, roadmaps, specifications, and performance measurements described in this project are done with the author's best effort. It is up to the reader to check and validate their accuracy and truthfulness. Furthermore nothing in this project constitutes a solicitation for investment.

View File

@@ -1,147 +0,0 @@
# Security Policy
1. [Reporting security problems](#reporting)
4. [Security Bug Bounties](#bounty)
2. [Incident Response Process](#process)
<a name="reporting"></a>
## Reporting security problems to Solana
**DO NOT CREATE AN ISSUE** to report a security problem. Instead, please send an
email to security@solana.com and provide your github username so we can add you
to a new draft security advisory for further discussion.
Expect a response as fast as possible, within one business day at the latest.
<a name="bounty"></a>
## Security Bug Bounties
We offer bounties for critical security issues. Please see below for more details.
Loss of Funds:
$500,000 USD in locked SOL tokens (locked for 12 months)
* Theft of funds without users signature from any account
* Theft of funds without users interaction in system, token, stake, vote programs
* Theft of funds that requires users signature - creating a vote program that drains the delegated stakes.
Consensus/Safety Violations:
$250,000 USD in locked SOL tokens (locked for 12 months)
* Consensus safety violation
* Tricking a validator to accept an optimistic confirmation or rooted slot without a double vote, etc..
Other Attacks:
$100,000 USD in locked SOL tokens (locked for 12 months)
* Protocol liveness attacks,
* Eclipse attacks,
* Remote attacks that partition the network,
DoS Attacks:
$25,000 USD in locked SOL tokens (locked for 12 months)
* Remote resource exaustion via Non-RPC protocols
RPC DoS/Crashes:
$5,000 USD in locked SOL tokens (locked for 12 months)
* RPC attacks
Eligibility:
* The participant submitting the bug bounty shall follow the process outlined within this document
* Valid exploits can be eligible even if they are not successfully executed on the cluster
* Multiple submissions for the same class of exploit are still eligible for compensation, though may be compensated at a lower rate, however these will be assessed on a case-by-case basis
* Participants must complete KYC and sign the participation agreement here when the registrations are open https://solana.com/validator-registration. Security exploits will still be assessed and open for submission at all times. This needs only be done prior to distribution of tokens.
Notes:
* All locked tokens can be staked during the lockup period
<a name="process"></a>
## Incident Response Process
In case an incident is discovered or reported, the following process will be
followed to contain, respond and remediate:
### 1. Establish a new draft security advisory
In response to an email to security@solana.com, a member of the `solana-labs/admins` group will
1. Create a new draft security advisory for the incident at https://github.com/solana-labs/solana/security/advisories
1. Add the reporter's github user and the `solana-labs/security-incident-response` group to the draft security advisory
1. Create a private fork of the repository (grey button towards the bottom of the page)
1. Respond to the reporter by email, sharing a link to the draft security advisory
### 2. Triage
Within the draft security advisory, discuss and determine the severity of the
issue. If necessary, members of the `solana-labs/security-incident-response`
group may add other github users to the advisory to assist.
If it is determined that this not a critical network issue then the advisory
should be closed and if more follow-up is required a normal Solana public github
issue should be created.
### 3. Prepare Fixes
For the affected branches, typically all three (edge, beta and stable), prepare
a fix for the issue and push them to the corresponding branch in the private
repository associated with the draft security advisory.
There is no CI available in the private repository so you must build from source
and manually verify fixes.
Code review from the reporter is ideal, as well as from multiple members of the
core development team.
### 4. Notify Security Group Validators
Once an ETA is available for the fix, a member of the
`solana-labs/security-incident-response` group should notify the validators so
they can prepare for an update using the "Solana Red Alert" notification system.
The teams are all over the world and it's critical to provide actionable
information at the right time. Don't be the person that wakes everybody up at
2am when a fix won't be available for hours.
### 5. Ship the patch
Once the fix is accepted, a member of the
`solana-labs/security-incident-response` group should prepare a single patch
file for each affected branch. The commit title for the patch should only
contain the advisory id, and not disclose any further details about the
incident.
Copy the patches to https://release.solana.com/ under a subdirectory named after
the advisory id (example:
https://release.solana.com/GHSA-hx59-f5g4-jghh/v1.4.patch). Contact a member of
the `solana-labs/admins` group if you require access to release.solana.com
Using the "Solana Red Alert" channel:
1. Notify validators that there's an issue and a patch will be provided in X minutes
2. If X minutes expires and there's no patch, notify of the delay and provide a
new ETA
3. Provide links to patches of https://release.solana.com/ for each affected branch
Validators can be expected to build the patch from source against the latest
release for the affected branch.
Since the software version will not change after the patch is applied, request
that each validator notify in the existing channel once they've updated. Manually
monitor the roll out until a sufficient amount of stake has updated - typically
at least 33.3% or 66.6% depending on the issue.
### 6. Public Disclosure and Release
Once the fix has been deployed to the security group validators, the patches from the security
advisory may be merged into the main source repository. A new official release
for each affected branch should be shipped and all validators requested to
upgrade as quickly as possible.
### 7. Security Advisory Bounty Accounting and Cleanup
If this issue is eligible for a bounty, prefix the title of the security
advisory with one of the following, depending on the severity:
* `[Bounty Category: Critical: Loss of Funds]`
* `[Bounty Category: Critical: Loss of Availability]`
* `[Bounty Category: Critical: DoS]`
* `[Bounty Category: Critical: Other]`
* `[Bounty Category: Non-critical]`
* `[Bounty Category: RPC]`
Confirm with the reporter that they agree with the severity assessment, and
discuss as required to reach a conclusion.
We currently do not use the Github workflow to publish security advisories.
Once the issue and fix have been disclosed, and a bounty category is assessed if
appropriate, the GitHub security advisory is no longer needed and can be closed.
Bounties are currently awarded once a quarter (TODO: link to this process, or
inline the workflow)

View File

@@ -1,11 +1,10 @@
[package]
name = "solana-account-decoder"
version = "1.6.2"
version = "1.4.7"
description = "Solana account decoder"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-account-decoder"
license = "Apache-2.0"
edition = "2018"
@@ -16,16 +15,15 @@ bs58 = "0.3.1"
bv = "0.11.1"
Inflector = "0.11.4"
lazy_static = "1.4.0"
serde = "1.0.122"
serde = "1.0.112"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-config-program = { path = "../programs/config", version = "=1.6.2" }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
solana-stake-program = { path = "../programs/stake", version = "=1.6.2" }
solana-vote-program = { path = "../programs/vote", version = "=1.6.2" }
spl-token-v2-0 = { package = "spl-token", version = "=3.1.0", features = ["no-entrypoint"] }
solana-config-program = { path = "../programs/config", version = "1.4.7" }
solana-sdk = { path = "../sdk", version = "1.4.7" }
solana-stake-program = { path = "../programs/stake", version = "1.4.7" }
solana-vote-program = { path = "../programs/vote", version = "1.4.7" }
spl-token-v2-0 = { package = "spl-token", version = "=3.0.0", features = ["no-entrypoint"] }
thiserror = "1.0"
zstd = "0.5.1"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,11 +1,9 @@
#![allow(clippy::integer_arithmetic)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde_derive;
pub mod parse_account_data;
pub mod parse_bpf_loader;
pub mod parse_config;
pub mod parse_nonce;
pub mod parse_stake;
@@ -14,20 +12,11 @@ pub mod parse_token;
pub mod parse_vote;
pub mod validator_info;
use {
crate::parse_account_data::{parse_account_data, AccountAdditionalData, ParsedAccount},
solana_sdk::{
account::ReadableAccount, account::WritableAccount, clock::Epoch,
fee_calculator::FeeCalculator, pubkey::Pubkey,
},
std::{
io::{Read, Write},
str::FromStr,
},
};
use crate::parse_account_data::{parse_account_data, AccountAdditionalData, ParsedAccount};
use solana_sdk::{account::Account, clock::Epoch, fee_calculator::FeeCalculator, pubkey::Pubkey};
use std::str::FromStr;
pub type StringAmount = String;
pub type StringDecimals = String;
/// A duplicate representation of an Account for pretty JSON serialization
#[derive(Serialize, Deserialize, Clone, Debug)]
@@ -55,92 +44,64 @@ pub enum UiAccountEncoding {
Base58,
Base64,
JsonParsed,
#[serde(rename = "base64+zstd")]
Base64Zstd,
}
impl UiAccount {
pub fn encode<T: ReadableAccount>(
pub fn encode(
pubkey: &Pubkey,
account: T,
account: Account,
encoding: UiAccountEncoding,
additional_data: Option<AccountAdditionalData>,
data_slice_config: Option<UiDataSliceConfig>,
) -> Self {
let data = match encoding {
UiAccountEncoding::Binary => UiAccountData::LegacyBinary(
bs58::encode(slice_data(&account.data(), data_slice_config)).into_string(),
bs58::encode(slice_data(&account.data, data_slice_config)).into_string(),
),
UiAccountEncoding::Base58 => UiAccountData::Binary(
bs58::encode(slice_data(&account.data(), data_slice_config)).into_string(),
bs58::encode(slice_data(&account.data, data_slice_config)).into_string(),
encoding,
),
UiAccountEncoding::Base64 => UiAccountData::Binary(
base64::encode(slice_data(&account.data(), data_slice_config)),
base64::encode(slice_data(&account.data, data_slice_config)),
encoding,
),
UiAccountEncoding::Base64Zstd => {
let mut encoder = zstd::stream::write::Encoder::new(Vec::new(), 0).unwrap();
match encoder
.write_all(slice_data(&account.data(), data_slice_config))
.and_then(|()| encoder.finish())
{
Ok(zstd_data) => UiAccountData::Binary(base64::encode(zstd_data), encoding),
Err(_) => UiAccountData::Binary(
base64::encode(slice_data(&account.data(), data_slice_config)),
UiAccountEncoding::Base64,
),
}
}
UiAccountEncoding::JsonParsed => {
if let Ok(parsed_data) =
parse_account_data(pubkey, &account.owner(), &account.data(), additional_data)
parse_account_data(pubkey, &account.owner, &account.data, additional_data)
{
UiAccountData::Json(parsed_data)
} else {
UiAccountData::Binary(
base64::encode(&account.data()),
UiAccountEncoding::Base64,
)
UiAccountData::Binary(base64::encode(&account.data), UiAccountEncoding::Base64)
}
}
};
UiAccount {
lamports: account.lamports(),
lamports: account.lamports,
data,
owner: account.owner().to_string(),
executable: account.executable(),
rent_epoch: account.rent_epoch(),
owner: account.owner.to_string(),
executable: account.executable,
rent_epoch: account.rent_epoch,
}
}
pub fn decode<T: WritableAccount>(&self) -> Option<T> {
pub fn decode(&self) -> Option<Account> {
let data = match &self.data {
UiAccountData::Json(_) => None,
UiAccountData::LegacyBinary(blob) => bs58::decode(blob).into_vec().ok(),
UiAccountData::Binary(blob, encoding) => match encoding {
UiAccountEncoding::Base58 => bs58::decode(blob).into_vec().ok(),
UiAccountEncoding::Base64 => base64::decode(blob).ok(),
UiAccountEncoding::Base64Zstd => base64::decode(blob)
.ok()
.map(|zstd_data| {
let mut data = vec![];
zstd::stream::read::Decoder::new(zstd_data.as_slice())
.and_then(|mut reader| reader.read_to_end(&mut data))
.map(|_| data)
.ok()
})
.flatten(),
UiAccountEncoding::Binary | UiAccountEncoding::JsonParsed => None,
},
}?;
Some(T::create(
self.lamports,
Some(Account {
lamports: self.lamports,
data,
Pubkey::from_str(&self.owner).ok()?,
self.executable,
self.rent_epoch,
))
owner: Pubkey::from_str(&self.owner).ok()?,
executable: self.executable,
rent_epoch: self.rent_epoch,
})
}
}
@@ -190,7 +151,6 @@ fn slice_data(data: &[u8], data_slice_config: Option<UiDataSliceConfig>) -> &[u8
#[cfg(test)]
mod test {
use super::*;
use solana_sdk::account::{Account, AccountSharedData};
#[test]
fn test_slice_data() {
@@ -219,27 +179,4 @@ mod test {
});
assert_eq!(slice_data(&data, slice_config), &[] as &[u8]);
}
#[test]
fn test_base64_zstd() {
let encoded_account = UiAccount::encode(
&Pubkey::default(),
AccountSharedData::from(Account {
data: vec![0; 1024],
..Account::default()
}),
UiAccountEncoding::Base64Zstd,
None,
None,
);
assert!(matches!(
encoded_account.data,
UiAccountData::Binary(_, UiAccountEncoding::Base64Zstd)
));
let decoded_account = encoded_account.decode::<Account>().unwrap();
assert_eq!(decoded_account.data(), &vec![0; 1024]);
let decoded_account = encoded_account.decode::<AccountSharedData>().unwrap();
assert_eq!(decoded_account.data(), &vec![0; 1024]);
}
}

View File

@@ -1,5 +1,4 @@
use crate::{
parse_bpf_loader::parse_bpf_upgradeable_loader,
parse_config::parse_config,
parse_nonce::parse_nonce,
parse_stake::parse_stake,
@@ -14,7 +13,6 @@ use std::collections::HashMap;
use thiserror::Error;
lazy_static! {
static ref BPF_UPGRADEABLE_LOADER_PROGRAM_ID: Pubkey = solana_sdk::bpf_loader_upgradeable::id();
static ref CONFIG_PROGRAM_ID: Pubkey = solana_config_program::id();
static ref STAKE_PROGRAM_ID: Pubkey = solana_stake_program::id();
static ref SYSTEM_PROGRAM_ID: Pubkey = system_program::id();
@@ -23,10 +21,6 @@ lazy_static! {
static ref VOTE_PROGRAM_ID: Pubkey = solana_vote_program::id();
pub static ref PARSABLE_PROGRAM_IDS: HashMap<Pubkey, ParsableAccount> = {
let mut m = HashMap::new();
m.insert(
*BPF_UPGRADEABLE_LOADER_PROGRAM_ID,
ParsableAccount::BpfUpgradeableLoader,
);
m.insert(*CONFIG_PROGRAM_ID, ParsableAccount::Config);
m.insert(*SYSTEM_PROGRAM_ID, ParsableAccount::Nonce);
m.insert(*TOKEN_PROGRAM_ID, ParsableAccount::SplToken);
@@ -66,7 +60,6 @@ pub struct ParsedAccount {
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ParsableAccount {
BpfUpgradeableLoader,
Config,
Nonce,
SplToken,
@@ -88,12 +81,9 @@ pub fn parse_account_data(
) -> Result<ParsedAccount, ParseAccountError> {
let program_name = PARSABLE_PROGRAM_IDS
.get(program_id)
.ok_or(ParseAccountError::ProgramNotParsable)?;
.ok_or_else(|| ParseAccountError::ProgramNotParsable)?;
let additional_data = additional_data.unwrap_or_default();
let parsed_json = match program_name {
ParsableAccount::BpfUpgradeableLoader => {
serde_json::to_value(parse_bpf_upgradeable_loader(data)?)?
}
ParsableAccount::Config => serde_json::to_value(parse_config(data, pubkey)?)?,
ParsableAccount::Nonce => serde_json::to_value(parse_nonce(data)?)?,
ParsableAccount::SplToken => {
@@ -128,7 +118,7 @@ mod test {
let vote_state = VoteState::default();
let mut vote_account_data: Vec<u8> = vec![0; VoteState::size_of()];
let versioned = VoteStateVersions::new_current(vote_state);
let versioned = VoteStateVersions::Current(Box::new(vote_state));
VoteState::serialize(&versioned, &mut vote_account_data).unwrap();
let parsed = parse_account_data(
&account_pubkey,

View File

@@ -1,181 +0,0 @@
use crate::{
parse_account_data::{ParsableAccount, ParseAccountError},
UiAccountData, UiAccountEncoding,
};
use bincode::{deserialize, serialized_size};
use solana_sdk::{bpf_loader_upgradeable::UpgradeableLoaderState, pubkey::Pubkey};
pub fn parse_bpf_upgradeable_loader(
data: &[u8],
) -> Result<BpfUpgradeableLoaderAccountType, ParseAccountError> {
let account_state: UpgradeableLoaderState = deserialize(data).map_err(|_| {
ParseAccountError::AccountNotParsable(ParsableAccount::BpfUpgradeableLoader)
})?;
let parsed_account = match account_state {
UpgradeableLoaderState::Uninitialized => BpfUpgradeableLoaderAccountType::Uninitialized,
UpgradeableLoaderState::Buffer { authority_address } => {
let offset = if authority_address.is_some() {
UpgradeableLoaderState::buffer_data_offset().unwrap()
} else {
// This case included for code completeness; in practice, a Buffer account will
// always have authority_address.is_some()
UpgradeableLoaderState::buffer_data_offset().unwrap()
- serialized_size(&Pubkey::default()).unwrap() as usize
};
BpfUpgradeableLoaderAccountType::Buffer(UiBuffer {
authority: authority_address.map(|pubkey| pubkey.to_string()),
data: UiAccountData::Binary(
base64::encode(&data[offset as usize..]),
UiAccountEncoding::Base64,
),
})
}
UpgradeableLoaderState::Program {
programdata_address,
} => BpfUpgradeableLoaderAccountType::Program(UiProgram {
program_data: programdata_address.to_string(),
}),
UpgradeableLoaderState::ProgramData {
slot,
upgrade_authority_address,
} => {
let offset = if upgrade_authority_address.is_some() {
UpgradeableLoaderState::programdata_data_offset().unwrap()
} else {
UpgradeableLoaderState::programdata_data_offset().unwrap()
- serialized_size(&Pubkey::default()).unwrap() as usize
};
BpfUpgradeableLoaderAccountType::ProgramData(UiProgramData {
slot,
authority: upgrade_authority_address.map(|pubkey| pubkey.to_string()),
data: UiAccountData::Binary(
base64::encode(&data[offset as usize..]),
UiAccountEncoding::Base64,
),
})
}
};
Ok(parsed_account)
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase", tag = "type", content = "info")]
pub enum BpfUpgradeableLoaderAccountType {
Uninitialized,
Buffer(UiBuffer),
Program(UiProgram),
ProgramData(UiProgramData),
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiBuffer {
pub authority: Option<String>,
pub data: UiAccountData,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiProgram {
pub program_data: String,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiProgramData {
pub slot: u64,
pub authority: Option<String>,
pub data: UiAccountData,
}
#[cfg(test)]
mod test {
use super::*;
use bincode::serialize;
use solana_sdk::pubkey::Pubkey;
#[test]
fn test_parse_bpf_upgradeable_loader_accounts() {
let bpf_loader_state = UpgradeableLoaderState::Uninitialized;
let account_data = serialize(&bpf_loader_state).unwrap();
assert_eq!(
parse_bpf_upgradeable_loader(&account_data).unwrap(),
BpfUpgradeableLoaderAccountType::Uninitialized
);
let program = vec![7u8; 64]; // Arbitrary program data
let authority = Pubkey::new_unique();
let bpf_loader_state = UpgradeableLoaderState::Buffer {
authority_address: Some(authority),
};
let mut account_data = serialize(&bpf_loader_state).unwrap();
account_data.extend_from_slice(&program);
assert_eq!(
parse_bpf_upgradeable_loader(&account_data).unwrap(),
BpfUpgradeableLoaderAccountType::Buffer(UiBuffer {
authority: Some(authority.to_string()),
data: UiAccountData::Binary(base64::encode(&program), UiAccountEncoding::Base64),
})
);
// This case included for code completeness; in practice, a Buffer account will always have
// authority_address.is_some()
let bpf_loader_state = UpgradeableLoaderState::Buffer {
authority_address: None,
};
let mut account_data = serialize(&bpf_loader_state).unwrap();
account_data.extend_from_slice(&program);
assert_eq!(
parse_bpf_upgradeable_loader(&account_data).unwrap(),
BpfUpgradeableLoaderAccountType::Buffer(UiBuffer {
authority: None,
data: UiAccountData::Binary(base64::encode(&program), UiAccountEncoding::Base64),
})
);
let programdata_address = Pubkey::new_unique();
let bpf_loader_state = UpgradeableLoaderState::Program {
programdata_address,
};
let account_data = serialize(&bpf_loader_state).unwrap();
assert_eq!(
parse_bpf_upgradeable_loader(&account_data).unwrap(),
BpfUpgradeableLoaderAccountType::Program(UiProgram {
program_data: programdata_address.to_string(),
})
);
let authority = Pubkey::new_unique();
let slot = 42;
let bpf_loader_state = UpgradeableLoaderState::ProgramData {
slot,
upgrade_authority_address: Some(authority),
};
let mut account_data = serialize(&bpf_loader_state).unwrap();
account_data.extend_from_slice(&program);
assert_eq!(
parse_bpf_upgradeable_loader(&account_data).unwrap(),
BpfUpgradeableLoaderAccountType::ProgramData(UiProgramData {
slot,
authority: Some(authority.to_string()),
data: UiAccountData::Binary(base64::encode(&program), UiAccountEncoding::Base64),
})
);
let bpf_loader_state = UpgradeableLoaderState::ProgramData {
slot,
upgrade_authority_address: None,
};
let mut account_data = serialize(&bpf_loader_state).unwrap();
account_data.extend_from_slice(&program);
assert_eq!(
parse_bpf_upgradeable_loader(&account_data).unwrap(),
BpfUpgradeableLoaderAccountType::ProgramData(UiProgramData {
slot,
authority: None,
data: UiAccountData::Binary(base64::encode(&program), UiAccountEncoding::Base64),
})
);
}
}

View File

@@ -91,7 +91,6 @@ mod test {
use crate::validator_info::ValidatorInfo;
use serde_json::json;
use solana_config_program::create_config_account;
use solana_sdk::account::ReadableAccount;
#[test]
fn test_parse_config() {
@@ -102,7 +101,7 @@ mod test {
let stake_config_account = create_config_account(vec![], &stake_config, 10);
assert_eq!(
parse_config(
&stake_config_account.data(),
&stake_config_account.data,
&solana_stake_program::config::id()
)
.unwrap(),
@@ -125,7 +124,7 @@ mod test {
10,
);
assert_eq!(
parse_config(&validator_info_config_account.data(), &info_pubkey).unwrap(),
parse_config(&validator_info_config_account.data, &info_pubkey).unwrap(),
ConfigAccountType::ValidatorInfo(UiConfig {
keys: vec![
UiConfigKey {

View File

@@ -105,7 +105,6 @@ pub enum SysvarAccountType {
pub struct UiClock {
pub slot: Slot,
pub epoch: Epoch,
pub epoch_start_timestamp: UnixTimestamp,
pub leader_schedule_epoch: Epoch,
pub unix_timestamp: UnixTimestamp,
}
@@ -115,7 +114,6 @@ impl From<Clock> for UiClock {
Self {
slot: clock.slot,
epoch: clock.epoch,
epoch_start_timestamp: clock.epoch_start_timestamp,
leader_schedule_epoch: clock.leader_schedule_epoch,
unix_timestamp: clock.unix_timestamp,
}
@@ -214,13 +212,14 @@ pub struct UiStakeHistoryEntry {
mod test {
use super::*;
use solana_sdk::{
account::create_account_for_test, fee_calculator::FeeCalculator, hash::Hash,
account::create_account, fee_calculator::FeeCalculator, hash::Hash,
sysvar::recent_blockhashes::IterItem,
};
use std::iter::FromIterator;
#[test]
fn test_parse_sysvars() {
let clock_sysvar = create_account_for_test(&Clock::default());
let clock_sysvar = create_account(&Clock::default(), 1);
assert_eq!(
parse_sysvar(&clock_sysvar.data, &sysvar::clock::id()).unwrap(),
SysvarAccountType::Clock(UiClock::default()),
@@ -233,13 +232,13 @@ mod test {
first_normal_epoch: 1,
first_normal_slot: 12,
};
let epoch_schedule_sysvar = create_account_for_test(&epoch_schedule);
let epoch_schedule_sysvar = create_account(&epoch_schedule, 1);
assert_eq!(
parse_sysvar(&epoch_schedule_sysvar.data, &sysvar::epoch_schedule::id()).unwrap(),
SysvarAccountType::EpochSchedule(epoch_schedule),
);
let fees_sysvar = create_account_for_test(&Fees::default());
let fees_sysvar = create_account(&Fees::default(), 1);
assert_eq!(
parse_sysvar(&fees_sysvar.data, &sysvar::fees::id()).unwrap(),
SysvarAccountType::Fees(UiFees::default()),
@@ -249,10 +248,9 @@ mod test {
let fee_calculator = FeeCalculator {
lamports_per_signature: 10,
};
let recent_blockhashes: RecentBlockhashes = vec![IterItem(0, &hash, &fee_calculator)]
.into_iter()
.collect();
let recent_blockhashes_sysvar = create_account_for_test(&recent_blockhashes);
let recent_blockhashes =
RecentBlockhashes::from_iter(vec![IterItem(0, &hash, &fee_calculator)].into_iter());
let recent_blockhashes_sysvar = create_account(&recent_blockhashes, 1);
assert_eq!(
parse_sysvar(
&recent_blockhashes_sysvar.data,
@@ -270,13 +268,13 @@ mod test {
exemption_threshold: 2.0,
burn_percent: 5,
};
let rent_sysvar = create_account_for_test(&rent);
let rent_sysvar = create_account(&rent, 1);
assert_eq!(
parse_sysvar(&rent_sysvar.data, &sysvar::rent::id()).unwrap(),
SysvarAccountType::Rent(rent.into()),
);
let rewards_sysvar = create_account_for_test(&Rewards::default());
let rewards_sysvar = create_account(&Rewards::default(), 1);
assert_eq!(
parse_sysvar(&rewards_sysvar.data, &sysvar::rewards::id()).unwrap(),
SysvarAccountType::Rewards(UiRewards::default()),
@@ -284,7 +282,7 @@ mod test {
let mut slot_hashes = SlotHashes::default();
slot_hashes.add(1, hash);
let slot_hashes_sysvar = create_account_for_test(&slot_hashes);
let slot_hashes_sysvar = create_account(&slot_hashes, 1);
assert_eq!(
parse_sysvar(&slot_hashes_sysvar.data, &sysvar::slot_hashes::id()).unwrap(),
SysvarAccountType::SlotHashes(vec![UiSlotHashEntry {
@@ -295,7 +293,7 @@ mod test {
let mut slot_history = SlotHistory::default();
slot_history.add(42);
let slot_history_sysvar = create_account_for_test(&slot_history);
let slot_history_sysvar = create_account(&slot_history, 1);
assert_eq!(
parse_sysvar(&slot_history_sysvar.data, &sysvar::slot_history::id()).unwrap(),
SysvarAccountType::SlotHistory(UiSlotHistory {
@@ -311,7 +309,7 @@ mod test {
deactivating: 3,
};
stake_history.add(1, stake_history_entry.clone());
let stake_history_sysvar = create_account_for_test(&stake_history);
let stake_history_sysvar = create_account(&stake_history, 1);
assert_eq!(
parse_sysvar(&stake_history_sysvar.data, &sysvar::stake_history::id()).unwrap(),
SysvarAccountType::StakeHistory(vec![UiStakeHistoryEntry {

View File

@@ -1,6 +1,6 @@
use crate::{
parse_account_data::{ParsableAccount, ParseAccountError},
StringAmount, StringDecimals,
StringAmount,
};
use solana_sdk::pubkey::Pubkey;
use spl_token_v2_0::{
@@ -23,16 +23,6 @@ pub fn spl_token_v2_0_native_mint() -> Pubkey {
Pubkey::from_str(&spl_token_v2_0::native_mint::id().to_string()).unwrap()
}
// A helper function to convert a solana_sdk::pubkey::Pubkey to spl_sdk::pubkey::Pubkey
pub fn spl_token_v2_0_pubkey(pubkey: &Pubkey) -> SplTokenPubkey {
SplTokenPubkey::from_str(&pubkey.to_string()).unwrap()
}
// A helper function to convert a spl_sdk::pubkey::Pubkey to solana_sdk::pubkey::Pubkey
pub fn pubkey_from_spl_token_v2_0(pubkey: &SplTokenPubkey) -> Pubkey {
Pubkey::from_str(&pubkey.to_string()).unwrap()
}
pub fn parse_token(
data: &[u8],
mint_decimals: Option<u8>,
@@ -158,66 +148,46 @@ impl From<AccountState> for UiAccountState {
}
}
pub fn real_number_string(amount: u64, decimals: u8) -> StringDecimals {
let decimals = decimals as usize;
if decimals > 0 {
// Left-pad zeros to decimals + 1, so we at least have an integer zero
let mut s = format!("{:01$}", amount, decimals + 1);
// Add the decimal point (Sorry, "," locales!)
s.insert(s.len() - decimals, '.');
s
} else {
amount.to_string()
}
}
pub fn real_number_string_trimmed(amount: u64, decimals: u8) -> StringDecimals {
let mut s = real_number_string(amount, decimals);
if decimals > 0 {
let zeros_trimmed = s.trim_end_matches('0');
s = zeros_trimmed.trim_end_matches('.').to_string();
}
s
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiTokenAmount {
pub ui_amount: Option<f64>,
pub ui_amount: f64,
pub decimals: u8,
pub amount: StringAmount,
pub ui_amount_string: StringDecimals,
}
impl UiTokenAmount {
pub fn real_number_string(&self) -> String {
real_number_string(
u64::from_str(&self.amount).unwrap_or_default(),
self.decimals as u8,
)
let decimals = self.decimals as usize;
if decimals > 0 {
let amount = u64::from_str(&self.amount).unwrap_or(0);
// Left-pad zeros to decimals + 1, so we at least have an integer zero
let mut s = format!("{:01$}", amount, decimals + 1);
// Add the decimal point (Sorry, "," locales!)
s.insert(s.len() - decimals, '.');
s
} else {
self.amount.clone()
}
}
pub fn real_number_string_trimmed(&self) -> String {
if !self.ui_amount_string.is_empty() {
self.ui_amount_string.clone()
} else {
real_number_string_trimmed(
u64::from_str(&self.amount).unwrap_or_default(),
self.decimals as u8,
)
}
let s = self.real_number_string();
let zeros_trimmed = s.trim_end_matches('0');
let decimal_trimmed = zeros_trimmed.trim_end_matches('.');
decimal_trimmed.to_string()
}
}
pub fn token_amount_to_ui_amount(amount: u64, decimals: u8) -> UiTokenAmount {
let amount_decimals = 10_usize
.checked_pow(decimals as u32)
.map(|dividend| amount as f64 / dividend as f64);
// Use `amount_to_ui_amount()` once spl_token is bumped to a version that supports it: https://github.com/solana-labs/solana-program-library/pull/211
let amount_decimals = amount as f64 / 10_usize.pow(decimals as u32) as f64;
UiTokenAmount {
ui_amount: amount_decimals,
decimals,
amount: amount.to_string(),
ui_amount_string: real_number_string_trimmed(amount, decimals),
}
}
@@ -273,10 +243,9 @@ mod test {
mint: mint_pubkey.to_string(),
owner: owner_pubkey.to_string(),
token_amount: UiTokenAmount {
ui_amount: Some(0.42),
ui_amount: 0.42,
decimals: 2,
amount: "42".to_string(),
ui_amount_string: "0.42".to_string()
amount: "42".to_string()
},
delegate: None,
state: UiAccountState::Initialized,
@@ -357,87 +326,17 @@ mod test {
#[test]
fn test_ui_token_amount_real_string() {
assert_eq!(&real_number_string(1, 0), "1");
assert_eq!(&real_number_string_trimmed(1, 0), "1");
let token_amount = token_amount_to_ui_amount(1, 0);
assert_eq!(
token_amount.ui_amount_string,
real_number_string_trimmed(1, 0)
);
assert_eq!(token_amount.ui_amount, Some(1.0));
assert_eq!(&real_number_string(10, 0), "10");
assert_eq!(&real_number_string_trimmed(10, 0), "10");
let token_amount = token_amount_to_ui_amount(10, 0);
assert_eq!(
token_amount.ui_amount_string,
real_number_string_trimmed(10, 0)
);
assert_eq!(token_amount.ui_amount, Some(10.0));
assert_eq!(&real_number_string(1, 9), "0.000000001");
assert_eq!(&real_number_string_trimmed(1, 9), "0.000000001");
assert_eq!(&token_amount.real_number_string(), "1");
assert_eq!(&token_amount.real_number_string_trimmed(), "1");
let token_amount = token_amount_to_ui_amount(1, 9);
assert_eq!(
token_amount.ui_amount_string,
real_number_string_trimmed(1, 9)
);
assert_eq!(token_amount.ui_amount, Some(0.000000001));
assert_eq!(&real_number_string(1_000_000_000, 9), "1.000000000");
assert_eq!(&real_number_string_trimmed(1_000_000_000, 9), "1");
assert_eq!(&token_amount.real_number_string(), "0.000000001");
assert_eq!(&token_amount.real_number_string_trimmed(), "0.000000001");
let token_amount = token_amount_to_ui_amount(1_000_000_000, 9);
assert_eq!(
token_amount.ui_amount_string,
real_number_string_trimmed(1_000_000_000, 9)
);
assert_eq!(token_amount.ui_amount, Some(1.0));
assert_eq!(&real_number_string(1_234_567_890, 3), "1234567.890");
assert_eq!(&real_number_string_trimmed(1_234_567_890, 3), "1234567.89");
assert_eq!(&token_amount.real_number_string(), "1.000000000");
assert_eq!(&token_amount.real_number_string_trimmed(), "1");
let token_amount = token_amount_to_ui_amount(1_234_567_890, 3);
assert_eq!(
token_amount.ui_amount_string,
real_number_string_trimmed(1_234_567_890, 3)
);
assert_eq!(token_amount.ui_amount, Some(1234567.89));
assert_eq!(
&real_number_string(1_234_567_890, 25),
"0.0000000000000001234567890"
);
assert_eq!(
&real_number_string_trimmed(1_234_567_890, 25),
"0.000000000000000123456789"
);
let token_amount = token_amount_to_ui_amount(1_234_567_890, 20);
assert_eq!(
token_amount.ui_amount_string,
real_number_string_trimmed(1_234_567_890, 20)
);
assert_eq!(token_amount.ui_amount, None);
}
#[test]
fn test_ui_token_amount_real_string_zero() {
assert_eq!(&real_number_string(0, 0), "0");
assert_eq!(&real_number_string_trimmed(0, 0), "0");
let token_amount = token_amount_to_ui_amount(0, 0);
assert_eq!(
token_amount.ui_amount_string,
real_number_string_trimmed(0, 0)
);
assert_eq!(token_amount.ui_amount, Some(0.0));
assert_eq!(&real_number_string(0, 9), "0.000000000");
assert_eq!(&real_number_string_trimmed(0, 9), "0");
let token_amount = token_amount_to_ui_amount(0, 9);
assert_eq!(
token_amount.ui_amount_string,
real_number_string_trimmed(0, 9)
);
assert_eq!(token_amount.ui_amount, Some(0.0));
assert_eq!(&real_number_string(0, 25), "0.0000000000000000000000000");
assert_eq!(&real_number_string_trimmed(0, 25), "0");
let token_amount = token_amount_to_ui_amount(0, 20);
assert_eq!(
token_amount.ui_amount_string,
real_number_string_trimmed(0, 20)
);
assert_eq!(token_amount.ui_amount, None);
assert_eq!(&token_amount.real_number_string(), "1234567.890");
assert_eq!(&token_amount.real_number_string_trimmed(), "1234567.89");
}
}

View File

@@ -128,13 +128,11 @@ mod test {
fn test_parse_vote() {
let vote_state = VoteState::default();
let mut vote_account_data: Vec<u8> = vec![0; VoteState::size_of()];
let versioned = VoteStateVersions::new_current(vote_state);
let versioned = VoteStateVersions::Current(Box::new(vote_state));
VoteState::serialize(&versioned, &mut vote_account_data).unwrap();
let expected_vote_state = UiVoteState {
node_pubkey: Pubkey::default().to_string(),
authorized_withdrawer: Pubkey::default().to_string(),
..UiVoteState::default()
};
let mut expected_vote_state = UiVoteState::default();
expected_vote_state.node_pubkey = Pubkey::default().to_string();
expected_vote_state.authorized_withdrawer = Pubkey::default().to_string();
assert_eq!(
parse_vote(&vote_account_data).unwrap(),
VoteAccountType::Vote(expected_vote_state)

View File

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

View File

@@ -1,15 +1,14 @@
#![allow(clippy::integer_arithmetic)]
#[macro_use]
extern crate log;
use clap::{crate_description, crate_name, value_t, App, Arg};
use rayon::prelude::*;
use solana_measure::measure::Measure;
use solana_runtime::{
accounts::{create_test_accounts, update_accounts_bench, Accounts},
accounts::{create_test_accounts, update_accounts, Accounts},
accounts_index::Ancestors,
};
use solana_sdk::{genesis_config::ClusterType, pubkey::Pubkey};
use std::{collections::HashSet, env, fs, path::PathBuf};
use std::env;
use std::fs;
use std::path::PathBuf;
fn main() {
solana_logger::setup();
@@ -54,12 +53,10 @@ fn main() {
let path = PathBuf::from(env::var("FARF_DIR").unwrap_or_else(|_| "farf".to_owned()))
.join("accounts-bench");
println!("cleaning file system: {:?}", path);
if fs::remove_dir_all(path.clone()).is_err() {
println!("Warning: Couldn't remove {:?}", path);
}
let accounts =
Accounts::new_with_config(vec![path], &ClusterType::Testnet, HashSet::new(), false);
let accounts = Accounts::new(vec![path], &ClusterType::Testnet);
println!("Creating {} accounts", num_accounts);
let mut create_time = Measure::start("create accounts");
let pubkeys: Vec<_> = (0..num_slots)
@@ -88,8 +85,6 @@ fn main() {
ancestors.insert(i as u64, i - 1);
accounts.add_root(i as u64);
}
let mut elapsed = vec![0; iterations];
let mut elapsed_store = vec![0; iterations];
for x in 0..iterations {
if clean {
let mut time = Measure::start("clean");
@@ -97,43 +92,16 @@ fn main() {
time.stop();
println!("{}", time);
for slot in 0..num_slots {
update_accounts_bench(&accounts, &pubkeys, ((x + 1) * num_slots + slot) as u64);
update_accounts(&accounts, &pubkeys, ((x + 1) * num_slots + slot) as u64);
accounts.add_root((x * num_slots + slot) as u64);
}
} else {
let mut pubkeys: Vec<Pubkey> = vec![];
let mut time = Measure::start("hash");
let results = accounts.accounts_db.update_accounts_hash(0, &ancestors);
let hash = accounts.accounts_db.update_accounts_hash(0, &ancestors).0;
time.stop();
let mut time_store = Measure::start("hash using store");
let results_store = accounts.accounts_db.update_accounts_hash_with_index_option(
false,
false,
solana_sdk::clock::Slot::default(),
&ancestors,
None,
);
time_store.stop();
if results != results_store {
error!("results different: \n{:?}\n{:?}", results, results_store);
}
println!(
"hash,{},{},{},{}%",
results.0,
time,
time_store,
(time_store.as_us() as f64 / time.as_us() as f64 * 100.0f64) as u32
);
println!("hash: {} {}", hash, time);
create_test_accounts(&accounts, &mut pubkeys, 1, 0);
elapsed[x] = time.as_us();
elapsed_store[x] = time_store.as_us();
}
}
for x in elapsed {
info!("update_accounts_hash(us),{}", x);
}
for x in elapsed_store {
info!("calculate_accounts_hash_without_index(us),{}", x);
}
}

View File

@@ -1 +0,0 @@
/farf/

View File

@@ -1,34 +0,0 @@
[package]
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-accounts-cluster-bench"
version = "1.6.2"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
publish = false
[dependencies]
clap = "2.33.1"
log = "0.4.11"
rand = "0.7.0"
rayon = "1.4.1"
solana-account-decoder = { path = "../account-decoder", version = "=1.6.2" }
solana-clap-utils = { path = "../clap-utils", version = "=1.6.2" }
solana-client = { path = "../client", version = "=1.6.2" }
solana-core = { path = "../core", version = "=1.6.2" }
solana-measure = { path = "../measure", version = "=1.6.2" }
solana-logger = { path = "../logger", version = "=1.6.2" }
solana-net-utils = { path = "../net-utils", version = "=1.6.2" }
solana-faucet = { path = "../faucet", version = "=1.6.2" }
solana-runtime = { path = "../runtime", version = "=1.6.2" }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
solana-transaction-status = { path = "../transaction-status", version = "=1.6.2" }
solana-version = { path = "../version", version = "=1.6.2" }
spl-token-v2-0 = { package = "spl-token", version = "=3.1.0", features = ["no-entrypoint"] }
[dev-dependencies]
solana-local-cluster = { path = "../local-cluster", version = "=1.6.2" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,712 +0,0 @@
#![allow(clippy::integer_arithmetic)]
use clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg};
use log::*;
use rand::{thread_rng, Rng};
use rayon::prelude::*;
use solana_account_decoder::parse_token::spl_token_v2_0_pubkey;
use solana_clap_utils::input_parsers::pubkey_of;
use solana_client::rpc_client::RpcClient;
use solana_core::gossip_service::discover;
use solana_faucet::faucet::{request_airdrop_transaction, FAUCET_PORT};
use solana_measure::measure::Measure;
use solana_runtime::inline_spl_token_v2_0;
use solana_sdk::{
commitment_config::CommitmentConfig,
message::Message,
pubkey::Pubkey,
rpc_port::DEFAULT_RPC_PORT,
signature::{read_keypair_file, Keypair, Signature, Signer},
system_instruction, system_program,
timing::timestamp,
transaction::Transaction,
};
use solana_transaction_status::parse_token::spl_token_v2_0_instruction;
use std::{
net::SocketAddr,
process::exit,
sync::{
atomic::{AtomicBool, AtomicU64, Ordering},
Arc, RwLock,
},
thread::{sleep, Builder, JoinHandle},
time::{Duration, Instant},
};
pub fn airdrop_lamports(
client: &RpcClient,
faucet_addr: &SocketAddr,
id: &Keypair,
desired_balance: u64,
) -> bool {
let starting_balance = client.get_balance(&id.pubkey()).unwrap_or(0);
info!("starting balance {}", starting_balance);
if starting_balance < desired_balance {
let airdrop_amount = desired_balance - starting_balance;
info!(
"Airdropping {:?} lamports from {} for {}",
airdrop_amount,
faucet_addr,
id.pubkey(),
);
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();
match request_airdrop_transaction(&faucet_addr, &id.pubkey(), airdrop_amount, blockhash) {
Ok(transaction) => {
let mut tries = 0;
loop {
tries += 1;
let result = client.send_and_confirm_transaction(&transaction);
if result.is_ok() {
break;
}
if tries >= 5 {
panic!(
"Error requesting airdrop: to addr: {:?} amount: {} {:?}",
faucet_addr, airdrop_amount, result
)
}
}
}
Err(err) => {
panic!(
"Error requesting airdrop: {:?} to addr: {:?} amount: {}",
err, faucet_addr, airdrop_amount
);
}
};
let current_balance = client.get_balance(&id.pubkey()).unwrap_or_else(|e| {
panic!("airdrop error {}", e);
});
info!("current balance {}...", current_balance);
if current_balance - starting_balance != airdrop_amount {
info!(
"Airdrop failed? {} {} {} {}",
id.pubkey(),
current_balance,
starting_balance,
airdrop_amount,
);
}
}
true
}
// signature, timestamp, id
type PendingQueue = Vec<(Signature, u64, u64)>;
struct TransactionExecutor {
sig_clear_t: JoinHandle<()>,
sigs: Arc<RwLock<PendingQueue>>,
cleared: Arc<RwLock<Vec<u64>>>,
exit: Arc<AtomicBool>,
counter: AtomicU64,
client: RpcClient,
}
impl TransactionExecutor {
fn new(entrypoint_addr: SocketAddr) -> Self {
let sigs = Arc::new(RwLock::new(Vec::new()));
let cleared = Arc::new(RwLock::new(Vec::new()));
let exit = Arc::new(AtomicBool::new(false));
let sig_clear_t = Self::start_sig_clear_thread(&exit, &sigs, &cleared, entrypoint_addr);
let client =
RpcClient::new_socket_with_commitment(entrypoint_addr, CommitmentConfig::confirmed());
Self {
sigs,
cleared,
sig_clear_t,
exit,
counter: AtomicU64::new(0),
client,
}
}
fn num_outstanding(&self) -> usize {
self.sigs.read().unwrap().len()
}
fn push_transactions(&self, txs: Vec<Transaction>) -> Vec<u64> {
let mut ids = vec![];
let new_sigs = txs.into_iter().filter_map(|tx| {
let id = self.counter.fetch_add(1, Ordering::Relaxed);
ids.push(id);
match self.client.send_transaction(&tx) {
Ok(sig) => {
return Some((sig, timestamp(), id));
}
Err(e) => {
info!("error: {:#?}", e);
}
}
None
});
let mut sigs_w = self.sigs.write().unwrap();
sigs_w.extend(new_sigs);
ids
}
fn drain_cleared(&self) -> Vec<u64> {
std::mem::take(&mut *self.cleared.write().unwrap())
}
fn close(self) {
self.exit.store(true, Ordering::Relaxed);
self.sig_clear_t.join().unwrap();
}
fn start_sig_clear_thread(
exit: &Arc<AtomicBool>,
sigs: &Arc<RwLock<PendingQueue>>,
cleared: &Arc<RwLock<Vec<u64>>>,
entrypoint_addr: SocketAddr,
) -> JoinHandle<()> {
let sigs = sigs.clone();
let exit = exit.clone();
let cleared = cleared.clone();
Builder::new()
.name("sig_clear".to_string())
.spawn(move || {
let client = RpcClient::new_socket_with_commitment(
entrypoint_addr,
CommitmentConfig::confirmed(),
);
let mut success = 0;
let mut error_count = 0;
let mut timed_out = 0;
let mut last_log = Instant::now();
while !exit.load(Ordering::Relaxed) {
let sigs_len = sigs.read().unwrap().len();
if sigs_len > 0 {
let mut sigs_w = sigs.write().unwrap();
let mut start = Measure::start("sig_status");
let statuses: Vec<_> = sigs_w
.chunks(200)
.map(|sig_chunk| {
let only_sigs: Vec<_> = sig_chunk.iter().map(|s| s.0).collect();
client
.get_signature_statuses(&only_sigs)
.expect("status fail")
.value
})
.flatten()
.collect();
let mut num_cleared = 0;
let start_len = sigs_w.len();
let now = timestamp();
let mut new_ids = vec![];
let mut i = 0;
let mut j = 0;
while i != sigs_w.len() {
let mut retain = true;
let sent_ts = sigs_w[i].1;
if let Some(e) = &statuses[j] {
debug!("error: {:?}", e);
if e.status.is_ok() {
success += 1;
} else {
error_count += 1;
}
num_cleared += 1;
retain = false;
} else if now - sent_ts > 30_000 {
retain = false;
timed_out += 1;
}
if !retain {
new_ids.push(sigs_w.remove(i).2);
} else {
i += 1;
}
j += 1;
}
let final_sigs_len = sigs_w.len();
drop(sigs_w);
cleared.write().unwrap().extend(new_ids);
start.stop();
debug!(
"sigs len: {:?} success: {} took: {}ms cleared: {}/{}",
final_sigs_len,
success,
start.as_ms(),
num_cleared,
start_len,
);
if last_log.elapsed().as_millis() > 5000 {
info!(
"success: {} error: {} timed_out: {}",
success, error_count, timed_out,
);
last_log = Instant::now();
}
}
sleep(Duration::from_millis(200));
}
})
.unwrap()
}
}
struct SeedTracker {
max_created: Arc<AtomicU64>,
max_closed: Arc<AtomicU64>,
}
fn make_create_message(
keypair: &Keypair,
base_keypair: &Keypair,
max_created_seed: Arc<AtomicU64>,
num_instructions: usize,
balance: u64,
maybe_space: Option<u64>,
mint: Option<Pubkey>,
) -> Message {
let space = maybe_space.unwrap_or_else(|| thread_rng().gen_range(0, 1000));
let instructions: Vec<_> = (0..num_instructions)
.into_iter()
.map(|_| {
let program_id = if mint.is_some() {
inline_spl_token_v2_0::id()
} else {
system_program::id()
};
let seed = max_created_seed.fetch_add(1, Ordering::Relaxed).to_string();
let to_pubkey =
Pubkey::create_with_seed(&base_keypair.pubkey(), &seed, &program_id).unwrap();
let mut instructions = vec![system_instruction::create_account_with_seed(
&keypair.pubkey(),
&to_pubkey,
&base_keypair.pubkey(),
&seed,
balance,
space,
&program_id,
)];
if let Some(mint_address) = mint {
instructions.push(spl_token_v2_0_instruction(
spl_token_v2_0::instruction::initialize_account(
&spl_token_v2_0::id(),
&spl_token_v2_0_pubkey(&to_pubkey),
&spl_token_v2_0_pubkey(&mint_address),
&spl_token_v2_0_pubkey(&base_keypair.pubkey()),
)
.unwrap(),
));
}
instructions
})
.collect();
let instructions: Vec<_> = instructions.into_iter().flatten().collect();
Message::new(&instructions, Some(&keypair.pubkey()))
}
fn make_close_message(
keypair: &Keypair,
base_keypair: &Keypair,
max_closed_seed: Arc<AtomicU64>,
num_instructions: usize,
balance: u64,
spl_token: bool,
) -> Message {
let instructions: Vec<_> = (0..num_instructions)
.into_iter()
.map(|_| {
let program_id = if spl_token {
inline_spl_token_v2_0::id()
} else {
system_program::id()
};
let seed = max_closed_seed.fetch_add(1, Ordering::Relaxed).to_string();
let address =
Pubkey::create_with_seed(&base_keypair.pubkey(), &seed, &program_id).unwrap();
if spl_token {
spl_token_v2_0_instruction(
spl_token_v2_0::instruction::close_account(
&spl_token_v2_0::id(),
&spl_token_v2_0_pubkey(&address),
&spl_token_v2_0_pubkey(&keypair.pubkey()),
&spl_token_v2_0_pubkey(&base_keypair.pubkey()),
&[],
)
.unwrap(),
)
} else {
system_instruction::transfer_with_seed(
&address,
&base_keypair.pubkey(),
seed,
&program_id,
&keypair.pubkey(),
balance,
)
}
})
.collect();
Message::new(&instructions, Some(&keypair.pubkey()))
}
#[allow(clippy::too_many_arguments)]
fn run_accounts_bench(
entrypoint_addr: SocketAddr,
faucet_addr: SocketAddr,
keypair: &Keypair,
iterations: usize,
maybe_space: Option<u64>,
batch_size: usize,
close_nth: u64,
maybe_lamports: Option<u64>,
num_instructions: usize,
mint: Option<Pubkey>,
) {
assert!(num_instructions > 0);
let client =
RpcClient::new_socket_with_commitment(entrypoint_addr, CommitmentConfig::confirmed());
info!("Targetting {}", entrypoint_addr);
let mut last_blockhash = Instant::now();
let mut last_log = Instant::now();
let mut count = 0;
let mut recent_blockhash = client.get_recent_blockhash().expect("blockhash");
let mut tx_sent_count = 0;
let mut total_accounts_created = 0;
let mut total_accounts_closed = 0;
let mut balance = client.get_balance(&keypair.pubkey()).unwrap_or(0);
let mut last_balance = Instant::now();
let default_max_lamports = 1000;
let min_balance = maybe_lamports.unwrap_or_else(|| {
let space = maybe_space.unwrap_or(default_max_lamports);
client
.get_minimum_balance_for_rent_exemption(space as usize)
.expect("min balance")
});
let base_keypair = Keypair::new();
let seed_tracker = SeedTracker {
max_created: Arc::new(AtomicU64::default()),
max_closed: Arc::new(AtomicU64::default()),
};
info!("Starting balance: {}", balance);
let executor = TransactionExecutor::new(entrypoint_addr);
loop {
if last_blockhash.elapsed().as_millis() > 10_000 {
recent_blockhash = client.get_recent_blockhash().expect("blockhash");
last_blockhash = Instant::now();
}
let message = make_create_message(
keypair,
&base_keypair,
seed_tracker.max_created.clone(),
num_instructions,
min_balance,
maybe_space,
mint,
);
let fee = recent_blockhash.1.calculate_fee(&message);
let lamports = min_balance + fee;
if balance < lamports || last_balance.elapsed().as_millis() > 2000 {
if let Ok(b) = client.get_balance(&keypair.pubkey()) {
balance = b;
}
last_balance = Instant::now();
if balance < lamports {
info!(
"Balance {} is less than needed: {}, doing aidrop...",
balance, lamports
);
if !airdrop_lamports(&client, &faucet_addr, keypair, lamports * 100_000) {
warn!("failed airdrop, exiting");
return;
}
}
}
let sigs_len = executor.num_outstanding();
if sigs_len < batch_size {
let num_to_create = batch_size - sigs_len;
info!("creating {} new", num_to_create);
let txs: Vec<_> = (0..num_to_create)
.into_par_iter()
.map(|_| {
let message = make_create_message(
keypair,
&base_keypair,
seed_tracker.max_created.clone(),
num_instructions,
min_balance,
maybe_space,
mint,
);
let signers: Vec<&Keypair> = vec![keypair, &base_keypair];
Transaction::new(&signers, message, recent_blockhash.0)
})
.collect();
balance = balance.saturating_sub(lamports * txs.len() as u64);
info!("txs: {}", txs.len());
let new_ids = executor.push_transactions(txs);
info!("ids: {}", new_ids.len());
tx_sent_count += new_ids.len();
total_accounts_created += num_instructions * new_ids.len();
if close_nth > 0 {
let expected_closed = total_accounts_created as u64 / close_nth;
if expected_closed > total_accounts_closed {
let txs: Vec<_> = (0..expected_closed - total_accounts_closed)
.into_par_iter()
.map(|_| {
let message = make_close_message(
keypair,
&base_keypair,
seed_tracker.max_closed.clone(),
1,
min_balance,
mint.is_some(),
);
let signers: Vec<&Keypair> = vec![keypair, &base_keypair];
Transaction::new(&signers, message, recent_blockhash.0)
})
.collect();
balance = balance.saturating_sub(fee * txs.len() as u64);
info!("close txs: {}", txs.len());
let new_ids = executor.push_transactions(txs);
info!("close ids: {}", new_ids.len());
tx_sent_count += new_ids.len();
total_accounts_closed += new_ids.len() as u64;
}
}
} else {
let _ = executor.drain_cleared();
}
count += 1;
if last_log.elapsed().as_millis() > 3000 {
info!(
"total_accounts_created: {} total_accounts_closed: {} tx_sent_count: {} loop_count: {} balance: {}",
total_accounts_created, total_accounts_closed, tx_sent_count, count, balance
);
last_log = Instant::now();
}
if iterations != 0 && count >= iterations {
break;
}
if executor.num_outstanding() >= batch_size {
sleep(Duration::from_millis(500));
}
}
executor.close();
}
fn main() {
solana_logger::setup_with_default("solana=info");
let matches = App::new(crate_name!())
.about(crate_description!())
.version(solana_version::version!())
.arg(
Arg::with_name("entrypoint")
.long("entrypoint")
.takes_value(true)
.value_name("HOST:PORT")
.help("RPC entrypoint address. Usually <ip>:8899"),
)
.arg(
Arg::with_name("faucet_addr")
.long("faucet")
.takes_value(true)
.value_name("HOST:PORT")
.help("Faucet entrypoint address. Usually <ip>:9900"),
)
.arg(
Arg::with_name("space")
.long("space")
.takes_value(true)
.value_name("BYTES")
.help("Size of accounts to create"),
)
.arg(
Arg::with_name("lamports")
.long("lamports")
.takes_value(true)
.value_name("LAMPORTS")
.help("How many lamports to fund each account"),
)
.arg(
Arg::with_name("identity")
.long("identity")
.takes_value(true)
.value_name("FILE")
.help("keypair file"),
)
.arg(
Arg::with_name("batch_size")
.long("batch-size")
.takes_value(true)
.value_name("BYTES")
.help("Number of transactions to send per batch"),
)
.arg(
Arg::with_name("close_nth")
.long("close-frequency")
.takes_value(true)
.value_name("BYTES")
.help("Send close transactions after this many accounts created"),
)
.arg(
Arg::with_name("num_instructions")
.long("num-instructions")
.takes_value(true)
.value_name("NUM")
.help("Number of accounts to create on each transaction"),
)
.arg(
Arg::with_name("iterations")
.long("iterations")
.takes_value(true)
.value_name("NUM")
.help("Number of iterations to make"),
)
.arg(
Arg::with_name("check_gossip")
.long("check-gossip")
.help("Just use entrypoint address directly"),
)
.arg(
Arg::with_name("mint")
.long("mint")
.takes_value(true)
.help("Mint address to initialize account"),
)
.get_matches();
let skip_gossip = !matches.is_present("check_gossip");
let port = if skip_gossip { DEFAULT_RPC_PORT } else { 8001 };
let mut entrypoint_addr = SocketAddr::from(([127, 0, 0, 1], port));
if let Some(addr) = matches.value_of("entrypoint") {
entrypoint_addr = solana_net_utils::parse_host_port(addr).unwrap_or_else(|e| {
eprintln!("failed to parse entrypoint address: {}", e);
exit(1)
});
}
let mut faucet_addr = SocketAddr::from(([127, 0, 0, 1], FAUCET_PORT));
if let Some(addr) = matches.value_of("faucet_addr") {
faucet_addr = solana_net_utils::parse_host_port(addr).unwrap_or_else(|e| {
eprintln!("failed to parse entrypoint address: {}", e);
exit(1)
});
}
let space = value_t!(matches, "space", u64).ok();
let lamports = value_t!(matches, "lamports", u64).ok();
let batch_size = value_t!(matches, "batch_size", usize).unwrap_or(4);
let close_nth = value_t!(matches, "close_nth", u64).unwrap_or(0);
let iterations = value_t!(matches, "iterations", usize).unwrap_or(10);
let num_instructions = value_t!(matches, "num_instructions", usize).unwrap_or(1);
if num_instructions == 0 || num_instructions > 500 {
eprintln!("bad num_instructions: {}", num_instructions);
exit(1);
}
let mint = pubkey_of(&matches, "mint");
let keypair =
read_keypair_file(&value_t_or_exit!(matches, "identity", String)).expect("bad keypair");
let rpc_addr = if !skip_gossip {
info!("Finding cluster entry: {:?}", entrypoint_addr);
let (gossip_nodes, _validators) = discover(
None,
Some(&entrypoint_addr),
None,
Some(60),
None,
Some(&entrypoint_addr),
None,
0,
)
.unwrap_or_else(|err| {
eprintln!("Failed to discover {} node: {:?}", entrypoint_addr, err);
exit(1);
});
info!("done found {} nodes", gossip_nodes.len());
gossip_nodes[0].rpc
} else {
info!("Using {:?} as the RPC address", entrypoint_addr);
entrypoint_addr
};
run_accounts_bench(
rpc_addr,
faucet_addr,
&keypair,
iterations,
space,
batch_size,
close_nth,
lamports,
num_instructions,
mint,
);
}
#[cfg(test)]
pub mod test {
use super::*;
use solana_core::validator::ValidatorConfig;
use solana_local_cluster::{
local_cluster::{ClusterConfig, LocalCluster},
validator_configs::make_identical_validator_configs,
};
use solana_sdk::poh_config::PohConfig;
#[test]
fn test_accounts_cluster_bench() {
solana_logger::setup();
let validator_config = ValidatorConfig::default();
let num_nodes = 1;
let mut config = ClusterConfig {
cluster_lamports: 10_000_000,
poh_config: PohConfig::new_sleep(Duration::from_millis(50)),
node_stakes: vec![100; num_nodes],
validator_configs: make_identical_validator_configs(&validator_config, num_nodes),
..ClusterConfig::default()
};
let faucet_addr = SocketAddr::from(([127, 0, 0, 1], 9900));
let cluster = LocalCluster::new(&mut config);
let iterations = 10;
let maybe_space = None;
let batch_size = 100;
let close_nth = 100;
let maybe_lamports = None;
let num_instructions = 2;
let mut start = Measure::start("total accounts run");
run_accounts_bench(
cluster.entry_point_info.rpc,
faucet_addr,
&cluster.funding_keypair,
iterations,
maybe_space,
batch_size,
close_nth,
maybe_lamports,
num_instructions,
None,
);
start.stop();
info!("{}", start);
}
}

View File

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

View File

@@ -1,4 +1,3 @@
#![allow(clippy::integer_arithmetic)]
use clap::{crate_description, crate_name, value_t, App, Arg};
use crossbeam_channel::unbounded;
use log::*;
@@ -18,9 +17,7 @@ use solana_ledger::{
};
use solana_measure::measure::Measure;
use solana_perf::packet::to_packets_chunked;
use solana_runtime::{
accounts_background_service::AbsRequestSender, bank::Bank, bank_forks::BankForks,
};
use solana_runtime::{bank::Bank, bank_forks::BankForks};
use solana_sdk::{
hash::Hash,
signature::Keypair,
@@ -326,7 +323,7 @@ fn main() {
poh_recorder.lock().unwrap().set_bank(&bank);
assert!(poh_recorder.lock().unwrap().bank().is_some());
if bank.slot() > 32 {
bank_forks.set_root(root, &AbsRequestSender::default(), None);
bank_forks.set_root(root, &None, None);
root += 1;
}
debug!(

View File

@@ -1,30 +1,26 @@
[package]
name = "solana-banks-client"
version = "1.6.2"
version = "1.4.7"
description = "Solana banks client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-banks-client"
edition = "2018"
[dependencies]
async-trait = "0.1.36"
bincode = "1.3.1"
borsh = "0.8.1"
borsh-derive = "0.8.1"
futures = "0.3"
mio = "0.7.6"
solana-banks-interface = { path = "../banks-interface", version = "=1.6.2" }
solana-program = { path = "../sdk/program", version = "=1.6.2" }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
tarpc = { version = "0.24.1", features = ["full"] }
tokio = { version = "1.1", features = ["full"] }
tokio-serde = { version = "0.8", features = ["bincode"] }
solana-banks-interface = { path = "../banks-interface", version = "1.4.7" }
solana-sdk = { path = "../sdk", version = "1.4.7" }
tarpc = { version = "0.23.0", features = ["full"] }
tokio = { version = "0.3", features = ["full"] }
tokio-serde = { version = "0.6", features = ["bincode"] }
[dev-dependencies]
solana-runtime = { path = "../runtime", version = "=1.6.2" }
solana-banks-server = { path = "../banks-server", version = "=1.6.2" }
solana-runtime = { path = "../runtime", version = "1.4.7" }
solana-banks-server = { path = "../banks-server", version = "1.4.7" }
[lib]
crate-type = ["lib"]

View File

@@ -5,276 +5,200 @@
//! but they are undocumented, may change over time, and are generally more
//! cumbersome to use.
use borsh::BorshDeserialize;
use futures::{future::join_all, Future, FutureExt};
pub use solana_banks_interface::{BanksClient as TarpcClient, TransactionStatus};
use async_trait::async_trait;
use futures::future::join_all;
pub use solana_banks_interface::{BanksClient, TransactionStatus};
use solana_banks_interface::{BanksRequest, BanksResponse};
use solana_program::{
clock::Slot, fee_calculator::FeeCalculator, hash::Hash, program_pack::Pack, pubkey::Pubkey,
rent::Rent, sysvar,
};
use solana_sdk::{
account::{from_account, Account},
clock::Slot,
commitment_config::CommitmentLevel,
fee_calculator::FeeCalculator,
hash::Hash,
pubkey::Pubkey,
rent::Rent,
signature::Signature,
transaction::{self, Transaction},
sysvar,
transaction::Transaction,
transport,
};
use std::io::{self, Error, ErrorKind};
use tarpc::{
client::{self, channel::RequestDispatch, NewClient},
context::{self, Context},
rpc::{ClientMessage, Response},
client, context,
rpc::{transport::channel::UnboundedChannel, ClientMessage, Response},
serde_transport::tcp,
Transport,
};
use tokio::{net::ToSocketAddrs, time::Duration};
use tokio_serde::formats::Bincode;
// This exists only for backward compatibility
pub trait BanksClientExt {}
#[derive(Clone)]
pub struct BanksClient {
inner: TarpcClient,
}
impl BanksClient {
#[allow(clippy::new_ret_no_self)]
pub fn new<C>(
config: client::Config,
transport: C,
) -> NewClient<TarpcClient, RequestDispatch<BanksRequest, BanksResponse, C>>
where
C: Transport<ClientMessage<BanksRequest>, Response<BanksResponse>>,
{
TarpcClient::new(config, transport)
}
pub fn send_transaction_with_context(
&mut self,
ctx: Context,
transaction: Transaction,
) -> impl Future<Output = io::Result<()>> + '_ {
self.inner.send_transaction_with_context(ctx, transaction)
}
pub fn get_fees_with_commitment_and_context(
&mut self,
ctx: Context,
commitment: CommitmentLevel,
) -> impl Future<Output = io::Result<(FeeCalculator, Hash, Slot)>> + '_ {
self.inner
.get_fees_with_commitment_and_context(ctx, commitment)
}
pub fn get_transaction_status_with_context(
&mut self,
ctx: Context,
signature: Signature,
) -> impl Future<Output = io::Result<Option<TransactionStatus>>> + '_ {
self.inner
.get_transaction_status_with_context(ctx, signature)
}
pub fn get_slot_with_context(
&mut self,
ctx: Context,
commitment: CommitmentLevel,
) -> impl Future<Output = io::Result<Slot>> + '_ {
self.inner.get_slot_with_context(ctx, commitment)
}
pub fn process_transaction_with_commitment_and_context(
&mut self,
ctx: Context,
transaction: Transaction,
commitment: CommitmentLevel,
) -> impl Future<Output = io::Result<Option<transaction::Result<()>>>> + '_ {
self.inner
.process_transaction_with_commitment_and_context(ctx, transaction, commitment)
}
pub fn get_account_with_commitment_and_context(
&mut self,
ctx: Context,
address: Pubkey,
commitment: CommitmentLevel,
) -> impl Future<Output = io::Result<Option<Account>>> + '_ {
self.inner
.get_account_with_commitment_and_context(ctx, address, commitment)
}
#[async_trait]
pub trait BanksClientExt {
/// Send a transaction and return immediately. The server will resend the
/// transaction until either it is accepted by the cluster or the transaction's
/// blockhash expires.
pub fn send_transaction(
&mut self,
transaction: Transaction,
) -> impl Future<Output = io::Result<()>> + '_ {
self.send_transaction_with_context(context::current(), transaction)
}
/// Return the fee parameters associated with a recent, rooted blockhash. The cluster
/// will use the transaction's blockhash to look up these same fee parameters and
/// use them to calculate the transaction fee.
pub fn get_fees(
&mut self,
) -> impl Future<Output = io::Result<(FeeCalculator, Hash, Slot)>> + '_ {
self.get_fees_with_commitment_and_context(context::current(), CommitmentLevel::default())
}
/// Return the cluster rent
pub fn get_rent(&mut self) -> impl Future<Output = io::Result<Rent>> + '_ {
self.get_account(sysvar::rent::id()).map(|result| {
let rent_sysvar = result?
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Rent sysvar not present"))?;
from_account::<Rent, _>(&rent_sysvar).ok_or_else(|| {
io::Error::new(io::ErrorKind::Other, "Failed to deserialize Rent sysvar")
})
})
}
async fn send_transaction(&mut self, transaction: Transaction) -> io::Result<()>;
/// Return a recent, rooted blockhash from the server. The cluster will only accept
/// transactions with a blockhash that has not yet expired. Use the `get_fees`
/// method to get both a blockhash and the blockhash's last valid slot.
pub fn get_recent_blockhash(&mut self) -> impl Future<Output = io::Result<Hash>> + '_ {
self.get_fees().map(|result| Ok(result?.1))
}
async fn get_recent_blockhash(&mut self) -> io::Result<Hash>;
/// Return the fee parameters associated with a recent, rooted blockhash. The cluster
/// will use the transaction's blockhash to look up these same fee parameters and
/// use them to calculate the transaction fee.
async fn get_fees(&mut self) -> io::Result<(FeeCalculator, Hash, Slot)>;
/// Return the cluster rent
async fn get_rent(&mut self) -> io::Result<Rent>;
/// Send a transaction and return after the transaction has been rejected or
/// reached the given level of commitment.
pub fn process_transaction_with_commitment(
async fn process_transaction_with_commitment(
&mut self,
transaction: Transaction,
commitment: CommitmentLevel,
) -> impl Future<Output = transport::Result<()>> + '_ {
let mut ctx = context::current();
ctx.deadline += Duration::from_secs(50);
self.process_transaction_with_commitment_and_context(ctx, transaction, commitment)
.map(|result| match result? {
None => {
Err(Error::new(ErrorKind::TimedOut, "invalid blockhash or fee-payer").into())
}
Some(transaction_result) => Ok(transaction_result?),
})
}
) -> transport::Result<()>;
/// Send a transaction and return until the transaction has been finalized or rejected.
pub fn process_transaction(
&mut self,
transaction: Transaction,
) -> impl Future<Output = transport::Result<()>> + '_ {
self.process_transaction_with_commitment(transaction, CommitmentLevel::default())
}
pub async fn process_transactions_with_commitment(
&mut self,
transactions: Vec<Transaction>,
commitment: CommitmentLevel,
) -> transport::Result<()> {
let mut clients: Vec<_> = transactions.iter().map(|_| self.clone()).collect();
let futures = clients
.iter_mut()
.zip(transactions)
.map(|(client, transaction)| {
client.process_transaction_with_commitment(transaction, commitment)
});
let statuses = join_all(futures).await;
statuses.into_iter().collect() // Convert Vec<Result<_, _>> to Result<Vec<_>>
}
/// Send transactions and return until the transaction has been finalized or rejected.
pub fn process_transactions(
&mut self,
transactions: Vec<Transaction>,
) -> impl Future<Output = transport::Result<()>> + '_ {
self.process_transactions_with_commitment(transactions, CommitmentLevel::default())
}
/// Return the most recent rooted slot height. All transactions at or below this height
/// are said to be finalized. The cluster will not fork to a higher slot height.
pub fn get_root_slot(&mut self) -> impl Future<Output = io::Result<Slot>> + '_ {
self.get_slot_with_context(context::current(), CommitmentLevel::default())
}
/// Return the account at the given address at the slot corresponding to the given
/// commitment level. If the account is not found, None is returned.
pub fn get_account_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
) -> impl Future<Output = io::Result<Option<Account>>> + '_ {
self.get_account_with_commitment_and_context(context::current(), address, commitment)
}
/// Return the account at the given address at the time of the most recent root slot.
/// If the account is not found, None is returned.
pub fn get_account(
&mut self,
address: Pubkey,
) -> impl Future<Output = io::Result<Option<Account>>> + '_ {
self.get_account_with_commitment(address, CommitmentLevel::default())
}
/// Return the unpacked account data at the given address
/// If the account is not found, an error is returned
pub fn get_packed_account_data<T: Pack>(
&mut self,
address: Pubkey,
) -> impl Future<Output = io::Result<T>> + '_ {
self.get_account(address).map(|result| {
let account =
result?.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Account not found"))?;
T::unpack_from_slice(&account.data)
.map_err(|_| io::Error::new(io::ErrorKind::Other, "Failed to deserialize account"))
})
}
/// Return the unpacked account data at the given address
/// If the account is not found, an error is returned
pub fn get_account_data_with_borsh<T: BorshDeserialize>(
&mut self,
address: Pubkey,
) -> impl Future<Output = io::Result<T>> + '_ {
self.get_account(address).map(|result| {
let account =
result?.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "account not found"))?;
T::try_from_slice(&account.data)
})
}
/// Return the balance in lamports of an account at the given address at the slot
/// corresponding to the given commitment level.
pub fn get_balance_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
) -> impl Future<Output = io::Result<u64>> + '_ {
self.get_account_with_commitment_and_context(context::current(), address, commitment)
.map(|result| Ok(result?.map(|x| x.lamports).unwrap_or(0)))
}
/// Return the balance in lamports of an account at the given address at the time
/// of the most recent root slot.
pub fn get_balance(&mut self, address: Pubkey) -> impl Future<Output = io::Result<u64>> + '_ {
self.get_balance_with_commitment(address, CommitmentLevel::default())
}
/// Send a transaction and return after the transaction has been finalized or rejected.
async fn process_transaction(&mut self, transaction: Transaction) -> transport::Result<()>;
/// Return the status of a transaction with a signature matching the transaction's first
/// signature. Return None if the transaction is not found, which may be because the
/// blockhash was expired or the fee-paying account had insufficient funds to pay the
/// transaction fee. Note that servers rarely store the full transaction history. This
/// method may return None if the transaction status has been discarded.
pub fn get_transaction_status(
async fn get_transaction_status(
&mut self,
signature: Signature,
) -> impl Future<Output = io::Result<Option<TransactionStatus>>> + '_ {
self.get_transaction_status_with_context(context::current(), signature)
}
) -> io::Result<Option<TransactionStatus>>;
/// Same as get_transaction_status, but for multiple transactions.
pub async fn get_transaction_statuses(
async fn get_transaction_statuses(
&mut self,
signatures: Vec<Signature>,
) -> io::Result<Vec<Option<TransactionStatus>>>;
/// Return the most recent rooted slot height. All transactions at or below this height
/// are said to be finalized. The cluster will not fork to a higher slot height.
async fn get_root_slot(&mut self) -> io::Result<Slot>;
/// Return the account at the given address at the slot corresponding to the given
/// commitment level. If the account is not found, None is returned.
async fn get_account_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
) -> io::Result<Option<Account>>;
/// Return the account at the given address at the time of the most recent root slot.
/// If the account is not found, None is returned.
async fn get_account(&mut self, address: Pubkey) -> io::Result<Option<Account>>;
/// Return the balance in lamports of an account at the given address at the slot
/// corresponding to the given commitment level.
async fn get_balance_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
) -> io::Result<u64>;
/// Return the balance in lamports of an account at the given address at the time
/// of the most recent root slot.
async fn get_balance(&mut self, address: Pubkey) -> io::Result<u64>;
}
#[async_trait]
impl BanksClientExt for BanksClient {
async fn send_transaction(&mut self, transaction: Transaction) -> io::Result<()> {
self.send_transaction_with_context(context::current(), transaction)
.await
}
async fn get_fees(&mut self) -> io::Result<(FeeCalculator, Hash, Slot)> {
self.get_fees_with_commitment_and_context(context::current(), CommitmentLevel::Root)
.await
}
async fn get_rent(&mut self) -> io::Result<Rent> {
let rent_sysvar = self
.get_account(sysvar::rent::id())
.await?
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Rent sysvar not present"))?;
from_account::<Rent>(&rent_sysvar).ok_or_else(|| {
io::Error::new(io::ErrorKind::Other, "Failed to deserialize Rent sysvar")
})
}
async fn get_recent_blockhash(&mut self) -> io::Result<Hash> {
Ok(self.get_fees().await?.1)
}
async fn process_transaction_with_commitment(
&mut self,
transaction: Transaction,
commitment: CommitmentLevel,
) -> transport::Result<()> {
let mut ctx = context::current();
ctx.deadline += Duration::from_secs(50);
let result = self
.process_transaction_with_commitment_and_context(ctx, transaction, commitment)
.await?;
match result {
None => Err(Error::new(ErrorKind::TimedOut, "invalid blockhash or fee-payer").into()),
Some(transaction_result) => Ok(transaction_result?),
}
}
async fn process_transaction(&mut self, transaction: Transaction) -> transport::Result<()> {
self.process_transaction_with_commitment(transaction, CommitmentLevel::default())
.await
}
async fn get_root_slot(&mut self) -> io::Result<Slot> {
self.get_slot_with_context(context::current(), CommitmentLevel::Root)
.await
}
async fn get_account_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
) -> io::Result<Option<Account>> {
self.get_account_with_commitment_and_context(context::current(), address, commitment)
.await
}
async fn get_account(&mut self, address: Pubkey) -> io::Result<Option<Account>> {
self.get_account_with_commitment(address, CommitmentLevel::default())
.await
}
async fn get_balance_with_commitment(
&mut self,
address: Pubkey,
commitment: CommitmentLevel,
) -> io::Result<u64> {
let account = self
.get_account_with_commitment_and_context(context::current(), address, commitment)
.await?;
Ok(account.map(|x| x.lamports).unwrap_or(0))
}
async fn get_balance(&mut self, address: Pubkey) -> io::Result<u64> {
self.get_balance_with_commitment(address, CommitmentLevel::default())
.await
}
async fn get_transaction_status(
&mut self,
signature: Signature,
) -> io::Result<Option<TransactionStatus>> {
self.get_transaction_status_with_context(context::current(), signature)
.await
}
async fn get_transaction_statuses(
&mut self,
signatures: Vec<Signature>,
) -> io::Result<Vec<Option<TransactionStatus>>> {
@@ -295,30 +219,22 @@ impl BanksClient {
}
}
pub async fn start_client<C>(transport: C) -> io::Result<BanksClient>
where
C: Transport<ClientMessage<BanksRequest>, Response<BanksResponse>> + Send + 'static,
{
Ok(BanksClient {
inner: TarpcClient::new(client::Config::default(), transport).spawn()?,
})
pub async fn start_client(
transport: UnboundedChannel<Response<BanksResponse>, ClientMessage<BanksRequest>>,
) -> io::Result<BanksClient> {
BanksClient::new(client::Config::default(), transport).spawn()
}
pub async fn start_tcp_client<T: ToSocketAddrs>(addr: T) -> io::Result<BanksClient> {
let transport = tcp::connect(addr, Bincode::default).await?;
Ok(BanksClient {
inner: TarpcClient::new(client::Config::default(), transport).spawn()?,
})
BanksClient::new(client::Config::default(), transport).spawn()
}
#[cfg(test)]
mod tests {
use super::*;
use solana_banks_server::banks_server::start_local_server;
use solana_runtime::{
bank::Bank, bank_forks::BankForks, commitment::BlockCommitmentCache,
genesis_utils::create_genesis_config,
};
use solana_runtime::{bank::Bank, bank_forks::BankForks, genesis_utils::create_genesis_config};
use solana_sdk::{message::Message, signature::Signer, system_instruction};
use std::sync::{Arc, RwLock};
use tarpc::transport;
@@ -337,12 +253,9 @@ mod tests {
// `runtime.block_on()` just once, to run all the async code.
let genesis = create_genesis_config(10);
let bank = Bank::new(&genesis.genesis_config);
let slot = bank.slot();
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_slots(slot, slot),
));
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(
&genesis.genesis_config,
))));
let bob_pubkey = solana_sdk::pubkey::new_rand();
let mint_pubkey = genesis.mint_keypair.pubkey();
@@ -350,8 +263,9 @@ mod tests {
let message = Message::new(&[instruction], Some(&mint_pubkey));
Runtime::new()?.block_on(async {
let client_transport = start_local_server(bank_forks, block_commitment_cache).await;
let mut banks_client = start_client(client_transport).await?;
let client_transport = start_local_server(&bank_forks).await;
let mut banks_client =
BanksClient::new(client::Config::default(), client_transport).spawn()?;
let recent_blockhash = banks_client.get_recent_blockhash().await?;
let transaction = Transaction::new(&[&genesis.mint_keypair], message, recent_blockhash);
@@ -368,12 +282,9 @@ mod tests {
// server-side functionality is available to the client.
let genesis = create_genesis_config(10);
let bank = Bank::new(&genesis.genesis_config);
let slot = bank.slot();
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_slots(slot, slot),
));
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(
&genesis.genesis_config,
))));
let mint_pubkey = &genesis.mint_keypair.pubkey();
let bob_pubkey = solana_sdk::pubkey::new_rand();
@@ -381,8 +292,9 @@ mod tests {
let message = Message::new(&[instruction], Some(&mint_pubkey));
Runtime::new()?.block_on(async {
let client_transport = start_local_server(bank_forks, block_commitment_cache).await;
let mut banks_client = start_client(client_transport).await?;
let client_transport = start_local_server(&bank_forks).await;
let mut banks_client =
BanksClient::new(client::Config::default(), client_transport).spawn()?;
let (_, recent_blockhash, last_valid_slot) = banks_client.get_fees().await?;
let transaction = Transaction::new(&[&genesis.mint_keypair], message, recent_blockhash);
let signature = transaction.signatures[0];

View File

@@ -1,22 +1,17 @@
[package]
name = "solana-banks-interface"
version = "1.6.2"
version = "1.4.7"
description = "Solana banks RPC interface"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-banks-interface"
edition = "2018"
[dependencies]
mio = "0.7.6"
serde = { version = "1.0.122", features = ["derive"] }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
tarpc = { version = "0.24.1", features = ["full"] }
[dev-dependencies]
tokio = { version = "1.1", features = ["full"] }
serde = { version = "1.0.112", features = ["derive"] }
solana-sdk = { path = "../sdk", version = "1.4.7" }
tarpc = { version = "0.23.0", features = ["full"] }
[lib]
crate-type = ["lib"]

View File

@@ -10,19 +10,11 @@ use solana_sdk::{
transaction::{self, Transaction, TransactionError},
};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum TransactionConfirmationStatus {
Processed,
Confirmed,
Finalized,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct TransactionStatus {
pub slot: Slot,
pub confirmations: Option<usize>, // None = rooted
pub err: Option<TransactionError>,
pub confirmation_status: Option<TransactionConfirmationStatus>,
}
#[tarpc::service]

View File

@@ -1,27 +1,24 @@
[package]
name = "solana-banks-server"
version = "1.6.2"
version = "1.4.7"
description = "Solana banks server"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-banks-server"
edition = "2018"
[dependencies]
bincode = "1.3.1"
futures = "0.3"
log = "0.4.11"
mio = "0.7.6"
solana-banks-interface = { path = "../banks-interface", version = "=1.6.2" }
solana-runtime = { path = "../runtime", version = "=1.6.2" }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
solana-metrics = { path = "../metrics", version = "=1.6.2" }
tarpc = { version = "0.24.1", features = ["full"] }
tokio = { version = "1.1", features = ["full"] }
tokio-serde = { version = "0.8", features = ["bincode"] }
tokio-stream = "0.1"
log = "0.4.8"
solana-banks-interface = { path = "../banks-interface", version = "1.4.7" }
solana-runtime = { path = "../runtime", version = "1.4.7" }
solana-sdk = { path = "../sdk", version = "1.4.7" }
solana-metrics = { path = "../metrics", version = "1.4.7" }
tarpc = { version = "0.23.0", features = ["full"] }
tokio = { version = "0.3", features = ["full"] }
tokio-serde = { version = "0.6", features = ["bincode"] }
[lib]
crate-type = ["lib"]

View File

@@ -4,9 +4,7 @@ use futures::{
future,
prelude::stream::{self, StreamExt},
};
use solana_banks_interface::{
Banks, BanksRequest, BanksResponse, TransactionConfirmationStatus, TransactionStatus,
};
use solana_banks_interface::{Banks, BanksRequest, BanksResponse, TransactionStatus};
use solana_runtime::{bank::Bank, bank_forks::BankForks, commitment::BlockCommitmentCache};
use solana_sdk::{
account::Account,
@@ -62,7 +60,7 @@ impl BanksServer {
}
}
fn run(bank_forks: Arc<RwLock<BankForks>>, transaction_receiver: Receiver<TransactionInfo>) {
fn run(bank: &Bank, transaction_receiver: Receiver<TransactionInfo>) {
while let Ok(info) = transaction_receiver.recv() {
let mut transaction_infos = vec![info];
while let Ok(info) = transaction_receiver.try_recv() {
@@ -72,28 +70,21 @@ impl BanksServer {
.into_iter()
.map(|info| deserialize(&info.wire_transaction).unwrap())
.collect();
let bank = bank_forks.read().unwrap().working_bank();
let _ = bank.process_transactions(&transactions);
}
}
/// Useful for unit-testing
fn new_loopback(
bank_forks: Arc<RwLock<BankForks>>,
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
) -> Self {
fn new_loopback(bank_forks: Arc<RwLock<BankForks>>) -> Self {
let (transaction_sender, transaction_receiver) = channel();
let bank = bank_forks.read().unwrap().working_bank();
let slot = bank.slot();
{
// ensure that the commitment cache and bank are synced
let mut w_block_commitment_cache = block_commitment_cache.write().unwrap();
w_block_commitment_cache.set_all_slots(slot, slot);
}
let server_bank_forks = bank_forks.clone();
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::new_for_tests_with_slots(slot, slot),
));
Builder::new()
.name("solana-bank-forks-client".to_string())
.spawn(move || Self::run(server_bank_forks, transaction_receiver))
.spawn(move || Self::run(&bank, transaction_receiver))
.unwrap();
Self::new(bank_forks, block_commitment_cache, transaction_sender)
}
@@ -131,16 +122,6 @@ impl BanksServer {
}
}
fn verify_transaction(transaction: &Transaction) -> transaction::Result<()> {
if let Err(err) = transaction.verify() {
Err(err)
} else if let Err(err) = transaction.verify_precompiles() {
Err(err)
} else {
Ok(())
}
}
#[tarpc::server]
impl Banks for BanksServer {
async fn send_transaction_with_context(self, _: Context, transaction: Transaction) {
@@ -174,17 +155,11 @@ impl Banks for BanksServer {
_: Context,
signature: Signature,
) -> Option<TransactionStatus> {
let bank = self.bank(CommitmentLevel::Processed);
let bank = self.bank(CommitmentLevel::Recent);
let (slot, status) = bank.get_signature_status_slot(&signature)?;
let r_block_commitment_cache = self.block_commitment_cache.read().unwrap();
let optimistically_confirmed_bank = self.bank(CommitmentLevel::Confirmed);
let optimistically_confirmed =
optimistically_confirmed_bank.get_signature_status_slot(&signature);
let confirmations = if r_block_commitment_cache.root() >= slot
&& r_block_commitment_cache.highest_confirmed_root() >= slot
{
let confirmations = if r_block_commitment_cache.root() >= slot {
None
} else {
r_block_commitment_cache
@@ -195,13 +170,6 @@ impl Banks for BanksServer {
slot,
confirmations,
err: status.err(),
confirmation_status: if confirmations.is_none() {
Some(TransactionConfirmationStatus::Finalized)
} else if optimistically_confirmed.is_some() {
Some(TransactionConfirmationStatus::Confirmed)
} else {
Some(TransactionConfirmationStatus::Processed)
},
})
}
@@ -215,10 +183,6 @@ impl Banks for BanksServer {
transaction: Transaction,
commitment: CommitmentLevel,
) -> Option<transaction::Result<()>> {
if let Err(err) = verify_transaction(&transaction) {
return Some(Err(err));
}
let blockhash = &transaction.message.recent_blockhash;
let last_valid_slot = self
.bank_forks
@@ -242,15 +206,14 @@ impl Banks for BanksServer {
commitment: CommitmentLevel,
) -> Option<Account> {
let bank = self.bank(commitment);
bank.get_account(&address).map(Account::from)
bank.get_account(&address)
}
}
pub async fn start_local_server(
bank_forks: Arc<RwLock<BankForks>>,
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
bank_forks: &Arc<RwLock<BankForks>>,
) -> UnboundedChannel<Response<BanksResponse>, ClientMessage<BanksRequest>> {
let banks_server = BanksServer::new_loopback(bank_forks, block_commitment_cache);
let banks_server = BanksServer::new_loopback(bank_forks.clone());
let (client_transport, server_transport) = transport::channel::unbounded();
let server = server::new(server::Config::default())
.incoming(stream::once(future::ready(server_transport)))

View File

@@ -1,4 +1,3 @@
#![allow(clippy::integer_arithmetic)]
pub mod banks_server;
pub mod rpc_banks_service;
pub mod send_transaction_service;

View File

@@ -15,7 +15,6 @@ use tokio::{
runtime::Runtime,
time::{self, Duration},
};
use tokio_stream::wrappers::IntervalStream;
pub struct RpcBanksService {
thread_hdl: JoinHandle<()>,
@@ -36,7 +35,7 @@ async fn start_abortable_tcp_server(
block_commitment_cache.clone(),
)
.fuse();
let interval = IntervalStream::new(time::interval(Duration::from_millis(100))).fuse();
let interval = time::interval(Duration::from_millis(100)).fuse();
pin_mut!(server, interval);
loop {
select! {

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-bench-exchange"
version = "1.6.2"
version = "1.4.7"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -11,28 +11,28 @@ publish = false
[dependencies]
clap = "2.33.1"
itertools = "0.9.0"
log = "0.4.11"
log = "0.4.8"
num-derive = "0.3"
num-traits = "0.2"
rand = "0.7.0"
rayon = "1.5.0"
rayon = "1.4.0"
serde_json = "1.0.56"
serde_yaml = "0.8.13"
solana-clap-utils = { path = "../clap-utils", version = "=1.6.2" }
solana-core = { path = "../core", version = "=1.6.2" }
solana-genesis = { path = "../genesis", version = "=1.6.2" }
solana-client = { path = "../client", version = "=1.6.2" }
solana-faucet = { path = "../faucet", version = "=1.6.2" }
solana-exchange-program = { path = "../programs/exchange", version = "=1.6.2" }
solana-logger = { path = "../logger", version = "=1.6.2" }
solana-metrics = { path = "../metrics", version = "=1.6.2" }
solana-net-utils = { path = "../net-utils", version = "=1.6.2" }
solana-runtime = { path = "../runtime", version = "=1.6.2" }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
solana-version = { path = "../version", version = "=1.6.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.7" }
solana-core = { path = "../core", version = "1.4.7" }
solana-genesis = { path = "../genesis", version = "1.4.7" }
solana-client = { path = "../client", version = "1.4.7" }
solana-faucet = { path = "../faucet", version = "1.4.7" }
solana-exchange-program = { path = "../programs/exchange", version = "1.4.7" }
solana-logger = { path = "../logger", version = "1.4.7" }
solana-metrics = { path = "../metrics", version = "1.4.7" }
solana-net-utils = { path = "../net-utils", version = "1.4.7" }
solana-runtime = { path = "../runtime", version = "1.4.7" }
solana-sdk = { path = "../sdk", version = "1.4.7" }
solana-version = { path = "../version", version = "1.4.7" }
[dev-dependencies]
solana-local-cluster = { path = "../local-cluster", version = "=1.6.2" }
solana-local-cluster = { path = "../local-cluster", version = "1.4.7" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,5 +1,4 @@
#![allow(clippy::useless_attribute)]
#![allow(clippy::integer_arithmetic)]
use crate::order_book::*;
use itertools::izip;
@@ -391,7 +390,7 @@ fn swapper<T>(
while client
.get_balance_with_commitment(
&trade_infos[trade_index].trade_account,
CommitmentConfig::processed(),
CommitmentConfig::recent(),
)
.unwrap_or(0)
== 0
@@ -446,7 +445,7 @@ fn swapper<T>(
account_group = (account_group + 1) % account_groups as usize;
let (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.expect("Failed to get blockhash");
let to_swap_txs: Vec<_> = to_swap
.par_iter()
@@ -572,7 +571,7 @@ fn trader<T>(
account_group = (account_group + 1) % account_groups as usize;
let (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.expect("Failed to get blockhash");
trades.chunks(chunk_size).for_each(|chunk| {
@@ -659,7 +658,7 @@ where
{
for s in &tx.signatures {
if let Ok(Some(r)) =
sync_client.get_signature_status_with_commitment(s, CommitmentConfig::processed())
sync_client.get_signature_status_with_commitment(s, CommitmentConfig::recent())
{
match r {
Ok(_) => {
@@ -682,7 +681,7 @@ fn verify_funding_transfer<T: SyncClient + ?Sized>(
if verify_transaction(client, tx) {
for a in &tx.message().account_keys[1..] {
if client
.get_balance_with_commitment(a, CommitmentConfig::processed())
.get_balance_with_commitment(a, CommitmentConfig::recent())
.unwrap_or(0)
>= amount
{
@@ -765,7 +764,7 @@ pub fn fund_keys<T: Client>(client: &T, source: &Keypair, dests: &[Arc<Keypair>]
);
let (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.expect("blockhash");
to_fund_txs.par_iter_mut().for_each(|(k, tx)| {
tx.sign(&[*k], blockhash);
@@ -804,7 +803,7 @@ pub fn fund_keys<T: Client>(client: &T, source: &Keypair, dests: &[Arc<Keypair>]
funded.append(&mut new_funded);
funded.retain(|(k, b)| {
client
.get_balance_with_commitment(&k.pubkey(), CommitmentConfig::processed())
.get_balance_with_commitment(&k.pubkey(), CommitmentConfig::recent())
.unwrap_or(0)
> lamports
&& *b > lamports
@@ -858,7 +857,7 @@ pub fn create_token_accounts<T: Client>(
let mut retries = 0;
while !to_create_txs.is_empty() {
let (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.expect("Failed to get blockhash");
to_create_txs
.par_iter_mut()
@@ -904,7 +903,7 @@ pub fn create_token_accounts<T: Client>(
let mut new_notfunded: Vec<(&Arc<Keypair>, &Keypair)> = vec![];
for f in &notfunded {
if client
.get_balance_with_commitment(&f.1.pubkey(), CommitmentConfig::processed())
.get_balance_with_commitment(&f.1.pubkey(), CommitmentConfig::recent())
.unwrap_or(0)
== 0
{
@@ -969,7 +968,7 @@ pub fn airdrop_lamports<T: Client>(
id: &Keypair,
amount: u64,
) {
let balance = client.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::processed());
let balance = client.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::recent());
let balance = balance.unwrap_or(0);
if balance >= amount {
return;
@@ -987,7 +986,7 @@ pub fn airdrop_lamports<T: Client>(
let mut tries = 0;
loop {
let (blockhash, _fee_calculator, _last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.expect("Failed to get blockhash");
match request_airdrop_transaction(&faucet_addr, &id.pubkey(), amount_to_drop, blockhash) {
Ok(transaction) => {
@@ -996,14 +995,14 @@ pub fn airdrop_lamports<T: Client>(
for _ in 0..30 {
if let Ok(Some(_)) = client.get_signature_status_with_commitment(
&signature,
CommitmentConfig::processed(),
CommitmentConfig::recent(),
) {
break;
}
sleep(Duration::from_millis(100));
}
if client
.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::processed())
.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::recent())
.unwrap_or(0)
>= amount
{

View File

@@ -163,8 +163,7 @@ pub fn build_args<'a, 'b>(version: &'b str) -> App<'a, 'b> {
)
}
#[allow(clippy::field_reassign_with_default)]
pub fn extract_args(matches: &ArgMatches) -> Config {
pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
let mut args = Config::default();
args.entrypoint_addr = solana_net_utils::parse_host_port(

View File

@@ -1,4 +1,3 @@
#![allow(clippy::integer_arithmetic)]
pub mod bench;
mod cli;
pub mod order_book;

View File

@@ -1,23 +1,19 @@
use log::*;
use solana_bench_exchange::bench::{airdrop_lamports, do_bench_exchange, Config};
use solana_core::{
gossip_service::{discover_cluster, get_multi_client},
validator::ValidatorConfig,
};
use solana_exchange_program::{
exchange_processor::process_instruction, id, solana_exchange_program,
};
use solana_faucet::faucet::run_local_faucet_with_port;
use solana_local_cluster::{
local_cluster::{ClusterConfig, LocalCluster},
validator_configs::make_identical_validator_configs,
};
use solana_runtime::{bank::Bank, bank_client::BankClient};
use solana_sdk::{
genesis_config::create_genesis_config,
signature::{Keypair, Signer},
};
use std::{process::exit, sync::mpsc::channel, time::Duration};
use solana_core::gossip_service::{discover_cluster, get_multi_client};
use solana_core::validator::ValidatorConfig;
use solana_exchange_program::exchange_processor::process_instruction;
use solana_exchange_program::id;
use solana_exchange_program::solana_exchange_program;
use solana_faucet::faucet::run_local_faucet;
use solana_local_cluster::local_cluster::{ClusterConfig, LocalCluster};
use solana_runtime::bank::Bank;
use solana_runtime::bank_client::BankClient;
use solana_sdk::genesis_config::create_genesis_config;
use solana_sdk::signature::{Keypair, Signer};
use std::process::exit;
use std::sync::mpsc::channel;
use std::time::Duration;
#[test]
#[ignore]
@@ -26,17 +22,15 @@ fn test_exchange_local_cluster() {
const NUM_NODES: usize = 1;
let config = Config {
identity: Keypair::new(),
duration: Duration::from_secs(1),
fund_amount: 100_000,
threads: 1,
transfer_delay: 20, // 15
batch_size: 100, // 1000
chunk_size: 10, // 200
account_groups: 1, // 10
..Config::default()
};
let mut config = Config::default();
config.identity = Keypair::new();
config.duration = Duration::from_secs(1);
config.fund_amount = 100_000;
config.threads = 1;
config.transfer_delay = 20; // 15
config.batch_size = 100; // 1000;
config.chunk_size = 10; // 200;
config.account_groups = 1; // 10;
let Config {
fund_amount,
batch_size,
@@ -45,10 +39,10 @@ fn test_exchange_local_cluster() {
} = config;
let accounts_in_groups = batch_size * account_groups;
let cluster = LocalCluster::new(&mut ClusterConfig {
let cluster = LocalCluster::new(&ClusterConfig {
node_stakes: vec![100_000; NUM_NODES],
cluster_lamports: 100_000_000_000_000,
validator_configs: make_identical_validator_configs(&ValidatorConfig::default(), NUM_NODES),
validator_configs: vec![ValidatorConfig::default(); NUM_NODES],
native_instruction_processors: [solana_exchange_program!()].to_vec(),
..ClusterConfig::default()
});
@@ -61,11 +55,8 @@ fn test_exchange_local_cluster() {
);
let (addr_sender, addr_receiver) = channel();
run_local_faucet_with_port(faucet_keypair, addr_sender, Some(1_000_000_000_000), 0);
let faucet_addr = addr_receiver
.recv_timeout(Duration::from_secs(2))
.expect("run_local_faucet")
.expect("faucet_addr");
run_local_faucet(faucet_keypair, addr_sender, Some(1_000_000_000_000));
let faucet_addr = addr_receiver.recv_timeout(Duration::from_secs(2)).unwrap();
info!("Connecting to the cluster");
let nodes =
@@ -98,18 +89,15 @@ fn test_exchange_bank_client() {
bank.add_builtin("exchange_program", id(), process_instruction);
let clients = vec![BankClient::new(bank)];
do_bench_exchange(
clients,
Config {
identity,
duration: Duration::from_secs(1),
fund_amount: 100_000,
threads: 1,
transfer_delay: 20, // 0;
batch_size: 100, // 1500;
chunk_size: 10, // 1500;
account_groups: 1, // 50;
..Config::default()
},
);
let mut config = Config::default();
config.identity = identity;
config.duration = Duration::from_secs(1);
config.fund_amount = 100_000;
config.threads = 1;
config.transfer_delay = 20; // 0;
config.batch_size = 100; // 1500;
config.chunk_size = 10; // 1500;
config.account_groups = 1; // 50;
do_bench_exchange(clients, config);
}

View File

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

View File

@@ -1,4 +1,3 @@
#![allow(clippy::integer_arithmetic)]
use clap::{crate_description, crate_name, App, Arg};
use solana_streamer::packet::{Packet, Packets, PacketsRecycler, PACKET_DATA_SIZE};
use solana_streamer::streamer::{receiver, PacketReceiver};
@@ -75,7 +74,7 @@ fn main() -> Result<()> {
let mut read_channels = Vec::new();
let mut read_threads = Vec::new();
let recycler = PacketsRecycler::new_without_limit("bench-streamer-recycler-shrink-stats");
let recycler = PacketsRecycler::default();
for _ in 0..num_sockets {
let read = solana_net_utils::bind_to(ip_addr, port, false).unwrap();
read.set_read_timeout(Some(Duration::new(1, 0))).unwrap();
@@ -91,7 +90,6 @@ fn main() -> Result<()> {
s_reader,
recycler.clone(),
"bench-streamer-test",
1,
));
}

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-bench-tps"
version = "1.6.2"
version = "1.4.7"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -11,26 +11,27 @@ publish = false
[dependencies]
bincode = "1.3.1"
clap = "2.33.1"
log = "0.4.11"
rayon = "1.5.0"
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.6.2" }
solana-core = { path = "../core", version = "=1.6.2" }
solana-genesis = { path = "../genesis", version = "=1.6.2" }
solana-client = { path = "../client", version = "=1.6.2" }
solana-faucet = { path = "../faucet", version = "=1.6.2" }
solana-logger = { path = "../logger", version = "=1.6.2" }
solana-metrics = { path = "../metrics", version = "=1.6.2" }
solana-measure = { path = "../measure", version = "=1.6.2" }
solana-net-utils = { path = "../net-utils", version = "=1.6.2" }
solana-runtime = { path = "../runtime", version = "=1.6.2" }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
solana-version = { path = "../version", version = "=1.6.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.7" }
solana-core = { path = "../core", version = "1.4.7" }
solana-genesis = { path = "../genesis", version = "1.4.7" }
solana-client = { path = "../client", version = "1.4.7" }
solana-faucet = { path = "../faucet", version = "1.4.7" }
solana-logger = { path = "../logger", version = "1.4.7" }
solana-metrics = { path = "../metrics", version = "1.4.7" }
solana-measure = { path = "../measure", version = "1.4.7" }
solana-net-utils = { path = "../net-utils", version = "1.4.7" }
solana-runtime = { path = "../runtime", version = "1.4.7" }
solana-sdk = { path = "../sdk", version = "1.4.7" }
solana-version = { path = "../version", version = "1.4.7" }
[dev-dependencies]
serial_test = "0.4.0"
solana-local-cluster = { path = "../local-cluster", version = "=1.6.2" }
serial_test_derive = "0.4.0"
solana-local-cluster = { path = "../local-cluster", version = "1.4.7" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -8,7 +8,7 @@ use solana_measure::measure::Measure;
use solana_metrics::{self, datapoint_info};
use solana_sdk::{
client::Client,
clock::{DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE},
clock::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT, MAX_PROCESSING_AGE},
commitment_config::CommitmentConfig,
fee_calculator::FeeCalculator,
hash::Hash,
@@ -32,7 +32,8 @@ use std::{
};
// The point at which transactions become "too old", in seconds.
const MAX_TX_QUEUE_AGE: u64 = (MAX_PROCESSING_AGE as f64 * DEFAULT_S_PER_SLOT) as u64;
const MAX_TX_QUEUE_AGE: u64 =
MAX_PROCESSING_AGE as u64 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND;
pub const MAX_SPENDS_PER_TX: u64 = 4;
@@ -47,7 +48,7 @@ pub type SharedTransactions = Arc<RwLock<VecDeque<Vec<(Transaction, u64)>>>>;
fn get_recent_blockhash<T: Client>(client: &T) -> (Hash, FeeCalculator) {
loop {
match client.get_recent_blockhash_with_commitment(CommitmentConfig::processed()) {
match client.get_recent_blockhash_with_commitment(CommitmentConfig::recent()) {
Ok((blockhash, fee_calculator, _last_valid_slot)) => {
return (blockhash, fee_calculator)
}
@@ -496,7 +497,7 @@ fn do_tx_transfers<T: Client>(
fn verify_funding_transfer<T: Client>(client: &Arc<T>, tx: &Transaction, amount: u64) -> bool {
for a in &tx.message().account_keys[1..] {
match client.get_balance_with_commitment(a, CommitmentConfig::processed()) {
match client.get_balance_with_commitment(a, CommitmentConfig::recent()) {
Ok(balance) => return balance >= amount,
Err(err) => error!("failed to get balance {:?}", err),
}
@@ -761,7 +762,7 @@ pub fn airdrop_lamports<T: Client>(
};
let current_balance = client
.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::processed())
.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::recent())
.unwrap_or_else(|e| {
info!("airdrop error {}", e);
starting_balance
@@ -937,12 +938,10 @@ mod tests {
let bank = Bank::new(&genesis_config);
let client = Arc::new(BankClient::new(bank));
let config = Config {
id,
tx_count: 10,
duration: Duration::from_secs(5),
..Config::default()
};
let mut config = Config::default();
config.id = id;
config.tx_count = 10;
config.duration = Duration::from_secs(5);
let keypair_count = config.tx_count * config.keypair_multiplier;
let keypairs =
@@ -966,7 +965,7 @@ mod tests {
for kp in &keypairs {
assert_eq!(
client
.get_balance_with_commitment(&kp.pubkey(), CommitmentConfig::processed())
.get_balance_with_commitment(&kp.pubkey(), CommitmentConfig::recent())
.unwrap(),
lamports
);

View File

@@ -196,7 +196,7 @@ pub fn build_args<'a, 'b>(version: &'b str) -> App<'a, 'b> {
/// * `matches` - command line arguments parsed by clap
/// # Panics
/// Panics if there is trouble parsing any of the arguments
pub fn extract_args(matches: &ArgMatches) -> Config {
pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
let mut args = Config::default();
if let Some(addr) = matches.value_of("entrypoint") {

View File

@@ -1,3 +1,2 @@
#![allow(clippy::integer_arithmetic)]
pub mod bench;
pub mod cli;

View File

@@ -1,4 +1,3 @@
#![allow(clippy::integer_arithmetic)]
use log::*;
use solana_bench_tps::bench::{do_bench_tps, generate_and_fund_keypairs, generate_keypairs};
use solana_bench_tps::cli;

View File

@@ -1,31 +1,24 @@
#![allow(clippy::integer_arithmetic)]
use serial_test::serial;
use solana_bench_tps::{
bench::{do_bench_tps, generate_and_fund_keypairs},
cli::Config,
};
use serial_test_derive::serial;
use solana_bench_tps::bench::{do_bench_tps, generate_and_fund_keypairs};
use solana_bench_tps::cli::Config;
use solana_client::thin_client::create_client;
use solana_core::{cluster_info::VALIDATOR_PORT_RANGE, validator::ValidatorConfig};
use solana_faucet::faucet::run_local_faucet_with_port;
use solana_local_cluster::{
local_cluster::{ClusterConfig, LocalCluster},
validator_configs::make_identical_validator_configs,
};
use solana_core::cluster_info::VALIDATOR_PORT_RANGE;
use solana_core::validator::ValidatorConfig;
use solana_faucet::faucet::run_local_faucet;
use solana_local_cluster::local_cluster::{ClusterConfig, LocalCluster};
use solana_sdk::signature::{Keypair, Signer};
use std::{
sync::{mpsc::channel, Arc},
time::Duration,
};
use std::sync::{mpsc::channel, Arc};
use std::time::Duration;
fn test_bench_tps_local_cluster(config: Config) {
let native_instruction_processors = vec![];
solana_logger::setup();
const NUM_NODES: usize = 1;
let cluster = LocalCluster::new(&mut ClusterConfig {
let cluster = LocalCluster::new(&ClusterConfig {
node_stakes: vec![999_990; NUM_NODES],
cluster_lamports: 200_000_000,
validator_configs: make_identical_validator_configs(&ValidatorConfig::default(), NUM_NODES),
validator_configs: vec![ValidatorConfig::default(); NUM_NODES],
native_instruction_processors,
..ClusterConfig::default()
});
@@ -43,11 +36,8 @@ fn test_bench_tps_local_cluster(config: Config) {
));
let (addr_sender, addr_receiver) = channel();
run_local_faucet_with_port(faucet_keypair, addr_sender, None, 0);
let faucet_addr = addr_receiver
.recv_timeout(Duration::from_secs(2))
.expect("run_local_faucet")
.expect("faucet_addr");
run_local_faucet(faucet_keypair, addr_sender, None);
let faucet_addr = addr_receiver.recv_timeout(Duration::from_secs(2)).unwrap();
let lamports_per_account = 100;
@@ -70,9 +60,9 @@ fn test_bench_tps_local_cluster(config: Config) {
#[test]
#[serial]
fn test_bench_tps_local_cluster_solana() {
test_bench_tps_local_cluster(Config {
tx_count: 100,
duration: Duration::from_secs(10),
..Config::default()
});
let mut config = Config::default();
config.tx_count = 100;
config.duration = Duration::from_secs(10);
test_bench_tps_local_cluster(config);
}

View File

@@ -47,8 +47,6 @@ sudo ./setup-new-buildkite-agent/setup-buildkite.sh
```
- Copy the pubkey contents from `~buildkite-agent/.ssh/id_ecdsa.pub` and
add the pubkey as an authorized SSH key on github.
- In net/scripts/solana-user-authorized_keys.sh
- Bug mvines to add it to the "solana-grimes" github user
- Edit `/etc/buildkite-agent/buildkite-agent.cfg` and/or `/etc/systemd/system/buildkite-agent@*` to the desired configuration of the agent(s)
- Copy `ejson` keys from another CI node at `/opt/ejson/keys/`
to the same location on the new node.

View File

@@ -263,7 +263,7 @@ if [[ $BUILDKITE_BRANCH =~ ^pull ]]; then
annotate --style info --context pr-backlink \
"Github Pull Request: https://github.com/solana-labs/solana/$BUILDKITE_BRANCH"
if [[ $GITHUB_USER = "dependabot[bot]" ]]; then
if [[ $GITHUB_USER = "dependabot-preview[bot]" ]]; then
command_step dependabot "ci/dependabot-pr.sh" 5
wait_step
fi

View File

@@ -6,13 +6,13 @@ source ci/_
commit_range="$(git merge-base HEAD origin/master)..HEAD"
parsed_update_args="$(
git log "$commit_range" --author "dependabot\[bot\]" --oneline -n1 |
git log "$commit_range" --author "dependabot-preview" --oneline -n1 |
grep -o '[Bb]ump.*$' |
sed -r 's/[Bb]ump ([^ ]+) from ([^ ]+) to ([^ ]+)/-p \1:\2 --precise \3/'
)"
# relaxed_parsed_update_args is temporal measure...
relaxed_parsed_update_args="$(
git log "$commit_range" --author "dependabot\[bot\]" --oneline -n1 |
git log "$commit_range" --author "dependabot-preview" --oneline -n1 |
grep -o '[Bb]ump.*$' |
sed -r 's/[Bb]ump ([^ ]+) from [^ ]+ to ([^ ]+)/-p \1 --precise \2/'
)"

View File

@@ -1,45 +0,0 @@
#!/usr/bin/env bash
set -e
here="$(dirname "$0")"
src_root="$(readlink -f "${here}/..")"
cd "${src_root}"
source ci/rust-version.sh stable
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
# stdweb is unmaintained
#
# Blocked on multiple upstream crates removing their `stdweb` dependency.
--ignore RUSTSEC-2020-0056
# Potential segfault in the time crate
#
# Blocked on multiple crates updating `time` to >= 0.2.23
--ignore RUSTSEC-2020-0071
# difference is unmaintained
#
# Blocked on predicates v1.0.6 removing its dependency on `difference`
--ignore RUSTSEC-2020-0095
# generic-array: arr! macro erases lifetimes
#
# Blocked on libsecp256k1 releasing with upgraded dependencies
# https://github.com/paritytech/libsecp256k1/issues/66
--ignore RUSTSEC-2020-0146
)
scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit "${cargo_audit_ignores[@]}"

View File

@@ -1,4 +1,4 @@
FROM solanalabs/rust:1.50.0
FROM solanalabs/rust:1.46.0
ARG date
RUN set -x \

View File

@@ -1,6 +1,6 @@
# Note: when the rust version is changed also modify
# ci/rust-version.sh to pick up the new image tag
FROM rust:1.50.0
FROM rust:1.46.0
# Add Google Protocol Buffers for Libra's metrics library.
ENV PROTOC_VERSION 3.8.0

View File

@@ -78,6 +78,7 @@ nodes=(
--init-complete-file init-complete-node0.log \
--dynamic-port-range 8000-8050"
"multinode-demo/validator.sh \
--enable-rpc-exit \
--no-restart \
--dynamic-port-range 8050-8100
--init-complete-file init-complete-node1.log \
@@ -200,10 +201,17 @@ killNodes() {
[[ ${#pids[@]} -gt 0 ]] || return
# Try to use the RPC exit API to cleanly exit the first two nodes
# (dynamic nodes, -x, are just killed)
# (dynamic nodes, -x, are just killed since their RPC port is not known)
echo "--- RPC exit"
$solana_validator --ledger "$SOLANA_CONFIG_DIR"/bootstrap-validator exit --force || true
$solana_validator --ledger "$SOLANA_CONFIG_DIR"/validator exit --force || true
for port in 8899 18899; do
(
set -x
curl --retry 5 --retry-delay 2 --retry-connrefused \
-X POST -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1, "method":"validatorExit"}' \
http://localhost:$port
)
done
# Give the nodes a splash of time to cleanly exit before killing them
sleep 2

View File

@@ -19,7 +19,6 @@ declare prints=(
# Parts of the tree that are expected to be print free
declare print_free_tree=(
':core/src/**.rs'
':^core/src/validator.rs'
':faucet/src/**.rs'
':ledger/src/**.rs'
':metrics/src/**.rs'

View File

@@ -16,12 +16,21 @@ fi
[[ -f bpf-sdk.tar.bz2 ]]
)
source ci/upload-ci-artifact.sh
echo --- AWS S3 Store
if [[ -z $CHANNEL_OR_TAG ]]; then
echo Skipped
else
upload-s3-artifact "/solana/bpf-sdk.tar.bz2" "s3://solana-sdk/$CHANNEL_OR_TAG/bpf-sdk.tar.bz2"
(
set -x
docker run \
--rm \
--env AWS_ACCESS_KEY_ID \
--env AWS_SECRET_ACCESS_KEY \
--volume "$PWD:/solana" \
eremite/aws-cli:2018.12.18 \
/usr/bin/s3cmd --acl-public put /solana/bpf-sdk.tar.bz2 \
s3://solana-sdk/"$CHANNEL_OR_TAG"/bpf-sdk.tar.bz2
)
fi
exit 0

View File

@@ -113,10 +113,19 @@ for file in "${TARBALL_BASENAME}"-$TARGET.tar.bz2 "${TARBALL_BASENAME}"-$TARGET.
if [[ -n $BUILDKITE ]]; then
echo --- AWS S3 Store: "$file"
upload-s3-artifact "/solana/$file" s3://release.solana.com/"$CHANNEL_OR_TAG"/"$file"
(
set -x
$DRYRUN docker run \
--rm \
--env AWS_ACCESS_KEY_ID \
--env AWS_SECRET_ACCESS_KEY \
--volume "$PWD:/solana" \
eremite/aws-cli:2018.12.18 \
/usr/bin/s3cmd --acl-public put /solana/"$file" s3://release.solana.com/"$CHANNEL_OR_TAG"/"$file"
echo Published to:
$DRYRUN ci/format-url.sh https://release.solana.com/"$CHANNEL_OR_TAG"/"$file"
echo Published to:
$DRYRUN ci/format-url.sh https://release.solana.com/"$CHANNEL_OR_TAG"/"$file"
)
if [[ -n $TAG ]]; then
ci/upload-github-release-asset.sh "$file"
@@ -140,9 +149,7 @@ done
# Create install wrapper for release.solana.com
if [[ -n $DO_NOT_PUBLISH_TAR ]]; then
echo "Skipping publishing install wrapper"
elif [[ -n $BUILDKITE ]]; then
if [[ -n $BUILDKITE ]]; then
cat > release.solana.com-install <<EOF
SOLANA_RELEASE=$CHANNEL_OR_TAG
SOLANA_INSTALL_INIT_ARGS=$CHANNEL_OR_TAG
@@ -151,9 +158,19 @@ EOF
cat install/solana-install-init.sh >> release.solana.com-install
echo --- AWS S3 Store: "install"
$DRYRUN upload-s3-artifact "/solana/release.solana.com-install" "s3://release.solana.com/$CHANNEL_OR_TAG/install"
echo Published to:
$DRYRUN ci/format-url.sh https://release.solana.com/"$CHANNEL_OR_TAG"/install
(
set -x
$DRYRUN docker run \
--rm \
--env AWS_ACCESS_KEY_ID \
--env AWS_SECRET_ACCESS_KEY \
--volume "$PWD:/solana" \
eremite/aws-cli:2018.12.18 \
/usr/bin/s3cmd --acl-public put /solana/release.solana.com-install s3://release.solana.com/"$CHANNEL_OR_TAG"/install
echo Published to:
$DRYRUN ci/format-url.sh https://release.solana.com/"$CHANNEL_OR_TAG"/install
)
fi
echo --- ok

View File

@@ -25,8 +25,7 @@ snapshot_slot=1
while [[ $($solana_cli --url http://localhost:8899 slot --commitment recent) -le $((snapshot_slot + 1)) ]]; do
sleep 1
done
$solana_validator --ledger config/ledger exit --force || true
curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1, "method":"validatorExit"}' http://localhost:8899
wait $pid

View File

@@ -18,13 +18,13 @@
if [[ -n $RUST_STABLE_VERSION ]]; then
stable_version="$RUST_STABLE_VERSION"
else
stable_version=1.50.0
stable_version=1.46.0
fi
if [[ -n $RUST_NIGHTLY_VERSION ]]; then
nightly_version="$RUST_NIGHTLY_VERSION"
else
nightly_version=2021-02-18
nightly_version=2020-08-17
fi

View File

@@ -76,7 +76,7 @@ RestartForceExitStatus=SIGPIPE
TimeoutStartSec=10
TimeoutStopSec=0
KillMode=process
LimitNOFILE=700000
LimitNOFILE=500000
[Install]
WantedBy=multi-user.target

View File

@@ -8,5 +8,5 @@ source "$HERE"/utils.sh
ensure_env || exit 1
# Allow more files to be opened by a user
echo "* - nofile 700000" > /etc/security/limits.d/90-solana-nofiles.conf
echo "* - nofile 500000" > /etc/security/limits.d/90-solana-nofiles.conf

View File

@@ -7,7 +7,6 @@ SOLANA_ROOT="$HERE"/../..
source "$HERE"/utils.sh
ensure_env || exit 1
check_ssh_authorized_keys || exit 1
set -ex

View File

@@ -6,11 +6,6 @@ HERE="$(dirname "$0")"
source "$HERE"/utils.sh
ensure_env || exit 1
# This is a last ditch effort to prevent the caller from locking themselves
# out of the machine. Exiting here will likely leave the system in some
# half-configured state. To prevent this, duplicate the next line at the top
# of the entrypoint script.
check_ssh_authorized_keys || exit 1
set -xe
# Setup sshd

View File

@@ -14,33 +14,3 @@ ensure_env() {
$RC
}
# Some scripts disable SSH password logins. If no one hash setup authorized_keys
# this will result in the machine being remotely inaccessible. Check that the
# user running this script has setup their keys
check_ssh_authorized_keys() {
declare rc=false
declare user_home=
if [[ -n "$SUDO_USER" ]]; then
declare user uid gid home
declare passwd_entry
passwd_entry="$(grep "$SUDO_USER:[^:]*:$SUDO_UID:$SUDO_GID" /etc/passwd)"
IFS=: read -r user _ uid gid _ home _ <<<"$passwd_entry"
if [[ "$user" == "$SUDO_USER" && "$uid" == "$SUDO_UID" && "$gid" == "$SUDO_GID" ]]; then
user_home="$home"
fi
else
user_home="$HOME"
fi
declare authorized_keys="${user_home}/.ssh/authorized_keys"
if [[ -n "$user_home" ]]; then
[[ -s "$authorized_keys" ]] && rc=true
fi
if ! $rc; then
echo "ERROR! This script will disable SSH password logins and you don't"
echo "appear to have set up any authorized keys. Please add you SSH"
echo "public key to ${authorized_keys} before continuing!"
fi
$rc
}
check_ssh_authorized_keys

View File

@@ -23,10 +23,6 @@ fi
BENCH_FILE=bench_output.log
BENCH_ARTIFACT=current_bench_results.log
# solana-keygen required when building C programs
_ "$cargo" build --manifest-path=keygen/Cargo.toml
export PATH="$PWD/target/debug":$PATH
# Clear the C dependency files, if dependeny moves these files are not regenerated
test -d target/debug/bpf && find target/debug/bpf -name '*.d' -delete
test -d target/release/bpf && find target/release/bpf -name '*.d' -delete

View File

@@ -12,16 +12,6 @@ cargo="$(readlink -f "./cargo")"
scripts/increment-cargo-version.sh check
# Disallow uncommitted Cargo.lock changes
(
_ scripts/cargo-for-all-lock-files.sh tree
set +e
if ! _ git diff --exit-code; then
echo -e "\nError: Uncommitted Cargo.lock changes" 1>&2
exit 1
fi
)
echo --- build environment
(
set -x
@@ -62,24 +52,44 @@ else
fi
_ ci/order-crates-for-publishing.py
_ "$cargo" stable fmt --all -- --check
# -Z... is needed because of clippy bug: https://github.com/rust-lang/rust-clippy/issues/4612
# run nightly clippy for `sdk/` as there's a moderate amount of nightly-only code there
_ "$cargo" nightly clippy -Zunstable-options --workspace --all-targets -- --deny=warnings --deny=clippy::integer_arithmetic
_ "$cargo" nightly clippy \
-Zunstable-options --workspace --all-targets \
-- --deny=warnings --allow=clippy::stable_sort_primitive
_ "$cargo" stable fmt --all -- --check
cargo_audit_ignores=(
# failure is officially deprecated/unmaintained
#
# Blocked on multiple upstream crates removing their `failure` dependency.
--ignore RUSTSEC-2020-0036
_ ci/do-audit.sh
# `net2` crate has been deprecated; use `socket2` instead
#
# Blocked on https://github.com/paritytech/jsonrpc/issues/575
--ignore RUSTSEC-2020-0016
# stdweb is unmaintained
#
# Blocked on multiple upstream crates removing their `stdweb` dependency.
--ignore RUSTSEC-2020-0056
)
_ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit "${cargo_audit_ignores[@]}"
{
cd programs/bpf
_ "$cargo" stable audit
for project in rust/*/ ; do
echo "+++ do_bpf_checks $project"
(
cd "$project"
_ "$cargo" nightly clippy -- --deny=warnings --allow=clippy::missing_safety_doc
_ "$cargo" stable fmt -- --check
_ "$cargo" nightly test
_ "$cargo" nightly clippy -- --deny=warnings \
--allow=clippy::missing_safety_doc \
--allow=clippy::stable_sort_primitive
)
done
}

View File

@@ -8,16 +8,10 @@ source ci/_
(
echo --- git diff --check
set -x
if [[ -n $CI_BASE_BRANCH ]]
then branch="$CI_BASE_BRANCH"
else branch="master"
fi
# Look for failed mergify.io backports by searching leftover conflict markers
# Also check for any trailing whitespaces!
git fetch origin "$branch"
git diff "$(git merge-base HEAD "origin/$branch")" --check --oneline
git fetch origin "$CI_BASE_BRANCH"
git diff "$(git merge-base HEAD "origin/$CI_BASE_BRANCH")..HEAD" --check --oneline
)
echo

View File

@@ -21,10 +21,16 @@ export RUST_BACKTRACE=1
export RUSTFLAGS="-D warnings"
source scripts/ulimit-n.sh
# Clear cached json keypair files
rm -rf "$HOME/.config/solana"
# Clear the C dependency files, if dependency moves these files are not regenerated
test -d target/debug/bpf && find target/debug/bpf -name '*.d' -delete
test -d target/release/bpf && find target/release/bpf -name '*.d' -delete
# Clear the BPF sysroot files, they are not automatically rebuilt
rm -rf target/xargo # Issue #3105
# Limit compiler jobs to reduce memory usage
# on machines with 2gb/thread of memory
NPROC=$(nproc)
@@ -36,10 +42,6 @@ test-stable)
_ "$cargo" stable test --jobs "$NPROC" --all --exclude solana-local-cluster ${V:+--verbose} -- --nocapture
;;
test-stable-perf)
# solana-keygen required when building C programs
_ "$cargo" build --manifest-path=keygen/Cargo.toml
export PATH="$PWD/target/debug":$PATH
# BPF solana-sdk legacy compile test
./cargo-build-bpf --manifest-path sdk/Cargo.toml

View File

@@ -16,16 +16,3 @@ upload-ci-artifact() {
fi
}
upload-s3-artifact() {
echo "--- artifact: $1 to $2"
(
set -x
docker run \
--rm \
--env AWS_ACCESS_KEY_ID \
--env AWS_SECRET_ACCESS_KEY \
--volume "$PWD:/solana" \
eremite/aws-cli:2018.12.18 \
/usr/bin/s3cmd --acl-public put "$1" "$2"
)
}

View File

@@ -1,21 +1,20 @@
[package]
name = "solana-clap-utils"
version = "1.6.2"
version = "1.4.7"
description = "Solana utilities for the clap"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-clap-utils"
edition = "2018"
[dependencies]
clap = "2.33.0"
rpassword = "4.0"
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.2" }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
thiserror = "1.0.21"
tiny-bip39 = "0.8.0"
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.7" }
solana-sdk = { path = "../sdk", version = "1.4.7" }
thiserror = "1.0.20"
tiny-bip39 = "0.7.0"
url = "2.1.0"
chrono = "0.4"

View File

@@ -0,0 +1,22 @@
use crate::ArgConstant;
use clap::Arg;
pub const COMMITMENT_ARG: ArgConstant<'static> = ArgConstant {
name: "commitment",
long: "commitment",
help: "Return information at the selected commitment level",
};
pub fn commitment_arg<'a, 'b>() -> Arg<'a, 'b> {
commitment_arg_with_default("recent")
}
pub fn commitment_arg_with_default<'a, 'b>(default_value: &'static str) -> Arg<'a, 'b> {
Arg::with_name(COMMITMENT_ARG.name)
.long(COMMITMENT_ARG.long)
.takes_value(true)
.possible_values(&["recent", "single", "singleGossip", "root", "max"])
.default_value(default_value)
.value_name("COMMITMENT_LEVEL")
.help(COMMITMENT_ARG.help)
}

View File

@@ -167,12 +167,12 @@ pub fn resolve_signer(
name: &str,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<Option<String>, Box<dyn std::error::Error>> {
resolve_signer_from_path(
Ok(resolve_signer_from_path(
matches,
matches.value_of(name).unwrap(),
name,
wallet_manager,
)
)?)
}
pub fn lamports_of_sol(matches: &ArgMatches<'_>, name: &str) -> Option<u64> {
@@ -184,9 +184,13 @@ pub fn cluster_type_of(matches: &ArgMatches<'_>, name: &str) -> Option<ClusterTy
}
pub fn commitment_of(matches: &ArgMatches<'_>, name: &str) -> Option<CommitmentConfig> {
matches
.value_of(name)
.map(|value| CommitmentConfig::from_str(value).unwrap_or_default())
matches.value_of(name).map(|value| match value {
"max" => CommitmentConfig::max(),
"recent" => CommitmentConfig::recent(),
"root" => CommitmentConfig::root(),
"single" => CommitmentConfig::single(),
_ => CommitmentConfig::default(),
})
}
#[cfg(test)]

View File

@@ -1,9 +1,9 @@
use crate::keypair::{parse_keypair_path, KeypairUrl, ASK_KEYWORD};
use chrono::DateTime;
use solana_sdk::{
clock::{Epoch, Slot},
clock::Slot,
hash::Hash,
pubkey::{Pubkey, MAX_SEED_LEN},
pubkey::Pubkey,
signature::{read_keypair_file, Signature},
};
use std::fmt::Display;
@@ -148,40 +148,6 @@ where
}
}
pub fn is_url_or_moniker<T>(string: T) -> Result<(), String>
where
T: AsRef<str> + Display,
{
match url::Url::parse(&normalize_to_url_if_moniker(string.as_ref())) {
Ok(url) => {
if url.has_host() {
Ok(())
} else {
Err("no host provided".to_string())
}
}
Err(err) => Err(format!("{}", err)),
}
}
pub fn normalize_to_url_if_moniker<T: AsRef<str>>(url_or_moniker: T) -> String {
match url_or_moniker.as_ref() {
"m" | "mainnet-beta" => "https://api.mainnet-beta.solana.com",
"t" | "testnet" => "https://testnet.solana.com",
"d" | "devnet" => "https://devnet.solana.com",
"l" | "localhost" => "http://localhost:8899",
url => url,
}
.to_string()
}
pub fn is_epoch<T>(epoch: T) -> Result<(), String>
where
T: AsRef<str> + Display,
{
is_parsable_generic::<Epoch, _>(epoch)
}
pub fn is_slot<T>(slot: T) -> Result<(), String>
where
T: AsRef<str> + Display,
@@ -291,21 +257,6 @@ where
.map(|_| ())
}
pub fn is_derived_address_seed<T>(value: T) -> Result<(), String>
where
T: AsRef<str> + Display,
{
let value = value.as_ref();
if value.len() > MAX_SEED_LEN {
Err(format!(
"Address seed must not be longer than {} bytes",
MAX_SEED_LEN
))
} else {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -12,7 +12,6 @@ use solana_remote_wallet::{
};
use solana_sdk::{
hash::Hash,
message::Message,
pubkey::Pubkey,
signature::{
keypair_from_seed, keypair_from_seed_phrase_and_passphrase, read_keypair,
@@ -29,7 +28,6 @@ use std::{
pub struct SignOnly {
pub blockhash: Hash,
pub message: Option<String>,
pub present_signers: Vec<(Pubkey, Signature)>,
pub absent_signers: Vec<Pubkey>,
pub bad_signers: Vec<Pubkey>,
@@ -60,27 +58,6 @@ impl CliSignerInfo {
Some(0)
}
}
pub fn index_of_or_none(&self, pubkey: Option<Pubkey>) -> Option<usize> {
if let Some(pubkey) = pubkey {
self.signers
.iter()
.position(|signer| signer.pubkey() == pubkey)
} else {
None
}
}
pub fn signers_for_message(&self, message: &Message) -> Vec<&dyn Signer> {
self.signers
.iter()
.filter_map(|k| {
if message.signer_keys().contains(&&k.pubkey()) {
Some(k.as_ref())
} else {
None
}
})
.collect()
}
}
pub struct DefaultSigner {
@@ -122,15 +99,6 @@ impl DefaultSigner {
) -> Result<Box<dyn Signer>, Box<dyn std::error::Error>> {
signer_from_path(matches, &self.path, &self.arg_name, wallet_manager)
}
pub fn signer_from_path_with_config(
&self,
matches: &ArgMatches,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
config: &SignerFromPathConfig,
) -> Result<Box<dyn Signer>, Box<dyn std::error::Error>> {
signer_from_path_with_config(matches, &self.path, &self.arg_name, wallet_manager, config)
}
}
pub enum KeypairUrl {
@@ -168,35 +136,11 @@ pub fn presigner_from_pubkey_sigs(
})
}
#[derive(Debug)]
pub struct SignerFromPathConfig {
pub allow_null_signer: bool,
}
impl Default for SignerFromPathConfig {
fn default() -> Self {
Self {
allow_null_signer: false,
}
}
}
pub fn signer_from_path(
matches: &ArgMatches,
path: &str,
keypair_name: &str,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<Box<dyn Signer>, Box<dyn error::Error>> {
let config = SignerFromPathConfig::default();
signer_from_path_with_config(matches, path, keypair_name, wallet_manager, &config)
}
pub fn signer_from_path_with_config(
matches: &ArgMatches,
path: &str,
keypair_name: &str,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
config: &SignerFromPathConfig,
) -> Result<Box<dyn Signer>, Box<dyn error::Error>> {
match parse_keypair_path(path) {
KeypairUrl::Ask => {
@@ -240,7 +184,7 @@ pub fn signer_from_path_with_config(
.and_then(|presigners| presigner_from_pubkey_sigs(&pubkey, presigners));
if let Some(presigner) = presigner {
Ok(Box::new(presigner))
} else if config.allow_null_signer || matches.is_present(SIGN_ONLY_ARG.name) {
} else if matches.is_present(SIGN_ONLY_ARG.name) {
Ok(Box::new(NullSigner::new(&pubkey)))
} else {
Err(std::io::Error::new(
@@ -402,7 +346,6 @@ fn sanitize_seed_phrase(seed_phrase: &str) -> String {
#[cfg(test)]
mod tests {
use super::*;
use solana_sdk::system_instruction;
#[test]
fn test_sanitize_seed_phrase() {
@@ -412,35 +355,4 @@ mod tests {
sanitize_seed_phrase(seed_phrase)
);
}
#[test]
fn test_signer_info_signers_for_message() {
let source = Keypair::new();
let fee_payer = Keypair::new();
let nonsigner1 = Keypair::new();
let nonsigner2 = Keypair::new();
let recipient = Pubkey::new_unique();
let message = Message::new(
&[system_instruction::transfer(
&source.pubkey(),
&recipient,
42,
)],
Some(&fee_payer.pubkey()),
);
let signers = vec![
Box::new(fee_payer) as Box<dyn Signer>,
Box::new(source) as Box<dyn Signer>,
Box::new(nonsigner1) as Box<dyn Signer>,
Box::new(nonsigner2) as Box<dyn Signer>,
];
let signer_info = CliSignerInfo { signers };
let msg_signers = signer_info.signers_for_message(&message);
let signer_pubkeys = msg_signers.iter().map(|s| s.pubkey()).collect::<Vec<_>>();
let expect = vec![
signer_info.signers[0].pubkey(),
signer_info.signers[1].pubkey(),
];
assert_eq!(signer_pubkeys, expect);
}
}

View File

@@ -23,6 +23,7 @@ impl std::fmt::Debug for DisplayError {
}
}
pub mod commitment;
pub mod fee_payer;
pub mod input_parsers;
pub mod input_validators;

View File

@@ -19,12 +19,6 @@ pub const SIGNER_ARG: ArgConstant<'static> = ArgConstant {
help: "Provide a public-key/signature pair for the transaction",
};
pub const DUMP_TRANSACTION_MESSAGE: ArgConstant<'static> = ArgConstant {
name: "dump_transaction_message",
long: "dump-transaction-message",
help: "Display the base64 encoded binary transaction message in sign-only mode",
};
pub fn blockhash_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(BLOCKHASH_ARG.name)
.long(BLOCKHASH_ARG.long)
@@ -53,14 +47,6 @@ fn signer_arg<'a, 'b>() -> Arg<'a, 'b> {
.help(SIGNER_ARG.help)
}
pub fn dump_transaction_message<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(DUMP_TRANSACTION_MESSAGE.name)
.long(DUMP_TRANSACTION_MESSAGE.long)
.takes_value(false)
.requires(SIGN_ONLY_ARG.name)
.help(DUMP_TRANSACTION_MESSAGE.help)
}
pub trait ArgsConfig {
fn blockhash_arg<'a, 'b>(&self, arg: Arg<'a, 'b>) -> Arg<'a, 'b> {
arg
@@ -71,9 +57,6 @@ pub trait ArgsConfig {
fn signer_arg<'a, 'b>(&self, arg: Arg<'a, 'b>) -> Arg<'a, 'b> {
arg
}
fn dump_transaction_message_arg<'a, 'b>(&self, arg: Arg<'a, 'b>) -> Arg<'a, 'b> {
arg
}
}
pub trait OfflineArgs {
@@ -86,7 +69,6 @@ impl OfflineArgs for App<'_, '_> {
self.arg(config.blockhash_arg(blockhash_arg()))
.arg(config.sign_only_arg(sign_only_arg()))
.arg(config.signer_arg(signer_arg()))
.arg(config.dump_transaction_message_arg(dump_transaction_message()))
}
fn offline_args(self) -> Self {
struct NullArgsConfig {}

View File

@@ -3,16 +3,15 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-cli-config"
description = "Blockchain, Rebuilt for Scale"
version = "1.6.2"
version = "1.4.7"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-cli-config"
[dependencies]
dirs-next = "2.0.0"
lazy_static = "1.4.0"
serde = "1.0.122"
serde = "1.0.112"
serde_derive = "1.0.103"
serde_yaml = "0.8.13"
url = "2.1.1"

View File

@@ -17,10 +17,9 @@ pub struct Config {
pub json_rpc_url: String,
pub websocket_url: String,
pub keypair_path: String,
#[serde(default)]
pub address_labels: HashMap<String, String>,
#[serde(default)]
pub commitment: String,
}
impl Default for Config {
@@ -42,14 +41,11 @@ impl Default for Config {
"System Program".to_string(),
);
let commitment = "confirmed".to_string();
Self {
json_rpc_url,
websocket_url,
keypair_path,
address_labels,
commitment,
}
}
}
@@ -75,12 +71,22 @@ impl Config {
.set_scheme(if is_secure { "wss" } else { "ws" })
.expect("unable to set scheme");
if let Some(port) = json_rpc_url.port() {
let port = port.checked_add(1).expect("port out of range");
ws_url.set_port(Some(port)).expect("unable to set port");
ws_url.set_port(Some(port + 1)).expect("unable to set port");
}
ws_url.to_string()
}
pub fn compute_rpc_banks_url(json_rpc_url: &str) -> String {
let json_rpc_url: Option<Url> = json_rpc_url.parse().ok();
if json_rpc_url.is_none() {
return "".to_string();
}
let mut url = json_rpc_url.unwrap();
let port = url.port().unwrap_or(8899);
url.set_port(Some(port + 3)).expect("unable to set port");
url.to_string()
}
pub fn import_address_labels<P>(&mut self, filename: P) -> Result<(), io::Error>
where
P: AsRef<Path>,
@@ -127,4 +133,28 @@ mod test {
assert_eq!(Config::compute_websocket_url(&"garbage"), String::new());
}
#[test]
fn compute_rpc_banks_url() {
assert_eq!(
Config::compute_rpc_banks_url(&"http://devnet.solana.com"),
"http://devnet.solana.com:8902/".to_string()
);
assert_eq!(
Config::compute_rpc_banks_url(&"https://devnet.solana.com"),
"https://devnet.solana.com:8902/".to_string()
);
assert_eq!(
Config::compute_rpc_banks_url(&"http://example.com:8899"),
"http://example.com:8902/".to_string()
);
assert_eq!(
Config::compute_rpc_banks_url(&"https://example.com:1234"),
"https://example.com:1237/".to_string()
);
assert_eq!(Config::compute_rpc_banks_url(&"garbage"), String::new());
}
}

View File

@@ -3,29 +3,27 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-cli-output"
description = "Blockchain, Rebuilt for Scale"
version = "1.6.2"
version = "1.4.7"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-cli-output"
[dependencies]
base64 = "0.13.0"
chrono = { version = "0.4.11", features = ["serde"] }
console = "0.11.3"
humantime = "2.0.1"
Inflector = "0.11.4"
indicatif = "0.15.0"
serde = "1.0.122"
serde = "1.0.112"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "=1.6.2" }
solana-clap-utils = { path = "../clap-utils", version = "=1.6.2" }
solana-client = { path = "../client", version = "=1.6.2" }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
solana-stake-program = { path = "../programs/stake", version = "=1.6.2" }
solana-transaction-status = { path = "../transaction-status", version = "=1.6.2" }
solana-vote-program = { path = "../programs/vote", version = "=1.6.2" }
solana-account-decoder = { path = "../account-decoder", version = "1.4.7" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.7" }
solana-client = { path = "../client", version = "1.4.7" }
solana-sdk = { path = "../sdk", version = "1.4.7" }
solana-stake-program = { path = "../programs/stake", version = "1.4.7" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.7" }
solana-vote-program = { path = "../programs/vote", version = "1.4.7" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

File diff suppressed because it is too large Load Diff

View File

@@ -1,78 +1,33 @@
use {
crate::cli_output::CliSignatureVerificationStatus,
chrono::{DateTime, Local, NaiveDateTime, SecondsFormat, TimeZone, Utc},
console::style,
indicatif::{ProgressBar, ProgressStyle},
solana_sdk::{
clock::UnixTimestamp, hash::Hash, message::Message, native_token::lamports_to_sol,
program_utils::limited_deserialize, transaction::Transaction,
},
solana_transaction_status::UiTransactionStatusMeta,
std::{collections::HashMap, fmt, io},
use console::style;
use indicatif::{ProgressBar, ProgressStyle};
use solana_sdk::{
hash::Hash, native_token::lamports_to_sol, program_utils::limited_deserialize,
transaction::Transaction,
};
use solana_transaction_status::UiTransactionStatusMeta;
use std::{collections::HashMap, fmt, io};
#[derive(Clone, Debug)]
pub struct BuildBalanceMessageConfig {
pub use_lamports_unit: bool,
pub show_unit: bool,
pub trim_trailing_zeros: bool,
}
impl Default for BuildBalanceMessageConfig {
fn default() -> Self {
Self {
use_lamports_unit: false,
show_unit: true,
trim_trailing_zeros: true,
}
}
}
pub fn build_balance_message_with_config(
lamports: u64,
config: &BuildBalanceMessageConfig,
) -> String {
let value = if config.use_lamports_unit {
lamports.to_string()
pub fn build_balance_message(lamports: u64, use_lamports_unit: bool, show_unit: bool) -> String {
if use_lamports_unit {
let ess = if lamports == 1 { "" } else { "s" };
let unit = if show_unit {
format!(" lamport{}", ess)
} else {
"".to_string()
};
format!("{:?}{}", lamports, unit)
} else {
let sol = lamports_to_sol(lamports);
let sol_str = format!("{:.9}", sol);
if config.trim_trailing_zeros {
sol_str
.trim_end_matches('0')
.trim_end_matches('.')
.to_string()
} else {
sol_str
}
};
let unit = if config.show_unit {
if config.use_lamports_unit {
let ess = if lamports == 1 { "" } else { "s" };
format!(" lamport{}", ess)
} else {
" SOL".to_string()
}
} else {
"".to_string()
};
format!("{}{}", value, unit)
}
pub fn build_balance_message(lamports: u64, use_lamports_unit: bool, show_unit: bool) -> String {
build_balance_message_with_config(
lamports,
&BuildBalanceMessageConfig {
use_lamports_unit,
show_unit,
..BuildBalanceMessageConfig::default()
},
)
let pretty_sol = sol_str.trim_end_matches('0').trim_end_matches('.');
let unit = if show_unit { " SOL" } else { "" };
format!("{}{}", pretty_sol, unit)
}
}
// Pretty print a "name value"
pub fn println_name_value(name: &str, value: &str) {
let styled_value = if value.is_empty() {
let styled_value = if value == "" {
style("(not set)").italic()
} else {
style(value)
@@ -80,8 +35,8 @@ pub fn println_name_value(name: &str, value: &str) {
println!("{} {}", style(name).bold(), styled_value);
}
pub fn writeln_name_value(f: &mut dyn fmt::Write, name: &str, value: &str) -> fmt::Result {
let styled_value = if value.is_empty() {
pub fn writeln_name_value(f: &mut fmt::Formatter, name: &str, value: &str) -> fmt::Result {
let styled_value = if value == "" {
style("(not set)").italic()
} else {
style(value)
@@ -125,98 +80,35 @@ pub fn println_signers(
println!();
}
fn format_account_mode(message: &Message, index: usize) -> String {
format!(
"{}r{}{}", // accounts are always readable...
if message.is_signer(index) {
"s" // stands for signer
} else {
"-"
},
if message.is_writable(index) {
"w" // comment for consistent rust fmt (no joking; lol)
} else {
"-"
},
// account may be executable on-chain while not being
// designated as a program-id in the message
if message.maybe_executable(index) {
"x"
} else {
// programs to be executed via CPI cannot be identified as
// executable from the message
"-"
},
)
}
pub fn write_transaction<W: io::Write>(
w: &mut W,
transaction: &Transaction,
transaction_status: &Option<UiTransactionStatusMeta>,
prefix: &str,
sigverify_status: Option<&[CliSignatureVerificationStatus]>,
block_time: Option<UnixTimestamp>,
) -> io::Result<()> {
let message = &transaction.message;
if let Some(block_time) = block_time {
writeln!(
w,
"{}Block Time: {:?}",
prefix,
Local.timestamp(block_time, 0)
)?;
}
writeln!(
w,
"{}Recent Blockhash: {:?}",
prefix, message.recent_blockhash
)?;
let sigverify_statuses = if let Some(sigverify_status) = sigverify_status {
sigverify_status
.iter()
.map(|s| format!(" ({})", s))
.collect()
} else {
vec!["".to_string(); transaction.signatures.len()]
};
for (signature_index, (signature, sigverify_status)) in transaction
.signatures
.iter()
.zip(&sigverify_statuses)
.enumerate()
{
for (signature_index, signature) in transaction.signatures.iter().enumerate() {
writeln!(
w,
"{}Signature {}: {:?}{}",
prefix, signature_index, signature, sigverify_status,
"{}Signature {}: {:?}",
prefix, signature_index, signature
)?;
}
let mut fee_payer_index = None;
writeln!(w, "{}{:?}", prefix, message.header)?;
for (account_index, account) in message.account_keys.iter().enumerate() {
if fee_payer_index.is_none() && message.is_non_loader_key(account, account_index) {
fee_payer_index = Some(account_index)
}
writeln!(
w,
"{}Account {}: {} {}{}",
prefix,
account_index,
format_account_mode(message, account_index),
account,
if Some(account_index) == fee_payer_index {
" (fee payer)"
} else {
""
},
)?;
writeln!(w, "{}Account {}: {:?}", prefix, account_index, account)?;
}
for (instruction_index, instruction) in message.instructions.iter().enumerate() {
let program_pubkey = message.account_keys[instruction.program_id_index as usize];
writeln!(w, "{}Instruction {}", prefix, instruction_index)?;
writeln!(
w,
"{} Program: {} ({})",
"{} Program: {} ({})",
prefix, program_pubkey, instruction.program_id_index
)?;
for (account_index, account) in instruction.accounts.iter().enumerate() {
@@ -325,52 +217,15 @@ pub fn println_transaction(
transaction: &Transaction,
transaction_status: &Option<UiTransactionStatusMeta>,
prefix: &str,
sigverify_status: Option<&[CliSignatureVerificationStatus]>,
block_time: Option<UnixTimestamp>,
) {
let mut w = Vec::new();
if write_transaction(
&mut w,
transaction,
transaction_status,
prefix,
sigverify_status,
block_time,
)
.is_ok()
{
if write_transaction(&mut w, transaction, transaction_status, prefix).is_ok() {
if let Ok(s) = String::from_utf8(w) {
print!("{}", s);
}
}
}
pub fn writeln_transaction(
f: &mut dyn fmt::Write,
transaction: &Transaction,
transaction_status: &Option<UiTransactionStatusMeta>,
prefix: &str,
sigverify_status: Option<&[CliSignatureVerificationStatus]>,
block_time: Option<UnixTimestamp>,
) -> fmt::Result {
let mut w = Vec::new();
if write_transaction(
&mut w,
transaction,
transaction_status,
prefix,
sigverify_status,
block_time,
)
.is_ok()
{
if let Ok(s) = String::from_utf8(w) {
write!(f, "{}", s)?;
}
}
Ok(())
}
/// Creates a new process bar for processing that will take an unknown amount of time
pub fn new_spinner_progress_bar() -> ProgressBar {
let progress_bar = ProgressBar::new(42);
@@ -380,13 +235,6 @@ pub fn new_spinner_progress_bar() -> ProgressBar {
progress_bar
}
pub fn unix_timestamp_to_string(unix_timestamp: UnixTimestamp) -> String {
match NaiveDateTime::from_timestamp_opt(unix_timestamp, 0) {
Some(ndt) => DateTime::<Utc>::from_utc(ndt, Utc).to_rfc3339_opts(SecondsFormat::Secs, true),
None => format!("UnixTimestamp {}", unix_timestamp),
}
}
#[cfg(test)]
mod test {
use super::*;

View File

@@ -1,4 +1,3 @@
#![allow(clippy::integer_arithmetic)]
mod cli_output;
pub mod display;
pub use cli_output::*;

View File

@@ -3,11 +3,10 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-cli"
description = "Blockchain, Rebuilt for Scale"
version = "1.6.2"
version = "1.4.7"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-cli"
[dependencies]
bincode = "1.3.1"
@@ -18,39 +17,40 @@ criterion-stats = "0.3.0"
ctrlc = { version = "3.1.5", features = ["termination"] }
console = "0.11.3"
dirs-next = "2.0.0"
log = "0.4.11"
log = "0.4.8"
Inflector = "0.11.4"
indicatif = "0.15.0"
humantime = "2.0.1"
num-traits = "0.2"
pretty-hex = "0.2.1"
reqwest = { version = "0.11.2", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde = "1.0.122"
pretty-hex = "0.1.1"
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.6.2" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.6.2" }
solana-clap-utils = { path = "../clap-utils", version = "=1.6.2" }
solana-cli-config = { path = "../cli-config", version = "=1.6.2" }
solana-cli-output = { path = "../cli-output", version = "=1.6.2" }
solana-client = { path = "../client", version = "=1.6.2" }
solana-config-program = { path = "../programs/config", version = "=1.6.2" }
solana-faucet = { path = "../faucet", version = "=1.6.2" }
solana-logger = { path = "../logger", version = "=1.6.2" }
solana-net-utils = { path = "../net-utils", version = "=1.6.2" }
solana_rbpf = "=0.2.5"
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.2" }
solana-sdk = { path = "../sdk", version = "=1.6.2" }
solana-stake-program = { path = "../programs/stake", version = "=1.6.2" }
solana-transaction-status = { path = "../transaction-status", version = "=1.6.2" }
solana-version = { path = "../version", version = "=1.6.2" }
solana-vote-program = { path = "../programs/vote", version = "=1.6.2" }
thiserror = "1.0.21"
solana-account-decoder = { path = "../account-decoder", version = "1.4.7" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.4.7" }
solana-clap-utils = { path = "../clap-utils", version = "1.4.7" }
solana-cli-config = { path = "../cli-config", version = "1.4.7" }
solana-cli-output = { path = "../cli-output", version = "1.4.7" }
solana-client = { path = "../client", version = "1.4.7" }
solana-config-program = { path = "../programs/config", version = "1.4.7" }
solana-faucet = { path = "../faucet", version = "1.4.7" }
solana-logger = { path = "../logger", version = "1.4.7" }
solana-net-utils = { path = "../net-utils", version = "1.4.7" }
solana_rbpf = "=0.1.32"
solana-remote-wallet = { path = "../remote-wallet", version = "1.4.7" }
solana-sdk = { path = "../sdk", version = "1.4.7" }
solana-stake-program = { path = "../programs/stake", version = "1.4.7" }
solana-transaction-status = { path = "../transaction-status", version = "1.4.7" }
solana-version = { path = "../version", version = "1.4.7" }
solana-vote-program = { path = "../programs/vote", version = "1.4.7" }
solana-vote-signer = { path = "../vote-signer", version = "1.4.7" }
thiserror = "1.0.20"
tiny-bip39 = "0.7.0"
url = "2.1.1"
[dev-dependencies]
solana-core = { path = "../core", version = "=1.6.2" }
solana-core = { path = "../core", version = "1.4.7" }
tempfile = "3.1.0"
[[bin]]

View File

@@ -86,13 +86,9 @@ pub fn check_account_for_spend_multiple_fees_with_commitment(
return Err(CliError::InsufficientFundsForSpendAndFee(
lamports_to_sol(balance),
lamports_to_sol(fee),
*account_pubkey,
));
} else {
return Err(CliError::InsufficientFundsForFee(
lamports_to_sol(fee),
*account_pubkey,
));
return Err(CliError::InsufficientFundsForFee(lamports_to_sol(fee)));
}
}
Ok(())

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -19,22 +19,10 @@ use solana_sdk::{
};
use std::{collections::HashMap, fmt, sync::Arc};
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ForceActivation {
No,
Almost,
Yes,
}
#[derive(Debug, PartialEq)]
pub enum FeatureCliCommand {
Status {
features: Vec<Pubkey>,
},
Activate {
feature: Pubkey,
force: ForceActivation,
},
Status { features: Vec<Pubkey> },
Activate { feature: Pubkey },
}
#[derive(Serialize, Deserialize)]
@@ -70,8 +58,8 @@ impl fmt::Display for CliFeatures {
f,
"{}",
style(format!(
"{:<44} | {:<27} | {}",
"Feature", "Status", "Description"
"{:<44} {:<40} {}",
"Feature", "Description", "Status"
))
.bold()
)?;
@@ -79,15 +67,15 @@ impl fmt::Display for CliFeatures {
for feature in &self.features {
writeln!(
f,
"{:<44} | {:<27} | {}",
"{:<44} {:<40} {}",
feature.id,
feature.description,
match feature.status {
CliFeatureStatus::Inactive => style("inactive".to_string()).red(),
CliFeatureStatus::Pending => style("activation pending".to_string()).yellow(),
CliFeatureStatus::Active(activation_slot) =>
style(format!("active since slot {}", activation_slot)).green(),
},
feature.description,
}
)?;
}
if self.inactive && !self.feature_activation_allowed {
@@ -138,13 +126,6 @@ impl FeatureSubCommands for App<'_, '_> {
.index(1)
.required(true)
.help("The signer for the feature to activate"),
)
.arg(
Arg::with_name("force")
.long("yolo")
.hidden(true)
.multiple(true)
.help("Override activation sanity checks. Don't use this flag"),
),
),
)
@@ -171,20 +152,13 @@ pub fn parse_feature_subcommand(
("activate", Some(matches)) => {
let (feature_signer, feature) = signer_of(matches, "feature", wallet_manager)?;
let mut signers = vec![default_signer.signer_from_path(matches, wallet_manager)?];
let force = match matches.occurrences_of("force") {
2 => ForceActivation::Yes,
1 => ForceActivation::Almost,
_ => ForceActivation::No,
};
signers.push(feature_signer.unwrap());
let feature = feature.unwrap();
known_feature(&feature)?;
CliCommandInfo {
command: CliCommand::Feature(FeatureCliCommand::Activate { feature, force }),
command: CliCommand::Feature(FeatureCliCommand::Activate { feature }),
signers,
}
}
@@ -215,13 +189,11 @@ pub fn process_feature_subcommand(
) -> ProcessResult {
match feature_subcommand {
FeatureCliCommand::Status { features } => process_status(rpc_client, config, features),
FeatureCliCommand::Activate { feature, force } => {
process_activate(rpc_client, config, *feature, *force)
}
FeatureCliCommand::Activate { feature } => process_activate(rpc_client, config, *feature),
}
}
fn active_stake_by_feature_set(rpc_client: &RpcClient) -> Result<HashMap<u32, f64>, ClientError> {
fn active_stake_by_feature_set(rpc_client: &RpcClient) -> Result<HashMap<u32, u64>, ClientError> {
// Validator identity -> feature set
let feature_set_map = rpc_client
.get_cluster_nodes()?
@@ -239,7 +211,7 @@ fn active_stake_by_feature_set(rpc_client: &RpcClient) -> Result<HashMap<u32, f6
.sum();
// Sum all active stake by feature set
let mut active_stake_by_feature_set: HashMap<u32, u64> = HashMap::new();
let mut active_stake_by_feature_set = HashMap::new();
for vote_account in vote_accounts.current {
if let Some(Some(feature_set)) = feature_set_map.get(&vote_account.node_pubkey) {
*active_stake_by_feature_set.entry(*feature_set).or_default() +=
@@ -251,15 +223,11 @@ fn active_stake_by_feature_set(rpc_client: &RpcClient) -> Result<HashMap<u32, f6
}
}
Ok(active_stake_by_feature_set
.into_iter()
.map(|(feature_set, active_stake)| {
(
feature_set,
active_stake as f64 * 100. / total_active_stake as f64,
)
})
.collect())
// Convert active stake to a percentage so the caller doesn't need `total_active_stake`
for (_, val) in active_stake_by_feature_set.iter_mut() {
*val = *val * 100 / total_active_stake;
}
Ok(active_stake_by_feature_set)
}
// Feature activation is only allowed when 95% of the active stake is on the current feature set
@@ -270,7 +238,7 @@ fn feature_activation_allowed(rpc_client: &RpcClient, quiet: bool) -> Result<boo
let feature_activation_allowed = active_stake_by_feature_set
.get(&my_feature_set)
.map(|percentage| *percentage >= 95.)
.map(|percentage| *percentage >= 95)
.unwrap_or(false);
if !feature_activation_allowed && !quiet {
@@ -287,15 +255,15 @@ fn feature_activation_allowed(rpc_client: &RpcClient, quiet: bool) -> Result<boo
}
println!(
"{}",
style(format!("Tool Feature Set: {}", my_feature_set)).bold()
style(format!("Tool Feture Set: {}", my_feature_set)).bold()
);
println!("{}", style("Cluster Feature Sets and Stakes:").bold());
for (feature_set, percentage) in active_stake_by_feature_set.iter() {
if *feature_set == 0 {
println!(" unknown - {:.2}%", percentage);
println!("unknown - {}%", percentage);
} else {
println!(
" {:<10} - {:.2}% {}",
"{} - {}% {}",
feature_set,
percentage,
if *feature_set == my_feature_set {
@@ -361,14 +329,12 @@ fn process_activate(
rpc_client: &RpcClient,
config: &CliConfig,
feature_id: Pubkey,
force: ForceActivation,
) -> ProcessResult {
let account = rpc_client
.get_multiple_accounts(&[feature_id])?
.into_iter()
.next()
.unwrap();
if let Some(account) = account {
if feature::from_account(&account).is_some() {
return Err(format!("{} has already been activated", feature_id).into());
@@ -376,13 +342,7 @@ fn process_activate(
}
if !feature_activation_allowed(rpc_client, false)? {
match force {
ForceActivation::Almost =>
return Err("Add force argument once more to override the sanity check to force feature activation ".into()),
ForceActivation::Yes => println!("FEATURE ACTIVATION FORCED"),
ForceActivation::No =>
return Err("Feature activation is not allowed at this time".into()),
}
return Err("Feature activation is not allowed at this time".into());
}
let rent = rpc_client.get_minimum_balance_for_rent_exemption(Feature::size_of())?;

View File

@@ -1,7 +1,7 @@
use crate::cli::{CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult};
use clap::{App, ArgMatches, SubCommand};
use console::style;
use solana_clap_utils::keypair::*;
use solana_cli_output::CliInflation;
use solana_client::rpc_client::RpcClient;
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use std::sync::Arc;
@@ -34,18 +34,56 @@ pub fn parse_inflation_subcommand(
pub fn process_inflation_subcommand(
rpc_client: &RpcClient,
config: &CliConfig,
_config: &CliConfig,
inflation_subcommand: &InflationCliCommand,
) -> ProcessResult {
assert_eq!(*inflation_subcommand, InflationCliCommand::Show);
let governor = rpc_client.get_inflation_governor()?;
let current_rate = rpc_client.get_inflation_rate()?;
let current_inflation_rate = rpc_client.get_inflation_rate()?;
let inflation = CliInflation {
governor,
current_rate,
};
println!("{}", style("Inflation Governor:").bold());
if (governor.initial - governor.terminal).abs() < f64::EPSILON {
println!(
"Fixed APR: {:>5.2}%",
governor.terminal * 100.
);
} else {
println!("Initial APR: {:>5.2}%", governor.initial * 100.);
println!(
"Terminal APR: {:>5.2}%",
governor.terminal * 100.
);
println!("Rate reduction per year: {:>5.2}%", governor.taper * 100.);
}
if governor.foundation_term > 0. {
println!("Foundation percentage: {:>5.2}%", governor.foundation);
println!(
"Foundation term: {:.1} years",
governor.foundation_term
);
}
Ok(config.output_format.formatted_string(&inflation))
println!(
"\n{}",
style(format!(
"Inflation for Epoch {}:",
current_inflation_rate.epoch
))
.bold()
);
println!(
"Total APR: {:>5.2}%",
current_inflation_rate.total * 100.
);
println!(
"Staking APR: {:>5.2}%",
current_inflation_rate.validator * 100.
);
println!(
"Foundation APR: {:>5.2}%",
current_inflation_rate.foundation * 100.
);
Ok("".to_string())
}

View File

@@ -1,4 +1,3 @@
#![allow(clippy::integer_arithmetic)]
macro_rules! ACCOUNT_STRING {
() => {
r#", one of:
@@ -27,7 +26,6 @@ pub mod cluster_query;
pub mod feature;
pub mod inflation;
pub mod nonce;
pub mod program;
pub mod send_tpu;
pub mod spend_utils;
pub mod stake;

View File

@@ -3,8 +3,11 @@ use clap::{
SubCommand,
};
use console::style;
use solana_clap_utils::{
input_validators::{is_url, is_url_or_moniker, normalize_to_url_if_moniker},
commitment::COMMITMENT_ARG,
input_parsers::commitment_of,
input_validators::is_url,
keypair::{CliSigners, DefaultSigner, SKIP_SEED_PHRASE_VALIDATION_ARG},
DisplayError,
};
@@ -60,19 +63,12 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
);
let (keypair_setting_type, keypair_path) =
CliConfig::compute_keypair_path_setting("", &config.keypair_path);
let (commitment_setting_type, commitment) =
CliConfig::compute_commitment_config("", &config.commitment);
if let Some(field) = subcommand_matches.value_of("specific_setting") {
let (field_name, value, setting_type) = match field {
"json_rpc_url" => ("RPC URL", json_rpc_url, url_setting_type),
"websocket_url" => ("WebSocket URL", websocket_url, ws_setting_type),
"keypair" => ("Key Path", keypair_path, keypair_setting_type),
"commitment" => (
"Commitment",
commitment.commitment.to_string(),
commitment_setting_type,
),
_ => unreachable!(),
};
println_name_value_or(&format!("{}:", field_name), &value, setting_type);
@@ -81,16 +77,11 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
println_name_value_or("RPC URL:", &json_rpc_url, url_setting_type);
println_name_value_or("WebSocket URL:", &websocket_url, ws_setting_type);
println_name_value_or("Keypair Path:", &keypair_path, keypair_setting_type);
println_name_value_or(
"Commitment:",
&commitment.commitment.to_string(),
commitment_setting_type,
);
}
}
("set", Some(subcommand_matches)) => {
if let Some(url) = subcommand_matches.value_of("json_rpc_url") {
config.json_rpc_url = normalize_to_url_if_moniker(url);
config.json_rpc_url = url.to_string();
// Revert to a computed `websocket_url` value when `json_rpc_url` is
// changed
config.websocket_url = "".to_string();
@@ -101,9 +92,6 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
if let Some(keypair) = subcommand_matches.value_of("keypair") {
config.keypair_path = keypair.to_string();
}
if let Some(commitment) = subcommand_matches.value_of("commitment") {
config.commitment = commitment.to_string();
}
config.save(config_file)?;
@@ -117,18 +105,11 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
);
let (keypair_setting_type, keypair_path) =
CliConfig::compute_keypair_path_setting("", &config.keypair_path);
let (commitment_setting_type, commitment) =
CliConfig::compute_commitment_config("", &config.commitment);
println_name_value("Config File:", config_file);
println_name_value_or("RPC URL:", &json_rpc_url, url_setting_type);
println_name_value_or("WebSocket URL:", &websocket_url, ws_setting_type);
println_name_value_or("Keypair Path:", &keypair_path, keypair_setting_type);
println_name_value_or(
"Commitment:",
&commitment.commitment.to_string(),
commitment_setting_type,
);
}
("import-address-labels", Some(subcommand_matches)) => {
let filename = value_t_or_exit!(subcommand_matches, "filename", PathBuf);
@@ -184,20 +165,9 @@ pub fn parse_args<'a>(
path: default_signer_path.clone(),
};
let CliCommandInfo {
command,
mut signers,
} = parse_command(&matches, &default_signer, &mut wallet_manager)?;
let CliCommandInfo { command, signers } =
parse_command(&matches, &default_signer, &mut wallet_manager)?;
if signers.is_empty() {
if let Ok(signer_info) =
default_signer.generate_unique_signers(vec![None], matches, &mut wallet_manager)
{
signers.extend(signer_info.signers);
}
}
let verbose = matches.is_present("verbose");
let output_format = matches
.value_of("output_format")
.map(|value| match value {
@@ -205,16 +175,13 @@ pub fn parse_args<'a>(
"json-compact" => OutputFormat::JsonCompact,
_ => unreachable!(),
})
.unwrap_or(if verbose {
OutputFormat::DisplayVerbose
} else {
OutputFormat::Display
});
.unwrap_or(OutputFormat::Display);
let (_, commitment) = CliConfig::compute_commitment_config(
matches.value_of("commitment").unwrap_or(""),
&config.commitment,
);
let commitment = matches
.subcommand_name()
.and_then(|name| matches.subcommand_matches(name))
.and_then(|sub_matches| commitment_of(sub_matches, COMMITMENT_ARG.long))
.unwrap_or_default();
let address_labels = if matches.is_present("no_address_labels") {
HashMap::new()
@@ -231,13 +198,10 @@ pub fn parse_args<'a>(
keypair_path: default_signer_path,
rpc_client: None,
rpc_timeout,
verbose,
verbose: matches.is_present("verbose"),
output_format,
commitment,
send_transaction_config: RpcSendTransactionConfig {
preflight_commitment: Some(commitment.commitment),
..RpcSendTransactionConfig::default()
},
send_transaction_config: RpcSendTransactionConfig::default(),
address_labels,
},
signers,
@@ -245,7 +209,7 @@ pub fn parse_args<'a>(
}
fn main() -> Result<(), Box<dyn error::Error>> {
solana_logger::setup_with_default("off");
solana_logger::setup();
let matches = app(
crate_name!(),
crate_description!(),
@@ -269,14 +233,11 @@ fn main() -> Result<(), Box<dyn error::Error>> {
Arg::with_name("json_rpc_url")
.short("u")
.long("url")
.value_name("URL_OR_MONIKER")
.value_name("URL")
.takes_value(true)
.global(true)
.validator(is_url_or_moniker)
.help(
"URL for Solana's JSON RPC or moniker (or their first letter): \
[mainnet-beta, testnet, devnet, localhost]",
),
.validator(is_url)
.help("JSON RPC URL for the solana cluster"),
)
.arg(
Arg::with_name("websocket_url")
@@ -296,25 +257,6 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.takes_value(true)
.help("Filepath or URL to a keypair"),
)
.arg(
Arg::with_name("commitment")
.long("commitment")
.takes_value(true)
.possible_values(&[
"processed",
"confirmed",
"finalized",
"recent", // Deprecated as of v1.5.5
"single", // Deprecated as of v1.5.5
"singleGossip", // Deprecated as of v1.5.5
"root", // Deprecated as of v1.5.5
"max", // Deprecated as of v1.5.5
])
.value_name("COMMITMENT_LEVEL")
.hide_possible_values(true)
.global(true)
.help("Return information at the selected commitment level [possible values: processed, confirmed, finalized]"),
)
.arg(
Arg::with_name("verbose")
.long("verbose")
@@ -366,12 +308,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.index(1)
.value_name("CONFIG_FIELD")
.takes_value(true)
.possible_values(&[
"json_rpc_url",
"websocket_url",
"keypair",
"commitment",
])
.possible_values(&["json_rpc_url", "websocket_url", "keypair"])
.help("Return a specific config setting"),
),
)
@@ -380,7 +317,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.about("Set a config setting")
.group(
ArgGroup::with_name("config_settings")
.args(&["json_rpc_url", "websocket_url", "keypair", "commitment"])
.args(&["json_rpc_url", "websocket_url", "keypair"])
.multiple(true)
.required(true),
),

View File

@@ -332,7 +332,9 @@ pub fn process_authorize_nonce_account(
nonce_authority: SignerIndex,
new_authority: &Pubkey,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let nonce_authority = config.signers[nonce_authority];
let ix = authorize_nonce_account(nonce_account, &nonce_authority.pubkey(), new_authority);
@@ -347,7 +349,11 @@ pub fn process_authorize_nonce_account(
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<NonceError>(result, &config)
}
@@ -394,7 +400,9 @@ pub fn process_create_nonce_account(
Message::new(&ixs, Some(&config.signers[0].pubkey()))
};
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (message, lamports) = resolve_spend_tx_and_check_account_balance(
rpc_client,
@@ -406,7 +414,9 @@ pub fn process_create_nonce_account(
config.commitment,
)?;
if let Ok(nonce_account) = get_account(rpc_client, &nonce_account_address) {
if let Ok(nonce_account) =
get_account_with_commitment(rpc_client, &nonce_account_address, config.commitment)
{
let err_msg = if state_from_account(&nonce_account).is_ok() {
format!("Nonce account {} already exists", nonce_account_address)
} else {
@@ -429,7 +439,11 @@ pub fn process_create_nonce_account(
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<SystemError>(result, &config)
}
@@ -457,17 +471,20 @@ pub fn process_new_nonce(
(&nonce_account, "nonce_account_pubkey".to_string()),
)?;
if let Err(err) = rpc_client.get_account(&nonce_account) {
return Err(CliError::BadParameter(format!(
"Unable to advance nonce account {}. error: {}",
nonce_account, err
))
let nonce_account_check =
rpc_client.get_account_with_commitment(&nonce_account, config.commitment);
if nonce_account_check.is_err() || nonce_account_check.unwrap().value.is_none() {
return Err(CliError::BadParameter(
"Unable to create new nonce, no nonce account found".to_string(),
)
.into());
}
let nonce_authority = config.signers[nonce_authority];
let ix = advance_nonce_account(&nonce_account, &nonce_authority.pubkey());
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let message = Message::new(&[ix], Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
@@ -478,7 +495,11 @@ pub fn process_new_nonce(
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<SystemError>(result, &config)
}
@@ -520,7 +541,9 @@ pub fn process_withdraw_from_nonce_account(
destination_account_pubkey: &Pubkey,
lamports: u64,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let nonce_authority = config.signers[nonce_authority];
let ix = withdraw_nonce_account(
@@ -539,7 +562,11 @@ pub fn process_withdraw_from_nonce_account(
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<NonceError>(result, &config)
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +1,21 @@
use log::*;
use solana_client::rpc_response::{RpcContactInfo, RpcLeaderSchedule};
use solana_sdk::clock::NUM_CONSECUTIVE_LEADER_SLOTS;
use std::net::{SocketAddr, UdpSocket};
pub fn get_leader_tpus(
pub fn get_leader_tpu(
slot_index: u64,
num_leaders: u64,
leader_schedule: Option<&RpcLeaderSchedule>,
cluster_nodes: Option<&Vec<RpcContactInfo>>,
) -> Vec<SocketAddr> {
let leaders: Vec<_> = (0..num_leaders)
.filter_map(|i| {
leader_schedule?
) -> Option<SocketAddr> {
leader_schedule?
.iter()
.find(|(_pubkey, slots)| slots.iter().any(|slot| *slot as u64 == slot_index))
.and_then(|(pubkey, _)| {
cluster_nodes?
.iter()
.find(|(_pubkey, slots)| {
slots.iter().any(|slot| {
*slot as u64 == (slot_index + (i * NUM_CONSECUTIVE_LEADER_SLOTS))
})
})
.and_then(|(pubkey, _)| {
cluster_nodes?
.iter()
.find(|contact_info| contact_info.pubkey == *pubkey)
.and_then(|contact_info| contact_info.tpu)
})
.find(|contact_info| contact_info.pubkey == *pubkey)
.and_then(|contact_info| contact_info.tpu)
})
.collect();
let mut unique_leaders = vec![];
for leader in leaders.into_iter() {
if !unique_leaders.contains(&leader) {
unique_leaders.push(leader);
}
}
unique_leaders
}
pub fn send_transaction_tpu(

View File

@@ -107,22 +107,15 @@ where
return Err(CliError::InsufficientFundsForSpendAndFee(
lamports_to_sol(spend),
lamports_to_sol(fee),
*from_pubkey,
));
}
} else {
if from_balance < spend {
return Err(CliError::InsufficientFundsForSpend(
lamports_to_sol(spend),
*from_pubkey,
));
return Err(CliError::InsufficientFundsForSpend(lamports_to_sol(spend)));
}
if !check_account_for_balance_with_commitment(rpc_client, fee_pubkey, fee, commitment)?
{
return Err(CliError::InsufficientFundsForFee(
lamports_to_sol(fee),
*fee_pubkey,
));
return Err(CliError::InsufficientFundsForFee(lamports_to_sol(fee)));
}
}
Ok((message, spend))

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@ use std::{thread::sleep, time::Duration};
pub fn check_recent_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) {
(0..5).for_each(|tries| {
let balance = client
.get_balance_with_commitment(pubkey, CommitmentConfig::processed())
.get_balance_with_commitment(pubkey, CommitmentConfig::recent())
.unwrap()
.value;
if balance == expected_balance {
@@ -20,7 +20,7 @@ pub fn check_recent_balance(expected_balance: u64, client: &RpcClient, pubkey: &
pub fn check_ready(rpc_client: &RpcClient) {
while rpc_client
.get_slot_with_commitment(CommitmentConfig::processed())
.get_slot_with_commitment(CommitmentConfig::recent())
.unwrap()
< 5
{

View File

@@ -20,6 +20,7 @@ use solana_config_program::{config_instruction, get_config_data, ConfigKeys, Con
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
account::Account,
commitment_config::CommitmentConfig,
message::Message,
pubkey::Pubkey,
signature::{Keypair, Signer},
@@ -287,7 +288,9 @@ pub fn process_set_validator_info(
};
// Check existence of validator-info account
let balance = rpc_client.get_balance(&info_pubkey).unwrap_or(0);
let balance = rpc_client
.poll_get_balance_with_commitment(&info_pubkey, CommitmentConfig::default())
.unwrap_or(0);
let lamports =
rpc_client.get_minimum_balance_for_rent_exemption(ValidatorInfo::max_space() as usize)?;

View File

@@ -8,6 +8,7 @@ use crate::{
};
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
use solana_clap_utils::{
commitment::commitment_arg,
input_parsers::*,
input_validators::*,
keypair::{DefaultSigner, SignerIndex},
@@ -207,7 +208,8 @@ impl VoteSubCommands for App<'_, '_> {
.long("lamports")
.takes_value(false)
.help("Display balance in lamports instead of SOL"),
),
)
.arg(commitment_arg()),
)
.subcommand(
SubCommand::with_name("withdraw-from-vote-account")
@@ -492,7 +494,9 @@ pub fn process_create_vote_account(
}
}
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (message, _) = resolve_spend_tx_and_check_account_balance(
rpc_client,
@@ -505,7 +509,11 @@ pub fn process_create_vote_account(
)?;
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<SystemError>(result, &config)
}
@@ -528,7 +536,9 @@ pub fn process_vote_authorize(
(&authorized.pubkey(), "authorized_account".to_string()),
(new_authorized_pubkey, "new_authorized_pubkey".to_string()),
)?;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let ixs = vec![vote_instruction::authorize(
vote_account_pubkey, // vote account to update
&authorized.pubkey(), // current authorized
@@ -546,7 +556,11 @@ pub fn process_vote_authorize(
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<VoteError>(result, &config)
}
@@ -564,7 +578,9 @@ pub fn process_vote_update_validator(
(vote_account_pubkey, "vote_account_pubkey".to_string()),
(&new_identity_pubkey, "new_identity_account".to_string()),
)?;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let ixs = vec![vote_instruction::update_validator_identity(
vote_account_pubkey,
&authorized_withdrawer.pubkey(),
@@ -581,7 +597,11 @@ pub fn process_vote_update_validator(
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<VoteError>(result, &config)
}
@@ -593,7 +613,9 @@ pub fn process_vote_update_commission(
withdraw_authority: SignerIndex,
) -> ProcessResult {
let authorized_withdrawer = config.signers[withdraw_authority];
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let ixs = vec![vote_instruction::update_commission(
vote_account_pubkey,
&authorized_withdrawer.pubkey(),
@@ -610,7 +632,11 @@ pub fn process_vote_update_commission(
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<VoteError>(result, &config)
}
@@ -659,27 +685,22 @@ pub fn process_show_vote_account(
for vote in &vote_state.votes {
votes.push(vote.into());
}
for (epoch, credits, prev_credits) in vote_state.epoch_credits().iter().copied() {
for (epoch, credits, prev_credits) in vote_state.epoch_credits() {
let credits_earned = credits - prev_credits;
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(epoch);
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(*epoch);
epoch_voting_history.push(CliEpochVotingHistory {
epoch,
epoch: *epoch,
slots_in_epoch,
credits_earned,
credits,
prev_credits,
});
}
}
let epoch_rewards = match crate::stake::fetch_epoch_rewards(rpc_client, vote_account_address, 1)
{
Ok(rewards) => Some(rewards),
Err(error) => {
eprintln!("Failed to fetch epoch rewards: {:?}", error);
None
}
};
let epoch_rewards = Some(crate::stake::fetch_epoch_rewards(
rpc_client,
vote_account_address,
1,
)?);
let vote_account_data = CliVoteAccount {
account_balance: vote_account.lamports,
@@ -707,10 +728,14 @@ pub fn process_withdraw_from_vote_account(
withdraw_amount: SpendAmount,
destination_account_pubkey: &Pubkey,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let withdraw_authority = config.signers[withdraw_authority];
let current_balance = rpc_client.get_balance(&vote_account_pubkey)?;
let current_balance = rpc_client
.get_balance_with_commitment(&vote_account_pubkey, config.commitment)?
.value;
let minimum_balance = rpc_client.get_minimum_balance_for_rent_exemption(VoteState::size_of())?;
let lamports = match withdraw_amount {
@@ -743,7 +768,11 @@ pub fn process_withdraw_from_vote_account(
&transaction.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner(&transaction);
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&transaction,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<VoteError>(result, &config)
}

158
cli/tests/deploy.rs Normal file
View File

@@ -0,0 +1,158 @@
use serde_json::Value;
use solana_cli::cli::{process_command, CliCommand, CliConfig};
use solana_client::rpc_client::RpcClient;
use solana_core::test_validator::TestValidator;
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
bpf_loader,
commitment_config::CommitmentConfig,
pubkey::Pubkey,
signature::{Keypair, Signer},
};
use std::{
fs::{remove_dir_all, File},
io::Read,
path::PathBuf,
str::FromStr,
sync::mpsc::channel,
};
#[test]
fn test_cli_deploy_program() {
solana_logger::setup();
let mut pathbuf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
pathbuf.push("tests");
pathbuf.push("fixtures");
pathbuf.push("noop");
pathbuf.set_extension("so");
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = TestValidator::run();
let (sender, receiver) = channel();
run_local_faucet(alice, sender, None);
let faucet_addr = receiver.recv().unwrap();
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let mut file = File::open(pathbuf.to_str().unwrap()).unwrap();
let mut program_data = Vec::new();
file.read_to_end(&mut program_data).unwrap();
let minimum_balance_for_rent_exemption = rpc_client
.get_minimum_balance_for_rent_exemption(program_data.len())
.unwrap();
let mut config = CliConfig::recent_for_tests();
let keypair = Keypair::new();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.command = CliCommand::Airdrop {
faucet_host: None,
faucet_port: faucet_addr.port(),
pubkey: None,
lamports: 4 * minimum_balance_for_rent_exemption, // min balance for rent exemption for three programs + leftover for tx processing
};
config.signers = vec![&keypair];
process_command(&config).unwrap();
config.command = CliCommand::Deploy {
program_location: pathbuf.to_str().unwrap().to_string(),
address: None,
use_deprecated_loader: false,
allow_excessive_balance: false,
};
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
let program_id_str = json
.as_object()
.unwrap()
.get("programId")
.unwrap()
.as_str()
.unwrap();
let program_id = Pubkey::from_str(&program_id_str).unwrap();
let account0 = rpc_client
.get_account_with_commitment(&program_id, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
assert_eq!(account0.lamports, minimum_balance_for_rent_exemption);
assert_eq!(account0.owner, bpf_loader::id());
assert_eq!(account0.executable, true);
let mut file = File::open(pathbuf.to_str().unwrap().to_string()).unwrap();
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
assert_eq!(account0.data, elf);
// Test custom address
let custom_address_keypair = Keypair::new();
config.signers = vec![&keypair, &custom_address_keypair];
config.command = CliCommand::Deploy {
program_location: pathbuf.to_str().unwrap().to_string(),
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: false,
};
process_command(&config).unwrap();
let account1 = rpc_client
.get_account_with_commitment(&custom_address_keypair.pubkey(), CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
assert_eq!(account1.lamports, minimum_balance_for_rent_exemption);
assert_eq!(account1.owner, bpf_loader::id());
assert_eq!(account1.executable, true);
assert_eq!(account0.data, account1.data);
// Attempt to redeploy to the same address
process_command(&config).unwrap_err();
// Attempt to deploy to account with excess balance
let custom_address_keypair = Keypair::new();
config.command = CliCommand::Airdrop {
faucet_host: None,
faucet_port: faucet_addr.port(),
pubkey: None,
lamports: 2 * minimum_balance_for_rent_exemption, // Anything over minimum_balance_for_rent_exemption should trigger err
};
config.signers = vec![&custom_address_keypair];
process_command(&config).unwrap();
config.signers = vec![&keypair, &custom_address_keypair];
config.command = CliCommand::Deploy {
program_location: pathbuf.to_str().unwrap().to_string(),
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: false,
};
process_command(&config).unwrap_err();
// Use forcing parameter to deploy to account with excess balance
config.command = CliCommand::Deploy {
program_location: pathbuf.to_str().unwrap().to_string(),
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: true,
};
process_command(&config).unwrap();
let account2 = rpc_client
.get_account_with_commitment(&custom_address_keypair.pubkey(), CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
assert_eq!(account2.lamports, 2 * minimum_balance_for_rent_exemption);
assert_eq!(account2.owner, bpf_loader::id());
assert_eq!(account2.executable, true);
assert_eq!(account0.data, account2.data);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}

View File

@@ -9,7 +9,8 @@ use solana_client::{
nonce_utils,
rpc_client::RpcClient,
};
use solana_core::test_validator::TestValidator;
use solana_core::contact_info::ContactInfo;
use solana_core::test_validator::{TestValidator, TestValidatorOptions};
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
commitment_config::CommitmentConfig,
@@ -18,51 +19,69 @@ use solana_sdk::{
signature::{keypair_from_seed, Keypair, Signer},
system_program,
};
use std::{fs::remove_dir_all, sync::mpsc::channel};
#[test]
fn test_nonce() {
let mint_keypair = Keypair::new();
full_battery_tests(
TestValidator::with_no_fees(mint_keypair.pubkey()),
mint_keypair,
None,
false,
);
solana_logger::setup();
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = TestValidator::run();
full_battery_tests(leader_data, alice, None, false);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}
#[test]
fn test_nonce_with_seed() {
let mint_keypair = Keypair::new();
full_battery_tests(
TestValidator::with_no_fees(mint_keypair.pubkey()),
mint_keypair,
Some(String::from("seed")),
false,
);
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = TestValidator::run();
full_battery_tests(leader_data, alice, Some(String::from("seed")), false);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}
#[test]
fn test_nonce_with_authority() {
let mint_keypair = Keypair::new();
full_battery_tests(
TestValidator::with_no_fees(mint_keypair.pubkey()),
mint_keypair,
None,
true,
);
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = TestValidator::run();
full_battery_tests(leader_data, alice, None, true);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}
fn full_battery_tests(
test_validator: TestValidator,
mint_keypair: Keypair,
leader_data: ContactInfo,
alice: Keypair,
seed: Option<String>,
use_nonce_authority: bool,
) {
let faucet_addr = run_local_faucet(mint_keypair, None);
let (sender, receiver) = channel();
run_local_faucet(alice, sender, None);
let faucet_addr = receiver.recv().unwrap();
let rpc_client =
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
let json_rpc_url = test_validator.rpc_url();
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
let mut config_payer = CliConfig::recent_for_tests();
config_payer.json_rpc_url = json_rpc_url.clone();
@@ -212,11 +231,21 @@ fn full_battery_tests(
#[test]
fn test_create_account_with_seed() {
solana_logger::setup();
let mint_keypair = Keypair::new();
let test_validator = TestValidator::with_custom_fees(mint_keypair.pubkey(), 1);
let TestValidator {
server,
leader_data,
alice: mint_keypair,
ledger_path,
..
} = TestValidator::run_with_options(TestValidatorOptions {
fees: 1,
bootstrap_validator_lamports: 42_000,
..TestValidatorOptions::default()
});
let faucet_addr = run_local_faucet(mint_keypair, None);
let (sender, receiver) = channel();
run_local_faucet(mint_keypair, sender, None);
let faucet_addr = receiver.recv().unwrap();
let offline_nonce_authority_signer = keypair_from_seed(&[1u8; 32]).unwrap();
let online_nonce_creator_signer = keypair_from_seed(&[2u8; 32]).unwrap();
@@ -224,8 +253,7 @@ fn test_create_account_with_seed() {
let config = CliConfig::recent_for_tests();
// Setup accounts
let rpc_client =
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
let rpc_client = RpcClient::new_socket(leader_data.rpc);
request_and_confirm_airdrop(
&rpc_client,
&faucet_addr,
@@ -257,7 +285,8 @@ fn test_create_account_with_seed() {
check_recent_balance(0, &rpc_client, &nonce_address);
let mut creator_config = CliConfig::recent_for_tests();
creator_config.json_rpc_url = test_validator.rpc_url();
creator_config.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
creator_config.signers = vec![&online_nonce_creator_signer];
creator_config.command = CliCommand::CreateNonceAccount {
nonce_account: 0,
@@ -275,7 +304,7 @@ fn test_create_account_with_seed() {
let nonce_hash = nonce_utils::get_account_with_commitment(
&rpc_client,
&nonce_address,
CommitmentConfig::processed(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
@@ -293,15 +322,11 @@ fn test_create_account_with_seed() {
to: to_address,
from: 0,
sign_only: true,
dump_transaction_message: true,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::None(nonce_hash),
nonce_account: Some(nonce_address),
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
authority_config.output_format = OutputFormat::JsonCompact;
let sign_only_reply = process_command(&authority_config).unwrap();
@@ -311,15 +336,14 @@ fn test_create_account_with_seed() {
// And submit it
let mut submit_config = CliConfig::recent_for_tests();
submit_config.json_rpc_url = test_validator.rpc_url();
submit_config.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
submit_config.signers = vec![&authority_presigner];
submit_config.command = CliCommand::Transfer {
amount: SpendAmount::Some(10),
to: to_address,
from: 0,
sign_only: false,
dump_transaction_message: true,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::FeeCalculator(
blockhash_query::Source::NonceAccount(nonce_address),
@@ -328,12 +352,13 @@ fn test_create_account_with_seed() {
nonce_account: Some(nonce_address),
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
process_command(&submit_config).unwrap();
check_recent_balance(241, &rpc_client, &nonce_address);
check_recent_balance(31, &rpc_client, &offline_nonce_authority_signer.pubkey());
check_recent_balance(4000, &rpc_client, &online_nonce_creator_signer.pubkey());
check_recent_balance(10, &rpc_client, &to_address);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,20 +2,24 @@ use solana_cli::cli::{process_command, CliCommand, CliConfig};
use solana_client::rpc_client::RpcClient;
use solana_core::test_validator::TestValidator;
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
commitment_config::CommitmentConfig,
signature::{Keypair, Signer},
};
use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair};
use std::{fs::remove_dir_all, sync::mpsc::channel};
#[test]
fn test_cli_request_airdrop() {
let mint_keypair = Keypair::new();
let test_validator = TestValidator::with_no_fees(mint_keypair.pubkey());
let faucet_addr = run_local_faucet(mint_keypair, None);
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = TestValidator::run();
let (sender, receiver) = channel();
run_local_faucet(alice, sender, None);
let faucet_addr = receiver.recv().unwrap();
let mut bob_config = CliConfig::recent_for_tests();
bob_config.json_rpc_url = test_validator.rpc_url();
bob_config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
bob_config.command = CliCommand::Airdrop {
faucet_host: None,
faucet_port: faucet_addr.port(),
@@ -28,11 +32,14 @@ fn test_cli_request_airdrop() {
let sig_response = process_command(&bob_config);
sig_response.unwrap();
let rpc_client =
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let balance = rpc_client
.get_balance(&bob_config.signers[0].pubkey())
.unwrap();
.get_balance_with_commitment(&bob_config.signers[0].pubkey(), CommitmentConfig::recent())
.unwrap()
.value;
assert_eq!(balance, 50);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@ use solana_client::{
nonce_utils,
rpc_client::RpcClient,
};
use solana_core::test_validator::TestValidator;
use solana_core::test_validator::{TestValidator, TestValidatorOptions};
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
commitment_config::CommitmentConfig,
@@ -17,22 +17,33 @@ use solana_sdk::{
pubkey::Pubkey,
signature::{keypair_from_seed, Keypair, NullSigner, Signer},
};
use std::{fs::remove_dir_all, sync::mpsc::channel};
#[test]
fn test_transfer() {
solana_logger::setup();
let mint_keypair = Keypair::new();
let test_validator = TestValidator::with_custom_fees(mint_keypair.pubkey(), 1);
let faucet_addr = run_local_faucet(mint_keypair, None);
let TestValidator {
server,
leader_data,
alice: mint_keypair,
ledger_path,
..
} = TestValidator::run_with_options(TestValidatorOptions {
fees: 1,
bootstrap_validator_lamports: 42_000,
..TestValidatorOptions::default()
});
let rpc_client =
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
let (sender, receiver) = channel();
run_local_faucet(mint_keypair, sender, None);
let faucet_addr = receiver.recv().unwrap();
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let default_signer = Keypair::new();
let default_offline_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
config.json_rpc_url = test_validator.rpc_url();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
let sender_pubkey = config.signers[0].pubkey();
@@ -51,15 +62,11 @@ fn test_transfer() {
to: recipient_pubkey,
from: 0,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
process_command(&config).unwrap();
check_recent_balance(49_989, &rpc_client, &sender_pubkey);
@@ -71,15 +78,11 @@ fn test_transfer() {
to: recipient_pubkey,
from: 0,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
assert!(process_command(&config).is_err());
check_recent_balance(49_989, &rpc_client, &sender_pubkey);
@@ -97,21 +100,20 @@ fn test_transfer() {
check_recent_balance(50, &rpc_client, &offline_pubkey);
// Offline transfer
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
let (blockhash, _, _) = rpc_client
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.unwrap()
.value;
offline.command = CliCommand::Transfer {
amount: SpendAmount::Some(10),
to: recipient_pubkey,
from: 0,
sign_only: true,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::None(blockhash),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
offline.output_format = OutputFormat::JsonCompact;
let sign_only_reply = process_command(&offline).unwrap();
@@ -124,15 +126,11 @@ fn test_transfer() {
to: recipient_pubkey,
from: 0,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::FeeCalculator(blockhash_query::Source::Cluster, blockhash),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
process_command(&config).unwrap();
check_recent_balance(39, &rpc_client, &offline_pubkey);
@@ -157,7 +155,7 @@ fn test_transfer() {
let nonce_hash = nonce_utils::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::processed(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
@@ -170,8 +168,6 @@ fn test_transfer() {
to: recipient_pubkey,
from: 0,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::FeeCalculator(
blockhash_query::Source::NonceAccount(nonce_account.pubkey()),
@@ -180,8 +176,6 @@ fn test_transfer() {
nonce_account: Some(nonce_account.pubkey()),
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
process_command(&config).unwrap();
check_recent_balance(49_976 - minimum_nonce_balance, &rpc_client, &sender_pubkey);
@@ -189,7 +183,7 @@ fn test_transfer() {
let new_nonce_hash = nonce_utils::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::processed(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
@@ -210,7 +204,7 @@ fn test_transfer() {
let nonce_hash = nonce_utils::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::processed(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
@@ -223,15 +217,11 @@ fn test_transfer() {
to: recipient_pubkey,
from: 0,
sign_only: true,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::None(nonce_hash),
nonce_account: Some(nonce_account.pubkey()),
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
let sign_only_reply = process_command(&offline).unwrap();
let sign_only = parse_sign_only_reply_string(&sign_only_reply);
@@ -243,8 +233,6 @@ fn test_transfer() {
to: recipient_pubkey,
from: 0,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::FeeCalculator(
blockhash_query::Source::NonceAccount(nonce_account.pubkey()),
@@ -253,20 +241,32 @@ fn test_transfer() {
nonce_account: Some(nonce_account.pubkey()),
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
process_command(&config).unwrap();
check_recent_balance(28, &rpc_client, &offline_pubkey);
check_recent_balance(40, &rpc_client, &recipient_pubkey);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}
#[test]
fn test_transfer_multisession_signing() {
solana_logger::setup();
let mint_keypair = Keypair::new();
let test_validator = TestValidator::with_custom_fees(mint_keypair.pubkey(), 1);
let faucet_addr = run_local_faucet(mint_keypair, None);
let TestValidator {
server,
leader_data,
alice: mint_keypair,
ledger_path,
..
} = TestValidator::run_with_options(TestValidatorOptions {
fees: 1,
bootstrap_validator_lamports: 42_000,
..TestValidatorOptions::default()
});
let (sender, receiver) = channel();
run_local_faucet(mint_keypair, sender, None);
let faucet_addr = receiver.recv().unwrap();
let to_pubkey = Pubkey::new(&[1u8; 32]);
let offline_from_signer = keypair_from_seed(&[2u8; 32]).unwrap();
@@ -275,8 +275,7 @@ fn test_transfer_multisession_signing() {
let config = CliConfig::recent_for_tests();
// Setup accounts
let rpc_client =
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
let rpc_client = RpcClient::new_socket(leader_data.rpc);
request_and_confirm_airdrop(
&rpc_client,
&faucet_addr,
@@ -299,7 +298,10 @@ fn test_transfer_multisession_signing() {
check_ready(&rpc_client);
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
let (blockhash, _, _) = rpc_client
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.unwrap()
.value;
// Offline fee-payer signs first
let mut fee_payer_config = CliConfig::recent_for_tests();
@@ -313,15 +315,11 @@ fn test_transfer_multisession_signing() {
to: to_pubkey,
from: 1,
sign_only: true,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::None(blockhash),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
fee_payer_config.output_format = OutputFormat::JsonCompact;
let sign_only_reply = process_command(&fee_payer_config).unwrap();
@@ -343,15 +341,11 @@ fn test_transfer_multisession_signing() {
to: to_pubkey,
from: 1,
sign_only: true,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::None(blockhash),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
from_config.output_format = OutputFormat::JsonCompact;
let sign_only_reply = process_command(&from_config).unwrap();
@@ -363,44 +357,53 @@ fn test_transfer_multisession_signing() {
// Finally submit to the cluster
let mut config = CliConfig::recent_for_tests();
config.json_rpc_url = test_validator.rpc_url();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&fee_payer_presigner, &from_presigner];
config.command = CliCommand::Transfer {
amount: SpendAmount::Some(42),
to: to_pubkey,
from: 1,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::FeeCalculator(blockhash_query::Source::Cluster, blockhash),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
process_command(&config).unwrap();
check_recent_balance(1, &rpc_client, &offline_from_signer.pubkey());
check_recent_balance(1, &rpc_client, &offline_fee_payer_signer.pubkey());
check_recent_balance(42, &rpc_client, &to_pubkey);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}
#[test]
fn test_transfer_all() {
solana_logger::setup();
let mint_keypair = Keypair::new();
let test_validator = TestValidator::with_custom_fees(mint_keypair.pubkey(), 1);
let faucet_addr = run_local_faucet(mint_keypair, None);
let TestValidator {
server,
leader_data,
alice: mint_keypair,
ledger_path,
..
} = TestValidator::run_with_options(TestValidatorOptions {
fees: 1,
bootstrap_validator_lamports: 42_000,
..TestValidatorOptions::default()
});
let rpc_client =
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
let (sender, receiver) = channel();
run_local_faucet(mint_keypair, sender, None);
let faucet_addr = receiver.recv().unwrap();
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let default_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
config.json_rpc_url = test_validator.rpc_url();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
let sender_pubkey = config.signers[0].pubkey();
@@ -419,122 +422,16 @@ fn test_transfer_all() {
to: recipient_pubkey,
from: 0,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
process_command(&config).unwrap();
check_recent_balance(0, &rpc_client, &sender_pubkey);
check_recent_balance(49_999, &rpc_client, &recipient_pubkey);
}
#[test]
fn test_transfer_unfunded_recipient() {
solana_logger::setup();
let mint_keypair = Keypair::new();
let test_validator = TestValidator::with_custom_fees(mint_keypair.pubkey(), 1);
let faucet_addr = run_local_faucet(mint_keypair, None);
let rpc_client =
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
let default_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
config.json_rpc_url = test_validator.rpc_url();
config.signers = vec![&default_signer];
let sender_pubkey = config.signers[0].pubkey();
let recipient_pubkey = Pubkey::new(&[1u8; 32]);
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &sender_pubkey, 50_000, &config)
.unwrap();
check_recent_balance(50_000, &rpc_client, &sender_pubkey);
check_recent_balance(0, &rpc_client, &recipient_pubkey);
check_ready(&rpc_client);
// Plain ole transfer
config.command = CliCommand::Transfer {
amount: SpendAmount::All,
to: recipient_pubkey,
from: 0,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: false,
no_wait: false,
blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
// Expect failure due to unfunded recipient and the lack of the `allow_unfunded_recipient` flag
process_command(&config).unwrap_err();
}
#[test]
fn test_transfer_with_seed() {
solana_logger::setup();
let mint_keypair = Keypair::new();
let test_validator = TestValidator::with_custom_fees(mint_keypair.pubkey(), 1);
let faucet_addr = run_local_faucet(mint_keypair, None);
let rpc_client =
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
let default_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
config.json_rpc_url = test_validator.rpc_url();
config.signers = vec![&default_signer];
let sender_pubkey = config.signers[0].pubkey();
let recipient_pubkey = Pubkey::new(&[1u8; 32]);
let derived_address_seed = "seed".to_string();
let derived_address_program_id = solana_stake_program::id();
let derived_address = Pubkey::create_with_seed(
&sender_pubkey,
&derived_address_seed,
&derived_address_program_id,
)
.unwrap();
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &sender_pubkey, 1, &config).unwrap();
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &derived_address, 50_000, &config)
.unwrap();
check_recent_balance(1, &rpc_client, &sender_pubkey);
check_recent_balance(50_000, &rpc_client, &derived_address);
check_recent_balance(0, &rpc_client, &recipient_pubkey);
check_ready(&rpc_client);
// Transfer with seed
config.command = CliCommand::Transfer {
amount: SpendAmount::Some(50_000),
to: recipient_pubkey,
from: 0,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: Some(derived_address_seed),
derived_address_program_id: Some(derived_address_program_id),
};
process_command(&config).unwrap();
check_recent_balance(0, &rpc_client, &sender_pubkey);
check_recent_balance(50_000, &rpc_client, &recipient_pubkey);
check_recent_balance(0, &rpc_client, &derived_address);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}

View File

@@ -15,19 +15,26 @@ use solana_sdk::{
signature::{Keypair, Signer},
};
use solana_vote_program::vote_state::{VoteAuthorize, VoteState, VoteStateVersions};
use std::{fs::remove_dir_all, sync::mpsc::channel};
#[test]
fn test_vote_authorize_and_withdraw() {
let mint_keypair = Keypair::new();
let test_validator = TestValidator::with_no_fees(mint_keypair.pubkey());
let faucet_addr = run_local_faucet(mint_keypair, None);
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = TestValidator::run();
let (sender, receiver) = channel();
run_local_faucet(alice, sender, None);
let faucet_addr = receiver.recv().unwrap();
let rpc_client =
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let default_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
config.json_rpc_url = test_validator.rpc_url();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
request_and_confirm_airdrop(
@@ -53,7 +60,9 @@ fn test_vote_authorize_and_withdraw() {
};
process_command(&config).unwrap();
let vote_account = rpc_client
.get_account(&vote_account_keypair.pubkey())
.get_account_with_commitment(&vote_account_keypair.pubkey(), CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let vote_state: VoteStateVersions = vote_account.state().unwrap();
let authorized_withdrawer = vote_state.convert_to_current().authorized_withdrawer;
@@ -71,15 +80,11 @@ fn test_vote_authorize_and_withdraw() {
to: vote_account_pubkey,
from: 0,
sign_only: false,
dump_transaction_message: false,
allow_unfunded_recipient: true,
no_wait: false,
blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster),
nonce_account: None,
nonce_authority: 0,
fee_payer: 0,
derived_address_seed: None,
derived_address_program_id: None,
};
process_command(&config).unwrap();
let expected_balance = expected_balance + 1_000;
@@ -95,7 +100,9 @@ fn test_vote_authorize_and_withdraw() {
};
process_command(&config).unwrap();
let vote_account = rpc_client
.get_account(&vote_account_keypair.pubkey())
.get_account_with_commitment(&vote_account_keypair.pubkey(), CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let vote_state: VoteStateVersions = vote_account.state().unwrap();
let authorized_withdrawer = vote_state.convert_to_current().authorized_withdrawer;
@@ -123,4 +130,7 @@ fn test_vote_authorize_and_withdraw() {
withdraw_authority: 1,
};
process_command(&config).unwrap();
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}

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