Compare commits

..

274 Commits

Author SHA1 Message Date
Sebastian.Bor
ebb5fc1285 chore: conflate use statement
(cherry picked from commit 6d11d5dd9f)
2021-05-04 10:28:45 -07:00
Sebastian.Bor
4cfb3dcc7b fix: add bpf_loader_upgradeable to ProgramTest default builtins
(cherry picked from commit 4ede5117f9)
2021-05-04 10:28:45 -07:00
Ruud van Asseldonk
e8fff4561e Document that Transaction::sign might panic (#17026)
(cherry picked from commit 9abfa65920)
2021-05-04 09:06:36 -07:00
Jeff Washington (jwash)
b56e66310d Revert "reclaims unref accounts from index (#16838) (#17005)"
This reverts commit 3e43b042eb.
2021-05-04 08:48:13 -07:00
mergify[bot]
bda3bd1557 Correct days/year (#17024) (#17033)
(cherry picked from commit 46d2755205)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-05-04 11:22:26 +00:00
mergify[bot]
7723673038 test-validator: Plumb --limit-ledger-size (#17027)
(cherry picked from commit f17b80236f)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-05-04 10:09:53 +00:00
mergify[bot]
c69e667f5e Update web3.js import sample (#17022)
(cherry picked from commit 9ff17a1c18)

Co-authored-by: Colin Gray <colin@cgray.dev>
2021-05-04 06:49:20 +00:00
mergify[bot]
6157860c0a Implement Bip32 for seed-phrase/passphrase signing (backport #16942) (#17018)
* Implement Bip32 for seed-phrase/passphrase signing (#16942)

* Add Keypair helpers for bip32 derivation

* Plumb bip32 for SignerSourceKind::Ask

* Support full-path querystring

* Use as_ref

* Add public wrappers for from_uri cases

* Support master root derivations (and fix too-deep print

* Add ask:// HD documentation

* Update ASK elsewhere in docs

(cherry picked from commit 694c674aa6)

# Conflicts:
#	programs/bpf/Cargo.lock

* Fix conflict

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-05-04 03:58:23 +00:00
mergify[bot]
32fc4e3d0f Add keys (backport #17014) (#17015)
* Rotate keys

(cherry picked from commit b2778f34f5)

* Key rotation

(cherry picked from commit b948a18841)

* Add keys

(cherry picked from commit 6318705607)

Co-authored-by: publish-docs.sh <maintainers@solana.com>
2021-05-04 01:34:53 +00:00
Michael Vines
ee0c0c4a59 Add ALL support to withdraw-stake subcommand
(cherry picked from commit cf779c63c5)
2021-05-03 13:55:35 -07:00
Ryan M. Shea
356117819c Add hackathon banner (#17010) 2021-05-03 19:47:34 +00:00
mergify[bot]
834c96a374 validates gossip addresses before sending pull-requests (backport #16748) (#17009)
* uses Mutex instead of RwLock for ping_cache

(cherry picked from commit 2231017b35)

* validates gossip addresses before sending pull-requests

IP addresses need to be validated before sending packets to them.
This commit, sends a ping packet to nodes before any pull requests.
Pull requests are then only sent to the nodes which have responded with
the correct hash of their respective ping packet.

(cherry picked from commit 7cea2c4466)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-05-03 19:40:02 +00:00
mergify[bot]
2195d980a2 patches local pending push messages processing (#16833) (#17007)
process_push_messages writes local pending push messages to the crds
table, but it discards the return value:
https://github.com/solana-labs/solana/blob/cf779c63c/core/src/crds_gossip.rs#L96-L102

In order to exclude outdated values from the next pull-request, we need
to record the hash of values purged/overridden by the local push
messages, otherwise pull-responses will return outdated values back to
the node:
https://github.com/solana-labs/solana/blob/c1829dd00/core/src/crds_gossip_pull.rs#L447-L452

Additionally, gossip packets arrive and are processed out of order. So,
local pending push messages should be flushed *before* generating bloom
filters for pull-requests, preventing pull-responses returning the same
values back to the node itself. This requires flipping order of
generating pull and push messages:
https://github.com/solana-labs/solana/blob/cf779c63c/core/src/cluster_info.rs#L1757-L1762

Both above bugs cause redundant traffic and bandwidth waste in gossip
pull-responses.

(cherry picked from commit a698e34744)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-05-03 17:27:38 +00:00
mergify[bot]
3e43b042eb reclaims unref accounts from index (#16838) (#17005)
(cherry picked from commit 6381ee38eb)

Co-authored-by: Jeff Washington (jwash) <75863576+jeffwashington@users.noreply.github.com>
2021-05-03 17:10:09 +00:00
mergify[bot]
851742e5d9 Update sysvars.md (#16998) (#16999)
a typo

(cherry picked from commit 43ccaf14b0)

Co-authored-by: Max Block <40041609+max-block@users.noreply.github.com>
2021-05-03 09:58:20 +00:00
mergify[bot]
c6c7feb0c2 Retry latest vote if expired (#16735) (#16927)
(cherry picked from commit b5d30846d6)

Co-authored-by: carllin <carl@solana.com>
2021-05-03 05:13:29 +00:00
Justin Starry
1fde69ef48 Docs cleanup (#16997) 2021-05-03 02:59:03 +00:00
mergify[bot]
894bedcae7 Remove errant backslash (#16994) (#16995)
(cherry picked from commit d7166c5778)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-05-02 20:20:30 +00:00
mergify[bot]
47f15eaa03 Corrected typo in calling between programs document (backport #16991) (#16993)
* Corrected typo in calling between programs document (#16991)

* Corrected typo in calling between programs document

* corrected another typo

Co-authored-by: Srinivas Valekar <srinivasvalekar@Srinivass-MacBook-Pro.local>
(cherry picked from commit c003f8e93c)

# Conflicts:
#	docs/src/developing/programming-model/calling-between-programs.md

* Fix conflict

Co-authored-by: srinivas valekar <srinivas.valekar@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-05-02 18:40:41 +00:00
mergify[bot]
b0c0739db9 Allow SetUpgradeAuthority instruction in CPI calls (backport #16676) (#16954)
* Allow SetUpgradeAuthority instruction in CPI calls (#16676)

* feat: allow SetAuthority in CLI calls

* chore: clippy match_like_matches_macro

* chore: clippy match_like_matches_macro

* chore: rename CLI to CPI

* chore: move check for cpi authorised instruction to syscalls

* chore: add set_upgrade_authority cpi test

* chore: assert upgrade authority was changed

* feat: gate set_upgrade_authority via cpi with a feature

* chore: move feature to the end of the list

* chore: remove white spaces

* chore: remove white spaces

* chore: update comment to rerun build

(cherry picked from commit 1a658c7f31)

# Conflicts:
#	programs/bpf/Cargo.toml
#	programs/bpf_loader/src/syscalls.rs
#	sdk/src/feature_set.rs

* chore: fixe merge conflicts

Co-authored-by: Sebastian Bor <Sebastian_Bor@hotmail.com>
2021-04-30 20:47:38 +00:00
mergify[bot]
c3dc23e84a docs: fix copy-pasta breaking typo in getRecentBlockhash example (#16962)
(cherry picked from commit 3d98321b38)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-30 04:24:40 +00:00
mergify[bot]
cc7fc447a4 Distinguish max replayed and max observed vote (#16936) (#16956)
(cherry picked from commit 5981399612)

Co-authored-by: carllin <carl@solana.com>
2021-04-30 00:48:56 +00:00
mergify[bot]
a401b2b4cf Refactor SignerSource to expose DerivationPath to other kinds of signers (backport #16933) (#16941)
* Refactor SignerSource to expose DerivationPath to other kinds of signers (#16933)

* One use statement

* Add stdin uri scheme

* Convert parse_signer_source to return Result

* A-Z deps

* Convert Usb data to Locator

* Pull DerivationPath out of Locator

* Wrap SignerSource to share derivation_path

* Review comments

* Check Filepath existence, readability in parse_signer_source

(cherry picked from commit d6f30b7537)

# Conflicts:
#	sdk/Cargo.toml

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-04-29 09:11:56 +00:00
mergify[bot]
d8c66c8981 Add skip rate to solana validators (#16939)
(cherry picked from commit d640ac143b)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-29 07:14:26 +00:00
Michael Vines
49a415414f Add getBlockProduction RPC method 2021-04-28 21:38:53 -07:00
mergify[bot]
6c540d2ada Fixup rpc-endpoints (#16924) (#16930)
(cherry picked from commit 783bd79e9d)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-28 14:44:16 -06:00
joeaba
da62ebac1a Update rpc-endpoints.md (#16926) 2021-04-29 00:12:42 +05:30
mergify[bot]
25aee12502 retains peer's contact-info when making pull requests (#16715) (#16907)
ClusterInfo::new_pull_requests has to lookup contact-infos:
https://github.com/solana-labs/solana/blob/a1ef2bd74/core/src/cluster_info.rs#L1663-L1673

when it was already available when making pull requests:
https://github.com/solana-labs/solana/blob/a1ef2bd74/core/src/crds_gossip_pull.rs#L232

(cherry picked from commit 25054bfd35)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-28 14:54:54 +00:00
mergify[bot]
d8e8528797 removes delayed crds inserts when upserting gossip table (#16806) (#16905)
It is crucial that VersionedCrdsValue::insert_timestamp does not go
backward in time:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds.rs#L67-L79

Otherwise methods such as get_votes and get_epoch_slots_since will
break, which will break their downstream flow, including vote-listener
and optimistic confirmation:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1197-L1215
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1274-L1298

For that, Crds::new_versioned is intended to be called "atomically" with
Crds::insert_verioned (as the comment already says so):
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds.rs#L126-L129

However, currently this is violated in the code. For example,
filter_pull_responses creates VersionedCrdsValues (with the current
timestamp), then acquires an exclusive lock on gossip, then
process_pull_responses writes those values to the crds table:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L2375-L2392

Depending on the workload and lock contention, the insert_timestamps may
well be in the past when these values finally are inserted into gossip.

To avoid such scenarios, this commit:
  * removes Crds::new_versioned and Crd::insert_versioned.
  * makes VersionedCrdsValue constructor private, only invoked in
    Crds::insert, so that insert_timestamp is populated right before
    insert.

This will improve insert_timestamp monotonicity as long as Crds::insert
is not called with a stalled timestamp. Following commits may further
improve this by calling timestamp() inside Crds::insert, and/or
switching to std::time::Instant which guarantees monotonicity.

(cherry picked from commit 1ac2a8cfa5)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-28 13:36:21 +00:00
mergify[bot]
ed8c796877 moves cluster-info metrics to a separate module (#16883) (#16898)
(cherry picked from commit b17d5eeaee)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-28 04:18:46 +00:00
mergify[bot]
ec750cf3eb Add allowed-ip list to faucet (#16891) (#16897)
(cherry picked from commit 36574c30ef)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-28 03:32:37 +00:00
mergify[bot]
4a35053fba uses current timestamp when flushing local pending push queue (#16808) (#16896)
local_message_pending_push_queue is recording timestamps at the time the
value is created, and uses that when the pending values are flushed:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L321
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds_gossip.rs#L96-L102

which is then used as the insert_timestamp when inserting values in the
crds table:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds_gossip_push.rs#L183

The flushing may happen 100ms after the values are created (or even
later if there is a lock contention). This will cause non-monotone
insert_timestamps in the crds table (where time goes backward),
hindering the usability of insert_timestamps for other computations.

For example both ClusterInfo::get_votes and get_epoch_slots_since rely
on monotone insert_timestamps when values are inserted into the table:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1197-L1215
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1274-L1298

This commit removes timestamps from local_message_pending_push_queue and
uses current timestamp when flushing the queue.

(cherry picked from commit b468ead1b1)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-28 01:59:29 +00:00
mergify[bot]
9797178ad1 Refactor remote-wallet path parsing (backport #16798) (#16894)
* SDK: More conversions for `Pubkey`

(cherry picked from commit 9b7120bf73)

* SDK: More conversion for `DerivationPath`

(cherry picked from commit 722de942ca)

* remote-wallet: Add helpers for locating remote wallets

(cherry picked from commit 64fcb792c2)

* remote-wallet: Plumb `Locator` into `RemoteWalletInfo`

(cherry picked from commit 3d12be29ec)

* remote-wallet: `derivation-path` crate doesn't like empty trailing child indexes

(cherry picked from commit 4ce4f04c58)

* remote-wallet: Move `Locator` to its own module

(cherry picked from commit cac666d035)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-28 01:20:41 +00:00
mergify[bot]
dbc58455df Retain alloc'd and updated data in cpi (backport #16850) (#16890)
* Retain alloc'd and updated data in cpi (#16850)

(cherry picked from commit 9b3a59f030)

# Conflicts:
#	programs/bpf_loader/src/syscalls.rs
#	sdk/src/feature_set.rs

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
2021-04-27 23:01:43 +00:00
mergify[bot]
4a3f851e49 Enable multiple payers in accounts-cluster-bench (#16889) (#16892)
* Enable multiple payer keypairs

* Suppress tx creation if batch size == 0

* Suppress logs when waiting to create txs

* Double airdrop threshold to prevent stall when closing accounts

(cherry picked from commit 283f587afe)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-27 22:43:06 +00:00
mergify[bot]
5a3bf5c90e limits to data_header.size when combining shreds' payloads (backport #16708) (#16870)
* limits to data_header.size when combining shreds' payloads (#16708)

Shredder::deshred is ignoring data_header.size when combining shreds' payloads:
https://github.com/solana-labs/solana/blob/37b8587d4/ledger/src/shred.rs#L940-L961

Also adding more sanity checks on the alignment of data shreds indices.

(cherry picked from commit 0f3ac51cf1)

# Conflicts:
#	ledger/src/shred.rs

* removes backport merge conflicts

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-27 14:44:58 +00:00
mergify[bot]
de6ec11efc records hash of values purged by expired pull-responses (#16800) (#16871)
process_pull_responses should record hash of values purged by expired
responses (as well as unexpired ones):
https://github.com/solana-labs/solana/blob/c1829dd00/core/src/crds_gossip_pull.rs#L385-L387

otherwise, these values are not excluded from following pull-requests
(from likely different nodes):
https://github.com/solana-labs/solana/blob/c1829dd00/core/src/crds_gossip_pull.rs#L447-L452

and would waste bandwidth should they be included in subsequent
pull-responses.

(cherry picked from commit 3b8d6b59fb)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-27 13:26:11 +00:00
mergify[bot]
7aec87c086 Add getVoteAccounts RPC method parameter to restrict results to a single vote account (#16859)
(cherry picked from commit 59fc33635a)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-27 05:43:44 +00:00
mergify[bot]
eabc21c23a block-production subcommand now uses SlotHistory sysvar when possible (#16858)
(cherry picked from commit b66a68975b)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-27 05:32:59 +00:00
mergify[bot]
713f346211 Fix limit-ledger-size syntax (#16856) (#16857)
(cherry picked from commit 3af8cb0150)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-27 04:41:35 +00:00
Michael Vines
a81bc0ecf8 solana leader-schedule -um works again
(cherry picked from commit c2becbc0a8)
2021-04-26 17:32:05 -07:00
mergify[bot]
a3f1580b8b Update bpf loader info on native-programs docs (#16840) (#16845)
* Update bpf loader info on native-programs docs

* Link to program deployment docs

(cherry picked from commit 5eb5d9b2f5)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-26 20:41:36 +00:00
mergify[bot]
4f20798654 removes old runtime feature gates in gossip and turbine (#16633) (#16828)
(cherry picked from commit 9706512115)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-26 18:40:42 +00:00
mergify[bot]
0ecd1755a6 docs: getInflationReward rpc output fields should be in lower camel case (#16802) (#16805)
(cherry picked from commit ec37a843a4)

Co-authored-by: Josh <josh.hundley@gmail.com>
2021-04-24 19:37:55 +00:00
mergify[bot]
57dd8a555a Disable flaky test_poh_service (#16772) (#16797)
(cherry picked from commit 63436cc2bf)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-24 04:38:27 +00:00
Michael Vines
f64cd4a75a Show last vote/root behind distance in solana validators output
(cherry picked from commit c1829dd00b)
2021-04-23 20:12:15 -07:00
mergify[bot]
2ce6c86c2a runtime: checked math for Bank::withdraw (#16788)
(cherry picked from commit be29568318)

# Conflicts:
#	runtime/src/bank.rs

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-24 00:25:41 +00:00
Michael Vines
ff9573714b get_packed_len() now correctly handles u32/i32 types
(cherry picked from commit 1500011fc6)
2021-04-23 13:52:10 -07:00
mergify[bot]
826111cf79 Restore text wrapping (#16776) (#16780)
(cherry picked from commit da58f20a99)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-23 17:34:47 +00:00
mergify[bot]
f31f1d0f52 fix reference to Rust Restrictions section (#16763) (#16775)
(cherry picked from commit e9a616cfc2)

Co-authored-by: strykerin <dacosta.pereirafabio@gmail.com>
2021-04-23 17:02:27 +00:00
mergify[bot]
e220f7067b docs: fix formatting issue (#16761) (#16774)
(cherry picked from commit c217ee3a00)

Co-authored-by: strykerin <dacosta.pereirafabio@gmail.com>
2021-04-23 17:02:18 +00:00
mergify[bot]
d9726e61bc retains crds values if the origin is still active (#16576) (#16771)
Local timestamps are updated for records associated with a pubkey if the
origin is still active:
https://github.com/solana-labs/solana/blob/c8ed14c64/core/src/crds.rs#L301-L311

However this is done inconsistently on some gossip paths (pull requests
and pull responses) but not all (e.g. push messages). Additionally
update_record_timestamp is inefficient since there can be ~800 values
associated with each pubkey.

This commit updates records timestamps only on contact-infos; and,
instead utilizes origin's timestamp when purging old values.

(cherry picked from commit 2c82f2154d)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-23 16:42:54 +00:00
mergify[bot]
786fa4f22e removes first_coding_index from erasure recovery code (#16646) (#16770)
first_coding_index is the same as the set_index and is so redundant:
https://github.com/solana-labs/solana/blob/37b8587d4/ledger/src/blockstore_meta.rs#L49-L60

(cherry picked from commit 03194145c0)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-23 13:21:27 +00:00
mergify[bot]
5b74678e37 Ingest votes from gossip into fork choice (#16560) (#16724)
(cherry picked from commit 4c94f8933f)

Co-authored-by: carllin <carl@solana.com>
2021-04-23 07:20:10 +00:00
mergify[bot]
d203bd1998 Add TPU client for sending txs to the current leader tpu port (#16736) (#16762)
* Add TPU client for sending txs to the current leader tpu port

* Update tpu_client.rs

(cherry picked from commit 75b8434b76)

Co-authored-by: Justin Starry <justin@solana.com>
2021-04-23 02:50:30 +00:00
mergify[bot]
5f5fa38d85 program-test: Add large bootstrap stake for realistic warmups (backport #16739) (#16741)
* program-test: Add large bootstrap stake for realistic warmups (#16739)

(cherry picked from commit f4214637a9)

# Conflicts:
#	program-test/Cargo.toml

* Fix merge conflict

Co-authored-by: Jon Cinque <jon.cinque@gmail.com>
2021-04-22 23:07:52 +00:00
mergify[bot]
fadf1efa41 Update getLeaderSchedule options (#16749) (#16752)
(cherry picked from commit 636b5987af)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-22 21:02:46 +00:00
mergify[bot]
0269fffa5a Remove unactivated ristretto syscall (backport #16727) (#16745)
* Remove unactivated ristretto syscall (#16727)

(cherry picked from commit be4df39a4c)

# Conflicts:
#	programs/bpf/Cargo.lock
#	programs/bpf/rust/ristretto/Cargo.toml
#	programs/bpf/tests/programs.rs
#	programs/bpf_loader/src/syscalls.rs

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
2021-04-22 18:33:27 +00:00
mergify[bot]
50e441a9ed Update secp instruction link in docs (#16729) (#16733)
(cherry picked from commit b22c13dcd7)

Co-authored-by: Jack May <jack@solana.com>
2021-04-22 04:53:38 +00:00
mergify[bot]
9413051053 Clean up "APR" language around inflation rewards (#16732)
(cherry picked from commit b8b54567b1)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-22 03:29:52 +00:00
mergify[bot]
13e176a633 getLeaderSchedule now supports filtered results based on validator identity (#16731)
(cherry picked from commit 6004c0abf5)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-22 02:29:01 +00:00
mergify[bot]
9268239c75 Make metrics tests independent of RUST_LOG env var (#16710) (#16730)
Previously, running the tests with RUST_LOG=none would fail, because the
env logger would set its filter level to reject all log messages, and
incrementing a counter only happens if the global logger has at least
the specified log level. Having the tests behave differently when
RUST_LOG is set is surprising, they should be self-contained.

Nix' buildRustPackage sets RUST_LOG="" to make the build logs less
verbose. I have trouble packaging Solana for Nix because of this, and I
believe making the tests independent of the environment is a good
solution for this.

(cherry picked from commit 3f92abedd5)

Co-authored-by: Ruud van Asseldonk <dev@veniogames.com>
2021-04-22 01:41:07 +00:00
mergify[bot]
e51d7af847 verify_pubkey() now takes a ref (#16725)
(cherry picked from commit 91b6888e15)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-21 23:22:13 +00:00
mergify[bot]
147ba1de69 Update float docs (#16695) (#16726)
(cherry picked from commit bb2b4c7e0b)

Co-authored-by: Jack May <jack@solana.com>
2021-04-21 22:55:00 +00:00
mergify[bot]
7cc709c82a CLI: Make pay subcommand a proper alias of transfer (#16721)
(cherry picked from commit 63957f0677)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-21 22:40:11 +00:00
mergify[bot]
a2395e8730 Add --seed support to delegate-stake and withdraw-stake commands (#16717)
(cherry picked from commit ba9a502e7e)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-21 21:49:39 +00:00
mergify[bot]
ae605f8f02 expands number of erasure coding shreds in the last batch in slots (backport #16484) (#16707)
* expands number of erasure coding shreds in the last batch in slots (#16484)

Number of parity coding shreds is always less than the number of data
shreds in FEC blocks:
https://github.com/solana-labs/solana/blob/6907a2366/ledger/src/shred.rs#L719

Data shreds are batched in chunks of 32 shreds each:
https://github.com/solana-labs/solana/blob/6907a2366/ledger/src/shred.rs#L714

However the very last batch of data shreds in a slot can be small, in
which case the loss rate can be exacerbated.

This commit expands the number of coding shreds in the last FEC block in
slots to: 64 - number of data shreds; so that FEC blocks are always 64
data and parity coding shreds each.

As a consequence of this, the last FEC block has more parity coding
shreds than data shreds. So for some shred indices we will have a coding
shred but no data shreds. This should not cause any kind of overlapping
FEC blocks as in:
https://github.com/solana-labs/solana/pull/10095
since this is done only for the very last batch in a slot, and the next
slot will reset the shred index.

(cherry picked from commit 37b8587d4e)

# Conflicts:
#	core/benches/shredder.rs
#	ledger/src/shred.rs

* removes backport merge conflicts

* ignore the flaky test for now

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-21 15:25:26 +00:00
mergify[bot]
ea2cc90215 Improve net scripts (backport #16699) (#16700)
* Pass limit-ledger-size value

(cherry picked from commit 51b748408c)

* Initialize non-bootstrap ndoes with faucet address

(cherry picked from commit 053120e04c)

Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-04-21 08:45:11 +00:00
mergify[bot]
e15ddbb979 Add port and gossip options to solana-test-validator (#16696) (#16698)
(cherry picked from commit 0924c2d070)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-21 03:46:52 +00:00
mergify[bot]
bbd8bd2e74 Enforce host aligned memory for program regions (backport #16590) (#16683)
* Enforce host aligned memory for program regions (#16590)

(cherry picked from commit 08d5253651)

# Conflicts:
#	cli/Cargo.toml
#	programs/bpf/Cargo.toml
#	programs/bpf/benches/bpf_loader.rs
#	programs/bpf/tests/programs.rs
#	programs/bpf_loader/Cargo.toml
#	programs/bpf_loader/src/lib.rs

* fix conflicts

Co-authored-by: Jack May <jack@solana.com>
2021-04-21 01:47:00 +00:00
mergify[bot]
a5794efe16 getVoteAccounts: Limit the length of the epoch_credits array (#16692)
(cherry picked from commit 34addee882)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-20 22:55:17 +00:00
mergify[bot]
27095378fa Remove unwrap from bpf_loader serialization (#16645) (#16649)
(cherry picked from commit 2409bb18f3)

Co-authored-by: Jack May <jack@solana.com>
2021-04-20 16:35:45 +00:00
mergify[bot]
a8836649cb uses current local timestamp when recording purged values (#16675)
CrdsGossipPull.purged_values is meant to record recently purged values
so that they are excluded from imminent pull requests, until the entire
cluster have synced to the updated value:
https://github.com/solana-labs/solana/blob/c826cddbb/core/src/crds_gossip_pull.rs#L449-L454

However, VersionedCrdsValue.local_timestamp represents the local time
when the value was last updated, and given that crds values may have
different timeouts based on stake, it does not necessarily represent how
recently the value was purged:
https://github.com/solana-labs/solana/blob/c826cddbb/core/src/crds.rs#L75-L76

As such, recording current local timestamp when purging values is more
appropriate. Additionally, purge_purged assumes that the purge_values is
sorted in timestamps when draining the old ones; which is not true if
those timestamps are VersionedCrdsValue.local_timestamp:
https://github.com/solana-labs/solana/blob/c826cddbb/core/src/crds_gossip_pull.rs#L563-L571

(cherry picked from commit bc90e04e64)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-20 12:42:30 +00:00
mergify[bot]
cc81830f13 CLI: Limit stake-history output by default (#16673)
(cherry picked from commit f91de6a84d)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-20 11:36:15 +00:00
mergify[bot]
558a46f5d5 RPC: use finalized as default pubsub commitment level (#16659) (#16666)
* RPC: use finalized as default pubsub commitment level

* update docs

* Fix tests

(cherry picked from commit a7e65c0034)

Co-authored-by: Justin Starry <justin@solana.com>
2021-04-20 09:47:50 +00:00
mergify[bot]
57add5366e Expand a couple docs sections (backport #16664) (#16671)
* docs: Flesh out address verification in integraion guide

(cherry picked from commit d575450ef0)

* docs: Expand native program descriptions

(cherry picked from commit 12678a819d)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-20 09:33:40 +00:00
mergify[bot]
5057aaddc0 Send votes to next leader's TPU instead of our TPU (#16663)
(cherry picked from commit c8b474cd0b)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-20 08:45:58 +00:00
mergify[bot]
3865219085 Remove unwrap (#16652) (#16657)
(cherry picked from commit 01786f684e)

Co-authored-by: Jack May <jack@solana.com>
2021-04-20 04:45:37 +00:00
mergify[bot]
6da06654ff Wrap derivation_path::DerivationPath (backport #16609) (#16651)
* Wrap derivation_path::DerivationPath (#16609)

* Replace custom DerivationPath impl

* Add method to parse full-path from str with hardening

* Convert Bip44 to trait

* Hoist more work on derivation-path

* Privatize Bip44 trait

(cherry picked from commit 185bbf2db5)

* Fix conflict

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-04-20 00:50:16 +00:00
mergify[bot]
4a375acebc Add --sort argument to solana validators (backport #16640) (#16655)
* Add --sort argument to `solana validators`

(cherry picked from commit b66faf7e80)

* Add line numbers to `solana validators` output

(cherry picked from commit 818c3198c1)

* Print the header as a footer when there's a large number of validators to show

(cherry picked from commit 1824b5a2ce)

* Add --number argument

(cherry picked from commit f14cf3ed1a)

* Prefix current validators with nbsp for easier sed-ing

(cherry picked from commit 568438aa6f)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-20 00:42:19 +00:00
mergify[bot]
9fcd465928 solana validators: Restore the meaning of "credits" in the JSON output (#16647)
(cherry picked from commit 1b63bdaf44)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-19 21:08:12 +00:00
mergify[bot]
1f8ef5e640 solana validators now shows current epoch credits instead of lifetime credits (#16639)
(cherry picked from commit f5f06904c3)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-19 18:52:27 +00:00
Michael Vines
a1b0f2f681 Increase test timeout 2021-04-19 04:12:16 +00:00
Michael Vines
f59d4f29d9 clippy 2021-04-19 04:12:16 +00:00
Michael Vines
b379004c3b Upgrade to Rust 1.51.0 2021-04-19 04:12:16 +00:00
mergify[bot]
25491780df Remove unnecessary clone (#16621)
(cherry picked from commit 6907a2366e)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-17 18:31:18 +00:00
mergify[bot]
4354ad3299 Documentation typo for langauge (#16620)
(cherry picked from commit 5399faaf53)

Co-authored-by: Guillaume Claret <dev@clarus.me>
2021-04-17 15:20:54 +00:00
Trent Nelson
4e94446fc3 Bump version to v1.6.7 2021-04-16 23:31:30 +00:00
mergify[bot]
d99795c000 Move derivation path into sdk (#16603) (#16607)
* Move DerivationPath to sdk

* Remove eprintln

(cherry picked from commit 52f4b96a80)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-16 23:23:14 +00:00
mergify[bot]
fe775a9716 CLI BIP32 prep: KeypairUrl refactor (backport #16592) (#16605)
* clap-utils: Rename KeypairUrl to SignerSource

(cherry picked from commit 09dcc9ea04)

* clap-utils: Reduce SignerSource's visibility

(cherry picked from commit c5ab3ba6f1)

* clap-utils: Use `uriparse` crate to parse `SignerSource`

(cherry picked from commit 5d1ef5d01d)

* clap-utils: Add explicit schemes for `ask` and `file` `SignerSource`s

(cherry picked from commit 6444f0e57b)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-16 21:14:31 +00:00
mergify[bot]
ac76a75937 Feature-gate hash-based duplicate transaction check (#16601)
(cherry picked from commit 285f3c9d56)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-16 19:59:55 +00:00
mergify[bot]
6c1678244f docs: Fix typo in program deploy instructions (#16572) (#16575)
(cherry picked from commit c8ed14c647)

Co-authored-by: Justin Starry <justin@solana.com>
2021-04-16 05:58:31 +00:00
mergify[bot]
63a9f33be1 Don't parse uninitialized system/nonce accounts (#16584) (#16587)
(cherry picked from commit ba77e48c12)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-15 23:39:16 +00:00
mergify[bot]
c9da91cb1c Rotate CODECOV_TOKEN (#16579)
(cherry picked from commit a535c0e129)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-15 16:15:20 +00:00
mergify[bot]
b3488e0139 Cli: move airdrop to rpc requests (#16557) (#16564)
* Add recent_blockhash to requestAirdrop

* Move tx confirmation to separate method

* Add RpcClient airdrop methods

* Request cli airdrop via RpcClient

* Pass optional faucet_addr into TestValidator and fix tests

* Update client/src/rpc_client.rs

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

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

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-15 07:35:19 +00:00
mergify[bot]
f3814a0478 docs: freshen and clarify rent-exempt dev description (#16562)
(cherry picked from commit 76ce28c723)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-15 04:35:08 +00:00
mergify[bot]
5e8d8cfb49 fix transaction spelling (#16558) (#16559)
(cherry picked from commit 1f29031b9d)

Co-authored-by: strykerin <dacosta.pereirafabio@gmail.com>
2021-04-15 02:24:26 +00:00
mergify[bot]
ad37276d83 dl-utils: use wide_msg everywhere for truncation on narrow terminals (#16555)
(cherry picked from commit e61b4b7d70)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-15 01:01:55 +00:00
mergify[bot]
719db7eed0 uses timeouts based on stake for filtering pull responses (#16549) (#16551)
filter_pull_responses is using default timeout when discarding pull
responses (except for ContactInfo):
https://github.com/solana-labs/solana/blob/f804ce63c/core/src/crds_gossip_pull.rs#L349-L350

But purging code uses timeouts based on stake:
https://github.com/solana-labs/solana/blob/f804ce63c/core/src/cluster_info.rs#L1867-L1870

So the crds value will not be purged from the sender's table and will be
sent again over the next pull request.

(cherry picked from commit d92721aab9)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-14 21:43:48 +00:00
mergify[bot]
4ddb72a32d prioritizes contact-infos in pull responses (#16541) (#16550)
Expired crds values where the contact-info does not exist are wasted:
https://github.com/solana-labs/solana/blob/f804ce63c/core/src/crds_gossip_pull.rs#L353-L378
and then are sent again over the next pull-request.

Also, the stake of the first response (which can be anything) is used to
weight all pull-responses to a node, while the rest of responses can
have different stake.
https://github.com/solana-labs/solana/blob/f804ce63c/core/src/cluster_info.rs#L2231

(cherry picked from commit f35a6a8be0)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-14 20:14:22 +00:00
mergify[bot]
ff1171338f Fix channel panic in tests (#16503) (#16543)
* Fix channel panic

* Add exit signal to PohRecorder because Crossbeam doesnt drop objects inside dropped channel

(cherry picked from commit f0c150cfb9)

Co-authored-by: carllin <carl@solana.com>
2021-04-14 19:04:31 +00:00
mergify[bot]
28683b0ad8 Fix sanity test flakiness by prebuilding binaries (#16530) (#16547)
* Fix sanity test flakiness by prebuilding binaries

* ignore shellcheck

* bump

* nudge

* simplify

(cherry picked from commit 328e7690f3)

Co-authored-by: Justin Starry <justin@solana.com>
2021-04-14 18:52:15 +00:00
Michael Vines
4ef3a679a4 Bump version to v1.6.6 2021-04-14 10:27:02 -07:00
Connor McFarlane
e02bcbdae2 Other hostname changes
(cherry picked from commit eddfe06a00)
2021-04-14 10:08:29 -07:00
Connor McFarlane
7b0187a148 Correct gossip hostname
(cherry picked from commit d684ec00aa)
2021-04-14 10:08:29 -07:00
Michael Vines
e92283c8d2 Add --faucet-port option
(cherry picked from commit f804ce63c2)
2021-04-14 09:39:27 -07:00
Jack May
ef3781d4ee fix cross-merge (#16535) 2021-04-14 10:16:24 +00:00
mergify[bot]
6da4bec41d Return sysvars via syscalls (bp #16422) (#16497)
* Return sysvars via syscalls (#16422)

(cherry picked from commit fa83f3bd73)

* bad merge

* Fix branch diffs

* nudge

Co-authored-by: Jack May <jack@solana.com>
2021-04-14 05:33:27 +00:00
mergify[bot]
31ed985fd0 RpcClient no longer panics in a tokio multi-threaded runtime (#16393)
(cherry picked from commit a4f0d8636a)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-14 03:17:33 +00:00
mergify[bot]
cdc10712b1 Bump scripts to current commitment variants (#16526) (#16527)
(cherry picked from commit 3bfae8e829)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-14 01:51:56 +00:00
mergify[bot]
935a836a7d bump solana_rbpf from 0.2.5 to 0.2.7 (backport #16515) (#16525)
* bump solana_rbpf from 0.2.5 to 0.2.7 (#16515)

(cherry picked from commit f7eadd9d70)

# Conflicts:
#	cli/Cargo.toml
#	programs/bpf/Cargo.toml
#	programs/bpf_loader/Cargo.toml
#	programs/bpf_loader/src/syscalls.rs

* Fix conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
Co-authored-by: Jack May <jack@solana.com>
2021-04-13 23:53:48 +00:00
mergify[bot]
97ba3cbeb0 Cleanup unsupported sysvars (backport #16390) (#16517)
* Cleanup unsupported sysvars (#16390)

* Cleanup unsupported sysvars

* fix ser description

(cherry picked from commit 92f4018b07)

# Conflicts:
#	runtime/src/bank.rs

* fix conflicts

Co-authored-by: Jack May <jack@solana.com>
2021-04-13 23:28:08 +00:00
mergify[bot]
e8ca35f9ec Deprecate RpcClient methods, RpcRequest variants (#16516) (#16519)
* Deprecate RpcClient methods, RpcRequest variants

* Update cli to getSupply

(cherry picked from commit ccb11a939f)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-13 22:23:39 +00:00
Michael Vines
d5aae9a8af Derive PartialEq for RpcStakeActivation 2021-04-13 12:33:46 -07:00
mergify[bot]
3bb8016a40 Remove blake3 from bpf program dependencies (#16506) (#16509)
(cherry picked from commit f641429056)

Co-authored-by: Justin Starry <justin@solana.com>
2021-04-13 11:18:26 +00:00
Justin Starry
579065443a v1.6: Use blake3 message hash in status cache (#16507) 2021-04-13 16:57:20 +08:00
Trent Nelson
81d636c2bf Merge pull request from GHSA-fmvj-vqp5-qqh9
* Sanitize permissions

* Forbid creating directories under ledger/rocksdb/

* hardened_unpack: Disallow dirs under rocksdb/ in genesis

* hardened_unpack: expand valid genesis entry test coverage

* hardened_unpack: rework old-style bsd directory entry rejection

Co-authored-by: Ivan Mironov <mironov.ivan@gmail.com>
2021-04-12 23:56:37 -06:00
Michael Vines
6a7ce8500b canonicalize authorized voter filepath
(cherry picked from commit 05ad979a2d)
2021-04-12 20:01:56 -07:00
mergify[bot]
8ee294639a validator: Add authorized-voter add/remove-all commands (bp #16492) (#16496)
* Clean up build warning

(cherry picked from commit 17a173ebb5)

* Add authorized-voter add/remove-all commands

(cherry picked from commit 2229b70c4e)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-04-13 00:07:06 +00:00
Tyera Eulberg
b275f65ef1 Add address_cache and exclude loopback from ip limit (#16491) 2021-04-12 20:31:30 +00:00
mergify[bot]
37c2b68677 poll checking for new record in poh service after every batch of hashes instead of busy waiting (#16167) (#16486)
* poll waiting in poh service after every batch of hashes

* clippy

(cherry picked from commit 414c7070cb)

Co-authored-by: Jeff Washington (jwash) <75863576+jeffwashington@users.noreply.github.com>
2021-04-12 19:07:23 +00:00
mergify[bot]
d9944c8ae3 TransactionRecorder uses unique channel so we can use Recv instead of RecvTimeout (#16195) (#16485)
* time

* new channel each call

* new channel every time

(cherry picked from commit 5eff23db0c)

Co-authored-by: Jeff Washington (jwash) <75863576+jeffwashington@users.noreply.github.com>
2021-04-12 18:56:22 +00:00
mergify[bot]
6c8bbdca0a Allow fork choice to support multiple versions of a slot (#16266) (#16480)
(cherry picked from commit dc7030ffaa)

Co-authored-by: carllin <carl@solana.com>
2021-04-12 09:14:02 +00:00
Michael Vines
10e8f3ab32 Fix up App formatting
(cherry picked from commit ef30943c5c)
2021-04-11 23:36:31 -07:00
mergify[bot]
8c0b0f235e docker: Expose all ports in Dockerfile, add back localnet.sh (#16401) (#16474)
* docker: Expose all ports in Dockerfile, add back localnet.sh

* Add documentation for where to find containers

* Obliterate script

(cherry picked from commit 448d5be79f)

Co-authored-by: Jon Cinque <jon.cinque@gmail.com>
2021-04-11 20:17:08 +00:00
mergify[bot]
ec8ba76e4d Fix account copy step in program test message processor (#16469) (#16472)
(cherry picked from commit 278c125d99)

Co-authored-by: Justin Starry <justin@solana.com>
2021-04-11 20:31:22 +08:00
mergify[bot]
60fba7be75 Track gossip vote updates per hash for replay stage (#16421) (#16468)
* Track gossip vote updates per hash for replay stage

(cherry picked from commit 99b3aab703)

Co-authored-by: carllin <carl@solana.com>
2021-04-11 09:33:28 +00:00
mergify[bot]
24075ceeff Fill in not-yet-finalized block-time if possible (#16460) (#16463)
(cherry picked from commit 8bc0bdd40b)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-09 21:48:16 +00:00
mergify[bot]
f7ef1e68b0 patches bug in banking stage where buffered packets are never retained (#16276) (#16458)
banking_stage::handle_forwarding is retaining buffered packets with
empty index, so nothing is held:
https://github.com/solana-labs/solana/blob/6f3926b64/core/src/banking_stage.rs#L520

(cherry picked from commit 701fc93343)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-09 18:44:32 +00:00
mergify[bot]
723e7f11b9 Simplify some pattern-matches (#16402) (#16446)
When those match an exact combinator on Option / Result.

Tool-aided by [comby-rust](https://github.com/huitseeker/comby-rust).

(cherry picked from commit b08cff9e77)

Co-authored-by: François Garillot <4142+huitseeker@users.noreply.github.com>
2021-04-08 20:45:01 +00:00
mergify[bot]
f7211d3c07 Cli: use get_inflation_rewards and limit epochs queried (#16408) (#16444)
* Fix block-with-limit when not finalized blocks found

* Enable confirmed commitment in getInflationReward

* Use get_inflation_rewards in cli

* Line up rewards output

* Add range validator

* Change cli epoch arg -> num epochs

* Add solana inflation rewards subcommand

* Consolidate epoch rewards meta

(cherry picked from commit bb9d2fd07a)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-08 18:16:04 +00:00
mergify[bot]
6234090361 Fix cargo-build/test-bpf --workspace (bp #16431) (#16432)
* Fix cargo-build/test-bpf --workspace (#16431)

(cherry picked from commit 878e52f0b9)

# Conflicts:
#	ci/test-stable.sh

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
2021-04-08 16:55:21 +00:00
mergify[bot]
a001c1c8f6 CI: Let cargo-install-all.sh resolve stable (#16430)
(cherry picked from commit 388ce12207)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-07 21:30:08 +00:00
mergify[bot]
7f62f4f621 CLI: Fix rent panic (#16417) (#16426)
* CLI: Fix `rent` panic on non-numeric input (+monikers)

* Update cli/src/cluster_query.rs

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

* Update cli/src/cluster_query.rs

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

* Update cli/src/cluster_query.rs

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

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

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-07 18:04:20 +00:00
mergify[bot]
8334a76e5b docs: Validator SOL reqs followup (#16424)
(cherry picked from commit 117860218f)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-07 16:15:20 +00:00
mergify[bot]
eadab5e2f0 No wallclock throttle tests (#16396) (#16399)
(cherry picked from commit 1219842a96)

Co-authored-by: carllin <carl@solana.com>
2021-04-07 11:05:51 +00:00
mergify[bot]
8bb7b53f3b Speed up net.sh builds (bp #16360) (#16420)
* Speed up net.sh builds (#16360)

* Speed up net.sh builds

* feedback

* Update net/net.sh

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

* feedback

* fix

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

# Conflicts:
#	scripts/cargo-install-all.sh

* fix

Co-authored-by: Justin Starry <justin@solana.com>
2021-04-07 09:03:53 +00:00
Trent Nelson
8c7b8e8c5d docs: Add validator SOL reqs
(cherry picked from commit 0e42a35e4f)
2021-04-06 22:47:48 -06:00
mergify[bot]
a2857928a4 Rpc: introduce get_inflation_reward rpc call (#16278) (#16410)
* feat: introduce get_inflation_reward rpc call

* fix: style suggestions

* fix: more style changes and match how other rpc functions are defined

* feat: get reward for a single epoch

* feat: default to the most recent epoch

* fix: don't factor out get_confirmed_block

* style: introduce from impl for RpcEncodingConfigWrapper

* style: bring commitment into variable

* feat: support multiple pubkeys for get_inflation_reward

* feat: add get_inflation_reward to rpc client

* feat: return rewards in order

* fix: rename pubkeys to addresses

* docs: introduce jsonrpc docs for get_inflation_reward

* style: early return in map (not sure which is more idiomatic)

* fix: call the rpc client function args addresses as well

* fix: style

* fix: filter out only addresses we care about

* style: make this more idiomatic

* fix: change rpc client epoch to optional and include some docs edits

* feat: filter out rent rewards in get_inflation_reward

* feat: add option epoch config param to get_inflation_reward

* feat: rpc client get_inflation_reward takes epoch instead of config and some filter staking and voting rewards

(cherry picked from commit e501fa5f0b)

Co-authored-by: Josh <josh.hundley@gmail.com>
2021-04-07 02:26:45 +00:00
mergify[bot]
f6780d72b1 Faucet: repurpose cap and slice args to apply to single IPs (bp #16381) (#16400)
* Faucet: repurpose cap and slice args to apply to single IPs (#16381)

* Single use stmt

* Log request IP

* Switch cap and slice to apply per IP

* Use SOL in logs, error msgs

* Use thiserror instead of overloading io::Error

* Return memo transaction for requests that exceed per-request-cap

* Handle faucet memos in cli

* Add some docs, esp about memo transaction

* Use SOL symbol & standardize memo

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

* Differentiate faucet tx-length errors

* Populate signature in cli airdrop memo case

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

# Conflicts:
#	Cargo.lock
#	client/Cargo.toml
#	faucet/Cargo.toml

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-04-06 08:48:10 +00:00
mergify[bot]
5d003c6dab Use spl-memo v3.0.1 (#16384) (#16397)
* Use memo v3.0.1, which simplifies id imports

* tree

(cherry picked from commit ae7bc8299d)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-06 05:12:04 +00:00
mergify[bot]
79ee0e06b2 Cluster info shred spies (bp #16389) (#16395)
* cluster-info: Don't subtract non-shred spies from node count

(cherry picked from commit b6b08706b9)

* cluster-info: Get rid of some integer math while we're here

(cherry picked from commit b71875df61)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-06 01:37:16 +00:00
mergify[bot]
443f132de5 Add cluster state verifier logging (#16330) (#16336)
* Add cluster state verifier logging

* Add duplicate-slots iterator to ledger tool

(cherry picked from commit 4e5ef6bce2)

Co-authored-by: carllin <carl@solana.com>
2021-04-06 01:25:12 +00:00
mergify[bot]
95299e43a2 validator: Use a const for wait for supermajority threshold (#16392)
(cherry picked from commit 7a2a39093d)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-06 00:53:05 +00:00
mergify[bot]
0cf1894ede issue #10831: added --with-memo option to all cli commands that submit (bp #16291) (#16387)
* issue #10831: added --with-memo option to all cli commands that submit (#16291)

* issue #10831: added --with-memo option to all cli commands that submit
transactions.  Also, improve the block command to show UTF-8 string instead
of integer values for memo program data.

* Fixed tests and changed some syntax according to feedback.

* Use spl_memo id (all versions where applicable) instead of hardcoding id.

* Update Cargo.toml in programs/bpf.

* Update formatting via cargo fmt.

* Update to use spl_memo version 3.0.1, which simplifies package imports

(cherry picked from commit 364af3a3e0)

# Conflicts:
#	cli-output/Cargo.toml
#	cli/Cargo.toml

* Fix conflicts

Co-authored-by: bji <bryan@ischo.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-04-05 23:14:16 +00:00
mergify[bot]
f2f4f28c0b merkle-tree: fix build when targeting bpf (bp #16335) (#16342)
* merkle-tree: Add Xargo.toml

(cherry picked from commit a1d9b53cd7)

* merkle-tree: Get `Hash` et. al from program instead of sdk

(cherry picked from commit ddc0a16cec)

* merkle-tree: Use `matches` crate when targeting eBPF

(cherry picked from commit a44c32694f)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-04-05 21:57:26 +00:00
Michael Vines
57da68d563 Update Cargo.toml 2021-04-05 14:02:34 -07:00
Michael Vines
8d2337ccf8 Update Cargo.toml 2021-04-05 14:02:34 -07:00
Michael Vines
270749185c Adjust tokio version to just "1"
(cherry picked from commit 43feef7362)

# Conflicts:
#	faucet/Cargo.toml
#	net-utils/Cargo.toml
2021-04-05 14:02:34 -07:00
Michael Vines
6184254416 Reduce test-validator ledger size
(cherry picked from commit b242f82696)
2021-04-05 09:24:49 -07:00
mergify[bot]
c8bb13b3f7 Fixup AncestorIterator method (bp #16357) (#16359)
* Fixup iterator method (#16357)

(cherry picked from commit 1a13d22984)

* Only get Blockstore::last_root once (#16362)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-05 05:27:58 +00:00
Tyera Eulberg
5da83c1491 Bump version to v1.6.5 (#16361) 2021-04-04 22:00:40 -06:00
Michael Vines
b04ce80255 Add channel version check
(cherry picked from commit 527adbed34)
2021-04-04 13:53:50 -07:00
sakridge
a788021181 Bump version to v1.6.4 (#16345) 2021-04-04 13:31:35 -07:00
mergify[bot]
553e9fb8cd Set ticks_per_slot higher for banking stage tests (#16094) (#16356)
Tests are timing out because the bank hit the MaxTickHeight and
will not process the transactions.

(cherry picked from commit 96ccc40f0a)

Co-authored-by: sakridge <sakridge@gmail.com>
2021-04-04 20:29:53 +00:00
Michael Vines
f1bc7ec4fa wait-for-restart-window works again for unstaked nodes
(cherry picked from commit a679aebc82)
2021-04-04 12:59:13 -07:00
mergify[bot]
581181e87f Fix test_replay_commitment_cache (#16131) (#16355)
(cherry picked from commit 9b94741290)

Co-authored-by: sakridge <sakridge@gmail.com>
2021-04-04 19:41:45 +00:00
mergify[bot]
36e1f9fae8 Bump bpf-tools to version v1.5 (#16331) (#16350)
The new version of bpf-tools eliminates the separate
rust-bpf-sysroot. The Rust standard libraries for the BPF target are
built in tree when the compiler is built.  The standard libraries code
is slightly more optimized and some reduction of compute budget can be
expected with this version of bpf-tools.

(cherry picked from commit 1359bceb5d)

Co-authored-by: Dmitri Makarov <dmakarov@users.noreply.github.com>
2021-04-04 16:58:52 +00:00
Justin Starry
f10ae394c8 Remove unprocessed transactions from log notifications (#16349)
(cherry picked from commit 0596cf5405)
2021-04-04 09:38:23 -07:00
mergify[bot]
f7905d369a Throttle PoH ticks by cumulative slot time (#16139) (#16315)
* Throttle PoH ticks by cumulative slot time

    * respond to pr feedback

    * saturating sub

    * updated comment

    (cherry picked from commit 4f4cffbd03)

    # Conflicts:
    #       core/src/poh_recorder.rs

Co-authored-by: Jeff Washington (jwash) <wash678@gmail.com>
2021-04-03 23:40:46 +00:00
mergify[bot]
ef079d202b Wait for 90 percent of stake before starting (#16340) (#16344)
(cherry picked from commit 3429785d9b)

Co-authored-by: sakridge <sakridge@gmail.com>
2021-04-03 22:50:58 +00:00
Michael Vines
b7efc2373c wait-for-restart-window now indicates how far away the next restart window is
(cherry picked from commit c8c89dd5f7)
2021-04-02 23:23:16 -07:00
Michael Vines
d3b50bc55b Remove UNSTABLE warning from logsSubscribe 2021-04-02 12:54:20 -07:00
mergify[bot]
8fd3465f8a Cleanup use (bp #16327) (#16328)
* Cleanup use (#16327)

(cherry picked from commit dee655df35)

# Conflicts:
#	Cargo.lock
#	program-test/Cargo.toml

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
2021-04-02 19:54:00 +00:00
mergify[bot]
23b9e6eae3 add metric for ticks from poh_recorder.record (#16047) (#16312)
(cherry picked from commit 2fc609a294)

    # Conflicts:
    #       core/src/poh_recorder.rs

Co-authored-by: Jeff Washington (jwash) <wash678@gmail.com>
2021-04-02 18:50:50 +00:00
mergify[bot]
fe1a977f9e Parse SPL associated-token-account instructions (bp #16318) (#16321)
* Parse SPL associated-token-account instructions (#16318)

(cherry picked from commit a902505810)

# Conflicts:
#	transaction-status/Cargo.toml

* Fix conflict

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-04-02 02:38:28 +00:00
mergify[bot]
5e538eff7c metrics for poh_recorder.record (#15998) (#16317)
(cherry picked from commit ddc758439e)

Co-authored-by: Jeff Washington (jwash) <75863576+jeffwashington@users.noreply.github.com>
2021-04-02 02:35:09 +00:00
mergify[bot]
3efe4b5478 increase timeout in TransactionRecorder.record (#16133) (#16314)
(cherry picked from commit 06ac0fe9a3)

Co-authored-by: Jeff Washington (jwash) <75863576+jeffwashington@users.noreply.github.com>
2021-04-02 00:58:52 +00:00
mergify[bot]
90e0d4fefe poh record metrics (#16092) (#16313)
(cherry picked from commit f68860a643)

Co-authored-by: Jeff Washington (jwash) <75863576+jeffwashington@users.noreply.github.com>
2021-04-01 21:27:16 +00:00
behzad nouri
2e983fb39f pushes addresses instead of insert 2021-04-01 11:14:05 -06:00
mergify[bot]
527b20fbbd nit: fix variable names (#16283) (#16295)
(cherry picked from commit aa45e81b3e)

Co-authored-by: Jack May <jack@solana.com>
2021-04-01 09:24:52 +00:00
mergify[bot]
a0c4b4e5fc Rpc: enable getConfirmedSignaturesForAddress2 to return confirmed (not yet finalized) data (#16281) (#16293)
* Update blockstore method to allow return of unfinalized signature

* Support confirmed sigs in getConfirmedSignaturesForAddress2

* Add deprecated comments

* Update docs

* Enable confirmed transaction-history in cli

* Return real confirmation_status; fill in not-yet-finalized block time if possible

(cherry picked from commit da27acabcc)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-01 06:30:36 +00:00
mergify[bot]
282315a721 Rpc: fix getConfirmedTransaction slot (#16288) (#16290)
* Fix transaction blockstore apis

* Update blockstore apis in rpc

(cherry picked from commit 18bd47dbe1)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-04-01 04:58:53 +00:00
mergify[bot]
b8198f8cc5 removes OrderedIterator and transaction batch iteration order (#16153) (#16285)
In TransactionBatch,
https://github.com/solana-labs/solana/blob/e50f59844/runtime/src/transaction_batch.rs#L4-L11
lock_results[i] is aligned with transactions[iteration_order[i]]:
https://github.com/solana-labs/solana/blob/e50f59844/runtime/src/bank.rs#L2414-L2424
https://github.com/solana-labs/solana/blob/e50f59844/runtime/src/accounts.rs#L788-L817

However load_and_execute_transactions is iterating over
  lock_results[iteration_order[i]]
https://github.com/solana-labs/solana/blob/e50f59844/runtime/src/bank.rs#L2878-L2889
and then returning i as for the index of the retryable transaction.

If iteratorion_order is [1, 2, 0], and i is 0, then:
  lock_results[iteration_order[i]] = lock_results[1]
which corresponds to
  transactions[iteration_order[1]] = transactions[2]
so neither i = 0, nor iteration_order[i] = 1 gives the correct index for the
corresponding transaction (which is 2).

This commit removes OrderedIterator and transaction batch iteration order
entirely. There is only one place in blockstore processor which the
iteration order is not ordinal:
https://github.com/solana-labs/solana/blob/e50f59844/ledger/src/blockstore_processor.rs#L269-L271
It seems like, instead of using an iteration order, that can shuffle entry
transactions in-place.

(cherry picked from commit 3f63ed9a72)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-04-01 01:28:01 +00:00
mergify[bot]
68ad2dcce1 Use more performant copy (#16282) (#16284)
(cherry picked from commit ad7f8e7f23)

Co-authored-by: Jack May <jack@solana.com>
2021-04-01 01:08:01 +00:00
mergify[bot]
e87c3421bc Update overview.md (#16280)
fix link which was broken/wrong

(cherry picked from commit c723251575)

Co-authored-by: Huge <mr.huge@seznam.cz>
2021-03-31 22:05:24 +00:00
mergify[bot]
20754a7115 Drop write lock on sysvars (#15497) (#16233)
* Drop write lock on sysvars

* adds env var for demoting sysvar write lock demotion

* moves demote logic to is_writable

* feature gates sysvar write lock demotion

* adds builtins to write lock demotion

* adds system program id to builtins

* adds Feature111...

* adds an abi-freeze test

* mvines set of builtin program keys

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

* update tests

* adds bpf loader keys

* Add test sysvar

* Plumb demote_sysvar to is_writable

* more plumbing of demote_sysvar_write_locks to is_writable

* patches test_program_bpf_instruction_introspection

* hard codes demote_sysvar_write_locks to false for serialization/encoding methods

* Revert "hard codes demote_sysvar_write_locks to false for serialization/encoding methods"

This reverts commit ae3e2d2e777437bddd753933097a210dcbc1b1fc.

* change the hardcoded ones to demote_sysvar_write_locks=true

* Use data_as_mut_slice

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
Co-authored-by: Michael Vines <mvines@gmail.com>
(cherry picked from commit 54c68ea83f)

Co-authored-by: sakridge <sakridge@gmail.com>
2021-03-31 20:23:20 +00:00
mergify[bot]
8a57ee181e Cleanup nits (bp #16211) (#16237)
* Cleanup nits (#16211)

(cherry picked from commit f84e88f0a2)

# Conflicts:
#	programs/bpf/Cargo.lock
#	programs/bpf/rust/sysvar/Cargo.toml

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
2021-03-31 10:01:18 +00:00
mergify[bot]
4e6b5a9808 Fix BPF ELF layout (#16256) (#16261)
* Fix BPF ELF layout

* whitespace

(cherry picked from commit bcd89dd34c)

Co-authored-by: Jack May <jack@solana.com>
2021-03-31 09:56:57 +00:00
mergify[bot]
f24fbde43b Helpful const and Arg doc (#16248) (#16252)
(cherry picked from commit 67b747938f)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-03-31 06:32:18 +00:00
Michael Vines
47f60c7607 Validator monitor now displays the max retransmit slot
(cherry picked from commit aac18d7564)
2021-03-30 21:57:23 -07:00
mergify[bot]
8b307ed409 security policy: Add out-of-scope section (bp #16249) (#16251)
* security policy: Add out-of-scope section

(cherry picked from commit e9e46ff521)

* Update SECURITY.md

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

Co-authored-by: Trent Nelson <trent@solana.com>
2021-03-31 04:49:17 +00:00
mergify[bot]
cf21719a07 Add get_max_retransmit_slot/get_max_shred_insert_slot to RpcClient (#16243)
(cherry picked from commit 2a1639836a)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-31 01:09:11 +00:00
mergify[bot]
3157b464c4 Align ProcessInstruction error handling (#16232) (#16238)
(cherry picked from commit ce7f7c2b6c)

Co-authored-by: Jack May <jack@solana.com>
2021-03-30 21:55:08 +00:00
mergify[bot]
2581db5748 docs: Reduce airdrop examples to 1 SOL (#16241)
(cherry picked from commit 2bcfbad653)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-03-30 21:52:42 +00:00
Trent Nelson
634959b3ab Bump version to v1.6.3 2021-03-30 16:17:47 +00:00
Trent Nelson
03b21f2e9d Bump version to v1.6.2 2021-03-30 00:06:01 -06:00
carllin
cc5565b17e Setup ReplayStage confirmation scaffolding for duplicate slots (#9698)
(cherry picked from commit 52703badfa)
2021-03-29 22:07:14 -06:00
mergify[bot]
50beef0b15 Allow incomplete features in frozen-abi (#16205)
(cherry picked from commit 9ba9d2a8ae)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-03-30 03:46:10 +00:00
mergify[bot]
06a54e1423 remove old code (#15988) (#15993)
(cherry picked from commit 9760fded2d)

Co-authored-by: Jeff Washington (jwash) <75863576+jeffwashington@users.noreply.github.com>
2021-03-30 00:50:27 +00:00
mergify[bot]
4d731ecd08 eliminate lock on record (#15929) (#16073)
* eliminate lock on record

* use same error as MaxHeightReached

* clippy

* review feedback

* refactor should_tick code

* pr feedback

(cherry picked from commit 57ba86c821)

Co-authored-by: Jeff Washington (jwash) <75863576+jeffwashington@users.noreply.github.com>
2021-03-30 00:46:13 +00:00
mergify[bot]
ee06789a66 sdk: Add try_from_slice_unchecked for Borsh (#16098) (#16158)
* sdk: Add try_from_slice_unchecked for Borsh

* Add tests

* Rename + clarify comment

* Rename back to unchecked

(cherry picked from commit cffa851e0f)

Co-authored-by: Jon Cinque <jon.cinque@gmail.com>
2021-03-29 23:15:34 +00:00
mergify[bot]
2dabe1d706 Add handling to close accounts to many-accounts bench (#16199) (#16201)
* gitignore farf

* Improve cli args

* Use derived addresses for accounts

* Add parameter to close every nth account created

(cherry picked from commit 1d145e1fc2)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-03-29 22:54:09 +00:00
Tyera Eulberg
3b1279a005 Future-aware enum name 2021-03-29 14:58:35 -06:00
mergify[bot]
5c9f85f28d Rpc: enable getConfirmedBlocks and getConfirmedBlocksWithLimit to return confirmed (not yet finalized) data (#16161) (#16198)
* Add commitment config capabilities

* Use rpc limit if no end_slot provided

* Limit to actually finalized blocks

* Support confirmed blocks in getConfirmedBlocks and getConfirmedBlocksWithLimit

* Update docs

* Add client plumbing

* Rename config enum

(cherry picked from commit 60ed8e2892)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-03-29 19:53:17 +00:00
mergify[bot]
e12dd46ef3 Derive PartialEq for StakeActivationState (#16196)
(cherry picked from commit 4e7bd45d4c)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-29 18:16:44 +00:00
mergify[bot]
c4fa03b478 Status cache improvements (#16174) (#16178)
(cherry picked from commit 5e5b63712b)

Co-authored-by: sakridge <sakridge@gmail.com>
2021-03-29 10:11:16 -07:00
mergify[bot]
9fb749deb7 Print the rust version when building bpf programs (#16181) (#16183)
(cherry picked from commit abada56ba1)

Co-authored-by: Justin Starry <justin@solana.com>
2021-03-29 07:18:55 +00:00
mergify[bot]
bd48344de2 Fix handling of invoked ix accounts in program-test (#16170) (#16176)
(cherry picked from commit 27ab415ecc)

Co-authored-by: Justin Starry <justin@solana.com>
2021-03-29 01:55:11 +00:00
mergify[bot]
78e54f1d2c Implement mnemonic support for solana-keygen grind (solana-labs#9325) (#16108) (#16173)
* Implement mnemonic support for solana-keygen grind (solana-labs#9325)

* Updated to include feedback from review.

* Renaming as per review feedback

* Fixed an incorrectly transcribed underscore

* Properly re-use string constants.

(cherry picked from commit e50f598449)

Co-authored-by: bji <bryan@ischo.com>
2021-03-28 07:05:17 +00:00
mergify[bot]
76a6576976 sdk: Use u32::MAX from std to unbreak BPF builds (#16171) (#16172)
(cherry picked from commit aabe186e3f)

Co-authored-by: Justin Starry <justin@solana.com>
2021-03-27 17:05:53 +00:00
mergify[bot]
92ec1ae255 Switch to a single use (#16169)
(cherry picked from commit 16e4ccca13)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-27 06:58:31 +00:00
Michael Vines
0d203728cc Add RpcClient::get_stake_activation() 2021-03-26 22:33:06 -07:00
mergify[bot]
625773e5b8 Rpc: enable getConfirmedBlock and getConfirmedTransaction to return confirmed (not yet finalized) data (bp #16142) (#16160)
* Rpc: enable getConfirmedBlock and getConfirmedTransaction to return confirmed (not yet finalized) data (#16142)

* Add Blockstore block and tx apis that allow unrooted responses

* Add TransactionStatusMessage, and send on bank freeze; also refactor TransactionStatusSender

* Track highest slot with tx-status writes complete

* Rename and unpub fn

* Add commitment to GetConfirmed input configs

* Support confirmed blocks in getConfirmedBlock

* Support confirmed txs in getConfirmedTransaction

* Update sigs-for-addr2 comment

* Enable confirmed block in cli

* Enable confirmed transaction in cli

* Review comments

* Rename blockstore method

(cherry picked from commit 433f1ead1c)

# Conflicts:
#	core/src/replay_stage.rs

* Fix conflict

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-03-27 04:51:53 +00:00
mergify[bot]
a4cb1e45ae Only print skipped leader slot message when the node is actually leader (#16156) (#16164)
Also, check vote signature after the vote is signed

(cherry picked from commit 60b4771fc6)

Co-authored-by: sakridge <sakridge@gmail.com>
2021-03-27 02:03:10 +00:00
mergify[bot]
8aded2778e Bump bpf-tools to version v1.4 (#16152) (#16154)
(cherry picked from commit 658ddd1c9c)

Co-authored-by: Dmitri Makarov <dmakarov@users.noreply.github.com>
2021-03-26 20:51:25 +00:00
mergify[bot]
d940c5b1a3 Skip leader slots until a vote lands (#15607) (#16147)
(cherry picked from commit b99ae8f334)

Co-authored-by: sakridge <sakridge@gmail.com>
2021-03-26 19:07:24 +00:00
Trent Nelson
1be045df94 sq: optimize
(cherry picked from commit 482c027d3b)
2021-03-25 21:31:52 -06:00
Trent Nelson
86191911c7 perf: use saturating/checked integer arithmetic
(cherry picked from commit 834fae684b)
2021-03-25 21:31:52 -06:00
mergify[bot]
8f852d8a6b makes test_pull_request_time_pruning smaller (#16128) (#16144)
(cherry picked from commit b041b55028)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-03-26 01:20:26 +00:00
Kristofer Peterson
68a439f8da Refactored ShortU16Visitor::visit_seq() to reject overflows, extra leading zeros and ensure one-to-one encoding. 2021-03-26 01:20:22 +00:00
Trent Nelson
e021832708 sdk: ShortU16 - rename variables for clarity
ShortU16's implementation embeds its usage as the length of a
ShortVec, confusingly referring to both a 'len' and a 'size'
at the same time.
2021-03-26 01:20:22 +00:00
Trent Nelson
87b11aa187 sdk: Add ShortU16 deser test 2021-03-26 01:20:22 +00:00
mergify[bot]
7475a6f444 makes turbine peer computation consistent between broadcast and retransmit (#14910) (#16143)
get_broadcast_peers is using tvu_peers:
https://github.com/solana-labs/solana/blob/84e52b606/core/src/broadcast_stage.rs#L362-L370
which is potentially inconsistent with retransmit_peers:
https://github.com/solana-labs/solana/blob/84e52b606/core/src/cluster_info.rs#L1332-L1345

Also, the leader does not include its own contact-info when broadcasting
shreds:
https://github.com/solana-labs/solana/blob/84e52b606/core/src/cluster_info.rs#L1324
but on the retransmit side, slot leader is removed only _after_ neighbors and
children are computed:
https://github.com/solana-labs/solana/blob/84e52b606/core/src/retransmit_stage.rs#L383-L384
So the turbine broadcast tree is different between the two stages.

This commit:
* Removes retransmit_peers. Broadcast and retransmit stages will use tvu_peers
  consistently.
* Retransmit stage removes slot leader _before_ computing children and
  neighbors.

(cherry picked from commit 570fd3f810)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-03-26 00:16:48 +00:00
mergify[bot]
86ce650661 Add timeout for local cluster partition tests (bp #16123) (#16137)
* Add timeout for local cluster partition tests (#16123)

* Add timeout for local cluster partition tests

* fix optimistic conf test logs

* Bump instruction count assertions

(cherry picked from commit e817a6db00)

# Conflicts:
#	local-cluster/Cargo.toml

* Fix conflict

Co-authored-by: Justin Starry <justin@solana.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2021-03-25 22:56:05 +00:00
mergify[bot]
4dc5a53014 Show bpf-tools download progress (#16135)
(cherry picked from commit 07273bfa9e)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-25 20:55:11 +00:00
mergify[bot]
5e35cf3536 program: Correct clamp in Message::signer_keys() (#16114)
(cherry picked from commit 8b3de72e2a)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-03-25 17:53:34 +00:00
Trent Nelson
e8a8d1efb3 clap-utils: Allow NullSigners outside sign-only mode
(cherry picked from commit 7f0ac6a67c)
2021-03-25 11:10:53 -06:00
mergify[bot]
defd9238fa Simplify account.rent_epoch handling for sysvar rent (bp #16049) (#16118)
* Simplify account.rent_epoch handling for sysvar rent (#16049)

* Add some code for special local testing

* Add comment to store_account_and_update_capitalization

* Simplify account.rent_epoch handling for sysvar rent

* Introduce *_for_test functions

* Add deprecation messages to existing api

(cherry picked from commit 6d5c6c17c5)

# Conflicts:
#	sdk/src/native_loader.rs

* Fix conflicts

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2021-03-25 17:17:43 +09:00
mergify[bot]
5f061dcea1 Support getBlockTime for unfinalized blocks (#16103) (#16110)
(cherry picked from commit a8ef29df27)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-03-25 04:18:00 +00:00
mergify[bot]
e6ee27a738 Add Exodus as Solana Mobile app option (#16100) (#16101)
* Add Exodus as Solana Mobile app option

* Update docs/src/wallet-guide/apps.md

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

Co-authored-by: Davey <35187388+davidzelaya@users.noreply.github.com>
2021-03-24 21:34:58 +00:00
mergify[bot]
dd2d25d698 limits CrdsGossipPull::pull_request_time size (#15793) (#16097)
There is no pruning logic on CrdsGossipPull::pull_request_time
https://github.com/solana-labs/solana/blob/79ac1997d/core/src/crds_gossip_pull.rs#L172-L174
potentially allowing this to take too much memory.

Additionally, CrdsGossipPush::last_pushed_to is pruning recent push
timestamps:
https://github.com/solana-labs/solana/blob/79ac1997d/core/src/crds_gossip_push.rs#L275-L279
instead of the older ones.

Co-authored-by: Nathan Hawkins <utsl@utsl.org>
(cherry picked from commit a6c23648cb)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-03-24 20:05:04 +00:00
Dmitri Makarov
9096c3df02 Adjust BPF test programs instruction counts 2021-03-24 11:59:59 +01:00
Dmitri Makarov
9f94c2a9a0 Bump bpf-tools to version v1.3
This brings in the fix for increased compute budget that wasn't caught
when bpf-tools v1.2 were released.
2021-03-24 11:59:59 +01:00
Dmitri Makarov
34213da9f4 Bump bpf-tools to v1.2 and get rid of xargo 2021-03-24 11:59:59 +01:00
mergify[bot]
c3c4991c44 rpc: add getSlotLeaders method (#16057) (#16079)
(cherry picked from commit e7fd7d46cf)

Co-authored-by: Justin Starry <justin@solana.com>
2021-03-23 19:27:18 +00:00
mergify[bot]
9d37a33dcd buffers data shreds to make larger erasure coded sets (bp #15849) (#16074)
* buffers data shreds to make larger erasure coded sets (#15849)

Broadcast stage batches up to 8 entries:
https://github.com/solana-labs/solana/blob/79280b304/core/src/broadcast_stage/broadcast_utils.rs#L26-L29
which will be serialized into some number of shreds and chunked into FEC
sets of at most 32 shreds each:
https://github.com/solana-labs/solana/blob/79280b304/ledger/src/shred.rs#L576-L597
So depending on the size of entries, FEC sets can be small, which may
aggravate loss rate.
For example 16 FEC sets of 2:2 data/code shreds each have higher loss
rate than one 32:32 set.

This commit broadcasts data shreds immediately, but also buffers them
until it has a batch of 32 data shreds, at which point 32 coding shreds
are generated and broadcasted.

(cherry picked from commit 4f82b897bc)

# Conflicts:
#	ledger/src/shred.rs

* removes backport merge conflicts

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-03-23 18:23:09 +00:00
mergify[bot]
a04ca03fee renames is_last_in_fec_set back to is_last_data (#15848) (#16075)
https://github.com/solana-labs/solana/pull/10095
renamed is_last_data to is_last_in_fec_set. However, the code shows that
this is actually meant to indicate where the serialized data is
complete:
https://github.com/solana-labs/solana/blob/420174d3d/ledger/src/shred.rs#L599-L600
https://github.com/solana-labs/solana/blob/420174d3d/ledger/src/shred.rs#L229-L231

There are multiple FEC sets for each `&[Entry]` serialized and this flag
does not represent shreds last in FEC sets (only the very last one by
overlap). So the name is wrong and confusing

(cherry picked from commit 3b85cbc504)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2021-03-23 16:59:47 +00:00
mergify[bot]
64ce4a6203 solana transfer now requires --allow-unfunded-recipient if the recipient doesn't exist (bp #16060) (#16067)
* transfer now requires --allow-unfunded-recipient if the recipient doesn't exist

(cherry picked from commit 3dff5c9dee)

* Avoid RPC in `--sign-only` mode

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

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-23 03:54:42 +00:00
mergify[bot]
7ac3c9ec76 Handle blockstore insert dup checks (#16051) (#16066)
(cherry picked from commit d76ad33597)

Co-authored-by: carllin <carl@solana.com>
2021-03-23 00:49:10 +00:00
mergify[bot]
7d91515e8d Make getStakeActivation response consistent for undelegated accounts (#16038) (#16040)
(cherry picked from commit 2ec24d438f)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-03-19 22:07:30 +00:00
mergify[bot]
4e3f2c3d2d program-test: Fix warp and staking issue (#16002) (#16031)
Since program-test creates a test genesis and then adds fees and rent,
some of the genesis accounts get rent-collected after warping.  Most
notably, `StakeConfig` gets rent-collected, causing any stake operations
to fail after warp.  This fix creates genesis with the `Rent` and
`FeeRateGovernor` actually used by the bank.

(cherry picked from commit 6cc22e62d4)

Co-authored-by: Jon Cinque <jon.cinque@gmail.com>
2021-03-19 14:54:58 +00:00
mergify[bot]
8b67ba6d3d docs: SIGUSR1 killing wrapper shell scripts (#16009)
(cherry picked from commit 07dc522981)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-03-19 07:45:34 +00:00
mergify[bot]
c2ce68ab90 Santize instruction index when loading instruction from sysvar (#15942) (#16004)
(cherry picked from commit 4c5660ba7a)

Co-authored-by: Justin Starry <justin@solana.com>
2021-03-19 02:48:41 +00:00
mergify[bot]
fe87cb1cd1 Update to reqwest 0.11.2 (#16000)
(cherry picked from commit 02b81dd05d)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-18 22:12:01 +00:00
mergify[bot]
1c8f6a836a cli cleanup (#15990) (#15997)
(cherry picked from commit 067b390194)

Co-authored-by: Jack May <jack@solana.com>
2021-03-18 20:03:04 +00:00
mergify[bot]
3d5ff7968e rpc: Add config options limiting getConfirmedBlock response data (#15970) (#15995)
* Add new confirmed block struct

* Add RpcConfirmedBlockConfig options

* Configure block response based on new options

* Add client api, use in cli fetch_epoch_rewards

* Update docs

* Apply review suggestions

(cherry picked from commit aa54c468ea)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-03-18 19:33:01 +00:00
Tyera Eulberg
d6160f7744 Avoid panic when validator doesn't have performance samples (#15976)
(cherry picked from commit ba33c9e18e)
2021-03-18 08:28:31 -07:00
mergify[bot]
5e9ce99abf remote-wallet: Expose Ledger app settings (#15978)
(cherry picked from commit 2dabcac0da)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-03-18 09:13:24 +00:00
mergify[bot]
ebd6fe7acb Avoid a panic when --slots-per-epoch is less than MINIMUM_SLOTS_PER_EPOCH (#15975)
(cherry picked from commit 4ab98fff02)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-18 07:17:50 +00:00
mergify[bot]
9e91a2c2fd Add Close instrruction and tooling to upgradeable loader (#15887) (#15972)
(cherry picked from commit 7f500d610c)

Co-authored-by: Jack May <jack@solana.com>
2021-03-18 06:02:57 +00:00
Michael Vines
899f57962a Add --slots-per-epoch argument
(cherry picked from commit 04c99cf7ea)
2021-03-17 17:25:51 -07:00
Michael Vines
3176b00e57 Add --slots-per-epoch validator
(cherry picked from commit c06ff47a90)
2021-03-17 17:25:51 -07:00
Jeff Washington (jwash)
08b9da8397 drop poh lock after record (#15930)
(cherry picked from commit 5460fb10a2)
2021-03-17 17:24:53 -07:00
mergify[bot]
2bc21ecba2 Allow unbounded wallclock processing time in tests (#15961) (#15966)
(cherry picked from commit f548a04fae)

Co-authored-by: carllin <carl@solana.com>
2021-03-18 00:22:06 +00:00
Jeff Washington (jwash)
5b2a65fab3 add metrics for tick producer and poh_recorder (#15931)
(cherry picked from commit 40997d0aef)
2021-03-17 16:36:50 -07:00
mergify[bot]
f5d56eabf3 Build full SPL in CI (bp #15886) (#15964)
* Build full SPL in CI

(cherry picked from commit 82269f1351)

* Avoid changing signature of ProgramTest::add_account

(cherry picked from commit 03180b502d)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-17 22:46:55 +00:00
Michael Vines
af45efb62c Notice the user when the --mint, --bpf-program, or --clone arguments are ignored
(cherry picked from commit 59c19d9fbf)
2021-03-17 14:10:14 -07:00
mergify[bot]
f528cda832 Ignore flaky test_banking_stage_entries_only and test_banking_stage_entryfication (#15959)
(cherry picked from commit 8a9b51952e)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-17 20:34:30 +00:00
mergify[bot]
eeef9f4e59 Separate snapshot location (bp #15840) (#15956)
* Add option for separate snapshot location

(cherry picked from commit 6126878f509c69e23480a5ec22b3271e2b16e072)
(cherry picked from commit 0209d334bd)

* Apply suggestions from code review

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

* add missed suggestion

(cherry picked from commit a43b3674c7)

* Revert to snapshots

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

* Revert to snapshots 2

(cherry picked from commit 20b53eb4b4)

* Revert to removing only tmp-

(cherry picked from commit a5d144b00f)

Co-authored-by: DimAn <diman@diman.io>
Co-authored-by: DimAn <andiman7000@gmail.com>
2021-03-17 20:25:18 +00:00
Michael Vines
32124b59e9 Download snapshot files with a tmp- prefix so they'll automatically be cleaned up if interrupted
(cherry picked from commit 58b980f9cd)
2021-03-17 10:18:18 -07:00
Michael Vines
aa9772f9c0 Replace solana-program-test when building example-helloworld 2021-03-17 09:08:41 -07:00
mergify[bot]
5f183bd773 Add helper for paring down signers to those requried by a tx message (bp #15899) (#15938)
* sdk: Add accessor for signer pubkeys of a tx message

(cherry picked from commit bf33ce8906)

* clap-utils: Add helper to `CliSignerInfo` for getting signers for a message

(cherry picked from commit 4e99f1e634)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-03-17 07:48:47 +00:00
mergify[bot]
2238e5001b solana-install init can now select a pre-release from Github (#15936)
(cherry picked from commit d9176c1903)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-17 04:31:55 +00:00
mergify[bot]
79fa7ef55c CLI: Support dumping the TX message in sign-only mode (#15933)
(cherry picked from commit 672e9c640f)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-03-17 04:13:21 +00:00
mergify[bot]
07df827411 Bump tokio to 1.1 (#15926) (#15928)
(cherry picked from commit 654449ce91)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-03-16 23:29:55 +00:00
mergify[bot]
a259ff0e72 Wallclock BankingStage Throttle (#15731) (#15890)
(cherry picked from commit c1ba265dd9)

Co-authored-by: carllin <carl@solana.com>
2021-03-16 21:12:59 +00:00
mergify[bot]
d7d3e767e7 fix: compute pre/post token balances on all accounts if token program present (#15900) (#15923)
* fix: compute pre/post token balances on all accounts if token program present

* fix: skip token program in balance query

* fix: prevent program ids from being collected

(cherry picked from commit 61112d4826)

Co-authored-by: Josh <josh.hundley@gmail.com>
2021-03-16 18:23:29 +00:00
mergify[bot]
6e8aa9af17 nit: fix spelling (#15908) (#15911)
(cherry picked from commit 5760cf0f41)

# Conflicts:
#	sdk/src/feature_set.rs

Co-authored-by: Jack May <jack@solana.com>
2021-03-16 10:58:39 -07:00
mergify[bot]
0236de7bc8 Encourage use of the default --ledger location (#15921)
(cherry picked from commit 1c261d293f)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-16 16:58:14 +00:00
mergify[bot]
899bd1572a Show flags for accounts in tx by solana confirm (#15804) (#15906)
* Show flags for accounts in tx by solana confirm

* Address review comments

* Improve comment a bit

* Apply suggestions from code review

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

* Further apply review suggestions

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

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2021-03-16 10:43:06 +00:00
mergify[bot]
97ec4cd44e Cli: better estimate of epoch time elapsed/remaining (#15893) (#15918)
* Add rpc_client api for getRecentPerformanceSamples

* Prep fn for variable avg slot time

* Use recent-perf-samples to more-accurately estimate epoch completed times

* Spell out average

(cherry picked from commit 3726358f51)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-03-16 09:58:51 +00:00
mergify[bot]
5500970a7e Add cargo-bpf-test --no-run flag, matching cargo-test (#15916)
(cherry picked from commit eb19e11688)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-16 09:45:35 +00:00
Michael Vines
caea04d8d5 Pin solana crate versions to prevent downstream users from accidentally mixing crate versions 2021-03-16 08:41:28 +00:00
Michael Vines
b1a90c3580 =1.6.1 2021-03-16 08:41:28 +00:00
mergify[bot]
5bd4e38345 Charge compute budget for bytes passed via cpi (#15874) (#15905)
(cherry picked from commit ad9901d7c6)

Co-authored-by: Jack May <jack@solana.com>
2021-03-16 07:57:32 +00:00
mergify[bot]
fddba08571 Improve Instruction::new deprecation warning (#15896)
(cherry picked from commit 8567b41d5f)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-16 05:18:31 +00:00
Michael Vines
87963764fa Export tokio for program-test clients
(cherry picked from commit 430ed6d774)
2021-03-15 22:14:17 -07:00
mergify[bot]
b691a159dd increment_cargo_version.sh tune ups (bp #15880) (#15892)
* Disallow version bump with dirty working tree

(cherry picked from commit 853e735edf)

* Ignore `not_paths` for `*.md` files when bumping version

(cherry picked from commit 510760d81b)

* Also ignore `*/node_modules/*` paths when bumping version

(cherry picked from commit 2bf46b789f)

Co-authored-by: Trent Nelson <trent@solana.com>
2021-03-16 02:07:46 +00:00
mergify[bot]
5af1d48be8 Display actual account length (#15875) (#15884)
(cherry picked from commit 60e5fd11c9)

Co-authored-by: Jack May <jack@solana.com>
2021-03-16 01:01:25 +00:00
mergify[bot]
3b3ec3313f Fix real_number_string_trimmed zero-decimal behavior (#15873) (#15877)
* Add failing test

* Don't strip zeroes from zero-decimal amounts

* Add zero-case test

(cherry picked from commit c40bd5f394)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2021-03-15 21:33:01 +00:00
Michael Vines
be00246fb5 Bump version to v1.6.1 2021-03-15 14:47:58 -06:00
Michael Vines
1d80ba9edf Update cargo lock files on version bump 2021-03-15 14:47:58 -06:00
mergify[bot]
4bcf976ecd Fix delinquent stake display (#15839)
(cherry picked from commit eab182188a)

Co-authored-by: Michael Vines <mvines@gmail.com>
2021-03-13 20:27:25 +00:00
897 changed files with 43451 additions and 88971 deletions

View File

@@ -36,7 +36,4 @@ export CARGO_TARGET_CACHE=$HOME/cargo-target-cache/"$CHANNEL"-"$BUILDKITE_LABEL"
# `std:
# "found possibly newer version of crate `std` which `xyz` depends on
rm -rf target/bpfel-unknown-unknown
if [[ $BUILDKITE_LABEL = "stable-perf" ]]; then
rm -rf target/release
fi
)

View File

@@ -73,7 +73,7 @@ jobs:
language: node_js
node_js:
- "lts/*"
- "node"
cache:
directories:

856
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,6 @@ members = [
"perf",
"validator",
"genesis",
"genesis-utils",
"gossip",
"install",
"keygen",
@@ -32,6 +31,7 @@ members = [
"log-analyzer",
"merkle-root-bench",
"merkle-tree",
"stake-o-matic",
"storage-bigtable",
"storage-proto",
"streamer",
@@ -39,20 +39,21 @@ members = [
"metrics",
"net-shaper",
"notifier",
"poh",
"poh-bench",
"program-test",
"programs/secp256k1",
"programs/bpf_loader",
"programs/budget",
"programs/config",
"programs/exchange",
"programs/failure",
"programs/noop",
"programs/ownable",
"programs/stake",
"programs/vest",
"programs/vote",
"remote-wallet",
"rpc",
"ramp-tps",
"runtime",
"runtime/store-tool",
"sdk",

View File

@@ -1,6 +1,6 @@
<p align="center">
<a href="https://solana.com">
<img alt="Solana" src="https://i.imgur.com/uBVzyX3.png" width="250" />
<img alt="Solana" src="https://i.imgur.com/OMnvVEz.png" width="250" />
</a>
</p>
@@ -32,12 +32,6 @@ $ sudo apt-get update
$ sudo apt-get install libssl-dev libudev-dev pkg-config zlib1g-dev llvm clang make
```
On Mac M1s, make sure you set up your terminal & homebrew [to use](https://5balloons.info/correct-way-to-install-and-use-homebrew-on-m1-macs/) Rosetta. You can install it with:
```bash
$ softwareupdate --install-rosetta
```
## **2. Download the source code.**
```bash

View File

@@ -51,27 +51,13 @@ The following components are out of scope for the bounty program
* Attacks that require social engineering
Eligibility:
* The participant submitting the bug report shall follow the process outlined within this document
* 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.
Payment of Bug Bounties:
* Payments for eligible bug reports are distributed monthly.
* Bounties for all bug reports submitted in a given month are paid out in the middle of the
following month.
* The SOL/USD conversion rate used for payments is the market price at the end of
the last day of the month for the month in which the bug was submitted.
* The reference for this price is the Closing Price given by Coingecko.com on
that date given here:
https://www.coingecko.com/en/coins/solana/historical_data/usd#panel
* For example, for all bugs submitted in March 2021, the SOL/USD price for bug
payouts is the Close price on 2021-03-31 of $19.49. This applies to all bugs
submitted in March 2021, to be paid in mid-April 2021.
* Bug bounties are paid out in
[stake accounts](https://solana.com/staking) with a
[lockup](https://docs.solana.com/staking/stake-accounts#lockups)
expiring 12 months from the last day of the month in which the bug was submitted.
Notes:
* All locked tokens can be staked during the lockup period
<a name="process"></a>
## Incident Response Process

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-account-decoder"
version = "1.7.2"
version = "1.6.7"
description = "Solana account decoder"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -19,10 +19,11 @@ lazy_static = "1.4.0"
serde = "1.0.122"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-config-program = { path = "../programs/config", version = "=1.7.2" }
solana-sdk = { path = "../sdk", version = "=1.7.2" }
solana-vote-program = { path = "../programs/vote", version = "=1.7.2" }
spl-token-v2-0 = { package = "spl-token", version = "=3.1.1", features = ["no-entrypoint"] }
solana-config-program = { path = "../programs/config", version = "=1.6.7" }
solana-sdk = { path = "../sdk", version = "=1.6.7" }
solana-stake-program = { path = "../programs/stake", version = "=1.6.7" }
solana-vote-program = { path = "../programs/vote", version = "=1.6.7" }
spl-token-v2-0 = { package = "spl-token", version = "=3.1.0", features = ["no-entrypoint"] }
thiserror = "1.0"
zstd = "0.5.1"

View File

@@ -48,7 +48,7 @@ pub enum UiAccountData {
Binary(String, UiAccountEncoding),
}
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum UiAccountEncoding {
Binary, // Legacy. Retained for RPC backwards compatibility
@@ -62,7 +62,7 @@ pub enum UiAccountEncoding {
impl UiAccount {
pub fn encode<T: ReadableAccount>(
pubkey: &Pubkey,
account: &T,
account: T,
encoding: UiAccountEncoding,
additional_data: Option<AccountAdditionalData>,
data_slice_config: Option<UiDataSliceConfig>,
@@ -224,7 +224,7 @@ mod test {
fn test_base64_zstd() {
let encoded_account = UiAccount::encode(
&Pubkey::default(),
&AccountSharedData::from(Account {
AccountSharedData::from(Account {
data: vec![0; 1024],
..Account::default()
}),

View File

@@ -9,14 +9,14 @@ use crate::{
};
use inflector::Inflector;
use serde_json::Value;
use solana_sdk::{instruction::InstructionError, pubkey::Pubkey, stake, system_program, sysvar};
use solana_sdk::{instruction::InstructionError, pubkey::Pubkey, system_program, sysvar};
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 = stake::program::id();
static ref STAKE_PROGRAM_ID: Pubkey = solana_stake_program::id();
static ref SYSTEM_PROGRAM_ID: Pubkey = system_program::id();
static ref SYSVAR_PROGRAM_ID: Pubkey = sysvar::id();
static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v2_0();

View File

@@ -6,10 +6,10 @@ use bincode::deserialize;
use serde_json::Value;
use solana_config_program::{get_config_data, ConfigKeys};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::stake::config::{self as stake_config, Config as StakeConfig};
use solana_stake_program::config::Config as StakeConfig;
pub fn parse_config(data: &[u8], pubkey: &Pubkey) -> Result<ConfigAccountType, ParseAccountError> {
let parsed_account = if pubkey == &stake_config::id() {
let parsed_account = if pubkey == &solana_stake_program::config::id() {
get_config_data(data)
.ok()
.and_then(|data| deserialize::<StakeConfig>(data).ok())
@@ -101,7 +101,11 @@ mod test {
};
let stake_config_account = create_config_account(vec![], &stake_config, 10);
assert_eq!(
parse_config(&stake_config_account.data(), &stake_config::id()).unwrap(),
parse_config(
&stake_config_account.data(),
&solana_stake_program::config::id()
)
.unwrap(),
ConfigAccountType::StakeConfig(UiStakeConfig {
warmup_cooldown_rate: 0.25,
slash_penalty: 50,

View File

@@ -4,7 +4,7 @@ use crate::{
};
use bincode::deserialize;
use solana_sdk::clock::{Epoch, UnixTimestamp};
use solana_sdk::stake::state::{Authorized, Delegation, Lockup, Meta, Stake, StakeState};
use solana_stake_program::stake_state::{Authorized, Delegation, Lockup, Meta, Stake, StakeState};
pub fn parse_stake(data: &[u8]) -> Result<StakeAccountType, ParseAccountError> {
let stake_state: StakeState = deserialize(data)

View File

@@ -14,23 +14,23 @@ use std::str::FromStr;
// A helper function to convert spl_token_v2_0::id() as spl_sdk::pubkey::Pubkey to
// solana_sdk::pubkey::Pubkey
pub fn spl_token_id_v2_0() -> Pubkey {
Pubkey::new_from_array(spl_token_v2_0::id().to_bytes())
Pubkey::from_str(&spl_token_v2_0::id().to_string()).unwrap()
}
// A helper function to convert spl_token_v2_0::native_mint::id() as spl_sdk::pubkey::Pubkey to
// solana_sdk::pubkey::Pubkey
pub fn spl_token_v2_0_native_mint() -> Pubkey {
Pubkey::new_from_array(spl_token_v2_0::native_mint::id().to_bytes())
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::new_from_array(pubkey.to_bytes())
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::new_from_array(pubkey.to_bytes())
Pubkey::from_str(&pubkey.to_string()).unwrap()
}
pub fn parse_token(

View File

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

View File

@@ -6,12 +6,10 @@ use rayon::prelude::*;
use solana_measure::measure::Measure;
use solana_runtime::{
accounts::{create_test_accounts, update_accounts_bench, Accounts},
accounts_db::AccountShrinkThreshold,
accounts_index::AccountSecondaryIndexes,
ancestors::Ancestors,
accounts_index::Ancestors,
};
use solana_sdk::{genesis_config::ClusterType, pubkey::Pubkey};
use std::{env, fs, path::PathBuf};
use std::{collections::HashSet, env, fs, path::PathBuf};
fn main() {
solana_logger::setup();
@@ -60,13 +58,8 @@ fn main() {
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,
AccountSecondaryIndexes::default(),
false,
AccountShrinkThreshold::default(),
);
let accounts =
Accounts::new_with_config(vec![path], &ClusterType::Testnet, HashSet::new(), false);
println!("Creating {} accounts", num_accounts);
let mut create_time = Measure::start("create accounts");
let pubkeys: Vec<_> = (0..num_slots)
@@ -90,19 +83,17 @@ fn main() {
num_slots,
create_time
);
let mut ancestors = Vec::with_capacity(num_slots);
ancestors.push(0);
let mut ancestors: Ancestors = vec![(0, 0)].into_iter().collect();
for i in 1..num_slots {
ancestors.push(i as u64);
ancestors.insert(i as u64, i - 1);
accounts.add_root(i as u64);
}
let ancestors = Ancestors::from(ancestors);
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");
accounts.accounts_db.clean_accounts(None, false);
accounts.accounts_db.clean_accounts(None);
time.stop();
println!("{}", time);
for slot in 0..num_slots {
@@ -121,7 +112,6 @@ fn main() {
solana_sdk::clock::Slot::default(),
&ancestors,
None,
false,
);
time_store.stop();
if results != results_store {

View File

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

View File

@@ -6,8 +6,8 @@ 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_gossip::gossip_service::discover;
use solana_measure::measure::Measure;
use solana_runtime::inline_spl_token_v2_0;
use solana_sdk::{
@@ -363,7 +363,7 @@ fn run_accounts_bench(
iterations: usize,
maybe_space: Option<u64>,
batch_size: usize,
close_nth_batch: u64,
close_nth: u64,
maybe_lamports: Option<u64>,
num_instructions: usize,
mint: Option<Pubkey>,
@@ -441,7 +441,6 @@ fn run_accounts_bench(
}
}
// Create accounts
let sigs_len = executor.num_outstanding();
if sigs_len < batch_size {
let num_to_create = batch_size - sigs_len;
@@ -476,14 +475,10 @@ fn run_accounts_bench(
}
}
if close_nth_batch > 0 {
let num_batches_to_close =
total_accounts_created as u64 / (close_nth_batch * batch_size as u64);
let expected_closed = num_batches_to_close * batch_size as u64;
let max_closed_seed = seed_tracker.max_closed.load(Ordering::Relaxed);
// Close every account we've created with seed between max_closed_seed..expected_closed
if max_closed_seed < expected_closed {
let txs: Vec<_> = (0..expected_closed - max_closed_seed)
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(
@@ -577,14 +572,14 @@ fn main() {
.help("Number of transactions to send per batch"),
)
.arg(
Arg::with_name("close_nth_batch")
Arg::with_name("close_nth")
.long("close-frequency")
.takes_value(true)
.value_name("BYTES")
.help(
"Every `n` batches, create a batch of close transactions for
the earliest remaining batch of accounts created.
Note: Should be > 1 to avoid situations where the close \
"Send close transactions after this many accounts created. \
Note: a `close-frequency` value near or below `batch-size` \
may result in transaction-simulation errors, as the close \
transactions will be submitted before the corresponding \
create transactions have been confirmed",
),
@@ -637,7 +632,7 @@ fn main() {
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_batch = value_t!(matches, "close_nth_batch", u64).unwrap_or(0);
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 {
@@ -662,14 +657,14 @@ fn main() {
let rpc_addr = if !skip_gossip {
info!("Finding cluster entry: {:?}", entrypoint_addr);
let (gossip_nodes, _validators) = discover(
None, // keypair
None,
Some(&entrypoint_addr),
None, // num_nodes
Duration::from_secs(60), // timeout
None, // find_node_by_pubkey
Some(&entrypoint_addr), // find_node_by_gossip_addr
None, // my_gossip_addr
0, // my_shred_version
None,
Some(60),
None,
Some(&entrypoint_addr),
None,
0,
)
.unwrap_or_else(|err| {
eprintln!("Failed to discover {} node: {:?}", entrypoint_addr, err);
@@ -690,7 +685,7 @@ fn main() {
iterations,
space,
batch_size,
close_nth_batch,
close_nth,
lamports,
num_instructions,
mint,
@@ -725,7 +720,7 @@ pub mod test {
let iterations = 10;
let maybe_space = None;
let batch_size = 100;
let close_nth_batch = 100;
let close_nth = 100;
let maybe_lamports = None;
let num_instructions = 2;
let mut start = Measure::start("total accounts run");
@@ -736,7 +731,7 @@ pub mod test {
iterations,
maybe_space,
batch_size,
close_nth_batch,
close_nth,
maybe_lamports,
num_instructions,
None,

View File

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

View File

@@ -4,8 +4,13 @@ use crossbeam_channel::unbounded;
use log::*;
use rand::{thread_rng, Rng};
use rayon::prelude::*;
use solana_core::banking_stage::BankingStage;
use solana_gossip::{cluster_info::ClusterInfo, cluster_info::Node};
use solana_core::{
banking_stage::{create_test_recorder, BankingStage},
cluster_info::ClusterInfo,
cluster_info::Node,
poh_recorder::PohRecorder,
poh_recorder::WorkingBankEntry,
};
use solana_ledger::{
blockstore::Blockstore,
genesis_utils::{create_genesis_config, GenesisConfigInfo},
@@ -13,7 +18,6 @@ use solana_ledger::{
};
use solana_measure::measure::Measure;
use solana_perf::packet::to_packets_chunked;
use solana_poh::poh_recorder::{create_test_recorder, PohRecorder, WorkingBankEntry};
use solana_runtime::{
accounts_background_service::AbsRequestSender, bank::Bank, bank_forks::BankForks,
};
@@ -74,7 +78,7 @@ fn make_accounts_txs(
.into_par_iter()
.map(|_| {
let mut new = dummy.clone();
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen::<u8>()).collect();
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
if !same_payer {
new.message.account_keys[0] = solana_sdk::pubkey::new_rand();
}
@@ -185,7 +189,7 @@ fn main() {
genesis_config.hash(),
);
// Ignore any pesky duplicate signature errors in the case we are using single-payer
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen::<u8>()).collect();
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
fund.signatures = vec![Signature::new(&sig[0..64])];
let x = bank.process_transaction(&fund);
x.unwrap();
@@ -351,7 +355,7 @@ fn main() {
if bank.slot() > 0 && bank.slot() % 16 == 0 {
for tx in transactions.iter_mut() {
tx.message.recent_blockhash = bank.last_blockhash();
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen::<u8>()).collect();
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
tx.signatures[0] = Signature::new(&sig[0..64]);
}
verified = to_packets_chunked(&transactions.clone(), packets_per_chunk);

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-banks-client"
version = "1.7.2"
version = "1.6.7"
description = "Solana banks client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -15,16 +15,16 @@ borsh = "0.8.1"
borsh-derive = "0.8.1"
futures = "0.3"
mio = "0.7.6"
solana-banks-interface = { path = "../banks-interface", version = "=1.7.2" }
solana-program = { path = "../sdk/program", version = "=1.7.2" }
solana-sdk = { path = "../sdk", version = "=1.7.2" }
solana-banks-interface = { path = "../banks-interface", version = "=1.6.7" }
solana-program = { path = "../sdk/program", version = "=1.6.7" }
solana-sdk = { path = "../sdk", version = "=1.6.7" }
tarpc = { version = "0.24.1", features = ["full"] }
tokio = { version = "1", features = ["full"] }
tokio-serde = { version = "0.8", features = ["bincode"] }
[dev-dependencies]
solana-runtime = { path = "../runtime", version = "=1.7.2" }
solana-banks-server = { path = "../banks-server", version = "=1.7.2" }
solana-runtime = { path = "../runtime", version = "=1.6.7" }
solana-banks-server = { path = "../banks-server", version = "=1.6.7" }
[lib]
crate-type = ["lib"]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-banks-interface"
version = "1.7.2"
version = "1.6.7"
description = "Solana banks RPC interface"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -12,7 +12,7 @@ edition = "2018"
[dependencies]
mio = "0.7.6"
serde = { version = "1.0.122", features = ["derive"] }
solana-sdk = { path = "../sdk", version = "=1.7.2" }
solana-sdk = { path = "../sdk", version = "=1.6.7" }
tarpc = { version = "0.24.1", features = ["full"] }
[dev-dependencies]

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-banks-server"
version = "1.7.2"
version = "1.6.7"
description = "Solana banks server"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -14,10 +14,10 @@ bincode = "1.3.1"
futures = "0.3"
log = "0.4.11"
mio = "0.7.6"
solana-banks-interface = { path = "../banks-interface", version = "=1.7.2" }
solana-runtime = { path = "../runtime", version = "=1.7.2" }
solana-sdk = { path = "../sdk", version = "=1.7.2" }
solana-metrics = { path = "../metrics", version = "=1.7.2" }
solana-banks-interface = { path = "../banks-interface", version = "=1.6.7" }
solana-runtime = { path = "../runtime", version = "=1.6.7" }
solana-sdk = { path = "../sdk", version = "=1.6.7" }
solana-metrics = { path = "../metrics", version = "=1.6.7" }
tarpc = { version = "0.24.1", features = ["full"] }
tokio = { version = "1", features = ["full"] }
tokio-serde = { version = "0.8", features = ["bincode"] }

View File

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

View File

@@ -5,7 +5,7 @@ pub mod order_book;
use crate::bench::{airdrop_lamports, create_client_accounts_file, do_bench_exchange, Config};
use log::*;
use solana_gossip::gossip_service::{discover_cluster, get_multi_client};
use solana_core::gossip_service::{discover_cluster, get_multi_client};
use solana_sdk::signature::Signer;
fn main() {

View File

@@ -1,11 +1,13 @@
use log::*;
use solana_bench_exchange::bench::{airdrop_lamports, do_bench_exchange, Config};
use solana_core::validator::ValidatorConfig;
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_gossip::gossip_service::{discover_cluster, get_multi_client};
use solana_local_cluster::{
local_cluster::{ClusterConfig, LocalCluster},
validator_configs::make_identical_validator_configs,

View File

@@ -2,7 +2,7 @@
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-bench-streamer"
version = "1.7.2"
version = "1.6.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.7.2" }
solana-streamer = { path = "../streamer", version = "=1.7.2" }
solana-logger = { path = "../logger", version = "=1.7.2" }
solana-net-utils = { path = "../net-utils", version = "=1.7.2" }
solana-version = { path = "../version", version = "=1.7.2" }
solana-clap-utils = { path = "../clap-utils", version = "=1.6.7" }
solana-streamer = { path = "../streamer", version = "=1.6.7" }
solana-logger = { path = "../logger", version = "=1.6.7" }
solana-net-utils = { path = "../net-utils", version = "=1.6.7" }
solana-version = { path = "../version", version = "=1.6.7" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -75,7 +75,7 @@ fn main() -> Result<()> {
let mut read_channels = Vec::new();
let mut read_threads = Vec::new();
let recycler = PacketsRecycler::default();
let recycler = PacketsRecycler::new_without_limit("bench-streamer-recycler-shrink-stats");
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();
@@ -92,7 +92,6 @@ fn main() -> Result<()> {
recycler.clone(),
"bench-streamer-test",
1,
true,
));
}

View File

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

View File

@@ -2,8 +2,8 @@
use log::*;
use solana_bench_tps::bench::{do_bench_tps, generate_and_fund_keypairs, generate_keypairs};
use solana_bench_tps::cli;
use solana_core::gossip_service::{discover_cluster, get_client, get_multi_client};
use solana_genesis::Base64Account;
use solana_gossip::gossip_service::{discover_cluster, get_client, get_multi_client};
use solana_sdk::fee_calculator::FeeRateGovernor;
use solana_sdk::signature::{Keypair, Signer};
use solana_sdk::system_program;

View File

@@ -5,9 +5,8 @@ use solana_bench_tps::{
cli::Config,
};
use solana_client::thin_client::create_client;
use solana_core::validator::ValidatorConfig;
use solana_core::{cluster_info::VALIDATOR_PORT_RANGE, validator::ValidatorConfig};
use solana_faucet::faucet::run_local_faucet_with_port;
use solana_gossip::cluster_info::VALIDATOR_PORT_RANGE;
use solana_local_cluster::{
local_cluster::{ClusterConfig, LocalCluster},
validator_configs::make_identical_validator_configs,

View File

@@ -5,6 +5,9 @@ steps:
- command: "ci/publish-tarball.sh"
timeout_in_minutes: 60
name: "publish tarball"
- command: "ci/publish-bpf-sdk.sh"
timeout_in_minutes: 5
name: "publish bpf sdk"
- wait
- command: "sdk/docker-solana/build.sh"
timeout_in_minutes: 60

View File

@@ -1,4 +1,4 @@
FROM solanalabs/rust:1.52.1
FROM solanalabs/rust:1.51.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.52.1
FROM rust:1.51.0
# Add Google Protocol Buffers for Libra's metrics library.
ENV PROTOC_VERSION 3.8.0

27
ci/publish-bpf-sdk.sh Executable file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -e
cd "$(dirname "$0")/.."
eval "$(ci/channel-info.sh)"
if [[ -n "$CI_TAG" ]]; then
CHANNEL_OR_TAG=$CI_TAG
else
CHANNEL_OR_TAG=$CHANNEL
fi
(
set -x
sdk/bpf/scripts/package.sh
[[ -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"
fi
exit 0

View File

@@ -7,7 +7,7 @@ source multinode-demo/common.sh
rm -rf config/run/init-completed config/ledger config/snapshot-ledger
SOLANA_RUN_SH_VALIDATOR_ARGS="--snapshot-interval-slots 200" timeout 120 ./run.sh &
timeout 120 ./run.sh &
pid=$!
attempts=20
@@ -16,8 +16,6 @@ while [[ ! -f config/run/init-completed ]]; do
if ((--attempts == 0)); then
echo "Error: validator failed to boot"
exit 1
else
echo "Checking init"
fi
done
@@ -26,7 +24,6 @@ snapshot_slot=1
# wait a bit longer than snapshot_slot
while [[ $($solana_cli --url http://localhost:8899 slot --commitment processed) -le $((snapshot_slot + 1)) ]]; do
sleep 1
echo "Checking slot"
done
$solana_validator --ledger config/ledger exit --force || true

View File

@@ -18,13 +18,13 @@
if [[ -n $RUST_STABLE_VERSION ]]; then
stable_version="$RUST_STABLE_VERSION"
else
stable_version=1.52.1
stable_version=1.51.0
fi
if [[ -n $RUST_NIGHTLY_VERSION ]]; then
nightly_version="$RUST_NIGHTLY_VERSION"
else
nightly_version=2021-05-18
nightly_version=2021-04-18
fi

View File

@@ -27,7 +27,7 @@ BENCH_ARTIFACT=current_bench_results.log
_ "$cargo" build --manifest-path=keygen/Cargo.toml
export PATH="$PWD/target/debug":$PATH
# Clear the C dependency files, if dependency moves these files are not regenerated
# 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
@@ -45,14 +45,6 @@ _ "$cargo" nightly bench --manifest-path sdk/Cargo.toml ${V:+--verbose} \
_ "$cargo" nightly bench --manifest-path runtime/Cargo.toml ${V:+--verbose} \
-- -Z unstable-options --format=json | tee -a "$BENCH_FILE"
# Run gossip benches
_ "$cargo" nightly bench --manifest-path gossip/Cargo.toml ${V:+--verbose} \
-- -Z unstable-options --format=json | tee -a "$BENCH_FILE"
# Run poh benches
_ "$cargo" nightly bench --manifest-path poh/Cargo.toml ${V:+--verbose} \
-- -Z unstable-options --format=json | tee -a "$BENCH_FILE"
# Run core benches
_ "$cargo" nightly bench --manifest-path core/Cargo.toml ${V:+--verbose} \
-- -Z unstable-options --format=json | tee -a "$BENCH_FILE"

View File

@@ -44,7 +44,7 @@ test-stable-perf)
./cargo-build-bpf --manifest-path sdk/Cargo.toml
# BPF Program unit tests
"$cargo" test --manifest-path programs/bpf/Cargo.toml
"$cargo" stable test --manifest-path programs/bpf/Cargo.toml
cargo-build-bpf --manifest-path programs/bpf/Cargo.toml --bpf-sdk sdk/bpf
# BPF program system tests

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-clap-utils"
version = "1.7.2"
version = "1.6.7"
description = "Solana utilities for the clap"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -12,8 +12,8 @@ edition = "2018"
[dependencies]
clap = "2.33.0"
rpassword = "4.0"
solana-remote-wallet = { path = "../remote-wallet", version = "=1.7.2" }
solana-sdk = { path = "../sdk", version = "=1.7.2" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.7" }
solana-sdk = { path = "../sdk", version = "=1.6.7" }
thiserror = "1.0.21"
tiny-bip39 = "0.8.0"
uriparse = "0.6.3"

View File

@@ -17,9 +17,6 @@ use {
std::{str::FromStr, sync::Arc},
};
// Sentinel value used to indicate to write to screen instead of file
pub const STDOUT_OUTFILE_TOKEN: &str = "-";
// Return parsed values from matches at `name`
pub fn values_of<T>(matches: &ArgMatches<'_>, name: &str) -> Option<Vec<T>>
where
@@ -60,7 +57,7 @@ pub fn keypair_of(matches: &ArgMatches<'_>, name: &str) -> Option<Keypair> {
if let Some(value) = matches.value_of(name) {
if value == ASK_KEYWORD {
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
keypair_from_seed_phrase(name, skip_validation, true, None, true).ok()
keypair_from_seed_phrase(name, skip_validation, true, None).ok()
} else {
read_keypair_file(value).ok()
}
@@ -75,7 +72,7 @@ pub fn keypairs_of(matches: &ArgMatches<'_>, name: &str) -> Option<Vec<Keypair>>
.filter_map(|value| {
if value == ASK_KEYWORD {
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
keypair_from_seed_phrase(name, skip_validation, true, None, true).ok()
keypair_from_seed_phrase(name, skip_validation, true, None).ok()
} else {
read_keypair_file(value).ok()
}

View File

@@ -96,26 +96,6 @@ where
.map_err(|err| format!("{}", err))
}
// Return an error if a `SignerSourceKind::Prompt` cannot be parsed
pub fn is_prompt_signer_source<T>(string: T) -> Result<(), String>
where
T: AsRef<str> + Display,
{
if string.as_ref() == ASK_KEYWORD {
return Ok(());
}
match parse_signer_source(string.as_ref())
.map_err(|err| format!("{}", err))?
.kind
{
SignerSourceKind::Prompt => Ok(()),
_ => Err(format!(
"Unable to parse input as `prompt:` URI scheme or `ASK` keyword: {}",
string
)),
}
}
// Return an error if string cannot be parsed as pubkey string or keypair file location
pub fn is_pubkey_or_keypair<T>(string: T) -> Result<(), String>
where
@@ -215,8 +195,8 @@ where
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://api.testnet.solana.com",
"d" | "devnet" => "https://api.devnet.solana.com",
"t" | "testnet" => "https://testnet.solana.com",
"d" | "devnet" => "https://devnet.solana.com",
"l" | "localhost" => "http://localhost:8899",
url => url,
}

View File

@@ -1,6 +1,6 @@
use {
crate::{
input_parsers::{pubkeys_sigs_of, STDOUT_OUTFILE_TOKEN},
input_parsers::pubkeys_sigs_of,
offline::{SIGNER_ARG, SIGN_ONLY_ARG},
ArgConstant,
},
@@ -18,17 +18,14 @@ use {
message::Message,
pubkey::Pubkey,
signature::{
generate_seed_from_seed_phrase_and_passphrase, keypair_from_seed,
keypair_from_seed_and_derivation_path, keypair_from_seed_phrase_and_passphrase,
generate_seed_from_seed_phrase_and_passphrase, keypair_from_seed_and_derivation_path,
read_keypair, read_keypair_file, Keypair, NullSigner, Presigner, Signature, Signer,
},
},
std::{
cell::RefCell,
convert::TryFrom,
error,
io::{stdin, stdout, Write},
ops::Deref,
process::exit,
str::FromStr,
sync::Arc,
@@ -92,48 +89,12 @@ impl CliSignerInfo {
}
}
#[derive(Debug, Default)]
pub struct DefaultSigner {
pub arg_name: String,
pub path: String,
is_path_checked: RefCell<bool>,
}
impl DefaultSigner {
pub fn new<AN: AsRef<str>, P: AsRef<str>>(arg_name: AN, path: P) -> Self {
let arg_name = arg_name.as_ref().to_string();
let path = path.as_ref().to_string();
Self {
arg_name,
path,
..Self::default()
}
}
fn path(&self) -> Result<&str, Box<dyn std::error::Error>> {
if !self.is_path_checked.borrow().deref() {
parse_signer_source(&self.path)
.and_then(|s| {
if let SignerSourceKind::Filepath(path) = &s.kind {
std::fs::metadata(path).map(|_| ()).map_err(|e| e.into())
} else {
Ok(())
}
})
.map_err(|_| {
std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"No default signer found, run \"solana-keygen new -o {}\" to create a new one",
self.path
),
)
})?;
*self.is_path_checked.borrow_mut() = true;
}
Ok(&self.path)
}
pub fn generate_unique_signers(
&self,
bulk_signers: Vec<Option<Box<dyn Signer>>>,
@@ -163,7 +124,7 @@ impl DefaultSigner {
matches: &ArgMatches,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<Box<dyn Signer>, Box<dyn std::error::Error>> {
signer_from_path(matches, self.path()?, &self.arg_name, wallet_manager)
signer_from_path(matches, &self.path, &self.arg_name, wallet_manager)
}
pub fn signer_from_path_with_config(
@@ -172,20 +133,13 @@ impl DefaultSigner {
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,
)
signer_from_path_with_config(matches, &self.path, &self.arg_name, wallet_manager, config)
}
}
pub(crate) struct SignerSource {
pub kind: SignerSourceKind,
pub derivation_path: Option<DerivationPath>,
pub legacy: bool,
}
impl SignerSource {
@@ -193,52 +147,18 @@ impl SignerSource {
Self {
kind,
derivation_path: None,
legacy: false,
}
}
fn new_legacy(kind: SignerSourceKind) -> Self {
Self {
kind,
derivation_path: None,
legacy: true,
}
}
}
const SIGNER_SOURCE_PROMPT: &str = "prompt";
const SIGNER_SOURCE_FILEPATH: &str = "file";
const SIGNER_SOURCE_USB: &str = "usb";
const SIGNER_SOURCE_STDIN: &str = "stdin";
const SIGNER_SOURCE_PUBKEY: &str = "pubkey";
pub(crate) enum SignerSourceKind {
Prompt,
Ask,
Filepath(String),
Usb(RemoteWalletLocator),
Stdin,
Pubkey(Pubkey),
}
impl AsRef<str> for SignerSourceKind {
fn as_ref(&self) -> &str {
match self {
Self::Prompt => SIGNER_SOURCE_PROMPT,
Self::Filepath(_) => SIGNER_SOURCE_FILEPATH,
Self::Usb(_) => SIGNER_SOURCE_USB,
Self::Stdin => SIGNER_SOURCE_STDIN,
Self::Pubkey(_) => SIGNER_SOURCE_PUBKEY,
}
}
}
impl std::fmt::Debug for SignerSourceKind {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let s: &str = self.as_ref();
write!(f, "{}", s)
}
}
#[derive(Debug, Error)]
pub(crate) enum SignerSourceError {
#[error("unrecognized signer source")]
@@ -255,54 +175,36 @@ pub(crate) fn parse_signer_source<S: AsRef<str>>(
source: S,
) -> Result<SignerSource, SignerSourceError> {
let source = source.as_ref();
let source = {
#[cfg(target_family = "windows")]
{
source.replace("\\", "/")
}
#[cfg(not(target_family = "windows"))]
{
source.to_string()
}
};
match uriparse::URIReference::try_from(source.as_str()) {
match uriparse::URIReference::try_from(source) {
Err(_) => Err(SignerSourceError::UnrecognizedSource),
Ok(uri) => {
if let Some(scheme) = uri.scheme() {
let scheme = scheme.as_str().to_ascii_lowercase();
match scheme.as_str() {
SIGNER_SOURCE_PROMPT => Ok(SignerSource {
kind: SignerSourceKind::Prompt,
"ask" => Ok(SignerSource {
kind: SignerSourceKind::Ask,
derivation_path: DerivationPath::from_uri_any_query(&uri)?,
legacy: false,
}),
SIGNER_SOURCE_FILEPATH => Ok(SignerSource::new(SignerSourceKind::Filepath(
"file" => Ok(SignerSource::new(SignerSourceKind::Filepath(
uri.path().to_string(),
))),
SIGNER_SOURCE_USB => Ok(SignerSource {
"stdin" => Ok(SignerSource::new(SignerSourceKind::Stdin)),
"usb" => Ok(SignerSource {
kind: SignerSourceKind::Usb(RemoteWalletLocator::new_from_uri(&uri)?),
derivation_path: DerivationPath::from_uri_key_query(&uri)?,
legacy: false,
}),
SIGNER_SOURCE_STDIN => Ok(SignerSource::new(SignerSourceKind::Stdin)),
_ => {
#[cfg(target_family = "windows")]
// On Windows, an absolute path's drive letter will be parsed as the URI
// scheme. Assume a filepath source in case of a single character shceme.
if scheme.len() == 1 {
return Ok(SignerSource::new(SignerSourceKind::Filepath(source)));
}
Err(SignerSourceError::UnrecognizedSource)
}
_ => Err(SignerSourceError::UnrecognizedSource),
}
} else {
match source.as_str() {
STDOUT_OUTFILE_TOKEN => Ok(SignerSource::new(SignerSourceKind::Stdin)),
ASK_KEYWORD => Ok(SignerSource::new_legacy(SignerSourceKind::Prompt)),
_ => match Pubkey::from_str(source.as_str()) {
match source {
"-" => Ok(SignerSource::new(SignerSourceKind::Stdin)),
ASK_KEYWORD => Ok(SignerSource::new(SignerSourceKind::Ask)),
_ => match Pubkey::from_str(source) {
Ok(pubkey) => Ok(SignerSource::new(SignerSourceKind::Pubkey(pubkey))),
Err(_) => std::fs::metadata(source.as_str())
.map(|_| SignerSource::new(SignerSourceKind::Filepath(source)))
Err(_) => std::fs::metadata(source)
.map(|_| {
SignerSource::new(SignerSourceKind::Filepath(source.to_string()))
})
.map_err(|err| err.into()),
},
}
@@ -357,17 +259,15 @@ pub fn signer_from_path_with_config(
let SignerSource {
kind,
derivation_path,
legacy,
} = parse_signer_source(path)?;
match kind {
SignerSourceKind::Prompt => {
SignerSourceKind::Ask => {
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
Ok(Box::new(keypair_from_seed_phrase(
keypair_name,
skip_validation,
false,
derivation_path,
legacy,
)?))
}
SignerSourceKind::Filepath(path) => match read_keypair_file(&path) {
@@ -439,30 +339,18 @@ pub fn resolve_signer_from_path(
let SignerSource {
kind,
derivation_path,
legacy,
} = parse_signer_source(path)?;
match kind {
SignerSourceKind::Prompt => {
SignerSourceKind::Ask => {
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
// This method validates the seed phrase, but returns `None` because there is no path
// on disk or to a device
keypair_from_seed_phrase(
keypair_name,
skip_validation,
false,
derivation_path,
legacy,
)
.map(|_| None)
keypair_from_seed_phrase(keypair_name, skip_validation, false, derivation_path).map(|_| None)
}
SignerSourceKind::Filepath(path) => match read_keypair_file(&path) {
Err(e) => Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"could not read keypair file \"{}\". \
Run \"solana-keygen new\" to create a keypair file: {}",
path, e
),
format!("could not read keypair file \"{}\". Run \"solana-keygen new\" to create a keypair file: {}", path, e),
)
.into()),
Ok(_) => Ok(Some(path.to_string())),
@@ -495,7 +383,7 @@ pub fn resolve_signer_from_path(
}
}
// Keyword used to indicate that the user should be prompted for a keypair seed phrase
// Keyword used to indicate that the user should be asked for a keypair seed phrase
pub const ASK_KEYWORD: &str = "ASK";
pub const SKIP_SEED_PHRASE_VALIDATION_ARG: ArgConstant<'static> = ArgConstant {
@@ -516,56 +404,6 @@ pub fn prompt_passphrase(prompt: &str) -> Result<String, Box<dyn error::Error>>
Ok(passphrase)
}
/// Parses a path into a SignerSource and returns a Keypair for supporting SignerSourceKinds
pub fn keypair_from_path(
matches: &ArgMatches,
path: &str,
keypair_name: &str,
confirm_pubkey: bool,
) -> Result<Keypair, Box<dyn error::Error>> {
let SignerSource {
kind,
derivation_path,
legacy,
} = parse_signer_source(path)?;
match kind {
SignerSourceKind::Prompt => {
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
Ok(keypair_from_seed_phrase(
keypair_name,
skip_validation,
confirm_pubkey,
derivation_path,
legacy,
)?)
}
SignerSourceKind::Filepath(path) => match read_keypair_file(&path) {
Err(e) => Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"could not read keypair file \"{}\". \
Run \"solana-keygen new\" to create a keypair file: {}",
path, e
),
)
.into()),
Ok(file) => Ok(file),
},
SignerSourceKind::Stdin => {
let mut stdin = std::io::stdin();
Ok(read_keypair(&mut stdin)?)
}
_ => Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"signer of type `{:?}` does not support Keypair output",
kind
),
)
.into()),
}
}
/// Reads user input from stdin to retrieve a seed phrase and passphrase for keypair derivation
/// Optionally skips validation of seed phrase
/// Optionally confirms recovered public key
@@ -574,7 +412,6 @@ pub fn keypair_from_seed_phrase(
skip_validation: bool,
confirm_pubkey: bool,
derivation_path: Option<DerivationPath>,
legacy: bool,
) -> Result<Keypair, Box<dyn error::Error>> {
let seed_phrase = prompt_password_stderr(&format!("[{}] seed phrase: ", keypair_name))?;
let seed_phrase = seed_phrase.trim();
@@ -585,12 +422,8 @@ pub fn keypair_from_seed_phrase(
let keypair = if skip_validation {
let passphrase = prompt_passphrase(&passphrase_prompt)?;
if legacy {
keypair_from_seed_phrase_and_passphrase(&seed_phrase, &passphrase)?
} else {
let seed = generate_seed_from_seed_phrase_and_passphrase(&seed_phrase, &passphrase);
keypair_from_seed_and_derivation_path(&seed, derivation_path)?
}
let seed = generate_seed_from_seed_phrase_and_passphrase(&seed_phrase, &passphrase);
keypair_from_seed_and_derivation_path(&seed, derivation_path)?
} else {
let sanitized = sanitize_seed_phrase(seed_phrase);
let parse_language_fn = || {
@@ -613,11 +446,7 @@ pub fn keypair_from_seed_phrase(
let mnemonic = parse_language_fn()?;
let passphrase = prompt_passphrase(&passphrase_prompt)?;
let seed = Seed::new(&mnemonic, &passphrase);
if legacy {
keypair_from_seed(seed.as_bytes())?
} else {
keypair_from_seed_and_derivation_path(&seed.as_bytes(), derivation_path)?
}
keypair_from_seed_and_derivation_path(&seed.as_bytes(), derivation_path)?
};
if confirm_pubkey {
@@ -692,28 +521,25 @@ mod tests {
#[test]
fn test_parse_signer_source() {
assert!(matches!(
parse_signer_source(STDOUT_OUTFILE_TOKEN).unwrap(),
parse_signer_source("-").unwrap(),
SignerSource {
kind: SignerSourceKind::Stdin,
derivation_path: None,
legacy: false,
}
));
let stdin = "stdin:".to_string();
let ask = "stdin:".to_string();
assert!(matches!(
parse_signer_source(&stdin).unwrap(),
parse_signer_source(&ask).unwrap(),
SignerSource {
kind: SignerSourceKind::Stdin,
derivation_path: None,
legacy: false,
}
));
assert!(matches!(
parse_signer_source(ASK_KEYWORD).unwrap(),
SignerSource {
kind: SignerSourceKind::Prompt,
kind: SignerSourceKind::Ask,
derivation_path: None,
legacy: true,
}
));
let pubkey = Pubkey::new_unique();
@@ -721,7 +547,6 @@ mod tests {
matches!(parse_signer_source(&pubkey.to_string()).unwrap(), SignerSource {
kind: SignerSourceKind::Pubkey(p),
derivation_path: None,
legacy: false,
}
if p == pubkey)
);
@@ -742,14 +567,12 @@ mod tests {
matches!(parse_signer_source(absolute_path_str).unwrap(), SignerSource {
kind: SignerSourceKind::Filepath(p),
derivation_path: None,
legacy: false,
} if p == absolute_path_str)
);
assert!(
matches!(parse_signer_source(&relative_path_str).unwrap(), SignerSource {
kind: SignerSourceKind::Filepath(p),
derivation_path: None,
legacy: false,
} if p == relative_path_str)
);
@@ -761,7 +584,6 @@ mod tests {
assert!(matches!(parse_signer_source(&usb).unwrap(), SignerSource {
kind: SignerSourceKind::Usb(u),
derivation_path: None,
legacy: false,
} if u == expected_locator));
let usb = "usb://ledger?key=0/0".to_string();
let expected_locator = RemoteWalletLocator {
@@ -772,7 +594,6 @@ mod tests {
assert!(matches!(parse_signer_source(&usb).unwrap(), SignerSource {
kind: SignerSourceKind::Usb(u),
derivation_path: d,
legacy: false,
} if u == expected_locator && d == expected_derivation_path));
// Catchall into SignerSource::Filepath fails
let junk = "sometextthatisnotapubkeyorfile".to_string();
@@ -782,27 +603,24 @@ mod tests {
Err(SignerSourceError::IoError(_))
));
let prompt = "prompt:".to_string();
let ask = "ask:".to_string();
assert!(matches!(
parse_signer_source(&prompt).unwrap(),
parse_signer_source(&ask).unwrap(),
SignerSource {
kind: SignerSourceKind::Prompt,
kind: SignerSourceKind::Ask,
derivation_path: None,
legacy: false,
}
));
assert!(
matches!(parse_signer_source(&format!("file:{}", absolute_path_str)).unwrap(), SignerSource {
kind: SignerSourceKind::Filepath(p),
derivation_path: None,
legacy: false,
} if p == absolute_path_str)
);
assert!(
matches!(parse_signer_source(&format!("file:{}", relative_path_str)).unwrap(), SignerSource {
kind: SignerSourceKind::Filepath(p),
derivation_path: None,
legacy: false,
} if p == relative_path_str)
);
}

View File

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

View File

@@ -107,13 +107,13 @@ mod test {
#[test]
fn compute_websocket_url() {
assert_eq!(
Config::compute_websocket_url(&"http://api.devnet.solana.com"),
"ws://api.devnet.solana.com/".to_string()
Config::compute_websocket_url(&"http://devnet.solana.com"),
"ws://devnet.solana.com/".to_string()
);
assert_eq!(
Config::compute_websocket_url(&"https://api.devnet.solana.com"),
"wss://api.devnet.solana.com/".to_string()
Config::compute_websocket_url(&"https://devnet.solana.com"),
"wss://devnet.solana.com/".to_string()
);
assert_eq!(

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-cli-output"
description = "Blockchain, Rebuilt for Scale"
version = "1.7.2"
version = "1.6.7"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -12,19 +12,20 @@ documentation = "https://docs.rs/solana-cli-output"
[dependencies]
base64 = "0.13.0"
chrono = { version = "0.4.11", features = ["serde"] }
console = "0.14.1"
console = "0.11.3"
humantime = "2.0.1"
Inflector = "0.11.4"
indicatif = "0.15.0"
serde = "1.0.122"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "=1.7.2" }
solana-clap-utils = { path = "../clap-utils", version = "=1.7.2" }
solana-client = { path = "../client", version = "=1.7.2" }
solana-sdk = { path = "../sdk", version = "=1.7.2" }
solana-transaction-status = { path = "../transaction-status", version = "=1.7.2" }
solana-vote-program = { path = "../programs/vote", version = "=1.7.2" }
solana-account-decoder = { path = "../account-decoder", version = "=1.6.7" }
solana-clap-utils = { path = "../clap-utils", version = "=1.6.7" }
solana-client = { path = "../client", version = "=1.6.7" }
solana-sdk = { path = "../sdk", version = "=1.6.7" }
solana-stake-program = { path = "../programs/stake", version = "=1.6.7" }
solana-transaction-status = { path = "../transaction-status", version = "=1.6.7" }
solana-vote-program = { path = "../programs/vote", version = "=1.6.7" }
spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
[package.metadata.docs.rs]

View File

@@ -15,8 +15,8 @@ use {
solana_account_decoder::parse_token::UiTokenAccount,
solana_clap_utils::keypair::SignOnly,
solana_client::rpc_response::{
RpcAccountBalance, RpcContactInfo, RpcInflationGovernor, RpcInflationRate, RpcKeyedAccount,
RpcSupply, RpcVoteAccountInfo,
RpcAccountBalance, RpcInflationGovernor, RpcInflationRate, RpcKeyedAccount, RpcSupply,
RpcVoteAccountInfo,
},
solana_sdk::{
clock::{Epoch, Slot, UnixTimestamp},
@@ -25,10 +25,10 @@ use {
native_token::lamports_to_sol,
pubkey::Pubkey,
signature::Signature,
stake::state::{Authorized, Lockup},
stake_history::StakeHistoryEntry,
transaction::{Transaction, TransactionError},
},
solana_stake_program::stake_state::{Authorized, Lockup},
solana_transaction_status::{
EncodedConfirmedBlock, EncodedTransaction, TransactionConfirmationStatus,
UiTransactionStatusMeta,
@@ -2126,9 +2126,6 @@ impl fmt::Display for CliBlock {
if let Some(block_time) = self.encoded_confirmed_block.block_time {
writeln!(f, "Block Time: {:?}", Local.timestamp(block_time, 0))?;
}
if let Some(block_height) = self.encoded_confirmed_block.block_height {
writeln!(f, "Block Height: {:?}", block_height)?;
}
if !self.encoded_confirmed_block.rewards.is_empty() {
let mut rewards = self.encoded_confirmed_block.rewards.clone();
rewards.sort_by(|a, b| a.pubkey.cmp(&b.pubkey));
@@ -2286,97 +2283,6 @@ impl fmt::Display for CliTransactionConfirmation {
}
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CliGossipNode {
#[serde(skip_serializing_if = "Option::is_none")]
pub ip_address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub identity_label: Option<String>,
pub identity_pubkey: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub gossip_port: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tpu_port: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rpc_host: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
}
impl CliGossipNode {
pub fn new(info: RpcContactInfo, labels: &HashMap<String, String>) -> Self {
Self {
ip_address: info.gossip.map(|addr| addr.ip().to_string()),
identity_label: labels.get(&info.pubkey).cloned(),
identity_pubkey: info.pubkey,
gossip_port: info.gossip.map(|addr| addr.port()),
tpu_port: info.tpu.map(|addr| addr.port()),
rpc_host: info.rpc.map(|addr| addr.to_string()),
version: info.version,
}
}
}
fn unwrap_to_string_or_none<T>(option: Option<T>) -> String
where
T: std::string::ToString,
{
unwrap_to_string_or_default(option, "none")
}
fn unwrap_to_string_or_default<T>(option: Option<T>, default: &str) -> String
where
T: std::string::ToString,
{
option
.as_ref()
.map(|v| v.to_string())
.unwrap_or_else(|| default.to_string())
}
impl fmt::Display for CliGossipNode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{:15} | {:44} | {:6} | {:5} | {:21} | {}",
unwrap_to_string_or_none(self.ip_address.as_ref()),
self.identity_label
.as_ref()
.unwrap_or(&self.identity_pubkey),
unwrap_to_string_or_none(self.gossip_port.as_ref()),
unwrap_to_string_or_none(self.tpu_port.as_ref()),
unwrap_to_string_or_none(self.rpc_host.as_ref()),
unwrap_to_string_or_default(self.version.as_ref(), "unknown"),
)
}
}
impl QuietDisplay for CliGossipNode {}
impl VerboseDisplay for CliGossipNode {}
#[derive(Serialize, Deserialize)]
pub struct CliGossipNodes(pub Vec<CliGossipNode>);
impl fmt::Display for CliGossipNodes {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(
f,
"IP Address | Node identifier \
| Gossip | TPU | RPC Address | Version\n\
----------------+----------------------------------------------+\
--------+-------+-----------------------+----------------",
)?;
for node in self.0.iter() {
writeln!(f, "{}", node)?;
}
writeln!(f, "Nodes: {}", self.0.len())
}
}
impl QuietDisplay for CliGossipNodes {}
impl VerboseDisplay for CliGossipNodes {}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -5,7 +5,7 @@ use {
indicatif::{ProgressBar, ProgressStyle},
solana_sdk::{
clock::UnixTimestamp, hash::Hash, message::Message, native_token::lamports_to_sol,
program_utils::limited_deserialize, pubkey::Pubkey, stake, transaction::Transaction,
program_utils::limited_deserialize, pubkey::Pubkey, transaction::Transaction,
},
solana_transaction_status::UiTransactionStatusMeta,
spl_memo::id as spl_memo_id,
@@ -244,9 +244,10 @@ pub fn write_transaction<W: io::Write>(
writeln!(w, "{} {:?}", prefix, vote_instruction)?;
raw = false;
}
} else if program_pubkey == stake::program::id() {
if let Ok(stake_instruction) =
limited_deserialize::<stake::instruction::StakeInstruction>(&instruction.data)
} else if program_pubkey == solana_stake_program::id() {
if let Ok(stake_instruction) = limited_deserialize::<
solana_stake_program::stake_instruction::StakeInstruction,
>(&instruction.data)
{
writeln!(w, "{} {:?}", prefix, stake_instruction)?;
raw = false;
@@ -321,38 +322,7 @@ pub fn write_transaction<W: io::Write>(
if !log_messages.is_empty() {
writeln!(w, "{}Log Messages:", prefix,)?;
for log_message in log_messages {
writeln!(w, "{} {}", prefix, log_message)?;
}
}
}
if let Some(rewards) = &transaction_status.rewards {
if !rewards.is_empty() {
writeln!(w, "{}Rewards:", prefix,)?;
writeln!(
w,
"{} {:<44} {:^15} {:<15} {:<20}",
prefix, "Address", "Type", "Amount", "New Balance"
)?;
for reward in rewards {
let sign = if reward.lamports < 0 { "-" } else { "" };
writeln!(
w,
"{} {:<44} {:^15} {:<15} {}",
prefix,
reward.pubkey,
if let Some(reward_type) = reward.reward_type {
format!("{}", reward_type)
} else {
"-".to_string()
},
format!(
"{}{:<14.9}",
sign,
lamports_to_sol(reward.lamports.abs() as u64)
),
format!("{:<18.9}", lamports_to_sol(reward.post_balance),)
)?;
writeln!(w, "{} {}", prefix, log_message,)?;
}
}
}

View File

@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-cli"
description = "Blockchain, Rebuilt for Scale"
version = "1.7.2"
version = "1.6.7"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -16,7 +16,7 @@ chrono = { version = "0.4.11", features = ["serde"] }
clap = "2.33.1"
criterion-stats = "0.3.0"
ctrlc = { version = "3.1.5", features = ["termination"] }
console = "0.14.1"
console = "0.11.3"
dirs-next = "2.0.0"
log = "0.4.11"
Inflector = "0.11.4"
@@ -28,29 +28,30 @@ reqwest = { version = "0.11.2", default-features = false, features = ["blocking"
serde = "1.0.122"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "=1.7.2" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.7.2" }
solana-clap-utils = { path = "../clap-utils", version = "=1.7.2" }
solana-cli-config = { path = "../cli-config", version = "=1.7.2" }
solana-cli-output = { path = "../cli-output", version = "=1.7.2" }
solana-client = { path = "../client", version = "=1.7.2" }
solana-config-program = { path = "../programs/config", version = "=1.7.2" }
solana-faucet = { path = "../faucet", version = "=1.7.2" }
solana-logger = { path = "../logger", version = "=1.7.2" }
solana-net-utils = { path = "../net-utils", version = "=1.7.2" }
solana_rbpf = "=0.2.11"
solana-remote-wallet = { path = "../remote-wallet", version = "=1.7.2" }
solana-sdk = { path = "../sdk", version = "=1.7.2" }
solana-transaction-status = { path = "../transaction-status", version = "=1.7.2" }
solana-version = { path = "../version", version = "=1.7.2" }
solana-vote-program = { path = "../programs/vote", version = "=1.7.2" }
solana-account-decoder = { path = "../account-decoder", version = "=1.6.7" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.6.7" }
solana-clap-utils = { path = "../clap-utils", version = "=1.6.7" }
solana-cli-config = { path = "../cli-config", version = "=1.6.7" }
solana-cli-output = { path = "../cli-output", version = "=1.6.7" }
solana-client = { path = "../client", version = "=1.6.7" }
solana-config-program = { path = "../programs/config", version = "=1.6.7" }
solana-faucet = { path = "../faucet", version = "=1.6.7" }
solana-logger = { path = "../logger", version = "=1.6.7" }
solana-net-utils = { path = "../net-utils", version = "=1.6.7" }
solana_rbpf = "=0.2.8"
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.7" }
solana-sdk = { path = "../sdk", version = "=1.6.7" }
solana-stake-program = { path = "../programs/stake", version = "=1.6.7" }
solana-transaction-status = { path = "../transaction-status", version = "=1.6.7" }
solana-version = { path = "../version", version = "=1.6.7" }
solana-vote-program = { path = "../programs/vote", version = "=1.6.7" }
spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
thiserror = "1.0.21"
tiny-bip39 = "0.7.0"
url = "2.1.1"
[dev-dependencies]
solana-core = { path = "../core", version = "=1.7.2" }
solana-core = { path = "../core", version = "=1.6.7" }
tempfile = "3.1.0"
[[bin]]

View File

@@ -231,9 +231,18 @@ mod tests {
mocks.insert(RpcRequest::GetBalance, account_balance_response);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert!(check_account_for_balance(&rpc_client, &pubkey, 1).unwrap());
assert!(check_account_for_balance(&rpc_client, &pubkey, account_balance).unwrap());
assert!(!check_account_for_balance(&rpc_client, &pubkey, account_balance + 1).unwrap());
assert_eq!(
check_account_for_balance(&rpc_client, &pubkey, 1).unwrap(),
true
);
assert_eq!(
check_account_for_balance(&rpc_client, &pubkey, account_balance).unwrap(),
true
);
assert_eq!(
check_account_for_balance(&rpc_client, &pubkey, account_balance + 1).unwrap(),
false
);
}
#[test]

View File

@@ -29,11 +29,10 @@ use solana_client::{
nonce_utils,
rpc_client::RpcClient,
rpc_config::{
RpcLargestAccountsFilter, RpcSendTransactionConfig, RpcTransactionConfig,
RpcConfirmedTransactionConfig, RpcLargestAccountsFilter, RpcSendTransactionConfig,
RpcTransactionLogsFilter,
},
rpc_request::{RpcError, RpcResponseErrorData},
rpc_response::{RpcKeyedAccount, RpcSimulateTransactionResult},
rpc_response::RpcKeyedAccount,
};
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
@@ -45,15 +44,14 @@ use solana_sdk::{
message::Message,
pubkey::Pubkey,
signature::{Signature, Signer, SignerError},
stake::{
self,
instruction::LockupArgs,
state::{Lockup, StakeAuthorize},
},
system_instruction::{self, SystemError},
system_program,
transaction::{Transaction, TransactionError},
};
use solana_stake_program::{
stake_instruction::LockupArgs,
stake_state::{Lockup, StakeAuthorize},
};
use solana_transaction_status::{EncodedTransaction, UiTransactionEncoding};
use solana_vote_program::vote_state::VoteAuthorize;
use std::{
@@ -278,7 +276,6 @@ pub enum CliCommand {
memo: Option<String>,
fee_payer: SignerIndex,
custodian: Option<SignerIndex>,
no_wait: bool,
},
StakeSetLockup {
stake_account_pubkey: Pubkey,
@@ -933,7 +930,7 @@ pub type ProcessResult = Result<String, Box<dyn std::error::Error>>;
fn resolve_derived_address_program_id(matches: &ArgMatches<'_>, arg_name: &str) -> Option<Pubkey> {
matches.value_of(arg_name).and_then(|v| match v {
"NONCE" => Some(system_program::id()),
"STAKE" => Some(stake::program::id()),
"STAKE" => Some(solana_stake_program::id()),
"VOTE" => Some(solana_vote_program::id()),
_ => pubkey_of(matches, arg_name),
})
@@ -1043,9 +1040,9 @@ fn process_confirm(
let mut transaction = None;
let mut get_transaction_error = None;
if config.verbose {
match rpc_client.get_transaction_with_config(
match rpc_client.get_confirmed_transaction_with_config(
signature,
RpcTransactionConfig {
RpcConfirmedTransactionConfig {
encoding: Some(UiTransactionEncoding::Base64),
commitment: Some(CommitmentConfig::confirmed()),
},
@@ -1125,7 +1122,7 @@ fn process_show_account(
pubkey: account_pubkey.to_string(),
account: UiAccount::encode(
account_pubkey,
&account,
account,
UiAccountEncoding::Base64,
None,
None,
@@ -1682,7 +1679,6 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
memo,
fee_payer,
custodian,
no_wait,
} => process_stake_authorize(
&rpc_client,
config,
@@ -1696,7 +1692,6 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
*nonce_authority,
memo.as_ref(),
*fee_payer,
*no_wait,
),
CliCommand::StakeSetLockup {
stake_account_pubkey,
@@ -1958,28 +1953,6 @@ where
{
match result {
Err(err) => {
// If transaction simulation returns a known Custom InstructionError, decode it
if let ClientErrorKind::RpcError(RpcError::RpcResponseError {
data:
RpcResponseErrorData::SendTransactionPreflightFailure(
RpcSimulateTransactionResult {
err:
Some(TransactionError::InstructionError(
_,
InstructionError::Custom(code),
)),
..
},
),
..
}) = err.kind()
{
if let Some(specific_error) = E::decode_custom_error_to_enum(*code) {
return Err(specific_error.into());
}
}
// If the transaction was instead submitted and returned a known Custom
// InstructionError, decode it
if let ClientErrorKind::TransactionError(TransactionError::InstructionError(
_,
InstructionError::Custom(code),
@@ -2323,7 +2296,10 @@ mod tests {
let default_keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &default_keypair_file).unwrap();
let default_signer = DefaultSigner::new("keypair", &default_keypair_file);
let default_signer = DefaultSigner {
arg_name: "keypair".to_string(),
path: default_keypair_file,
};
let signer_info = default_signer
.generate_unique_signers(vec![], &matches, &mut None)
@@ -2401,7 +2377,10 @@ mod tests {
let keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &keypair_file).unwrap();
let keypair = read_keypair_file(&keypair_file).unwrap();
let default_signer = DefaultSigner::new("", &keypair_file);
let default_signer = DefaultSigner {
path: keypair_file.clone(),
arg_name: "".to_string(),
};
// Test Airdrop Subcommand
let test_airdrop =
test_commands
@@ -2488,7 +2467,7 @@ mod tests {
let from_pubkey = Some(solana_sdk::pubkey::new_rand());
let from_str = from_pubkey.unwrap().to_string();
for (name, program_id) in &[
("STAKE", stake::program::id()),
("STAKE", solana_stake_program::id()),
("VOTE", solana_vote_program::id()),
("NONCE", system_program::id()),
] {
@@ -2524,7 +2503,7 @@ mod tests {
command: CliCommand::CreateAddressWithSeed {
from_pubkey: None,
seed: "seed".to_string(),
program_id: stake::program::id(),
program_id: solana_stake_program::id(),
},
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
@@ -2787,11 +2766,11 @@ mod tests {
config.command = CliCommand::CreateAddressWithSeed {
from_pubkey: Some(from_pubkey),
seed: "seed".to_string(),
program_id: stake::program::id(),
program_id: solana_stake_program::id(),
};
let address = process_command(&config);
let expected_address =
Pubkey::create_with_seed(&from_pubkey, "seed", &stake::program::id()).unwrap();
Pubkey::create_with_seed(&from_pubkey, "seed", &solana_stake_program::id()).unwrap();
assert_eq!(address.unwrap(), expected_address.to_string());
// Need airdrop cases
@@ -2929,7 +2908,10 @@ mod tests {
let default_keypair = Keypair::new();
let default_keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &default_keypair_file).unwrap();
let default_signer = DefaultSigner::new("", &default_keypair_file);
let default_signer = DefaultSigner {
path: default_keypair_file.clone(),
arg_name: "".to_string(),
};
//Test Transfer Subcommand, SOL
let from_keypair = keypair_from_seed(&[0u8; 32]).unwrap();
@@ -3178,7 +3160,7 @@ mod tests {
memo: None,
fee_payer: 0,
derived_address_seed: Some(derived_address_seed),
derived_address_program_id: Some(stake::program::id()),
derived_address_program_id: Some(solana_stake_program::id()),
},
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into(),],
}

View File

@@ -24,9 +24,9 @@ use solana_client::{
pubsub_client::PubsubClient,
rpc_client::{GetConfirmedSignaturesForAddress2Config, RpcClient},
rpc_config::{
RpcAccountInfoConfig, RpcBlockConfig, RpcLargestAccountsConfig, RpcLargestAccountsFilter,
RpcProgramAccountsConfig, RpcTransactionConfig, RpcTransactionLogsConfig,
RpcTransactionLogsFilter,
RpcAccountInfoConfig, RpcConfirmedBlockConfig, RpcConfirmedTransactionConfig,
RpcLargestAccountsConfig, RpcLargestAccountsFilter, RpcProgramAccountsConfig,
RpcTransactionLogsConfig, RpcTransactionLogsFilter,
},
rpc_filter,
rpc_response::SlotInfo,
@@ -46,9 +46,7 @@ use solana_sdk::{
rent::Rent,
rpc_port::DEFAULT_RPC_PORT_STR,
signature::Signature,
slot_history,
stake::{self, state::StakeState},
system_instruction, system_program,
slot_history, system_instruction, system_program,
sysvar::{
self,
slot_history::SlotHistory,
@@ -57,11 +55,13 @@ use solana_sdk::{
timing,
transaction::Transaction,
};
use solana_stake_program::stake_state::StakeState;
use solana_transaction_status::UiTransactionEncoding;
use solana_vote_program::vote_state::VoteState;
use std::{
collections::{BTreeMap, HashMap, VecDeque},
fmt,
net::SocketAddr,
str::FromStr,
sync::{
atomic::{AtomicBool, Ordering},
@@ -1028,12 +1028,12 @@ pub fn process_get_block(
};
let encoded_confirmed_block = rpc_client
.get_block_with_config(
.get_confirmed_block_with_config(
slot,
RpcBlockConfig {
RpcConfirmedBlockConfig {
encoding: Some(UiTransactionEncoding::Base64),
commitment: Some(CommitmentConfig::confirmed()),
..RpcBlockConfig::default()
..RpcConfirmedBlockConfig::default()
},
)?
.into();
@@ -1094,8 +1094,8 @@ pub fn process_get_slot(rpc_client: &RpcClient, _config: &CliConfig) -> ProcessR
}
pub fn process_get_block_height(rpc_client: &RpcClient, _config: &CliConfig) -> ProcessResult {
let block_height = rpc_client.get_block_height()?;
Ok(block_height.to_string())
let epoch_info = rpc_client.get_epoch_info()?;
Ok(epoch_info.block_height.to_string())
}
pub fn parse_show_block_production(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
@@ -1185,7 +1185,7 @@ pub fn process_show_block_production(
start_slot = minimum_ledger_slot;
}
let confirmed_blocks = rpc_client.get_blocks(start_slot, Some(end_slot))?;
let confirmed_blocks = rpc_client.get_confirmed_blocks(start_slot, Some(end_slot))?;
(confirmed_blocks, start_slot)
};
@@ -1655,14 +1655,40 @@ pub fn process_live_slots(config: &CliConfig) -> ProcessResult {
pub fn process_show_gossip(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
let cluster_nodes = rpc_client.get_cluster_nodes()?;
let nodes: Vec<_> = cluster_nodes
fn format_port(addr: Option<SocketAddr>) -> String {
addr.map(|addr| addr.port().to_string())
.unwrap_or_else(|| "none".to_string())
}
let s: Vec<_> = cluster_nodes
.into_iter()
.map(|node| CliGossipNode::new(node, &config.address_labels))
.map(|node| {
format!(
"{:15} | {:44} | {:6} | {:5} | {:21} | {}",
node.gossip
.map(|addr| addr.ip().to_string())
.unwrap_or_else(|| "none".to_string()),
format_labeled_address(&node.pubkey, &config.address_labels),
format_port(node.gossip),
format_port(node.tpu),
node.rpc
.map(|addr| addr.to_string())
.unwrap_or_else(|| "none".to_string()),
node.version.unwrap_or_else(|| "unknown".to_string()),
)
})
.collect();
Ok(config
.output_format
.formatted_string(&CliGossipNodes(nodes)))
Ok(format!(
"IP Address | Node identifier \
| Gossip | TPU | RPC Address | Version\n\
----------------+----------------------------------------------+\
--------+-------+-----------------------+----------------\n\
{}\n\
Nodes: {}",
s.join("\n"),
s.len(),
))
}
pub fn process_show_stakes(
@@ -1677,11 +1703,11 @@ pub fn process_show_stakes(
progress_bar.set_message("Fetching stake accounts...");
let mut program_accounts_config = RpcProgramAccountsConfig {
filters: None,
account_config: RpcAccountInfoConfig {
encoding: Some(solana_account_decoder::UiAccountEncoding::Base64),
..RpcAccountInfoConfig::default()
},
..RpcProgramAccountsConfig::default()
};
if let Some(vote_account_pubkeys) = vote_account_pubkeys {
@@ -1708,7 +1734,7 @@ pub fn process_show_stakes(
}
}
let all_stake_accounts = rpc_client
.get_program_accounts_with_config(&stake::program::id(), program_accounts_config)?;
.get_program_accounts_with_config(&solana_stake_program::id(), program_accounts_config)?;
let stake_history_account = rpc_client.get_account(&stake_history::id())?;
let clock_account = rpc_client.get_account(&sysvar::clock::id())?;
let clock: Clock = from_account(&clock_account).ok_or_else(|| {
@@ -1915,7 +1941,7 @@ pub fn process_transaction_history(
limit: usize,
show_transactions: bool,
) -> ProcessResult {
let results = rpc_client.get_signatures_for_address_with_config(
let results = rpc_client.get_confirmed_signatures_for_address2_with_config(
address,
GetConfirmedSignaturesForAddress2Config {
before,
@@ -1954,9 +1980,9 @@ pub fn process_transaction_history(
if show_transactions {
if let Ok(signature) = result.signature.parse::<Signature>() {
match rpc_client.get_transaction_with_config(
match rpc_client.get_confirmed_transaction_with_config(
&signature,
RpcTransactionConfig {
RpcConfirmedTransactionConfig {
encoding: Some(UiTransactionEncoding::Base64),
commitment: Some(CommitmentConfig::confirmed()),
},
@@ -2099,7 +2125,10 @@ mod tests {
let default_keypair = Keypair::new();
let (default_keypair_file, mut tmp_file) = make_tmp_file();
write_keypair(&default_keypair, tmp_file.as_file_mut()).unwrap();
let default_signer = DefaultSigner::new("", &default_keypair_file);
let default_signer = DefaultSigner {
path: default_keypair_file,
arg_name: String::new(),
};
let test_cluster_version = test_commands
.clone()

View File

@@ -10,6 +10,7 @@ macro_rules! ACCOUNT_STRING {
};
}
#[macro_use]
macro_rules! pubkey {
($arg:expr, $help:expr) => {
$arg.takes_value(true)

View File

@@ -179,7 +179,10 @@ pub fn parse_args<'a>(
&config.keypair_path,
);
let default_signer = DefaultSigner::new(default_signer_arg_name, &default_signer_path);
let default_signer = DefaultSigner {
arg_name: default_signer_arg_name,
path: default_signer_path.clone(),
};
let CliCommandInfo {
command,

View File

@@ -596,7 +596,10 @@ mod tests {
let default_keypair = Keypair::new();
let (default_keypair_file, mut tmp_file) = make_tmp_file();
write_keypair(&default_keypair, tmp_file.as_file_mut()).unwrap();
let default_signer = DefaultSigner::new("", &default_keypair_file);
let default_signer = DefaultSigner {
path: default_keypair_file.clone(),
arg_name: String::new(),
};
let (keypair_file, mut tmp_file) = make_tmp_file();
let nonce_account_keypair = Keypair::new();
write_keypair(&nonce_account_keypair, tmp_file.as_file_mut()).unwrap();

View File

@@ -150,7 +150,7 @@ impl ProgramSubCommands for App<'_, '_> {
pubkey!(Arg::with_name("program_id")
.long("program-id")
.value_name("PROGRAM_ID"),
"Executable program's address, must be a keypair for initial deploys, can be a pubkey for upgrades \
"Executable program's address, must be a signer for initial deploys, can be a pubkey for upgrades \
[default: address of keypair at /path/to/program-keypair.json if present, otherwise a random address]"),
)
.arg(
@@ -886,11 +886,6 @@ fn process_program_deploy(
)?;
let result = if do_deploy {
if program_signer.is_none() {
return Err(
"Initial deployments require a keypair be provided for the program id".into(),
);
}
do_process_program_write_and_deploy(
rpc_client.clone(),
config,
@@ -1107,7 +1102,6 @@ fn get_buffers(
data_slice: Some(UiDataSliceConfig { offset: 0, length }),
..RpcAccountInfoConfig::default()
},
..RpcProgramAccountsConfig::default()
},
)?;
Ok(results)
@@ -1412,7 +1406,6 @@ fn process_close(
data_slice: Some(UiDataSliceConfig { offset: 0, length }),
..RpcAccountInfoConfig::default()
},
..RpcProgramAccountsConfig::default()
},
)?;
@@ -2136,7 +2129,10 @@ mod tests {
let default_keypair = Keypair::new();
let keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &keypair_file).unwrap();
let default_signer = DefaultSigner::new("", &keypair_file);
let default_signer = DefaultSigner {
path: keypair_file.clone(),
arg_name: "".to_string(),
};
let test_command = test_commands.clone().get_matches_from(vec![
"test",
@@ -2344,7 +2340,10 @@ mod tests {
let default_keypair = Keypair::new();
let keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &keypair_file).unwrap();
let default_signer = DefaultSigner::new("", &keypair_file);
let default_signer = DefaultSigner {
path: keypair_file.clone(),
arg_name: "".to_string(),
};
// defaults
let test_command = test_commands.clone().get_matches_from(vec![
@@ -2492,7 +2491,10 @@ mod tests {
let default_keypair = Keypair::new();
let keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &keypair_file).unwrap();
let default_signer = DefaultSigner::new("", &keypair_file);
let default_signer = DefaultSigner {
path: keypair_file.clone(),
arg_name: "".to_string(),
};
let program_pubkey = Pubkey::new_unique();
let new_authority_pubkey = Pubkey::new_unique();
@@ -2600,7 +2602,10 @@ mod tests {
let default_keypair = Keypair::new();
let keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &keypair_file).unwrap();
let default_signer = DefaultSigner::new("", &keypair_file);
let default_signer = DefaultSigner {
path: keypair_file.clone(),
arg_name: "".to_string(),
};
let buffer_pubkey = Pubkey::new_unique();
let new_authority_pubkey = Pubkey::new_unique();
@@ -2657,7 +2662,10 @@ mod tests {
let default_keypair = Keypair::new();
let keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &keypair_file).unwrap();
let default_signer = DefaultSigner::new("", &keypair_file);
let default_signer = DefaultSigner {
path: keypair_file,
arg_name: "".to_string(),
};
// defaults
let buffer_pubkey = Pubkey::new_unique();
@@ -2756,7 +2764,10 @@ mod tests {
let default_keypair = Keypair::new();
let keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &keypair_file).unwrap();
let default_signer = DefaultSigner::new("", &keypair_file);
let default_signer = DefaultSigner {
path: keypair_file.clone(),
arg_name: "".to_string(),
};
// defaults
let buffer_pubkey = Pubkey::new_unique();

View File

@@ -36,11 +36,6 @@ use solana_sdk::{
feature, feature_set,
message::Message,
pubkey::Pubkey,
stake::{
self,
instruction::{self as stake_instruction, LockupArgs, StakeError},
state::{Authorized, Lockup, Meta, StakeAuthorize, StakeState},
},
system_instruction::SystemError,
sysvar::{
clock,
@@ -48,6 +43,10 @@ use solana_sdk::{
},
transaction::Transaction,
};
use solana_stake_program::{
stake_instruction::{self, LockupArgs, StakeError},
stake_state::{Authorized, Lockup, Meta, StakeAuthorize, StakeState},
};
use solana_vote_program::vote_state::VoteState;
use std::{ops::Deref, sync::Arc};
@@ -239,12 +238,6 @@ impl StakeSubCommands for App<'_, '_> {
.nonce_args(false)
.arg(fee_payer_arg())
.arg(custodian_arg())
.arg(
Arg::with_name("no_wait")
.long("no-wait")
.takes_value(false)
.help("Return signature immediately after submitting the transaction, instead of waiting for confirmations"),
)
)
.subcommand(
SubCommand::with_name("deactivate-stake")
@@ -634,7 +627,6 @@ pub fn parse_stake_authorize(
signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?;
let (fee_payer, fee_payer_pubkey) = signer_of(matches, FEE_PAYER_ARG.name, wallet_manager)?;
let (custodian, custodian_pubkey) = signer_of(matches, "custodian", wallet_manager)?;
let no_wait = matches.is_present("no_wait");
bulk_signers.push(fee_payer);
if nonce_account.is_some() {
@@ -671,7 +663,6 @@ pub fn parse_stake_authorize(
memo,
fee_payer: signer_info.index_of(fee_payer_pubkey).unwrap(),
custodian: custodian_pubkey.and_then(|_| signer_info.index_of(custodian_pubkey)),
no_wait,
},
signers: signer_info.signers,
})
@@ -972,7 +963,7 @@ pub fn process_create_stake_account(
) -> ProcessResult {
let stake_account = config.signers[stake_account];
let stake_account_address = if let Some(seed) = seed {
Pubkey::create_with_seed(&stake_account.pubkey(), &seed, &stake::program::id())?
Pubkey::create_with_seed(&stake_account.pubkey(), &seed, &solana_stake_program::id())?
} else {
stake_account.pubkey()
};
@@ -1040,7 +1031,7 @@ pub fn process_create_stake_account(
if !sign_only {
if let Ok(stake_account) = rpc_client.get_account(&stake_account_address) {
let err_msg = if stake_account.owner == stake::program::id() {
let err_msg = if stake_account.owner == solana_stake_program::id() {
format!("Stake account {} already exists", stake_account_address)
} else {
format!(
@@ -1103,7 +1094,6 @@ pub fn process_stake_authorize(
nonce_authority: SignerIndex,
memo: Option<&String>,
fee_payer: SignerIndex,
no_wait: bool,
) -> ProcessResult {
let mut ixs = Vec::new();
let custodian = custodian.map(|index| config.signers[index]);
@@ -1167,11 +1157,7 @@ pub fn process_stake_authorize(
&tx.message,
config.commitment,
)?;
let result = if no_wait {
rpc_client.send_transaction(&tx)
} else {
rpc_client.send_and_confirm_transaction_with_spinner(&tx)
};
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<StakeError>(result, &config)
}
}
@@ -1196,7 +1182,7 @@ pub fn process_deactivate_stake_account(
let stake_authority = config.signers[stake_authority];
let stake_account_address = if let Some(seed) = seed {
Pubkey::create_with_seed(&stake_account_pubkey, seed, &stake::program::id())?
Pubkey::create_with_seed(&stake_account_pubkey, seed, &solana_stake_program::id())?
} else {
*stake_account_pubkey
};
@@ -1274,7 +1260,7 @@ pub fn process_withdraw_stake(
let custodian = custodian.map(|index| config.signers[index]);
let stake_account_address = if let Some(seed) = seed {
Pubkey::create_with_seed(&stake_account_pubkey, seed, &stake::program::id())?
Pubkey::create_with_seed(&stake_account_pubkey, seed, &solana_stake_program::id())?
} else {
*stake_account_pubkey
};
@@ -1395,14 +1381,18 @@ pub fn process_split_stake(
let stake_authority = config.signers[stake_authority];
let split_stake_account_address = if let Some(seed) = split_stake_account_seed {
Pubkey::create_with_seed(&split_stake_account.pubkey(), &seed, &stake::program::id())?
Pubkey::create_with_seed(
&split_stake_account.pubkey(),
&seed,
&solana_stake_program::id(),
)?
} else {
split_stake_account.pubkey()
};
if !sign_only {
if let Ok(stake_account) = rpc_client.get_account(&split_stake_account_address) {
let err_msg = if stake_account.owner == stake::program::id() {
let err_msg = if stake_account.owner == solana_stake_program::id() {
format!(
"Stake account {} already exists",
split_stake_account_address
@@ -1537,7 +1527,7 @@ pub fn process_merge_stake(
if !sign_only {
for stake_account_address in &[stake_account_pubkey, source_stake_account_pubkey] {
if let Ok(stake_account) = rpc_client.get_account(stake_account_address) {
if stake_account.owner != stake::program::id() {
if stake_account.owner != solana_stake_program::id() {
return Err(CliError::BadParameter(format!(
"Account {} is not a stake account",
stake_account_address
@@ -1873,7 +1863,7 @@ pub fn process_show_stake_account(
with_rewards: Option<usize>,
) -> ProcessResult {
let stake_account = rpc_client.get_account(stake_account_address)?;
if stake_account.owner != stake::program::id() {
if stake_account.owner != solana_stake_program::id() {
return Err(CliError::RpcRequestError(format!(
"{:?} is not a stake account",
stake_account_address,
@@ -2114,7 +2104,10 @@ mod tests {
let default_keypair = Keypair::new();
let (default_keypair_file, mut tmp_file) = make_tmp_file();
write_keypair(&default_keypair, tmp_file.as_file_mut()).unwrap();
let default_signer = DefaultSigner::new("", &default_keypair_file);
let default_signer = DefaultSigner {
path: default_keypair_file.clone(),
arg_name: String::new(),
};
let (keypair_file, mut tmp_file) = make_tmp_file();
let stake_account_keypair = Keypair::new();
write_keypair(&stake_account_keypair, tmp_file.as_file_mut()).unwrap();
@@ -2158,7 +2151,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into(),],
},
@@ -2196,7 +2188,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),
@@ -2238,7 +2229,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),
@@ -2269,7 +2259,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into(),],
},
@@ -2297,7 +2286,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),
@@ -2331,7 +2319,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),
@@ -2366,7 +2353,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into(),],
},
@@ -2398,7 +2384,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),
@@ -2409,35 +2394,6 @@ mod tests {
},
);
// Test Authorize Subcommand w/ no-wait
let test_authorize = test_commands.clone().get_matches_from(vec![
"test",
"stake-authorize",
&stake_account_string,
"--new-stake-authority",
&stake_account_string,
"--no-wait",
]);
assert_eq!(
parse_command(&test_authorize, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::StakeAuthorize {
stake_account_pubkey,
new_authorizations: vec![(StakeAuthorize::Staker, stake_account_pubkey, 0)],
sign_only: false,
dump_transaction_message: false,
blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster),
nonce_account: None,
nonce_authority: 0,
memo: None,
fee_payer: 0,
custodian: None,
no_wait: true,
},
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()],
}
);
// Test Authorize Subcommand w/ sign-only
let blockhash = Hash::default();
let blockhash_string = format!("{}", blockhash);
@@ -2465,7 +2421,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()],
}
@@ -2505,7 +2460,6 @@ mod tests {
memo: None,
fee_payer: 1,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),
@@ -2555,7 +2509,6 @@ mod tests {
memo: None,
fee_payer: 1,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),
@@ -2591,7 +2544,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()],
}
@@ -2632,7 +2584,6 @@ mod tests {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),
@@ -2669,7 +2620,6 @@ mod tests {
memo: None,
fee_payer: 1,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),
@@ -2710,7 +2660,6 @@ mod tests {
memo: None,
fee_payer: 1,
custodian: None,
no_wait: false,
},
signers: vec![
read_keypair_file(&default_keypair_file).unwrap().into(),

View File

@@ -826,7 +826,10 @@ mod tests {
let default_keypair = Keypair::new();
let (default_keypair_file, mut tmp_file) = make_tmp_file();
write_keypair(&default_keypair, tmp_file.as_file_mut()).unwrap();
let default_signer = DefaultSigner::new("", &default_keypair_file);
let default_signer = DefaultSigner {
path: default_keypair_file.clone(),
arg_name: String::new(),
};
let test_authorize_voter = test_commands.clone().get_matches_from(vec![
"test",

View File

@@ -72,7 +72,7 @@ fn test_cli_program_deploy_non_upgradeable() {
let account0 = rpc_client.get_account(&program_id).unwrap();
assert_eq!(account0.lamports, minimum_balance_for_rent_exemption);
assert_eq!(account0.owner, bpf_loader::id());
assert!(account0.executable);
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();
@@ -93,7 +93,7 @@ fn test_cli_program_deploy_non_upgradeable() {
.unwrap();
assert_eq!(account1.lamports, minimum_balance_for_rent_exemption);
assert_eq!(account1.owner, bpf_loader::id());
assert!(account1.executable);
assert_eq!(account1.executable, true);
assert_eq!(account1.data, account0.data);
// Attempt to redeploy to the same address
@@ -129,7 +129,7 @@ fn test_cli_program_deploy_non_upgradeable() {
.unwrap();
assert_eq!(account2.lamports, 2 * minimum_balance_for_rent_exemption);
assert_eq!(account2.owner, bpf_loader::id());
assert!(account2.executable);
assert_eq!(account2.executable, true);
assert_eq!(account2.data, account0.data);
}
@@ -289,7 +289,7 @@ fn test_cli_program_deploy_with_authority() {
let program_account = rpc_client.get_account(&program_keypair.pubkey()).unwrap();
assert_eq!(program_account.lamports, minimum_balance_for_program);
assert_eq!(program_account.owner, bpf_loader_upgradeable::id());
assert!(program_account.executable);
assert_eq!(program_account.executable, true);
let (programdata_pubkey, _) = Pubkey::find_program_address(
&[program_keypair.pubkey().as_ref()],
&bpf_loader_upgradeable::id(),
@@ -300,7 +300,7 @@ fn test_cli_program_deploy_with_authority() {
minimum_balance_for_programdata
);
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
assert!(!programdata_account.executable);
assert_eq!(programdata_account.executable, false);
assert_eq!(
programdata_account.data[UpgradeableLoaderState::programdata_data_offset().unwrap()..],
program_data[..]
@@ -332,7 +332,7 @@ fn test_cli_program_deploy_with_authority() {
let program_account = rpc_client.get_account(&program_pubkey).unwrap();
assert_eq!(program_account.lamports, minimum_balance_for_program);
assert_eq!(program_account.owner, bpf_loader_upgradeable::id());
assert!(program_account.executable);
assert_eq!(program_account.executable, true);
let (programdata_pubkey, _) =
Pubkey::find_program_address(&[program_pubkey.as_ref()], &bpf_loader_upgradeable::id());
let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
@@ -341,7 +341,7 @@ fn test_cli_program_deploy_with_authority() {
minimum_balance_for_programdata
);
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
assert!(!programdata_account.executable);
assert_eq!(programdata_account.executable, false);
assert_eq!(
programdata_account.data[UpgradeableLoaderState::programdata_data_offset().unwrap()..],
program_data[..]
@@ -364,7 +364,7 @@ fn test_cli_program_deploy_with_authority() {
let program_account = rpc_client.get_account(&program_pubkey).unwrap();
assert_eq!(program_account.lamports, minimum_balance_for_program);
assert_eq!(program_account.owner, bpf_loader_upgradeable::id());
assert!(program_account.executable);
assert_eq!(program_account.executable, true);
let (programdata_pubkey, _) =
Pubkey::find_program_address(&[program_pubkey.as_ref()], &bpf_loader_upgradeable::id());
let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
@@ -373,7 +373,7 @@ fn test_cli_program_deploy_with_authority() {
minimum_balance_for_programdata
);
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
assert!(!programdata_account.executable);
assert_eq!(programdata_account.executable, false);
assert_eq!(
programdata_account.data[UpgradeableLoaderState::programdata_data_offset().unwrap()..],
program_data[..]
@@ -418,7 +418,7 @@ fn test_cli_program_deploy_with_authority() {
let program_account = rpc_client.get_account(&program_pubkey).unwrap();
assert_eq!(program_account.lamports, minimum_balance_for_program);
assert_eq!(program_account.owner, bpf_loader_upgradeable::id());
assert!(program_account.executable);
assert_eq!(program_account.executable, true);
let (programdata_pubkey, _) =
Pubkey::find_program_address(&[program_pubkey.as_ref()], &bpf_loader_upgradeable::id());
let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
@@ -427,7 +427,7 @@ fn test_cli_program_deploy_with_authority() {
minimum_balance_for_programdata
);
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
assert!(!programdata_account.executable);
assert_eq!(programdata_account.executable, false);
assert_eq!(
programdata_account.data[UpgradeableLoaderState::programdata_data_offset().unwrap()..],
program_data[..]

View File

@@ -17,11 +17,10 @@ use solana_sdk::{
nonce::State as NonceState,
pubkey::Pubkey,
signature::{keypair_from_seed, Keypair, Signer},
stake::{
self,
instruction::LockupArgs,
state::{Lockup, StakeAuthorize, StakeState},
},
};
use solana_stake_program::{
stake_instruction::LockupArgs,
stake_state::{Lockup, StakeAuthorize, StakeState},
};
#[test]
@@ -140,7 +139,7 @@ fn test_seed_stake_delegation_and_deactivation() {
let stake_address = Pubkey::create_with_seed(
&config_validator.signers[0].pubkey(),
"hi there",
&stake::program::id(),
&solana_stake_program::id(),
)
.expect("bad seed");
@@ -609,7 +608,6 @@ fn test_stake_authorize() {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
};
process_command(&config).unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
@@ -640,7 +638,6 @@ fn test_stake_authorize() {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
};
process_command(&config).unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
@@ -666,7 +663,6 @@ fn test_stake_authorize() {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
};
process_command(&config).unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
@@ -692,7 +688,6 @@ fn test_stake_authorize() {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
};
config_offline.output_format = OutputFormat::JsonCompact;
let sign_reply = process_command(&config_offline).unwrap();
@@ -711,7 +706,6 @@ fn test_stake_authorize() {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
};
process_command(&config).unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
@@ -762,7 +756,6 @@ fn test_stake_authorize() {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
};
let sign_reply = process_command(&config_offline).unwrap();
let sign_only = parse_sign_only_reply_string(&sign_reply);
@@ -785,7 +778,6 @@ fn test_stake_authorize() {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
};
process_command(&config).unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
@@ -889,7 +881,6 @@ fn test_stake_authorize_with_fee_payer() {
memo: None,
fee_payer: 1,
custodian: None,
no_wait: false,
};
process_command(&config).unwrap();
// `config` balance has not changed, despite submitting the TX
@@ -911,7 +902,6 @@ fn test_stake_authorize_with_fee_payer() {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
};
config_offline.output_format = OutputFormat::JsonCompact;
let sign_reply = process_command(&config_offline).unwrap();
@@ -930,7 +920,6 @@ fn test_stake_authorize_with_fee_payer() {
memo: None,
fee_payer: 0,
custodian: None,
no_wait: false,
};
process_command(&config).unwrap();
// `config`'s balance again has not changed
@@ -1134,7 +1123,7 @@ fn test_stake_set_lockup() {
stake_account: 1,
seed: None,
staker: Some(offline_pubkey),
withdrawer: Some(config.signers[0].pubkey()),
withdrawer: Some(offline_pubkey),
lockup,
amount: SpendAmount::Some(10 * minimum_stake_balance),
sign_only: false,
@@ -1558,6 +1547,6 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
};
process_command(&config).unwrap();
let seed_address =
Pubkey::create_with_seed(&stake_pubkey, seed, &stake::program::id()).unwrap();
Pubkey::create_with_seed(&stake_pubkey, seed, &solana_stake_program::id()).unwrap();
check_recent_balance(50_000, &rpc_client, &seed_address);
}

View File

@@ -16,7 +16,6 @@ use solana_sdk::{
nonce::State as NonceState,
pubkey::Pubkey,
signature::{keypair_from_seed, Keypair, NullSigner, Signer},
stake,
};
#[test]
@@ -514,7 +513,7 @@ fn test_transfer_with_seed() {
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 = stake::program::id();
let derived_address_program_id = solana_stake_program::id();
let derived_address = Pubkey::create_with_seed(
&sender_pubkey,
&derived_address_seed,

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-client"
version = "1.7.2"
version = "1.6.7"
description = "Solana Client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -24,14 +24,14 @@ semver = "0.11.0"
serde = "1.0.122"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "=1.7.2" }
solana-clap-utils = { path = "../clap-utils", version = "=1.7.2" }
solana-faucet = { path = "../faucet", version = "=1.7.2" }
solana-net-utils = { path = "../net-utils", version = "=1.7.2" }
solana-sdk = { path = "../sdk", version = "=1.7.2" }
solana-transaction-status = { path = "../transaction-status", version = "=1.7.2" }
solana-version = { path = "../version", version = "=1.7.2" }
solana-vote-program = { path = "../programs/vote", version = "=1.7.2" }
solana-account-decoder = { path = "../account-decoder", version = "=1.6.7" }
solana-clap-utils = { path = "../clap-utils", version = "=1.6.7" }
solana-faucet = { path = "../faucet", version = "=1.6.7" }
solana-net-utils = { path = "../net-utils", version = "=1.6.7" }
solana-sdk = { path = "../sdk", version = "=1.6.7" }
solana-transaction-status = { path = "../transaction-status", version = "=1.6.7" }
solana-version = { path = "../version", version = "=1.6.7" }
solana-vote-program = { path = "../programs/vote", version = "=1.6.7" }
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }
tungstenite = "0.10.1"
@@ -40,7 +40,7 @@ url = "2.1.1"
[dev-dependencies]
assert_matches = "1.3.0"
jsonrpc-http-server = "17.0.0"
solana-logger = { path = "../logger", version = "=1.7.2" }
solana-logger = { path = "../logger", version = "=1.6.7" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -361,7 +361,7 @@ mod tests {
let nonce_pubkey = Pubkey::new(&[4u8; 32]);
let rpc_nonce_account = UiAccount::encode(
&nonce_pubkey,
&nonce_account,
nonce_account,
UiAccountEncoding::Base64,
None,
None,

View File

@@ -7,11 +7,7 @@ use {
rpc_sender::RpcSender,
},
log::*,
reqwest::{
self,
header::{CONTENT_TYPE, RETRY_AFTER},
StatusCode,
},
reqwest::{self, header::CONTENT_TYPE, StatusCode},
std::{
sync::{
atomic::{AtomicU64, Ordering},
@@ -87,24 +83,14 @@ impl RpcSender for HttpSender {
if response.status() == StatusCode::TOO_MANY_REQUESTS
&& too_many_requests_retries > 0
{
let mut duration = Duration::from_millis(500);
if let Some(retry_after) = response.headers().get(RETRY_AFTER) {
if let Ok(retry_after) = retry_after.to_str() {
if let Ok(retry_after) = retry_after.parse::<u64>() {
if retry_after < 120 {
duration = Duration::from_secs(retry_after);
}
}
}
}
too_many_requests_retries -= 1;
debug!(
"Too many requests: server responded with {:?}, {} retries left, pausing for {:?}",
response, too_many_requests_retries, duration
"Server responded with {:?}, {} retries left",
response, too_many_requests_retries
);
sleep(duration);
// Sleep for 500ms to give the server a break
sleep(Duration::from_millis(500));
continue;
}
return Err(response.error_for_status().unwrap_err().into());

View File

@@ -13,7 +13,6 @@ pub mod rpc_cache;
pub mod rpc_client;
pub mod rpc_config;
pub mod rpc_custom_error;
pub mod rpc_deprecated_config;
pub mod rpc_filter;
pub mod rpc_request;
pub mod rpc_response;

View File

@@ -1,8 +1,3 @@
#[allow(deprecated)]
use crate::rpc_deprecated_config::{
RpcConfirmedBlockConfig, RpcConfirmedTransactionConfig,
RpcGetConfirmedSignaturesForAddress2Config,
};
use {
crate::{
client_error::{ClientError, ClientErrorKind, Result as ClientResult},
@@ -182,23 +177,6 @@ impl RpcClient {
Ok(requested_commitment)
}
#[allow(deprecated)]
fn maybe_map_request(&self, mut request: RpcRequest) -> Result<RpcRequest, RpcError> {
if self.get_node_version()? < semver::Version::new(1, 7, 0) {
request = match request {
RpcRequest::GetBlock => RpcRequest::GetConfirmedBlock,
RpcRequest::GetBlocks => RpcRequest::GetConfirmedBlocks,
RpcRequest::GetBlocksWithLimit => RpcRequest::GetConfirmedBlocksWithLimit,
RpcRequest::GetSignaturesForAddress => {
RpcRequest::GetConfirmedSignaturesForAddress2
}
RpcRequest::GetTransaction => RpcRequest::GetConfirmedTransaction,
_ => request,
};
}
Ok(request)
}
pub fn confirm_transaction(&self, signature: &Signature) -> ClientResult<bool> {
Ok(self
.confirm_transaction_with_commitment(signature, self.commitment_config)?
@@ -426,20 +404,6 @@ impl RpcClient {
)
}
pub fn get_block_height(&self) -> ClientResult<u64> {
self.get_block_height_with_commitment(self.commitment_config)
}
pub fn get_block_height_with_commitment(
&self,
commitment_config: CommitmentConfig,
) -> ClientResult<u64> {
self.send(
RpcRequest::GetBlockHeight,
json!([self.maybe_map_commitment(commitment_config)?]),
)
}
pub fn get_slot_leaders(&self, start_slot: Slot, limit: u64) -> ClientResult<Vec<Pubkey>> {
self.send(RpcRequest::GetSlotLeaders, json!([start_slot, limit]))
.and_then(|slot_leaders: Vec<String>| {
@@ -501,6 +465,27 @@ impl RpcClient {
)
}
#[deprecated(since = "1.5.19", note = "Please use RpcClient::supply() instead")]
#[allow(deprecated)]
pub fn total_supply(&self) -> ClientResult<u64> {
self.total_supply_with_commitment(self.commitment_config)
}
#[deprecated(
since = "1.5.19",
note = "Please use RpcClient::supply_with_commitment() instead"
)]
#[allow(deprecated)]
pub fn total_supply_with_commitment(
&self,
commitment_config: CommitmentConfig,
) -> ClientResult<u64> {
self.send(
RpcRequest::GetTotalSupply,
json!([self.maybe_map_commitment(commitment_config)?]),
)
}
pub fn get_largest_accounts_with_config(
&self,
config: RpcLargestAccountsConfig,
@@ -571,43 +556,10 @@ impl RpcClient {
self.send(RpcRequest::GetClusterNodes, Value::Null)
}
pub fn get_block(&self, slot: Slot) -> ClientResult<EncodedConfirmedBlock> {
self.get_block_with_encoding(slot, UiTransactionEncoding::Json)
}
pub fn get_block_with_encoding(
&self,
slot: Slot,
encoding: UiTransactionEncoding,
) -> ClientResult<EncodedConfirmedBlock> {
self.send(
self.maybe_map_request(RpcRequest::GetBlock)?,
json!([slot, encoding]),
)
}
pub fn get_block_with_config(
&self,
slot: Slot,
config: RpcBlockConfig,
) -> ClientResult<UiConfirmedBlock> {
self.send(
self.maybe_map_request(RpcRequest::GetBlock)?,
json!([slot, config]),
)
}
#[deprecated(since = "1.7.0", note = "Please use RpcClient::get_block() instead")]
#[allow(deprecated)]
pub fn get_confirmed_block(&self, slot: Slot) -> ClientResult<EncodedConfirmedBlock> {
self.get_confirmed_block_with_encoding(slot, UiTransactionEncoding::Json)
}
#[deprecated(
since = "1.7.0",
note = "Please use RpcClient::get_block_with_encoding() instead"
)]
#[allow(deprecated)]
pub fn get_confirmed_block_with_encoding(
&self,
slot: Slot,
@@ -616,11 +568,6 @@ impl RpcClient {
self.send(RpcRequest::GetConfirmedBlock, json!([slot, encoding]))
}
#[deprecated(
since = "1.7.0",
note = "Please use RpcClient::get_block_with_config() instead"
)]
#[allow(deprecated)]
pub fn get_confirmed_block_with_config(
&self,
slot: Slot,
@@ -629,56 +576,6 @@ impl RpcClient {
self.send(RpcRequest::GetConfirmedBlock, json!([slot, config]))
}
pub fn get_blocks(&self, start_slot: Slot, end_slot: Option<Slot>) -> ClientResult<Vec<Slot>> {
self.send(
self.maybe_map_request(RpcRequest::GetBlocks)?,
json!([start_slot, end_slot]),
)
}
pub fn get_blocks_with_commitment(
&self,
start_slot: Slot,
end_slot: Option<Slot>,
commitment_config: CommitmentConfig,
) -> ClientResult<Vec<Slot>> {
let json = if end_slot.is_some() {
json!([
start_slot,
end_slot,
self.maybe_map_commitment(commitment_config)?
])
} else {
json!([start_slot, self.maybe_map_commitment(commitment_config)?])
};
self.send(self.maybe_map_request(RpcRequest::GetBlocks)?, json)
}
pub fn get_blocks_with_limit(&self, start_slot: Slot, limit: usize) -> ClientResult<Vec<Slot>> {
self.send(
self.maybe_map_request(RpcRequest::GetBlocksWithLimit)?,
json!([start_slot, limit]),
)
}
pub fn get_blocks_with_limit_and_commitment(
&self,
start_slot: Slot,
limit: usize,
commitment_config: CommitmentConfig,
) -> ClientResult<Vec<Slot>> {
self.send(
self.maybe_map_request(RpcRequest::GetBlocksWithLimit)?,
json!([
start_slot,
limit,
self.maybe_map_commitment(commitment_config)?
]),
)
}
#[deprecated(since = "1.7.0", note = "Please use RpcClient::get_blocks() instead")]
#[allow(deprecated)]
pub fn get_confirmed_blocks(
&self,
start_slot: Slot,
@@ -690,11 +587,6 @@ impl RpcClient {
)
}
#[deprecated(
since = "1.7.0",
note = "Please use RpcClient::get_blocks_with_commitment() instead"
)]
#[allow(deprecated)]
pub fn get_confirmed_blocks_with_commitment(
&self,
start_slot: Slot,
@@ -713,11 +605,6 @@ impl RpcClient {
self.send(RpcRequest::GetConfirmedBlocks, json)
}
#[deprecated(
since = "1.7.0",
note = "Please use RpcClient::get_blocks_with_limit() instead"
)]
#[allow(deprecated)]
pub fn get_confirmed_blocks_with_limit(
&self,
start_slot: Slot,
@@ -729,11 +616,6 @@ impl RpcClient {
)
}
#[deprecated(
since = "1.7.0",
note = "Please use RpcClient::get_blocks_with_limit_and_commitment() instead"
)]
#[allow(deprecated)]
pub fn get_confirmed_blocks_with_limit_and_commitment(
&self,
start_slot: Slot,
@@ -750,41 +632,33 @@ impl RpcClient {
)
}
pub fn get_signatures_for_address(
&self,
address: &Pubkey,
) -> ClientResult<Vec<RpcConfirmedTransactionStatusWithSignature>> {
self.get_signatures_for_address_with_config(
address,
GetConfirmedSignaturesForAddress2Config::default(),
)
}
pub fn get_signatures_for_address_with_config(
&self,
address: &Pubkey,
config: GetConfirmedSignaturesForAddress2Config,
) -> ClientResult<Vec<RpcConfirmedTransactionStatusWithSignature>> {
let config = RpcSignaturesForAddressConfig {
before: config.before.map(|signature| signature.to_string()),
until: config.until.map(|signature| signature.to_string()),
limit: config.limit,
commitment: config.commitment,
};
let result: Vec<RpcConfirmedTransactionStatusWithSignature> = self.send(
self.maybe_map_request(RpcRequest::GetSignaturesForAddress)?,
json!([address.to_string(), config]),
)?;
Ok(result)
}
#[deprecated(
since = "1.7.0",
note = "Please use RpcClient::get_signatures_for_address() instead"
since = "1.5.19",
note = "Please use RpcClient::get_confirmed_signatures_for_address2() instead"
)]
#[allow(deprecated)]
pub fn get_confirmed_signatures_for_address(
&self,
address: &Pubkey,
start_slot: Slot,
end_slot: Slot,
) -> ClientResult<Vec<Signature>> {
let signatures_base58_str: Vec<String> = self.send(
RpcRequest::GetConfirmedSignaturesForAddress,
json!([address.to_string(), start_slot, end_slot]),
)?;
let mut signatures = vec![];
for signature_base58_str in signatures_base58_str {
signatures.push(
signature_base58_str.parse::<Signature>().map_err(|err| {
Into::<ClientError>::into(RpcError::ParseError(err.to_string()))
})?,
);
}
Ok(signatures)
}
pub fn get_confirmed_signatures_for_address2(
&self,
address: &Pubkey,
@@ -795,11 +669,6 @@ impl RpcClient {
)
}
#[deprecated(
since = "1.7.0",
note = "Please use RpcClient::get_signatures_for_address_with_config() instead"
)]
#[allow(deprecated)]
pub fn get_confirmed_signatures_for_address2_with_config(
&self,
address: &Pubkey,
@@ -820,33 +689,6 @@ impl RpcClient {
Ok(result)
}
pub fn get_transaction(
&self,
signature: &Signature,
encoding: UiTransactionEncoding,
) -> ClientResult<EncodedConfirmedTransaction> {
self.send(
self.maybe_map_request(RpcRequest::GetTransaction)?,
json!([signature.to_string(), encoding]),
)
}
pub fn get_transaction_with_config(
&self,
signature: &Signature,
config: RpcTransactionConfig,
) -> ClientResult<EncodedConfirmedTransaction> {
self.send(
self.maybe_map_request(RpcRequest::GetTransaction)?,
json!([signature.to_string(), config]),
)
}
#[deprecated(
since = "1.7.0",
note = "Please use RpcClient::get_transaction() instead"
)]
#[allow(deprecated)]
pub fn get_confirmed_transaction(
&self,
signature: &Signature,
@@ -858,11 +700,6 @@ impl RpcClient {
)
}
#[deprecated(
since = "1.7.0",
note = "Please use RpcClient::get_transaction_with_config() instead"
)]
#[allow(deprecated)]
pub fn get_confirmed_transaction_with_config(
&self,
signature: &Signature,
@@ -1056,7 +893,7 @@ impl RpcClient {
commitment_config: CommitmentConfig,
) -> RpcResult<Option<Account>> {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64Zstd),
encoding: Some(UiAccountEncoding::Base64),
commitment: Some(self.maybe_map_commitment(commitment_config)?),
data_slice: None,
};
@@ -1111,7 +948,7 @@ impl RpcClient {
commitment_config: CommitmentConfig,
) -> RpcResult<Vec<Option<Account>>> {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64Zstd),
encoding: Some(UiAccountEncoding::Base64),
commitment: Some(self.maybe_map_commitment(commitment_config)?),
data_slice: None,
};
@@ -1177,11 +1014,12 @@ impl RpcClient {
self.get_program_accounts_with_config(
pubkey,
RpcProgramAccountsConfig {
filters: None,
account_config: RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64Zstd),
encoding: Some(UiAccountEncoding::Base64),
commitment: Some(self.commitment_config),
..RpcAccountInfoConfig::default()
},
..RpcProgramAccountsConfig::default()
},
)
}
@@ -1191,10 +1029,7 @@ impl RpcClient {
pubkey: &Pubkey,
config: RpcProgramAccountsConfig,
) -> ClientResult<Vec<(Pubkey, Account)>> {
let commitment = config
.account_config
.commitment
.unwrap_or_else(|| self.commitment());
let commitment = config.account_config.commitment.unwrap_or_default();
let commitment = self.maybe_map_commitment(commitment)?;
let account_config = RpcAccountInfoConfig {
commitment: Some(commitment),
@@ -1244,7 +1079,6 @@ impl RpcClient {
blockhash,
fee_calculator,
last_valid_slot,
..
},
}) = self
.send::<Response<RpcFees>>(
@@ -1252,19 +1086,6 @@ impl RpcClient {
json!([self.maybe_map_commitment(commitment_config)?]),
) {
(context, blockhash, fee_calculator, last_valid_slot)
} else if let Ok(Response {
context,
value:
DeprecatedRpcFees {
blockhash,
fee_calculator,
last_valid_slot,
},
}) = self.send::<Response<DeprecatedRpcFees>>(
RpcRequest::GetFees,
json!([self.maybe_map_commitment(commitment_config)?]),
) {
(context, blockhash, fee_calculator, last_valid_slot)
} else if let Ok(Response {
context,
value:
@@ -2062,7 +1883,7 @@ mod tests {
// Send erroneous parameter
let blockhash: ClientResult<String> =
rpc_client.send(RpcRequest::GetRecentBlockhash, json!(["parameter"]));
assert!(blockhash.is_err());
assert_eq!(blockhash.is_err(), true);
}
#[test]

View File

@@ -23,24 +23,14 @@ pub struct RpcSendTransactionConfig {
pub encoding: Option<UiTransactionEncoding>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcSimulateTransactionAccountsConfig {
pub encoding: Option<UiAccountEncoding>,
pub addresses: Vec<String>,
}
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcSimulateTransactionConfig {
#[serde(default)]
pub sig_verify: bool,
#[serde(default)]
pub replace_recent_blockhash: bool,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
pub encoding: Option<UiTransactionEncoding>,
pub accounts: Option<RpcSimulateTransactionAccountsConfig>,
}
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
@@ -137,7 +127,6 @@ pub struct RpcProgramAccountsConfig {
pub filters: Option<Vec<RpcFilterType>>,
#[serde(flatten)]
pub account_config: RpcAccountInfoConfig,
pub with_context: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@@ -172,7 +161,7 @@ pub struct RpcSignatureSubscribeConfig {
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcSignaturesForAddressConfig {
pub struct RpcGetConfirmedSignaturesForAddress2Config {
pub before: Option<String>, // Signature as base-58 string
pub until: Option<String>, // Signature as base-58 string
pub limit: Option<usize>,
@@ -194,17 +183,6 @@ impl<T: EncodingConfig + Default + Copy> RpcEncodingConfigWrapper<T> {
RpcEncodingConfigWrapper::Current(config) => config.unwrap_or_default(),
}
}
pub fn convert<U: EncodingConfig + From<T>>(&self) -> RpcEncodingConfigWrapper<U> {
match self {
RpcEncodingConfigWrapper::Deprecated(encoding) => {
RpcEncodingConfigWrapper::Deprecated(*encoding)
}
RpcEncodingConfigWrapper::Current(config) => {
RpcEncodingConfigWrapper::Current(config.map(|config| config.into()))
}
}
}
}
pub trait EncodingConfig {
@@ -213,7 +191,7 @@ pub trait EncodingConfig {
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcBlockConfig {
pub struct RpcConfirmedBlockConfig {
pub encoding: Option<UiTransactionEncoding>,
pub transaction_details: Option<TransactionDetails>,
pub rewards: Option<bool>,
@@ -221,7 +199,7 @@ pub struct RpcBlockConfig {
pub commitment: Option<CommitmentConfig>,
}
impl EncodingConfig for RpcBlockConfig {
impl EncodingConfig for RpcConfirmedBlockConfig {
fn new_with_encoding(encoding: &Option<UiTransactionEncoding>) -> Self {
Self {
encoding: *encoding,
@@ -230,7 +208,7 @@ impl EncodingConfig for RpcBlockConfig {
}
}
impl RpcBlockConfig {
impl RpcConfirmedBlockConfig {
pub fn rewards_only() -> Self {
Self {
transaction_details: Some(TransactionDetails::None),
@@ -247,21 +225,21 @@ impl RpcBlockConfig {
}
}
impl From<RpcBlockConfig> for RpcEncodingConfigWrapper<RpcBlockConfig> {
fn from(config: RpcBlockConfig) -> Self {
impl From<RpcConfirmedBlockConfig> for RpcEncodingConfigWrapper<RpcConfirmedBlockConfig> {
fn from(config: RpcConfirmedBlockConfig) -> Self {
RpcEncodingConfigWrapper::Current(Some(config))
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcTransactionConfig {
pub struct RpcConfirmedTransactionConfig {
pub encoding: Option<UiTransactionEncoding>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
}
impl EncodingConfig for RpcTransactionConfig {
impl EncodingConfig for RpcConfirmedTransactionConfig {
fn new_with_encoding(encoding: &Option<UiTransactionEncoding>) -> Self {
Self {
encoding: *encoding,
@@ -272,16 +250,16 @@ impl EncodingConfig for RpcTransactionConfig {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RpcBlocksConfigWrapper {
pub enum RpcConfirmedBlocksConfigWrapper {
EndSlotOnly(Option<Slot>),
CommitmentOnly(Option<CommitmentConfig>),
}
impl RpcBlocksConfigWrapper {
impl RpcConfirmedBlocksConfigWrapper {
pub fn unzip(&self) -> (Option<Slot>, Option<CommitmentConfig>) {
match &self {
RpcBlocksConfigWrapper::EndSlotOnly(end_slot) => (*end_slot, None),
RpcBlocksConfigWrapper::CommitmentOnly(commitment) => (None, *commitment),
RpcConfirmedBlocksConfigWrapper::EndSlotOnly(end_slot) => (*end_slot, None),
RpcConfirmedBlocksConfigWrapper::CommitmentOnly(commitment) => (None, *commitment),
}
}
}

View File

@@ -15,8 +15,6 @@ pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64
pub const JSON_RPC_SERVER_ERROR_SLOT_SKIPPED: i64 = -32007;
pub const JSON_RPC_SERVER_ERROR_NO_SNAPSHOT: i64 = -32008;
pub const JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED: i64 = -32009;
pub const JSON_RPC_SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX: i64 = -32010;
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_HISTORY_NOT_AVAILABLE: i64 = -32011;
pub enum RpcCustomError {
BlockCleanedUp {
@@ -42,10 +40,6 @@ pub enum RpcCustomError {
LongTermStorageSlotSkipped {
slot: Slot,
},
KeyExcludedFromSecondaryIndex {
index_key: String,
},
TransactionHistoryNotAvailable,
}
#[derive(Debug, Serialize, Deserialize)]
@@ -123,24 +117,6 @@ impl From<RpcCustomError> for Error {
message: format!("Slot {} was skipped, or missing in long-term storage", slot),
data: None,
},
RpcCustomError::KeyExcludedFromSecondaryIndex { index_key } => Self {
code: ErrorCode::ServerError(
JSON_RPC_SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX,
),
message: format!(
"{} excluded from account secondary indexes; \
this RPC method unavailable for key",
index_key
),
data: None,
},
RpcCustomError::TransactionHistoryNotAvailable => Self {
code: ErrorCode::ServerError(
JSON_RPC_SERVER_ERROR_TRANSACTION_HISTORY_NOT_AVAILABLE,
),
message: "Transaction history is not available from this node".to_string(),
data: None,
},
}
}
}

View File

@@ -1,120 +0,0 @@
#![allow(deprecated)]
use {
crate::rpc_config::{
EncodingConfig, RpcBlockConfig, RpcEncodingConfigWrapper, RpcTransactionConfig,
},
solana_sdk::{clock::Slot, commitment_config::CommitmentConfig},
solana_transaction_status::{TransactionDetails, UiTransactionEncoding},
};
#[deprecated(
since = "1.7.0",
note = "Please use RpcSignaturesForAddressConfig instead"
)]
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcGetConfirmedSignaturesForAddress2Config {
pub before: Option<String>, // Signature as base-58 string
pub until: Option<String>, // Signature as base-58 string
pub limit: Option<usize>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
}
#[deprecated(since = "1.7.0", note = "Please use RpcBlockConfig instead")]
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcConfirmedBlockConfig {
pub encoding: Option<UiTransactionEncoding>,
pub transaction_details: Option<TransactionDetails>,
pub rewards: Option<bool>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
}
impl EncodingConfig for RpcConfirmedBlockConfig {
fn new_with_encoding(encoding: &Option<UiTransactionEncoding>) -> Self {
Self {
encoding: *encoding,
..Self::default()
}
}
}
impl RpcConfirmedBlockConfig {
pub fn rewards_only() -> Self {
Self {
transaction_details: Some(TransactionDetails::None),
..Self::default()
}
}
pub fn rewards_with_commitment(commitment: Option<CommitmentConfig>) -> Self {
Self {
transaction_details: Some(TransactionDetails::None),
commitment,
..Self::default()
}
}
}
impl From<RpcConfirmedBlockConfig> for RpcEncodingConfigWrapper<RpcConfirmedBlockConfig> {
fn from(config: RpcConfirmedBlockConfig) -> Self {
RpcEncodingConfigWrapper::Current(Some(config))
}
}
impl From<RpcConfirmedBlockConfig> for RpcBlockConfig {
fn from(config: RpcConfirmedBlockConfig) -> Self {
Self {
encoding: config.encoding,
transaction_details: config.transaction_details,
rewards: config.rewards,
commitment: config.commitment,
}
}
}
#[deprecated(since = "1.7.0", note = "Please use RpcTransactionConfig instead")]
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcConfirmedTransactionConfig {
pub encoding: Option<UiTransactionEncoding>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
}
impl EncodingConfig for RpcConfirmedTransactionConfig {
fn new_with_encoding(encoding: &Option<UiTransactionEncoding>) -> Self {
Self {
encoding: *encoding,
..Self::default()
}
}
}
impl From<RpcConfirmedTransactionConfig> for RpcTransactionConfig {
fn from(config: RpcConfirmedTransactionConfig) -> Self {
Self {
encoding: config.encoding,
commitment: config.commitment,
}
}
}
#[deprecated(since = "1.7.0", note = "Please use RpcBlocksConfigWrapper instead")]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RpcConfirmedBlocksConfigWrapper {
EndSlotOnly(Option<Slot>),
CommitmentOnly(Option<CommitmentConfig>),
}
impl RpcConfirmedBlocksConfigWrapper {
pub fn unzip(&self) -> (Option<Slot>, Option<CommitmentConfig>) {
match &self {
RpcConfirmedBlocksConfigWrapper::EndSlotOnly(end_slot) => (*end_slot, None),
RpcConfirmedBlocksConfigWrapper::CommitmentOnly(commitment) => (None, *commitment),
}
}
}

View File

@@ -11,34 +11,21 @@ pub enum RpcRequest {
DeregisterNode,
GetAccountInfo,
GetBalance,
GetBlock,
GetBlockHeight,
GetBlockProduction,
GetBlocks,
GetBlocksWithLimit,
GetBlockTime,
GetClusterNodes,
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlock instead")]
GetConfirmedBlock,
#[deprecated(since = "1.7.0", note = "Please use RpcRequest::GetBlocks instead")]
GetConfirmedBlocks,
#[deprecated(
since = "1.7.0",
note = "Please use RpcRequest::GetBlocksWithLimit instead"
)]
GetConfirmedBlocksWithLimit,
#[deprecated(
since = "1.7.0",
note = "Please use RpcRequest::GetSignaturesForAddress instead"
)]
GetConfirmedSignaturesForAddress2,
#[deprecated(
since = "1.7.0",
note = "Please use RpcRequest::GetTransaction instead"
)]
GetConfirmedTransaction,
#[deprecated(
since = "1.5.19",
note = "Please use RpcRequest::GetConfirmedSignaturesForAddress2 instead"
)]
GetConfirmedSignaturesForAddress,
GetConfirmedSignaturesForAddress2,
GetConfirmedTransaction,
GetEpochInfo,
GetEpochSchedule,
GetFeeCalculatorForBlockhash,
@@ -61,7 +48,6 @@ pub enum RpcRequest {
GetRecentBlockhash,
GetRecentPerformanceSamples,
GetSnapshotSlot,
GetSignaturesForAddress,
GetSignatureStatuses,
GetSlot,
GetSlotLeader,
@@ -76,7 +62,10 @@ pub enum RpcRequest {
GetTokenAccountsByDelegate,
GetTokenAccountsByOwner,
GetTokenSupply,
GetTransaction,
#[deprecated(since = "1.5.19", note = "Please use RpcRequest::GetSupply instead")]
GetTotalSupply,
GetTransactionCount,
GetVersion,
GetVoteAccounts,
@@ -95,16 +84,13 @@ impl fmt::Display for RpcRequest {
RpcRequest::DeregisterNode => "deregisterNode",
RpcRequest::GetAccountInfo => "getAccountInfo",
RpcRequest::GetBalance => "getBalance",
RpcRequest::GetBlock => "getBlock",
RpcRequest::GetBlockHeight => "getBlockHeight",
RpcRequest::GetBlockProduction => "getBlockProduction",
RpcRequest::GetBlocks => "getBlocks",
RpcRequest::GetBlocksWithLimit => "getBlocksWithLimit",
RpcRequest::GetBlockTime => "getBlockTime",
RpcRequest::GetClusterNodes => "getClusterNodes",
RpcRequest::GetConfirmedBlock => "getConfirmedBlock",
RpcRequest::GetConfirmedBlocks => "getConfirmedBlocks",
RpcRequest::GetConfirmedBlocksWithLimit => "getConfirmedBlocksWithLimit",
RpcRequest::GetConfirmedSignaturesForAddress => "getConfirmedSignaturesForAddress",
RpcRequest::GetConfirmedSignaturesForAddress2 => "getConfirmedSignaturesForAddress2",
RpcRequest::GetConfirmedTransaction => "getConfirmedTransaction",
RpcRequest::GetEpochInfo => "getEpochInfo",
@@ -129,7 +115,6 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
RpcRequest::GetRecentPerformanceSamples => "getRecentPerformanceSamples",
RpcRequest::GetSnapshotSlot => "getSnapshotSlot",
RpcRequest::GetSignaturesForAddress => "getSignaturesForAddress",
RpcRequest::GetSignatureStatuses => "getSignatureStatuses",
RpcRequest::GetSlot => "getSlot",
RpcRequest::GetSlotLeader => "getSlotLeader",
@@ -144,7 +129,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetTokenAccountsByDelegate => "getTokenAccountsByDelegate",
RpcRequest::GetTokenAccountsByOwner => "getTokenAccountsByOwner",
RpcRequest::GetTokenSupply => "getTokenSupply",
RpcRequest::GetTransaction => "getTransaction",
RpcRequest::GetTotalSupply => "getTotalSupply",
RpcRequest::GetTransactionCount => "getTransactionCount",
RpcRequest::GetVersion => "getVersion",
RpcRequest::GetVoteAccounts => "getVoteAccounts",

View File

@@ -46,15 +46,6 @@ pub struct RpcFees {
pub blockhash: String,
pub fee_calculator: FeeCalculator,
pub last_valid_slot: Slot,
pub last_valid_block_height: u64,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct DeprecatedRpcFees {
pub blockhash: String,
pub fee_calculator: FeeCalculator,
pub last_valid_slot: Slot,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
@@ -215,8 +206,6 @@ pub struct RpcContactInfo {
pub version: Option<String>,
/// First 4 bytes of the FeatureSet identifier
pub feature_set: Option<u32>,
/// Shred version
pub shred_version: Option<u16>,
}
/// Map of leader base58 identity pubkeys to the slot indices relative to the first epoch slot
@@ -318,7 +307,6 @@ pub struct RpcSignatureConfirmation {
pub struct RpcSimulateTransactionResult {
pub err: Option<TransactionError>,
pub logs: Option<Vec<String>>,
pub accounts: Option<Vec<Option<UiAccount>>>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]

View File

@@ -1,7 +1,7 @@
[package]
name = "solana-core"
description = "Blockchain, Rebuilt for Scale"
version = "1.7.2"
version = "1.6.7"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-core"
readme = "../README.md"
@@ -22,12 +22,19 @@ bv = { version = "0.11.1", features = ["serde"] }
bs58 = "0.3.1"
byteorder = "1.3.4"
chrono = { version = "0.4.11", features = ["serde"] }
core_affinity = "0.5.10"
crossbeam-channel = "0.4"
ed25519-dalek = "=1.0.1"
fs_extra = "1.2.0"
flate2 = "1.0"
indexmap = { version = "1.5", features = ["rayon"] }
itertools = "0.9.0"
jsonrpc-core = "17.0.0"
jsonrpc-core-client = { version = "17.0.0", features = ["ipc", "ws"] }
jsonrpc-derive = "17.0.0"
jsonrpc-http-server = "17.0.0"
jsonrpc-pubsub = "17.0.0"
jsonrpc-ws-server = "17.0.0"
libc = "0.2.81"
log = "0.4.11"
lru = "0.6.1"
@@ -39,52 +46,52 @@ rand_chacha = "0.2.2"
rand_core = "0.6.2"
raptorq = "1.4.2"
rayon = "1.5.0"
regex = "1.3.9"
retain_mut = "0.1.2"
serde = "1.0.122"
serde_bytes = "0.11"
serde_derive = "1.0.103"
solana-account-decoder = { path = "../account-decoder", version = "=1.7.2" }
solana-banks-server = { path = "../banks-server", version = "=1.7.2" }
solana-clap-utils = { path = "../clap-utils", version = "=1.7.2" }
solana-client = { path = "../client", version = "=1.7.2" }
solana-gossip = { path = "../gossip", version = "=1.7.2" }
solana-ledger = { path = "../ledger", version = "=1.7.2" }
solana-logger = { path = "../logger", version = "=1.7.2" }
solana-merkle-tree = { path = "../merkle-tree", version = "=1.7.2" }
solana-metrics = { path = "../metrics", version = "=1.7.2" }
solana-measure = { path = "../measure", version = "=1.7.2" }
solana-net-utils = { path = "../net-utils", version = "=1.7.2" }
solana-perf = { path = "../perf", version = "=1.7.2" }
solana-poh = { path = "../poh", version = "=1.7.2" }
solana-program-test = { path = "../program-test", version = "=1.7.2" }
solana-rpc = { path = "../rpc", version = "=1.7.2" }
solana-runtime = { path = "../runtime", version = "=1.7.2" }
solana-sdk = { path = "../sdk", version = "=1.7.2" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.7.2" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.7.2" }
solana-streamer = { path = "../streamer", version = "=1.7.2" }
solana-transaction-status = { path = "../transaction-status", version = "=1.7.2" }
solana-version = { path = "../version", version = "=1.7.2" }
solana-vote-program = { path = "../programs/vote", version = "=1.7.2" }
spl-token-v2-0 = { package = "spl-token", version = "=3.1.1", features = ["no-entrypoint"] }
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "=1.6.7" }
solana-banks-server = { path = "../banks-server", version = "=1.6.7" }
solana-clap-utils = { path = "../clap-utils", version = "=1.6.7" }
solana-client = { path = "../client", version = "=1.6.7" }
solana-faucet = { path = "../faucet", version = "=1.6.7" }
solana-ledger = { path = "../ledger", version = "=1.6.7" }
solana-logger = { path = "../logger", version = "=1.6.7" }
solana-merkle-tree = { path = "../merkle-tree", version = "=1.6.7" }
solana-metrics = { path = "../metrics", version = "=1.6.7" }
solana-measure = { path = "../measure", version = "=1.6.7" }
solana-net-utils = { path = "../net-utils", version = "=1.6.7" }
solana-perf = { path = "../perf", version = "=1.6.7" }
solana-program-test = { path = "../program-test", version = "=1.6.7" }
solana-runtime = { path = "../runtime", version = "=1.6.7" }
solana-sdk = { path = "../sdk", version = "=1.6.7" }
solana-frozen-abi = { path = "../frozen-abi", version = "=1.6.7" }
solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.6.7" }
solana-stake-program = { path = "../programs/stake", version = "=1.6.7" }
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.6.7" }
solana-streamer = { path = "../streamer", version = "=1.6.7" }
solana-sys-tuner = { path = "../sys-tuner", version = "=1.6.7" }
solana-transaction-status = { path = "../transaction-status", version = "=1.6.7" }
solana-version = { path = "../version", version = "=1.6.7" }
solana-vote-program = { path = "../programs/vote", version = "=1.6.7" }
spl-token-v2-0 = { package = "spl-token", version = "=3.1.0", features = ["no-entrypoint"] }
tempfile = "3.1.0"
thiserror = "1.0"
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.7.2" }
tokio = { version = "1", features = ["full"] }
tokio_02 = { version = "0.2", package = "tokio", features = ["full"] }
tokio-util = { version = "0.3", features = ["codec"] } # This crate needs to stay in sync with tokio_02, until that dependency can be removed
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.6.7" }
trees = "0.2.1"
[dev-dependencies]
jsonrpc-core = "17.1.0"
jsonrpc-core-client = { version = "17.1.0", features = ["ipc", "ws"] }
matches = "0.1.6"
num_cpus = "1.13.0"
reqwest = { version = "0.11.2", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde_json = "1.0.56"
serial_test = "0.4.0"
solana-stake-program = { path = "../programs/stake", version = "=1.7.2" }
solana-version = { path = "../version", version = "=1.7.2" }
symlink = "0.1.0"
systemstat = "0.1.5"
tokio_02 = { version = "0.2", package = "tokio", features = ["full"] }
[build-dependencies]
rustc_version = "0.2"
@@ -96,7 +103,13 @@ name = "banking_stage"
name = "blockstore"
[[bench]]
name = "cluster_info"
name = "crds"
[[bench]]
name = "crds_gossip_pull"
[[bench]]
name = "crds_shards"
[[bench]]
name = "gen_keys"
@@ -104,8 +117,14 @@ name = "gen_keys"
[[bench]]
name = "sigverify_stage"
[[bench]]
name = "poh"
[[bench]]
name = "retransmit_stage"
[[bench]]
name = "cluster_info"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -7,16 +7,16 @@ use crossbeam_channel::unbounded;
use log::*;
use rand::{thread_rng, Rng};
use rayon::prelude::*;
use solana_core::banking_stage::{BankingStage, BankingStageStats};
use solana_gossip::cluster_info::ClusterInfo;
use solana_gossip::cluster_info::Node;
use solana_core::banking_stage::{create_test_recorder, BankingStage, BankingStageStats};
use solana_core::cluster_info::ClusterInfo;
use solana_core::cluster_info::Node;
use solana_core::poh_recorder::WorkingBankEntry;
use solana_ledger::blockstore_processor::process_entries;
use solana_ledger::entry::{next_hash, Entry};
use solana_ledger::genesis_utils::{create_genesis_config, GenesisConfigInfo};
use solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path};
use solana_perf::packet::to_packets_chunked;
use solana_perf::test_tx::test_tx;
use solana_poh::poh_recorder::{create_test_recorder, WorkingBankEntry};
use solana_runtime::bank::Bank;
use solana_sdk::genesis_config::GenesisConfig;
use solana_sdk::hash::Hash;

View File

@@ -5,8 +5,8 @@ extern crate test;
use rand::{thread_rng, Rng};
use solana_core::broadcast_stage::broadcast_metrics::TransmitShredsStats;
use solana_core::broadcast_stage::{broadcast_shreds, get_broadcast_peers};
use solana_gossip::cluster_info::{ClusterInfo, Node};
use solana_gossip::contact_info::ContactInfo;
use solana_core::cluster_info::{ClusterInfo, Node};
use solana_core::contact_info::ContactInfo;
use solana_ledger::shred::Shred;
use solana_sdk::pubkey;
use solana_sdk::timing::timestamp;

View File

@@ -2,16 +2,14 @@
extern crate test;
use {
rand::{thread_rng, Rng},
rayon::ThreadPoolBuilder,
solana_gossip::{
crds::Crds, crds_gossip_pull::CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS, crds_value::CrdsValue,
},
solana_sdk::pubkey::Pubkey,
std::collections::HashMap,
test::Bencher,
};
use rand::{thread_rng, Rng};
use rayon::ThreadPoolBuilder;
use solana_core::crds::Crds;
use solana_core::crds_gossip_pull::CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS;
use solana_core::crds_value::CrdsValue;
use solana_sdk::pubkey::Pubkey;
use std::collections::HashMap;
use test::Bencher;
#[bench]
fn bench_find_old_labels(bencher: &mut Bencher) {

View File

@@ -2,18 +2,14 @@
extern crate test;
use {
rand::{thread_rng, Rng},
rayon::ThreadPoolBuilder,
solana_gossip::{
cluster_info::MAX_BLOOM_SIZE,
crds::Crds,
crds_gossip_pull::{CrdsFilter, CrdsGossipPull},
crds_value::CrdsValue,
},
solana_sdk::hash,
test::Bencher,
};
use rand::{thread_rng, Rng};
use rayon::ThreadPoolBuilder;
use solana_core::cluster_info::MAX_BLOOM_SIZE;
use solana_core::crds::Crds;
use solana_core::crds_gossip_pull::{CrdsFilter, CrdsGossipPull};
use solana_core::crds_value::CrdsValue;
use solana_sdk::hash;
use test::Bencher;
#[bench]
fn bench_hash_as_u64(bencher: &mut Bencher) {
@@ -33,8 +29,13 @@ fn bench_hash_as_u64(bencher: &mut Bencher) {
fn bench_build_crds_filters(bencher: &mut Bencher) {
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
let mut rng = thread_rng();
let crds_gossip_pull = CrdsGossipPull::default();
let mut crds_gossip_pull = CrdsGossipPull::default();
let mut crds = Crds::default();
for _ in 0..50_000 {
crds_gossip_pull
.purged_values
.push_back((solana_sdk::hash::new_rand(&mut rng), rng.gen()));
}
let mut num_inserts = 0;
for _ in 0..90_000 {
if crds

View File

@@ -2,17 +2,15 @@
extern crate test;
use {
rand::{thread_rng, Rng},
solana_gossip::{
crds::{Crds, VersionedCrdsValue},
crds_shards::CrdsShards,
crds_value::CrdsValue,
},
solana_sdk::timing::timestamp,
std::iter::repeat_with,
test::Bencher,
use rand::{thread_rng, Rng};
use solana_core::{
crds::{Crds, VersionedCrdsValue},
crds_shards::CrdsShards,
crds_value::CrdsValue,
};
use solana_sdk::timing::timestamp;
use std::iter::repeat_with;
use test::Bencher;
const CRDS_SHARDS_BITS: u32 = 8;
@@ -21,7 +19,7 @@ fn new_test_crds_value<R: Rng>(rng: &mut R) -> VersionedCrdsValue {
let label = value.label();
let mut crds = Crds::default();
crds.insert(value, timestamp()).unwrap();
crds.get(&label).cloned().unwrap()
crds.remove(&label).unwrap()
}
fn bench_crds_shards_find(bencher: &mut Bencher, num_values: usize, mask_bits: u32) {

View File

@@ -3,16 +3,12 @@
#![feature(test)]
extern crate test;
use {
solana_ledger::poh::Poh,
solana_poh::poh_service::DEFAULT_HASHES_PER_BATCH,
solana_sdk::hash::Hash,
std::sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex,
},
test::Bencher,
};
use solana_core::poh_service::DEFAULT_HASHES_PER_BATCH;
use solana_ledger::poh::Poh;
use solana_sdk::hash::Hash;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use test::Bencher;
const NUM_HASHES: u64 = 30_000; // Should require ~10ms on a 2017 MacBook Pro

View File

@@ -1,15 +1,11 @@
#![feature(test)]
extern crate test;
use {
solana_ledger::entry::{next_entry_mut, Entry, EntrySlice},
solana_sdk::{
hash::{hash, Hash},
signature::{Keypair, Signer},
system_transaction,
},
test::Bencher,
};
use solana_ledger::entry::{next_entry_mut, Entry, EntrySlice};
use solana_sdk::hash::{hash, Hash};
use solana_sdk::signature::{Keypair, Signer};
use solana_sdk::system_transaction;
use test::Bencher;
const NUM_HASHES: u64 = 400;
const NUM_ENTRIES: usize = 800;

View File

@@ -4,16 +4,16 @@ extern crate solana_core;
extern crate test;
use log::*;
use solana_core::cluster_info::{ClusterInfo, Node};
use solana_core::contact_info::ContactInfo;
use solana_core::max_slots::MaxSlots;
use solana_core::retransmit_stage::retransmitter;
use solana_gossip::cluster_info::{ClusterInfo, Node};
use solana_gossip::contact_info::ContactInfo;
use solana_ledger::entry::Entry;
use solana_ledger::genesis_utils::{create_genesis_config, GenesisConfigInfo};
use solana_ledger::leader_schedule_cache::LeaderScheduleCache;
use solana_ledger::shred::Shredder;
use solana_measure::measure::Measure;
use solana_perf::packet::{Packet, Packets};
use solana_rpc::max_slots::MaxSlots;
use solana_runtime::bank::Bank;
use solana_runtime::bank_forks::BankForks;
use solana_sdk::hash::Hash;
@@ -39,12 +39,7 @@ fn bench_retransmitter(bencher: &mut Bencher) {
const NUM_PEERS: usize = 4;
let mut peer_sockets = Vec::new();
for _ in 0..NUM_PEERS {
// This ensures that cluster_info.id() is the root of turbine
// retransmit tree and so the shreds are retransmited to all other
// nodes in the cluster.
let id = std::iter::repeat_with(pubkey::new_rand)
.find(|pk| cluster_info.id() < *pk)
.unwrap();
let id = pubkey::new_rand();
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let mut contact_info = ContactInfo::new_localhost(&id, timestamp());
contact_info.tvu = socket.local_addr().unwrap();

View File

@@ -8,7 +8,7 @@ use raptorq::{Decoder, Encoder};
use solana_ledger::entry::{create_ticks, Entry};
use solana_ledger::shred::{
max_entries_per_n_shred, max_ticks_per_n_shreds, ProcessShredsStats, Shred, Shredder,
MAX_DATA_SHREDS_PER_FEC_BLOCK, SHRED_PAYLOAD_SIZE, SIZE_OF_CODING_SHRED_HEADERS,
MAX_DATA_SHREDS_PER_FEC_BLOCK, SHRED_PAYLOAD_SIZE, SIZE_OF_DATA_SHRED_IGNORED_TAIL,
SIZE_OF_DATA_SHRED_PAYLOAD,
};
use solana_perf::test_tx;
@@ -55,7 +55,7 @@ fn make_shreds(num_shreds: usize) -> Vec<Shred> {
fn make_concatenated_shreds(num_shreds: usize) -> Vec<u8> {
let data_shreds = make_shreds(num_shreds);
let valid_shred_data_len = (SHRED_PAYLOAD_SIZE - SIZE_OF_CODING_SHRED_HEADERS) as usize;
let valid_shred_data_len = (SHRED_PAYLOAD_SIZE - SIZE_OF_DATA_SHRED_IGNORED_TAIL) as usize;
let mut data: Vec<u8> = vec![0; num_shreds * valid_shred_data_len];
for (i, shred) in (data_shreds[0..num_shreds]).iter().enumerate() {
data[i * valid_shred_data_len..(i + 1) * valid_shred_data_len]
@@ -163,7 +163,7 @@ fn bench_shredder_decoding(bencher: &mut Bencher) {
fn bench_shredder_coding_raptorq(bencher: &mut Bencher) {
let symbol_count = MAX_DATA_SHREDS_PER_FEC_BLOCK;
let data = make_concatenated_shreds(symbol_count as usize);
let valid_shred_data_len = (SHRED_PAYLOAD_SIZE - SIZE_OF_CODING_SHRED_HEADERS) as usize;
let valid_shred_data_len = (SHRED_PAYLOAD_SIZE - SIZE_OF_DATA_SHRED_IGNORED_TAIL) as usize;
bencher.iter(|| {
let encoder = Encoder::with_defaults(&data, valid_shred_data_len as u16);
encoder.get_encoded_packets(symbol_count);
@@ -174,7 +174,7 @@ fn bench_shredder_coding_raptorq(bencher: &mut Bencher) {
fn bench_shredder_decoding_raptorq(bencher: &mut Bencher) {
let symbol_count = MAX_DATA_SHREDS_PER_FEC_BLOCK;
let data = make_concatenated_shreds(symbol_count as usize);
let valid_shred_data_len = (SHRED_PAYLOAD_SIZE - SIZE_OF_CODING_SHRED_HEADERS) as usize;
let valid_shred_data_len = (SHRED_PAYLOAD_SIZE - SIZE_OF_DATA_SHRED_IGNORED_TAIL) as usize;
let encoder = Encoder::with_defaults(&data, valid_shred_data_len as u16);
let mut packets = encoder.get_encoded_packets(symbol_count as u32);
packets.shuffle(&mut rand::thread_rng());

View File

@@ -4,9 +4,11 @@
// hash on gossip. Monitor gossip for messages from validators in the --trusted-validators
// set and halt the node if a mismatch is detected.
use crate::snapshot_packager_service::PendingSnapshotPackage;
use crate::{
cluster_info::{ClusterInfo, MAX_SNAPSHOT_HASHES},
snapshot_packager_service::PendingSnapshotPackage,
};
use rayon::ThreadPool;
use solana_gossip::cluster_info::{ClusterInfo, MAX_SNAPSHOT_HASHES};
use solana_runtime::{
accounts_db,
snapshot_package::{AccountsPackage, AccountsPackagePre, AccountsPackageReceiver},
@@ -41,7 +43,7 @@ impl AccountsHashVerifier {
let exit = exit.clone();
let cluster_info = cluster_info.clone();
let t_accounts_hash_verifier = Builder::new()
.name("solana-hash-accounts".to_string())
.name("solana-accounts-hash".to_string())
.spawn(move || {
let mut hashes = vec![];
let mut thread_pool_storage = None;
@@ -216,7 +218,8 @@ impl AccountsHashVerifier {
#[cfg(test)]
mod tests {
use super::*;
use solana_gossip::{cluster_info::make_accounts_hashes_message, contact_info::ContactInfo};
use crate::cluster_info::make_accounts_hashes_message;
use crate::contact_info::ContactInfo;
use solana_runtime::bank_forks::ArchiveFormat;
use solana_runtime::snapshot_utils::SnapshotVersion;
use solana_sdk::{

View File

@@ -1,21 +1,27 @@
//! The `banking_stage` processes Transaction messages. It is intended to be used
//! to contruct a software pipeline. The stage uses all available CPU cores and
//! can do its processing in parallel with signature verification on the GPU.
use crate::packet_hasher::PacketHasher;
use crate::{
cluster_info::ClusterInfo,
packet_hasher::PacketHasher,
poh_recorder::{PohRecorder, PohRecorderError, TransactionRecorder, WorkingBankEntry},
poh_service::{self, PohService},
};
use crossbeam_channel::{Receiver as CrossbeamReceiver, RecvTimeoutError};
use itertools::Itertools;
use lru::LruCache;
use retain_mut::RetainMut;
use solana_gossip::cluster_info::ClusterInfo;
use solana_ledger::{blockstore_processor::TransactionStatusSender, entry::hash_transactions};
use solana_measure::measure::Measure;
use solana_ledger::{
blockstore::Blockstore, blockstore_processor::TransactionStatusSender,
entry::hash_transactions, leader_schedule_cache::LeaderScheduleCache,
};
use solana_measure::{measure::Measure, thread_mem_usage};
use solana_metrics::{inc_new_counter_debug, inc_new_counter_info};
use solana_perf::{
cuda_runtime::PinnedVec,
packet::{limited_deserialize, Packet, Packets, PACKETS_PER_BATCH},
perf_libs,
};
use solana_poh::poh_recorder::{PohRecorder, PohRecorderError, TransactionRecorder};
use solana_runtime::{
accounts_db::ErrorCounters,
bank::{
@@ -33,6 +39,7 @@ use solana_sdk::{
MAX_TRANSACTION_FORWARDING_DELAY_GPU,
},
message::Message,
poh_config::PohConfig,
pubkey::Pubkey,
short_vec::decode_shortu16_len,
signature::Signature,
@@ -50,7 +57,8 @@ use std::{
mem::size_of,
net::UdpSocket,
ops::DerefMut,
sync::atomic::{AtomicU64, AtomicUsize, Ordering},
sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering},
sync::mpsc::Receiver,
sync::{Arc, Mutex},
thread::{self, Builder, JoinHandle},
time::Duration,
@@ -271,6 +279,7 @@ impl BankingStage {
Builder::new()
.name("solana-banking-stage-tx".to_string())
.spawn(move || {
thread_mem_usage::datapoint("solana-banking-stage-tx");
Self::process_loop(
my_pubkey,
&verified_receiver,
@@ -807,7 +816,6 @@ impl BankingStage {
TransactionTokenBalancesSet::new(pre_token_balances, post_token_balances),
inner_instructions,
transaction_logs,
tx_results.rent_debits,
);
}
}
@@ -1384,29 +1392,65 @@ fn next_leader_tpu_forwards(
}
}
pub fn create_test_recorder(
bank: &Arc<Bank>,
blockstore: &Arc<Blockstore>,
poh_config: Option<PohConfig>,
) -> (
Arc<AtomicBool>,
Arc<Mutex<PohRecorder>>,
PohService,
Receiver<WorkingBankEntry>,
) {
let exit = Arc::new(AtomicBool::new(false));
let poh_config = Arc::new(poh_config.unwrap_or_default());
let (mut poh_recorder, entry_receiver, record_receiver) = PohRecorder::new(
bank.tick_height(),
bank.last_blockhash(),
bank.slot(),
Some((4, 4)),
bank.ticks_per_slot(),
&Pubkey::default(),
blockstore,
&Arc::new(LeaderScheduleCache::new_from_bank(&bank)),
&poh_config,
exit.clone(),
);
poh_recorder.set_bank(&bank);
let poh_recorder = Arc::new(Mutex::new(poh_recorder));
let poh_service = PohService::new(
poh_recorder.clone(),
&poh_config,
&exit,
bank.ticks_per_slot(),
poh_service::DEFAULT_PINNED_CPU_CORE,
poh_service::DEFAULT_HASHES_PER_BATCH,
record_receiver,
);
(exit, poh_recorder, poh_service, entry_receiver)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
cluster_info::Node, poh_recorder::Record, poh_recorder::WorkingBank,
transaction_status_service::TransactionStatusService,
};
use crossbeam_channel::unbounded;
use itertools::Itertools;
use solana_gossip::cluster_info::Node;
use solana_ledger::{
blockstore::{entries_to_test_shreds, Blockstore},
blockstore::entries_to_test_shreds,
entry::{next_entry, Entry, EntrySlice},
genesis_utils::{create_genesis_config, GenesisConfigInfo},
get_tmp_ledger_path,
leader_schedule_cache::LeaderScheduleCache,
};
use solana_perf::packet::to_packets_chunked;
use solana_poh::{
poh_recorder::{create_test_recorder, Record, WorkingBank, WorkingBankEntry},
poh_service::PohService,
};
use solana_rpc::transaction_status_service::TransactionStatusService;
use solana_sdk::{
hash::Hash,
instruction::InstructionError,
poh_config::PohConfig,
signature::{Keypair, Signer},
system_instruction::SystemError,
system_transaction,
@@ -1416,10 +1460,7 @@ mod tests {
use std::{
net::SocketAddr,
path::Path,
sync::{
atomic::{AtomicBool, Ordering},
mpsc::Receiver,
},
sync::atomic::{AtomicBool, Ordering},
thread::sleep,
};
@@ -1507,7 +1548,7 @@ mod tests {
.collect();
trace!("done");
assert_eq!(entries.len(), genesis_config.ticks_per_slot as usize);
assert!(entries.verify(&start_hash));
assert_eq!(entries.verify(&start_hash), true);
assert_eq!(entries[entries.len() - 1].hash, bank.last_blockhash());
banking_stage.join().unwrap();
}
@@ -1616,7 +1657,7 @@ mod tests {
.map(|(_bank, (entry, _tick_height))| entry)
.collect();
assert!(entries.verify(&blockhash));
assert_eq!(entries.verify(&blockhash), true);
if !entries.is_empty() {
blockhash = entries.last().unwrap().hash;
for entry in entries {
@@ -2084,7 +2125,7 @@ mod tests {
}
trace!("done ticking");
assert!(done);
assert_eq!(done, true);
let transactions = vec![system_transaction::transfer(
&mint_keypair,

View File

@@ -1,19 +1,17 @@
use {
crate::{bigtable_upload, blockstore::Blockstore},
solana_runtime::commitment::BlockCommitmentCache,
std::{
sync::atomic::{AtomicBool, Ordering},
sync::{Arc, RwLock},
thread::{self, Builder, JoinHandle},
},
tokio::runtime::Runtime,
use solana_ledger::blockstore::Blockstore;
use solana_runtime::commitment::BlockCommitmentCache;
use std::{
sync::atomic::{AtomicBool, Ordering},
sync::{Arc, RwLock},
thread::{self, Builder, JoinHandle},
};
use tokio::runtime::Runtime;
// Delay uploading the largest confirmed root for this many slots. This is done in an attempt to
// ensure that the `CacheBlockMetaService` has had enough time to add the block time for the root
// ensure that the `CacheBlockTimeService` has had enough time to add the block time for the root
// before it's uploaded to BigTable.
//
// A more direct connection between CacheBlockMetaService and BigTableUploadService would be
// A more direct connection between CacheBlockTimeService and BigTableUploadService would be
// preferable...
const LARGEST_CONFIRMED_ROOT_UPLOAD_DELAY: usize = 100;
@@ -70,7 +68,7 @@ impl BigTableUploadService {
continue;
}
let result = runtime.block_on(bigtable_upload::upload_confirmed_blocks(
let result = runtime.block_on(solana_ledger::bigtable_upload::upload_confirmed_blocks(
blockstore.clone(),
bigtable_ledger_storage.clone(),
start_slot,

View File

@@ -1,26 +1,25 @@
//! A stage to broadcast data from a leader node to validators
#![allow(clippy::rc_buffer)]
use self::{
broadcast_duplicates_run::BroadcastDuplicatesRun,
broadcast_fake_shreds_run::BroadcastFakeShredsRun, broadcast_metrics::*,
fail_entry_verification_broadcast_run::FailEntryVerificationBroadcastRun,
standard_broadcast_run::StandardBroadcastRun,
};
use crate::result::{Error, Result};
use crate::contact_info::ContactInfo;
use crate::crds_gossip_pull::CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS;
use crate::weighted_shuffle::weighted_best;
use crate::{
cluster_info::{ClusterInfo, ClusterInfoError},
poh_recorder::WorkingBankEntry,
result::{Error, Result},
};
use crossbeam_channel::{
Receiver as CrossbeamReceiver, RecvTimeoutError as CrossbeamRecvTimeoutError,
Sender as CrossbeamSender,
};
use solana_gossip::{
cluster_info::{self, ClusterInfo, ClusterInfoError},
contact_info::ContactInfo,
crds_gossip_pull::CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS,
weighted_shuffle::weighted_best,
};
use solana_ledger::{blockstore::Blockstore, shred::Shred};
use solana_measure::measure::Measure;
use solana_metrics::{inc_new_counter_error, inc_new_counter_info};
use solana_poh::poh_recorder::WorkingBankEntry;
use solana_runtime::bank::Bank;
use solana_sdk::timing::timestamp;
use solana_sdk::{clock::Slot, pubkey::Pubkey};
@@ -36,7 +35,6 @@ use std::{
time::{Duration, Instant},
};
mod broadcast_duplicates_run;
mod broadcast_fake_shreds_run;
pub mod broadcast_metrics;
pub(crate) mod broadcast_utils;
@@ -54,20 +52,11 @@ pub enum BroadcastStageReturnType {
ChannelDisconnected,
}
#[derive(PartialEq, Clone, Debug)]
pub struct BroadcastDuplicatesConfig {
/// Percentage of stake to send different version of slots to
pub stake_partition: u8,
/// Number of slots to wait before sending duplicate shreds
pub duplicate_send_delay: usize,
}
#[derive(PartialEq, Clone, Debug)]
pub enum BroadcastStageType {
Standard,
FailEntryVerification,
BroadcastFakeShreds,
BroadcastDuplicates(BroadcastDuplicatesConfig),
}
impl BroadcastStageType {
@@ -112,16 +101,6 @@ impl BroadcastStageType {
blockstore,
BroadcastFakeShredsRun::new(keypair, 0, shred_version),
),
BroadcastStageType::BroadcastDuplicates(config) => BroadcastStage::new(
sock,
cluster_info,
receiver,
retransmit_slots_receiver,
exit_sender,
blockstore,
BroadcastDuplicatesRun::new(keypair, shred_version, config.clone()),
),
}
}
}
@@ -384,6 +363,7 @@ pub fn get_broadcast_peers(
cluster_info: &ClusterInfo,
stakes: Option<&HashMap<Pubkey, u64>>,
) -> (Vec<ContactInfo>, Vec<(u64, usize)>) {
use crate::cluster_info;
let mut peers = cluster_info.tvu_peers();
let peers_and_stakes = cluster_info::stake_weight_peers(&mut peers, stakes);
(peers, peers_and_stakes)
@@ -460,8 +440,8 @@ fn num_live_peers(peers: &[ContactInfo]) -> i64 {
#[cfg(test)]
pub mod test {
use super::*;
use crate::cluster_info::{ClusterInfo, Node};
use crossbeam_channel::unbounded;
use solana_gossip::cluster_info::{ClusterInfo, Node};
use solana_ledger::{
blockstore::{make_slot_entries, Blockstore},
entry::create_ticks,

View File

@@ -1,333 +0,0 @@
use super::broadcast_utils::ReceiveResults;
use super::*;
use log::*;
use solana_ledger::entry::{create_ticks, Entry, EntrySlice};
use solana_ledger::shred::Shredder;
use solana_runtime::blockhash_queue::BlockhashQueue;
use solana_sdk::clock::Slot;
use solana_sdk::fee_calculator::FeeCalculator;
use solana_sdk::hash::Hash;
use solana_sdk::signature::{Keypair, Signer};
use solana_sdk::transaction::Transaction;
use std::collections::VecDeque;
use std::sync::Mutex;
// Queue which facilitates delivering shreds with a delay
type DelayedQueue = VecDeque<(Option<Pubkey>, Option<Vec<Shred>>)>;
#[derive(Clone)]
pub(super) struct BroadcastDuplicatesRun {
config: BroadcastDuplicatesConfig,
// Local queue for broadcast to track which duplicate blockhashes we've sent
duplicate_queue: BlockhashQueue,
// Shared queue between broadcast and transmit threads
delayed_queue: Arc<Mutex<DelayedQueue>>,
// Buffer for duplicate entries
duplicate_entries_buffer: Vec<Entry>,
last_duplicate_entry_hash: Hash,
last_broadcast_slot: Slot,
next_shred_index: u32,
shred_version: u16,
keypair: Arc<Keypair>,
}
impl BroadcastDuplicatesRun {
pub(super) fn new(
keypair: Arc<Keypair>,
shred_version: u16,
config: BroadcastDuplicatesConfig,
) -> Self {
let mut delayed_queue = DelayedQueue::new();
delayed_queue.resize(config.duplicate_send_delay, (None, None));
Self {
config,
delayed_queue: Arc::new(Mutex::new(delayed_queue)),
duplicate_queue: BlockhashQueue::default(),
duplicate_entries_buffer: vec![],
next_shred_index: u32::MAX,
last_broadcast_slot: 0,
last_duplicate_entry_hash: Hash::default(),
shred_version,
keypair,
}
}
fn queue_or_create_duplicate_entries(
&mut self,
bank: &Arc<Bank>,
receive_results: &ReceiveResults,
) -> (Vec<Entry>, u32) {
// If the last entry hash is default, grab the last blockhash from the parent bank
if self.last_duplicate_entry_hash == Hash::default() {
self.last_duplicate_entry_hash = bank.last_blockhash();
}
// Create duplicate entries by..
// 1) rearranging real entries so that all transaction entries are moved to
// the front and tick entries are moved to the back.
// 2) setting all transaction entries to zero hashes and all tick entries to `hashes_per_tick`.
// 3) removing any transactions which reference blockhashes which aren't in the
// duplicate blockhash queue.
let (duplicate_entries, next_shred_index) = if bank.slot() > MINIMUM_DUPLICATE_SLOT {
let mut tx_entries: Vec<Entry> = receive_results
.entries
.iter()
.filter_map(|entry| {
if entry.is_tick() {
return None;
}
let transactions: Vec<Transaction> = entry
.transactions
.iter()
.filter(|tx| {
self.duplicate_queue
.get_hash_age(&tx.message.recent_blockhash)
.is_some()
})
.cloned()
.collect();
if !transactions.is_empty() {
Some(Entry::new_mut(
&mut self.last_duplicate_entry_hash,
&mut 0,
transactions,
))
} else {
None
}
})
.collect();
let mut tick_entries = create_ticks(
receive_results.entries.tick_count(),
bank.hashes_per_tick().unwrap_or_default(),
self.last_duplicate_entry_hash,
);
self.duplicate_entries_buffer.append(&mut tx_entries);
self.duplicate_entries_buffer.append(&mut tick_entries);
// Only send out duplicate entries when the block is finished otherwise the
// recipient will start repairing for shreds they haven't received yet and
// hit duplicate slot issues before we want them to.
let entries = if receive_results.last_tick_height == bank.max_tick_height() {
self.duplicate_entries_buffer.drain(..).collect()
} else {
vec![]
};
// Set next shred index to 0 since we are sending the full slot
(entries, 0)
} else {
// Send real entries until we hit min duplicate slot
(receive_results.entries.clone(), self.next_shred_index)
};
// Save last duplicate entry hash to avoid invalid entry hash errors
if let Some(last_duplicate_entry) = duplicate_entries.last() {
self.last_duplicate_entry_hash = last_duplicate_entry.hash;
}
(duplicate_entries, next_shred_index)
}
}
/// Duplicate slots should only be sent once all validators have started.
/// This constant is intended to be used as a buffer so that all validators
/// are live before sending duplicate slots.
pub const MINIMUM_DUPLICATE_SLOT: Slot = 20;
impl BroadcastRun for BroadcastDuplicatesRun {
fn run(
&mut self,
blockstore: &Arc<Blockstore>,
receiver: &Receiver<WorkingBankEntry>,
socket_sender: &Sender<(TransmitShreds, Option<BroadcastShredBatchInfo>)>,
blockstore_sender: &Sender<(Arc<Vec<Shred>>, Option<BroadcastShredBatchInfo>)>,
) -> Result<()> {
// 1) Pull entries from banking stage
let receive_results = broadcast_utils::recv_slot_entries(receiver)?;
let bank = receive_results.bank.clone();
let last_tick_height = receive_results.last_tick_height;
if self.next_shred_index == u32::MAX {
self.next_shred_index = blockstore
.meta(bank.slot())
.expect("Database error")
.map(|meta| meta.consumed)
.unwrap_or(0) as u32
}
// We were not the leader, but just became leader again
if bank.slot() > self.last_broadcast_slot + 1 {
self.last_duplicate_entry_hash = Hash::default();
}
self.last_broadcast_slot = bank.slot();
let shredder = Shredder::new(
bank.slot(),
bank.parent().unwrap().slot(),
self.keypair.clone(),
(bank.tick_height() % bank.ticks_per_slot()) as u8,
self.shred_version,
)
.expect("Expected to create a new shredder");
let (data_shreds, coding_shreds, last_shred_index) = shredder.entries_to_shreds(
&receive_results.entries,
last_tick_height == bank.max_tick_height(),
self.next_shred_index,
);
let (duplicate_entries, next_duplicate_shred_index) =
self.queue_or_create_duplicate_entries(&bank, &receive_results);
let (duplicate_data_shreds, duplicate_coding_shreds, _) = if !duplicate_entries.is_empty() {
shredder.entries_to_shreds(
&duplicate_entries,
last_tick_height == bank.max_tick_height(),
next_duplicate_shred_index,
)
} else {
(vec![], vec![], 0)
};
// Manually track the shred index because relying on slot meta consumed is racy
if last_tick_height == bank.max_tick_height() {
self.next_shred_index = 0;
self.duplicate_queue
.register_hash(&self.last_duplicate_entry_hash, &FeeCalculator::default());
} else {
self.next_shred_index = last_shred_index;
}
// Partition network with duplicate and real shreds based on stake
let bank_epoch = bank.get_leader_schedule_epoch(bank.slot());
let mut duplicate_recipients = HashMap::new();
let mut real_recipients = HashMap::new();
let mut stakes: Vec<(Pubkey, u64)> = bank
.epoch_staked_nodes(bank_epoch)
.unwrap()
.into_iter()
.filter(|(pubkey, _)| *pubkey != self.keypair.pubkey())
.collect();
stakes.sort_by(|(l_key, l_stake), (r_key, r_stake)| {
if r_stake == l_stake {
l_key.cmp(&r_key)
} else {
r_stake.cmp(&l_stake)
}
});
let highest_staked_node = stakes.first().cloned().map(|x| x.0);
let stake_total: u64 = stakes.iter().map(|(_, stake)| *stake).sum();
let mut cumulative_stake: u64 = 0;
for (pubkey, stake) in stakes.into_iter().rev() {
cumulative_stake += stake;
if (100 * cumulative_stake / stake_total) as u8 <= self.config.stake_partition {
duplicate_recipients.insert(pubkey, stake);
} else {
real_recipients.insert(pubkey, stake);
}
}
if let Some(highest_staked_node) = highest_staked_node {
if bank.slot() > MINIMUM_DUPLICATE_SLOT && last_tick_height == bank.max_tick_height() {
warn!(
"{} sent duplicate slot {} to nodes: {:?}",
self.keypair.pubkey(),
bank.slot(),
&duplicate_recipients,
);
warn!(
"Duplicate shreds for slot {} will be broadcast in {} slot(s)",
bank.slot(),
self.config.duplicate_send_delay
);
let delayed_shreds: Option<Vec<Shred>> = vec![
duplicate_data_shreds.last().cloned(),
data_shreds.last().cloned(),
]
.into_iter()
.collect();
self.delayed_queue
.lock()
.unwrap()
.push_back((Some(highest_staked_node), delayed_shreds));
}
}
let duplicate_recipients = Arc::new(duplicate_recipients);
let real_recipients = Arc::new(real_recipients);
let data_shreds = Arc::new(data_shreds);
blockstore_sender.send((data_shreds.clone(), None))?;
// 3) Start broadcast step
socket_sender.send((
(
Some(duplicate_recipients.clone()),
Arc::new(duplicate_data_shreds),
),
None,
))?;
socket_sender.send((
(
Some(duplicate_recipients),
Arc::new(duplicate_coding_shreds),
),
None,
))?;
socket_sender.send(((Some(real_recipients.clone()), data_shreds), None))?;
socket_sender.send(((Some(real_recipients), Arc::new(coding_shreds)), None))?;
Ok(())
}
fn transmit(
&mut self,
receiver: &Arc<Mutex<TransmitReceiver>>,
cluster_info: &ClusterInfo,
sock: &UdpSocket,
) -> Result<()> {
// Check the delay queue for shreds that are ready to be sent
let (delayed_recipient, delayed_shreds) = {
let mut delayed_deque = self.delayed_queue.lock().unwrap();
if delayed_deque.len() > self.config.duplicate_send_delay {
delayed_deque.pop_front().unwrap()
} else {
(None, None)
}
};
let ((stakes, shreds), _) = receiver.lock().unwrap().recv()?;
let stakes = stakes.unwrap();
for peer in cluster_info.tvu_peers() {
// Forward shreds to circumvent gossip
if stakes.get(&peer.id).is_some() {
shreds.iter().for_each(|shred| {
sock.send_to(&shred.payload, &peer.tvu_forwards).unwrap();
});
}
// After a delay, broadcast duplicate shreds to a single node
if let Some(shreds) = delayed_shreds.as_ref() {
if Some(peer.id) == delayed_recipient {
shreds.iter().for_each(|shred| {
sock.send_to(&shred.payload, &peer.tvu).unwrap();
});
}
}
}
Ok(())
}
fn record(
&mut self,
receiver: &Arc<Mutex<RecordReceiver>>,
blockstore: &Arc<Blockstore>,
) -> Result<()> {
let (data_shreds, _) = receiver.lock().unwrap().recv()?;
blockstore.insert_shreds(data_shreds.to_vec(), None, true)?;
Ok(())
}
}

View File

@@ -138,7 +138,7 @@ impl BroadcastRun for BroadcastFakeShredsRun {
#[cfg(test)]
mod tests {
use super::*;
use solana_gossip::contact_info::ContactInfo;
use crate::contact_info::ContactInfo;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
#[test]

View File

@@ -1,6 +1,6 @@
use crate::poh_recorder::WorkingBankEntry;
use crate::result::Result;
use solana_ledger::{entry::Entry, shred::Shred};
use solana_poh::poh_recorder::WorkingBankEntry;
use solana_runtime::bank::Bank;
use solana_sdk::clock::Slot;
use std::{

View File

@@ -494,7 +494,7 @@ impl BroadcastRun for StandardBroadcastRun {
#[cfg(test)]
mod test {
use super::*;
use solana_gossip::cluster_info::{ClusterInfo, Node};
use crate::cluster_info::{ClusterInfo, Node};
use solana_ledger::genesis_utils::create_genesis_config;
use solana_ledger::{
blockstore::Blockstore, entry::create_ticks, get_tmp_ledger_path,

View File

@@ -1,74 +0,0 @@
pub use solana_ledger::blockstore_processor::CacheBlockMetaSender;
use {
crossbeam_channel::{Receiver, RecvTimeoutError},
solana_ledger::blockstore::Blockstore,
solana_measure::measure::Measure,
solana_runtime::bank::Bank,
std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread::{self, Builder, JoinHandle},
time::Duration,
},
};
pub type CacheBlockMetaReceiver = Receiver<Arc<Bank>>;
pub struct CacheBlockMetaService {
thread_hdl: JoinHandle<()>,
}
const CACHE_BLOCK_TIME_WARNING_MS: u64 = 150;
impl CacheBlockMetaService {
#[allow(clippy::new_ret_no_self)]
pub fn new(
cache_block_meta_receiver: CacheBlockMetaReceiver,
blockstore: Arc<Blockstore>,
exit: &Arc<AtomicBool>,
) -> Self {
let exit = exit.clone();
let thread_hdl = Builder::new()
.name("solana-cache-block-time".to_string())
.spawn(move || loop {
if exit.load(Ordering::Relaxed) {
break;
}
let recv_result = cache_block_meta_receiver.recv_timeout(Duration::from_secs(1));
match recv_result {
Err(RecvTimeoutError::Disconnected) => {
break;
}
Ok(bank) => {
let mut cache_block_meta_timer = Measure::start("cache_block_meta_timer");
Self::cache_block_meta(bank, &blockstore);
cache_block_meta_timer.stop();
if cache_block_meta_timer.as_ms() > CACHE_BLOCK_TIME_WARNING_MS {
warn!(
"cache_block_meta operation took: {}ms",
cache_block_meta_timer.as_ms()
);
}
}
_ => {}
}
})
.unwrap();
Self { thread_hdl }
}
fn cache_block_meta(bank: Arc<Bank>, blockstore: &Arc<Blockstore>) {
if let Err(e) = blockstore.cache_block_time(bank.slot(), bank.clock().unix_timestamp) {
error!("cache_block_time failed: slot {:?} {:?}", bank.slot(), e);
}
if let Err(e) = blockstore.cache_block_height(bank.slot(), bank.block_height()) {
error!("cache_block_height failed: slot {:?} {:?}", bank.slot(), e);
}
}
pub fn join(self) -> thread::Result<()> {
self.thread_hdl.join()
}
}

View File

@@ -0,0 +1,69 @@
use crossbeam_channel::{Receiver, RecvTimeoutError, Sender};
use solana_ledger::blockstore::Blockstore;
use solana_measure::measure::Measure;
use solana_runtime::bank::Bank;
use std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread::{self, Builder, JoinHandle},
time::Duration,
};
pub type CacheBlockTimeReceiver = Receiver<Arc<Bank>>;
pub type CacheBlockTimeSender = Sender<Arc<Bank>>;
pub struct CacheBlockTimeService {
thread_hdl: JoinHandle<()>,
}
const CACHE_BLOCK_TIME_WARNING_MS: u64 = 150;
impl CacheBlockTimeService {
#[allow(clippy::new_ret_no_self)]
pub fn new(
cache_block_time_receiver: CacheBlockTimeReceiver,
blockstore: Arc<Blockstore>,
exit: &Arc<AtomicBool>,
) -> Self {
let exit = exit.clone();
let thread_hdl = Builder::new()
.name("solana-cache-block-time".to_string())
.spawn(move || loop {
if exit.load(Ordering::Relaxed) {
break;
}
let recv_result = cache_block_time_receiver.recv_timeout(Duration::from_secs(1));
match recv_result {
Err(RecvTimeoutError::Disconnected) => {
break;
}
Ok(bank) => {
let mut cache_block_time_timer = Measure::start("cache_block_time_timer");
Self::cache_block_time(bank, &blockstore);
cache_block_time_timer.stop();
if cache_block_time_timer.as_ms() > CACHE_BLOCK_TIME_WARNING_MS {
warn!(
"cache_block_time operation took: {}ms",
cache_block_time_timer.as_ms()
);
}
}
_ => {}
}
})
.unwrap();
Self { thread_hdl }
}
fn cache_block_time(bank: Arc<Bank>, blockstore: &Arc<Blockstore>) {
if let Err(e) = blockstore.cache_block_time(bank.slot(), bank.clock().unix_timestamp) {
error!("cache_block_time failed: slot {:?} {:?}", bank.slot(), e);
}
}
pub fn join(self) -> thread::Result<()> {
self.thread_hdl.join()
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,11 @@
use {
crate::crds_gossip::CrdsGossip,
solana_measure::measure::Measure,
solana_sdk::pubkey::Pubkey,
std::{
collections::HashMap,
sync::{
atomic::{AtomicU64, Ordering},
RwLock,
},
time::Instant,
use crate::crds_gossip::CrdsGossip;
use solana_measure::measure::Measure;
use std::{
sync::{
atomic::{AtomicU64, Ordering},
RwLock,
},
time::Instant,
};
#[derive(Default)]
@@ -118,24 +114,17 @@ pub(crate) struct GossipStats {
pub(crate) trim_crds_table_failed: Counter,
pub(crate) trim_crds_table_purged_values_count: Counter,
pub(crate) tvu_peers: Counter,
pub(crate) verify_gossip_packets_time: Counter,
}
pub(crate) fn submit_gossip_stats(
stats: &GossipStats,
gossip: &RwLock<CrdsGossip>,
stakes: &HashMap<Pubkey, u64>,
) {
let (table_size, num_nodes, purged_values_size, failed_inserts_size) = {
pub(crate) fn submit_gossip_stats(stats: &GossipStats, gossip: &RwLock<CrdsGossip>) {
let (table_size, purged_values_size, failed_inserts_size) = {
let gossip = gossip.read().unwrap();
(
gossip.crds.len(),
gossip.crds.num_nodes(),
gossip.crds.num_purged(),
gossip.pull.purged_values.len(),
gossip.pull.failed_inserts.len(),
)
};
let num_nodes_staked = stakes.values().filter(|stake| **stake > 0).count();
datapoint_info!(
"cluster_info_stats",
("entrypoint", stats.entrypoint.clear(), i64),
@@ -153,8 +142,6 @@ pub(crate) fn submit_gossip_stats(
("table_size", table_size as i64, i64),
("purged_values_size", purged_values_size as i64, i64),
("failed_inserts_size", failed_inserts_size as i64, i64),
("num_nodes", num_nodes as i64, i64),
("num_nodes_staked", num_nodes_staked as i64, i64),
);
datapoint_info!(
"cluster_info_stats2",
@@ -172,11 +159,6 @@ pub(crate) fn submit_gossip_stats(
stats.process_gossip_packets_time.clear(),
i64
),
(
"verify_gossip_packets_time",
stats.verify_gossip_packets_time.clear(),
i64
),
(
"handle_batch_ping_messages_time",
stats.handle_batch_ping_messages_time.clear(),

View File

@@ -1,7 +1,12 @@
use crate::{
cluster_info::{ClusterInfo, GOSSIP_SLEEP_MILLIS},
crds_value::CrdsValueLabel,
optimistic_confirmation_verifier::OptimisticConfirmationVerifier,
optimistically_confirmed_bank_tracker::{BankNotification, BankNotificationSender},
poh_recorder::PohRecorder,
replay_stage::DUPLICATE_THRESHOLD,
result::{Error, Result},
rpc_subscriptions::RpcSubscriptions,
sigverify,
verified_vote_packets::VerifiedVotePackets,
vote_stake_tracker::VoteStakeTracker,
@@ -11,19 +16,9 @@ use crossbeam_channel::{
};
use itertools::izip;
use log::*;
use solana_gossip::{
cluster_info::{ClusterInfo, GOSSIP_SLEEP_MILLIS},
crds::Cursor,
crds_value::CrdsValueLabel,
};
use solana_ledger::blockstore::Blockstore;
use solana_metrics::inc_new_counter_debug;
use solana_perf::packet::{self, Packets};
use solana_poh::poh_recorder::PohRecorder;
use solana_rpc::{
optimistically_confirmed_bank_tracker::{BankNotification, BankNotificationSender},
rpc_subscriptions::RpcSubscriptions,
};
use solana_runtime::{
bank::Bank,
bank_forks::BankForks,
@@ -33,7 +28,7 @@ use solana_runtime::{
vote_sender_types::{ReplayVoteReceiver, ReplayedVote},
};
use solana_sdk::{
clock::{Epoch, Slot, DEFAULT_MS_PER_SLOT, DEFAULT_TICKS_PER_SLOT},
clock::{Epoch, Slot, DEFAULT_MS_PER_SLOT},
epoch_schedule::EpochSchedule,
hash::Hash,
pubkey::Pubkey,
@@ -331,18 +326,23 @@ impl ClusterInfoVoteListener {
verified_vote_label_packets_sender: VerifiedLabelVotePacketsSender,
verified_vote_transactions_sender: VerifiedVoteTransactionsSender,
) -> Result<()> {
let mut cursor = Cursor::default();
while !exit.load(Ordering::Relaxed) {
let (labels, votes) = cluster_info.get_votes(&mut cursor);
let mut last_ts = 0;
loop {
if exit.load(Ordering::Relaxed) {
return Ok(());
}
let (labels, votes, new_ts) = cluster_info.get_votes(last_ts);
inc_new_counter_debug!("cluster_info_vote_listener-recv_count", votes.len());
last_ts = new_ts;
if !votes.is_empty() {
let (vote_txs, packets) = Self::verify_votes(votes, labels);
verified_vote_transactions_sender.send(vote_txs)?;
verified_vote_label_packets_sender.send(packets)?;
}
sleep(Duration::from_millis(GOSSIP_SLEEP_MILLIS));
}
Ok(())
}
#[allow(clippy::type_complexity)]
@@ -384,14 +384,9 @@ impl ClusterInfoVoteListener {
return Ok(());
}
let would_be_leader = poh_recorder
.lock()
.unwrap()
.would_be_leader(20 * DEFAULT_TICKS_PER_SLOT);
if let Err(e) = verified_vote_packets.receive_and_process_vote_packets(
&verified_vote_label_packets_receiver,
&mut update_version,
would_be_leader,
) {
match e {
Error::CrossbeamRecvTimeoutError(RecvTimeoutError::Disconnected) => {
@@ -833,8 +828,8 @@ impl ClusterInfoVoteListener {
#[cfg(test)]
mod tests {
use super::*;
use crate::optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank;
use solana_perf::packet;
use solana_rpc::optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank;
use solana_runtime::{
bank::Bank,
commitment::BlockCommitmentCache,

View File

@@ -3,9 +3,8 @@ use crate::{
progress_map::ProgressMap,
};
use solana_sdk::{clock::Slot, hash::Hash};
use std::collections::{BTreeMap, BTreeSet};
use std::collections::{BTreeMap, HashMap, HashSet};
pub(crate) type DuplicateSlotsTracker = BTreeSet<Slot>;
pub(crate) type GossipDuplicateConfirmedSlots = BTreeMap<Slot, Hash>;
type SlotStateHandler = fn(Slot, &Hash, Option<&Hash>, bool, bool) -> Vec<ResultingStateChange>;
@@ -201,12 +200,19 @@ fn get_cluster_duplicate_confirmed_hash<'a>(
fn apply_state_changes(
slot: Slot,
progress: &mut ProgressMap,
fork_choice: &mut HeaviestSubtreeForkChoice,
ancestors: &HashMap<Slot, HashSet<Slot>>,
descendants: &HashMap<Slot, HashSet<Slot>>,
state_changes: Vec<ResultingStateChange>,
) {
for state_change in state_changes {
match state_change {
ResultingStateChange::MarkSlotDuplicate(bank_frozen_hash) => {
progress.set_unconfirmed_duplicate_slot(
slot,
descendants.get(&slot).unwrap_or(&HashSet::default()),
);
fork_choice.mark_fork_invalid_candidate(&(slot, bank_frozen_hash));
}
ResultingStateChange::RepairDuplicateConfirmedVersion(
@@ -217,20 +223,25 @@ fn apply_state_changes(
repair_correct_version(slot, &cluster_duplicate_confirmed_hash);
}
ResultingStateChange::DuplicateConfirmedSlotMatchesCluster(bank_frozen_hash) => {
progress.set_confirmed_duplicate_slot(
slot,
ancestors.get(&slot).unwrap_or(&HashSet::default()),
descendants.get(&slot).unwrap_or(&HashSet::default()),
);
fork_choice.mark_fork_valid_candidate(&(slot, bank_frozen_hash));
}
}
}
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn check_slot_agrees_with_cluster(
slot: Slot,
root: Slot,
frozen_hash: Option<Hash>,
duplicate_slots_tracker: &mut DuplicateSlotsTracker,
gossip_duplicate_confirmed_slots: &GossipDuplicateConfirmedSlots,
progress: &ProgressMap,
ancestors: &HashMap<Slot, HashSet<Slot>>,
descendants: &HashMap<Slot, HashSet<Slot>>,
progress: &mut ProgressMap,
fork_choice: &mut HeaviestSubtreeForkChoice,
slot_state_update: SlotStateUpdate,
) {
@@ -247,15 +258,6 @@ pub(crate) fn check_slot_agrees_with_cluster(
return;
}
// Needs to happen before the frozen_hash.is_none() check below to account for duplicate
// signals arriving before the bank is constructed in replay.
if matches!(slot_state_update, SlotStateUpdate::Duplicate) {
// If this slot has already been processed before, return
if !duplicate_slots_tracker.insert(slot) {
return;
}
}
if frozen_hash.is_none() {
// If the bank doesn't even exist in BankForks yet,
// then there's nothing to do as replay of the slot
@@ -266,18 +268,25 @@ pub(crate) fn check_slot_agrees_with_cluster(
let frozen_hash = frozen_hash.unwrap();
let gossip_duplicate_confirmed_hash = gossip_duplicate_confirmed_slots.get(&slot);
// If the bank hasn't been frozen yet, then we haven't duplicate confirmed a local version
// this slot through replay yet.
let is_local_replay_duplicate_confirmed = fork_choice
.is_duplicate_confirmed(&(slot, frozen_hash))
.unwrap_or(false);
let is_local_replay_duplicate_confirmed = progress.is_duplicate_confirmed(slot).expect("If the frozen hash exists, then the slot must exist in bank forks and thus in progress map");
let cluster_duplicate_confirmed_hash = get_cluster_duplicate_confirmed_hash(
slot,
gossip_duplicate_confirmed_hash,
&frozen_hash,
is_local_replay_duplicate_confirmed,
);
let is_slot_duplicate = duplicate_slots_tracker.contains(&slot);
let mut is_slot_duplicate =
progress.is_unconfirmed_duplicate(slot).expect("If the frozen hash exists, then the slot must exist in bank forks and thus in progress map");
if matches!(slot_state_update, SlotStateUpdate::Duplicate) {
if is_slot_duplicate {
// Already processed duplicate signal for this slot, no need to continue
return;
} else {
// Otherwise, mark the slot as duplicate so the appropriate state changes
// will trigger
is_slot_duplicate = true;
}
}
let is_dead = progress.is_dead(slot).expect("If the frozen hash exists, then the slot must exist in bank forks and thus in progress map");
info!(
@@ -300,7 +309,14 @@ pub(crate) fn check_slot_agrees_with_cluster(
is_slot_duplicate,
is_dead,
);
apply_state_changes(slot, fork_choice, state_changes);
apply_state_changes(
slot,
progress,
fork_choice,
ancestors,
descendants,
state_changes,
);
}
#[cfg(test)]
@@ -308,16 +324,15 @@ mod test {
use super::*;
use crate::consensus::test::VoteSimulator;
use solana_runtime::bank_forks::BankForks;
use std::{
collections::{HashMap, HashSet},
sync::RwLock,
};
use std::sync::RwLock;
use trees::tr;
struct InitialState {
heaviest_subtree_fork_choice: HeaviestSubtreeForkChoice,
progress: ProgressMap,
ancestors: HashMap<Slot, HashSet<Slot>>,
descendants: HashMap<Slot, HashSet<Slot>>,
slot: Slot,
bank_forks: RwLock<BankForks>,
}
@@ -326,6 +341,7 @@ mod test {
let forks = tr(0) / (tr(1) / (tr(2) / tr(3)));
let mut vote_simulator = VoteSimulator::new(1);
vote_simulator.fill_bank_forks(forks, &HashMap::new());
let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
let descendants = vote_simulator
.bank_forks
@@ -337,7 +353,9 @@ mod test {
InitialState {
heaviest_subtree_fork_choice: vote_simulator.heaviest_subtree_fork_choice,
progress: vote_simulator.progress,
ancestors,
descendants,
slot: 0,
bank_forks: vote_simulator.bank_forks,
}
}
@@ -608,159 +626,75 @@ mod test {
// Common state
let InitialState {
mut heaviest_subtree_fork_choice,
mut progress,
ancestors,
descendants,
slot,
bank_forks,
..
} = setup();
// MarkSlotDuplicate should mark progress map and remove
// the slot from fork choice
let duplicate_slot = bank_forks.read().unwrap().root() + 1;
let duplicate_slot_hash = bank_forks
.read()
.unwrap()
.get(duplicate_slot)
.unwrap()
.hash();
let slot_hash = bank_forks.read().unwrap().get(slot).unwrap().hash();
apply_state_changes(
duplicate_slot,
slot,
&mut progress,
&mut heaviest_subtree_fork_choice,
vec![ResultingStateChange::MarkSlotDuplicate(duplicate_slot_hash)],
&ancestors,
&descendants,
vec![ResultingStateChange::MarkSlotDuplicate(slot_hash)],
);
assert!(!heaviest_subtree_fork_choice
.is_candidate(&(duplicate_slot, duplicate_slot_hash))
.is_candidate_slot(&(slot, slot_hash))
.unwrap());
for child_slot in descendants
.get(&duplicate_slot)
.get(&slot)
.unwrap()
.iter()
.chain(std::iter::once(&duplicate_slot))
.chain(std::iter::once(&slot))
{
assert_eq!(
heaviest_subtree_fork_choice
.latest_invalid_ancestor(&(
*child_slot,
bank_forks.read().unwrap().get(*child_slot).unwrap().hash()
))
progress
.latest_unconfirmed_duplicate_ancestor(*child_slot)
.unwrap(),
duplicate_slot
slot
);
}
// DuplicateConfirmedSlotMatchesCluster should re-enable fork choice
apply_state_changes(
duplicate_slot,
slot,
&mut progress,
&mut heaviest_subtree_fork_choice,
&ancestors,
&descendants,
vec![ResultingStateChange::DuplicateConfirmedSlotMatchesCluster(
duplicate_slot_hash,
slot_hash,
)],
);
for child_slot in descendants
.get(&duplicate_slot)
.get(&slot)
.unwrap()
.iter()
.chain(std::iter::once(&duplicate_slot))
.chain(std::iter::once(&slot))
{
assert!(heaviest_subtree_fork_choice
.latest_invalid_ancestor(&(
*child_slot,
bank_forks.read().unwrap().get(*child_slot).unwrap().hash()
))
assert!(progress
.latest_unconfirmed_duplicate_ancestor(*child_slot)
.is_none());
}
assert!(heaviest_subtree_fork_choice
.is_candidate(&(duplicate_slot, duplicate_slot_hash))
.is_candidate_slot(&(slot, slot_hash))
.unwrap());
}
fn run_test_state_duplicate_then_bank_frozen(initial_bank_hash: Option<Hash>) {
// Common state
let InitialState {
mut heaviest_subtree_fork_choice,
progress,
bank_forks,
..
} = setup();
// Setup a duplicate slot state transition with the initial bank state of the duplicate slot
// determined by `initial_bank_hash`, which can be:
// 1) A default hash (unfrozen bank),
// 2) None (a slot that hasn't even started replay yet).
let root = 0;
let mut duplicate_slots_tracker = DuplicateSlotsTracker::default();
let gossip_duplicate_confirmed_slots = GossipDuplicateConfirmedSlots::default();
let duplicate_slot = 2;
check_slot_agrees_with_cluster(
duplicate_slot,
root,
initial_bank_hash,
&mut duplicate_slots_tracker,
&gossip_duplicate_confirmed_slots,
&progress,
&mut heaviest_subtree_fork_choice,
SlotStateUpdate::Duplicate,
);
assert!(duplicate_slots_tracker.contains(&duplicate_slot));
// Nothing should be applied yet to fork choice, since bank was not yet frozen
for slot in 2..=3 {
let slot_hash = bank_forks.read().unwrap().get(slot).unwrap().hash();
assert!(heaviest_subtree_fork_choice
.latest_invalid_ancestor(&(slot, slot_hash))
.is_none());
}
// Now freeze the bank
let frozen_duplicate_slot_hash = bank_forks
.read()
.unwrap()
.get(duplicate_slot)
.unwrap()
.hash();
check_slot_agrees_with_cluster(
duplicate_slot,
root,
Some(frozen_duplicate_slot_hash),
&mut duplicate_slots_tracker,
&gossip_duplicate_confirmed_slots,
&progress,
&mut heaviest_subtree_fork_choice,
SlotStateUpdate::Frozen,
);
// Progress map should have the correct updates, fork choice should mark duplicate
// as unvotable
assert!(heaviest_subtree_fork_choice
.is_unconfirmed_duplicate(&(duplicate_slot, frozen_duplicate_slot_hash))
.unwrap());
// The ancestor of the duplicate slot should be the best slot now
let (duplicate_ancestor, duplicate_parent_hash) = {
let r_bank_forks = bank_forks.read().unwrap();
let parent_bank = r_bank_forks.get(duplicate_slot).unwrap().parent().unwrap();
(parent_bank.slot(), parent_bank.hash())
};
assert_eq!(
heaviest_subtree_fork_choice.best_overall_slot(),
(duplicate_ancestor, duplicate_parent_hash)
);
}
#[test]
fn test_state_unfrozen_bank_duplicate_then_bank_frozen() {
run_test_state_duplicate_then_bank_frozen(Some(Hash::default()));
}
#[test]
fn test_state_unreplayed_bank_duplicate_then_bank_frozen() {
run_test_state_duplicate_then_bank_frozen(None);
}
#[test]
fn test_state_ancestor_confirmed_descendant_duplicate() {
// Common state
let InitialState {
mut heaviest_subtree_fork_choice,
progress,
mut progress,
ancestors,
descendants,
bank_forks,
..
} = setup();
@@ -771,7 +705,6 @@ mod test {
(3, slot3_hash)
);
let root = 0;
let mut duplicate_slots_tracker = DuplicateSlotsTracker::default();
let mut gossip_duplicate_confirmed_slots = GossipDuplicateConfirmedSlots::default();
// Mark slot 2 as duplicate confirmed
@@ -781,67 +714,36 @@ mod test {
2,
root,
Some(slot2_hash),
&mut duplicate_slots_tracker,
&gossip_duplicate_confirmed_slots,
&progress,
&ancestors,
&descendants,
&mut progress,
&mut heaviest_subtree_fork_choice,
SlotStateUpdate::DuplicateConfirmed,
);
assert!(heaviest_subtree_fork_choice
.is_duplicate_confirmed(&(2, slot2_hash))
.unwrap());
assert_eq!(
heaviest_subtree_fork_choice.best_overall_slot(),
(3, slot3_hash)
);
for slot in 0..=2 {
let slot_hash = bank_forks.read().unwrap().get(slot).unwrap().hash();
assert!(heaviest_subtree_fork_choice
.is_duplicate_confirmed(&(slot, slot_hash))
.unwrap());
assert!(heaviest_subtree_fork_choice
.latest_invalid_ancestor(&(slot, slot_hash))
.is_none());
}
// Mark 3 as duplicate, should not remove the duplicate confirmed slot 2 from
// fork choice
// Mark 3 as duplicate, should not remove slot 2 from fork choice
check_slot_agrees_with_cluster(
3,
root,
Some(slot3_hash),
&mut duplicate_slots_tracker,
&gossip_duplicate_confirmed_slots,
&progress,
&ancestors,
&descendants,
&mut progress,
&mut heaviest_subtree_fork_choice,
SlotStateUpdate::Duplicate,
);
assert!(duplicate_slots_tracker.contains(&3));
assert_eq!(
heaviest_subtree_fork_choice.best_overall_slot(),
(2, slot2_hash)
);
for slot in 0..=3 {
let slot_hash = bank_forks.read().unwrap().get(slot).unwrap().hash();
if slot <= 2 {
assert!(heaviest_subtree_fork_choice
.is_duplicate_confirmed(&(slot, slot_hash))
.unwrap());
assert!(heaviest_subtree_fork_choice
.latest_invalid_ancestor(&(slot, slot_hash))
.is_none());
} else {
assert!(!heaviest_subtree_fork_choice
.is_duplicate_confirmed(&(slot, slot_hash))
.unwrap());
assert_eq!(
heaviest_subtree_fork_choice
.latest_invalid_ancestor(&(slot, slot_hash))
.unwrap(),
3
);
}
}
}
#[test]
@@ -849,7 +751,9 @@ mod test {
// Common state
let InitialState {
mut heaviest_subtree_fork_choice,
progress,
mut progress,
ancestors,
descendants,
bank_forks,
..
} = setup();
@@ -860,30 +764,19 @@ mod test {
(3, slot3_hash)
);
let root = 0;
let mut duplicate_slots_tracker = DuplicateSlotsTracker::default();
let mut gossip_duplicate_confirmed_slots = GossipDuplicateConfirmedSlots::default();
// Mark 2 as duplicate
// Mark 2 as duplicate confirmed
check_slot_agrees_with_cluster(
2,
root,
Some(bank_forks.read().unwrap().get(2).unwrap().hash()),
&mut duplicate_slots_tracker,
&gossip_duplicate_confirmed_slots,
&progress,
&ancestors,
&descendants,
&mut progress,
&mut heaviest_subtree_fork_choice,
SlotStateUpdate::Duplicate,
);
assert!(duplicate_slots_tracker.contains(&2));
for slot in 2..=3 {
let slot_hash = bank_forks.read().unwrap().get(slot).unwrap().hash();
assert_eq!(
heaviest_subtree_fork_choice
.latest_invalid_ancestor(&(slot, slot_hash))
.unwrap(),
2
);
}
let slot1_hash = bank_forks.read().unwrap().get(1).unwrap().hash();
assert_eq!(
@@ -897,93 +790,14 @@ mod test {
3,
root,
Some(slot3_hash),
&mut duplicate_slots_tracker,
&gossip_duplicate_confirmed_slots,
&progress,
&ancestors,
&descendants,
&mut progress,
&mut heaviest_subtree_fork_choice,
SlotStateUpdate::DuplicateConfirmed,
);
for slot in 0..=3 {
let slot_hash = bank_forks.read().unwrap().get(slot).unwrap().hash();
assert!(heaviest_subtree_fork_choice
.is_duplicate_confirmed(&(slot, slot_hash))
.unwrap());
assert!(heaviest_subtree_fork_choice
.latest_invalid_ancestor(&(slot, slot_hash))
.is_none());
}
assert_eq!(
heaviest_subtree_fork_choice.best_overall_slot(),
(3, slot3_hash)
);
}
#[test]
fn test_state_descendant_confirmed_ancestor_duplicate() {
// Common state
let InitialState {
mut heaviest_subtree_fork_choice,
progress,
bank_forks,
..
} = setup();
let slot3_hash = bank_forks.read().unwrap().get(3).unwrap().hash();
assert_eq!(
heaviest_subtree_fork_choice.best_overall_slot(),
(3, slot3_hash)
);
let root = 0;
let mut duplicate_slots_tracker = DuplicateSlotsTracker::default();
let mut gossip_duplicate_confirmed_slots = GossipDuplicateConfirmedSlots::default();
// Mark 3 as duplicate confirmed
gossip_duplicate_confirmed_slots.insert(3, slot3_hash);
check_slot_agrees_with_cluster(
3,
root,
Some(slot3_hash),
&mut duplicate_slots_tracker,
&gossip_duplicate_confirmed_slots,
&progress,
&mut heaviest_subtree_fork_choice,
SlotStateUpdate::DuplicateConfirmed,
);
let verify_all_slots_duplicate_confirmed =
|bank_forks: &RwLock<BankForks>,
heaviest_subtree_fork_choice: &HeaviestSubtreeForkChoice| {
for slot in 0..=3 {
let slot_hash = bank_forks.read().unwrap().get(slot).unwrap().hash();
assert!(heaviest_subtree_fork_choice
.is_duplicate_confirmed(&(slot, slot_hash))
.unwrap());
assert!(heaviest_subtree_fork_choice
.latest_invalid_ancestor(&(slot, slot_hash))
.is_none());
}
};
verify_all_slots_duplicate_confirmed(&bank_forks, &heaviest_subtree_fork_choice);
assert_eq!(
heaviest_subtree_fork_choice.best_overall_slot(),
(3, slot3_hash)
);
// Mark ancestor 1 as duplicate, fork choice should be unaffected since
// slot 1 was duplicate confirmed by the confirmation on its
// descendant, 3.
let slot1_hash = bank_forks.read().unwrap().get(1).unwrap().hash();
check_slot_agrees_with_cluster(
1,
root,
Some(slot1_hash),
&mut duplicate_slots_tracker,
&gossip_duplicate_confirmed_slots,
&progress,
&mut heaviest_subtree_fork_choice,
SlotStateUpdate::Duplicate,
);
assert!(duplicate_slots_tracker.contains(&1));
verify_all_slots_duplicate_confirmed(&bank_forks, &heaviest_subtree_fork_choice);
assert_eq!(
heaviest_subtree_fork_choice.best_overall_slot(),
(3, slot3_hash)

View File

@@ -1,13 +1,16 @@
use crate::serve_repair::RepairType;
use itertools::Itertools;
use solana_gossip::{
cluster_info::ClusterInfo, contact_info::ContactInfo, crds::Cursor, epoch_slots::EpochSlots,
use crate::{
cluster_info::ClusterInfo, contact_info::ContactInfo, epoch_slots::EpochSlots,
serve_repair::RepairType,
};
use itertools::Itertools;
use solana_runtime::{bank_forks::BankForks, epoch_stakes::NodeIdToVoteAccounts};
use solana_sdk::{clock::Slot, pubkey::Pubkey};
use std::{
collections::{BTreeMap, HashMap, HashSet},
sync::{Arc, Mutex, RwLock},
sync::{
atomic::{AtomicU64, Ordering},
Arc, RwLock,
},
};
// Limit the size of cluster-slots map in case
@@ -19,26 +22,22 @@ pub type SlotPubkeys = HashMap<Pubkey, u64>;
#[derive(Default)]
pub struct ClusterSlots {
cluster_slots: RwLock<BTreeMap<Slot, Arc<RwLock<SlotPubkeys>>>>,
since: AtomicU64,
validator_stakes: RwLock<Arc<NodeIdToVoteAccounts>>,
epoch: RwLock<Option<u64>>,
cursor: Mutex<Cursor>,
}
impl ClusterSlots {
pub fn lookup(&self, slot: Slot) -> Option<Arc<RwLock<SlotPubkeys>>> {
self.cluster_slots.read().unwrap().get(&slot).cloned()
}
pub fn update(&self, root: Slot, cluster_info: &ClusterInfo, bank_forks: &RwLock<BankForks>) {
self.update_peers(bank_forks);
let epoch_slots = {
let mut cursor = self.cursor.lock().unwrap();
cluster_info.get_epoch_slots(&mut cursor)
};
self.update_internal(root, epoch_slots);
let since = self.since.load(Ordering::Relaxed);
let (epoch_slots, since) = cluster_info.get_epoch_slots_since(since);
self.update_internal(root, epoch_slots, since);
}
fn update_internal(&self, root: Slot, epoch_slots_list: Vec<EpochSlots>) {
fn update_internal(&self, root: Slot, epoch_slots_list: Vec<EpochSlots>, since: Option<u64>) {
// Attach validator's total stake.
let epoch_slots_list: Vec<_> = {
let validator_stakes = self.validator_stakes.read().unwrap();
@@ -87,6 +86,9 @@ impl ClusterSlots {
cluster_slots.split_off(&key);
}
}
if let Some(since) = since {
self.since.store(since + 1, Ordering::Relaxed);
}
}
pub fn collect(&self, id: &Pubkey) -> HashSet<Slot> {
@@ -204,20 +206,23 @@ mod tests {
fn test_default() {
let cs = ClusterSlots::default();
assert!(cs.cluster_slots.read().unwrap().is_empty());
assert_eq!(cs.since.load(Ordering::Relaxed), 0);
}
#[test]
fn test_update_noop() {
let cs = ClusterSlots::default();
cs.update_internal(0, vec![]);
cs.update_internal(0, vec![], None);
assert!(cs.cluster_slots.read().unwrap().is_empty());
assert_eq!(cs.since.load(Ordering::Relaxed), 0);
}
#[test]
fn test_update_empty() {
let cs = ClusterSlots::default();
let epoch_slot = EpochSlots::default();
cs.update_internal(0, vec![epoch_slot]);
cs.update_internal(0, vec![epoch_slot], Some(0));
assert_eq!(cs.since.load(Ordering::Relaxed), 1);
assert!(cs.lookup(0).is_none());
}
@@ -227,7 +232,8 @@ mod tests {
let cs = ClusterSlots::default();
let mut epoch_slot = EpochSlots::default();
epoch_slot.fill(&[0], 0);
cs.update_internal(0, vec![epoch_slot]);
cs.update_internal(0, vec![epoch_slot], Some(0));
assert_eq!(cs.since.load(Ordering::Relaxed), 1);
assert!(cs.lookup(0).is_none());
}
@@ -236,7 +242,8 @@ mod tests {
let cs = ClusterSlots::default();
let mut epoch_slot = EpochSlots::default();
epoch_slot.fill(&[1], 0);
cs.update_internal(0, vec![epoch_slot]);
cs.update_internal(0, vec![epoch_slot], Some(0));
assert_eq!(cs.since.load(Ordering::Relaxed), 1);
assert!(cs.lookup(0).is_none());
assert!(cs.lookup(1).is_some());
assert_eq!(
@@ -366,7 +373,7 @@ mod tests {
);
*cs.validator_stakes.write().unwrap() = map;
cs.update_internal(0, vec![epoch_slot]);
cs.update_internal(0, vec![epoch_slot], None);
assert!(cs.lookup(1).is_some());
assert_eq!(
cs.lookup(1)
@@ -383,7 +390,7 @@ mod tests {
let cs = ClusterSlots::default();
let mut epoch_slot = EpochSlots::default();
epoch_slot.fill(&[1], 0);
cs.update_internal(0, vec![epoch_slot]);
cs.update_internal(0, vec![epoch_slot], None);
let self_id = solana_sdk::pubkey::new_rand();
assert_eq!(
cs.generate_repairs_for_missing_slots(&self_id, 0),
@@ -397,7 +404,7 @@ mod tests {
let mut epoch_slot = EpochSlots::default();
epoch_slot.fill(&[1], 0);
let self_id = epoch_slot.from;
cs.update_internal(0, vec![epoch_slot]);
cs.update_internal(0, vec![epoch_slot], None);
let slots: Vec<Slot> = cs.collect(&self_id).into_iter().collect();
assert_eq!(slots, vec![1]);
}
@@ -408,7 +415,7 @@ mod tests {
let mut epoch_slot = EpochSlots::default();
epoch_slot.fill(&[1], 0);
let self_id = epoch_slot.from;
cs.update_internal(0, vec![epoch_slot]);
cs.update_internal(0, vec![epoch_slot], None);
assert!(cs
.generate_repairs_for_missing_slots(&self_id, 0)
.is_empty());

View File

@@ -1,32 +1,28 @@
use crate::cluster_slots::ClusterSlots;
use crossbeam_channel::{Receiver, RecvTimeoutError, Sender};
use solana_gossip::cluster_info::ClusterInfo;
use solana_ledger::blockstore::Blockstore;
use crate::{cluster_info::ClusterInfo, cluster_slots::ClusterSlots};
use solana_ledger::blockstore::{Blockstore, CompletedSlotsReceiver};
use solana_measure::measure::Measure;
use solana_runtime::bank_forks::BankForks;
use solana_sdk::{clock::Slot, pubkey::Pubkey};
use std::{
sync::{
atomic::{AtomicBool, Ordering},
mpsc::RecvTimeoutError,
{Arc, RwLock},
},
thread::{self, Builder, JoinHandle},
time::{Duration, Instant},
};
pub type ClusterSlotsUpdateReceiver = Receiver<Vec<Slot>>;
pub type ClusterSlotsUpdateSender = Sender<Vec<Slot>>;
#[derive(Default, Debug)]
struct ClusterSlotsServiceTiming {
pub lowest_slot_elapsed: u64,
pub process_cluster_slots_updates_elapsed: u64,
pub update_completed_slots_elapsed: u64,
}
impl ClusterSlotsServiceTiming {
fn update(&mut self, lowest_slot_elapsed: u64, process_cluster_slots_updates_elapsed: u64) {
fn update(&mut self, lowest_slot_elapsed: u64, update_completed_slots_elapsed: u64) {
self.lowest_slot_elapsed += lowest_slot_elapsed;
self.process_cluster_slots_updates_elapsed += process_cluster_slots_updates_elapsed;
self.update_completed_slots_elapsed += update_completed_slots_elapsed;
}
}
@@ -40,12 +36,12 @@ impl ClusterSlotsService {
cluster_slots: Arc<ClusterSlots>,
bank_forks: Arc<RwLock<BankForks>>,
cluster_info: Arc<ClusterInfo>,
cluster_slots_update_receiver: ClusterSlotsUpdateReceiver,
completed_slots_receiver: CompletedSlotsReceiver,
exit: Arc<AtomicBool>,
) -> Self {
let id = cluster_info.id();
Self::initialize_lowest_slot(id, &blockstore, &cluster_info);
Self::initialize_epoch_slots(&bank_forks, &cluster_info);
Self::initialize_epoch_slots(&blockstore, &cluster_info, &completed_slots_receiver);
let t_cluster_slots_service = Builder::new()
.name("solana-cluster-slots-service".to_string())
.spawn(move || {
@@ -54,7 +50,7 @@ impl ClusterSlotsService {
cluster_slots,
bank_forks,
cluster_info,
cluster_slots_update_receiver,
completed_slots_receiver,
exit,
)
})
@@ -74,7 +70,7 @@ impl ClusterSlotsService {
cluster_slots: Arc<ClusterSlots>,
bank_forks: Arc<RwLock<BankForks>>,
cluster_info: Arc<ClusterInfo>,
cluster_slots_update_receiver: ClusterSlotsUpdateReceiver,
completed_slots_receiver: CompletedSlotsReceiver,
exit: Arc<AtomicBool>,
) {
let mut cluster_slots_service_timing = ClusterSlotsServiceTiming::default();
@@ -83,8 +79,7 @@ impl ClusterSlotsService {
if exit.load(Ordering::Relaxed) {
break;
}
let slots = match cluster_slots_update_receiver.recv_timeout(Duration::from_millis(200))
{
let slots = match completed_slots_receiver.recv_timeout(Duration::from_millis(200)) {
Ok(slots) => Some(slots),
Err(RecvTimeoutError::Timeout) => None,
Err(RecvTimeoutError::Disconnected) => {
@@ -98,21 +93,17 @@ impl ClusterSlotsService {
let lowest_slot = blockstore.lowest_slot();
Self::update_lowest_slot(&id, lowest_slot, &cluster_info);
lowest_slot_elapsed.stop();
let mut process_cluster_slots_updates_elapsed =
Measure::start("process_cluster_slots_updates_elapsed");
let mut update_completed_slots_elapsed =
Measure::start("update_completed_slots_elapsed");
if let Some(slots) = slots {
Self::process_cluster_slots_updates(
slots,
&cluster_slots_update_receiver,
&cluster_info,
);
Self::update_completed_slots(slots, &completed_slots_receiver, &cluster_info);
}
cluster_slots.update(new_root, &cluster_info, &bank_forks);
process_cluster_slots_updates_elapsed.stop();
update_completed_slots_elapsed.stop();
cluster_slots_service_timing.update(
lowest_slot_elapsed.as_us(),
process_cluster_slots_updates_elapsed.as_us(),
update_completed_slots_elapsed.as_us(),
);
if last_stats.elapsed().as_secs() > 2 {
@@ -124,8 +115,8 @@ impl ClusterSlotsService {
i64
),
(
"process_cluster_slots_updates_elapsed",
cluster_slots_service_timing.process_cluster_slots_updates_elapsed,
"update_completed_slots_elapsed",
cluster_slots_service_timing.update_completed_slots_elapsed,
i64
),
);
@@ -135,12 +126,12 @@ impl ClusterSlotsService {
}
}
fn process_cluster_slots_updates(
fn update_completed_slots(
mut slots: Vec<Slot>,
cluster_slots_update_receiver: &ClusterSlotsUpdateReceiver,
completed_slots_receiver: &CompletedSlotsReceiver,
cluster_info: &ClusterInfo,
) {
while let Ok(mut more) = cluster_slots_update_receiver.try_recv() {
while let Ok(mut more) = completed_slots_receiver.try_recv() {
slots.append(&mut more);
}
#[allow(clippy::stable_sort_primitive)]
@@ -163,16 +154,30 @@ impl ClusterSlotsService {
cluster_info.push_lowest_slot(*id, lowest_slot);
}
fn initialize_epoch_slots(bank_forks: &RwLock<BankForks>, cluster_info: &ClusterInfo) {
// TODO: Should probably incorporate slots that were replayed on startup,
// and maybe some that were frozen < snapshot root in case validators restart
// from newer snapshots and lose history.
let frozen_banks = bank_forks.read().unwrap().frozen_banks();
let mut frozen_bank_slots: Vec<Slot> = frozen_banks.keys().cloned().collect();
frozen_bank_slots.sort_unstable();
fn initialize_epoch_slots(
blockstore: &Blockstore,
cluster_info: &ClusterInfo,
completed_slots_receiver: &CompletedSlotsReceiver,
) {
let root = blockstore.last_root();
let mut slots: Vec<_> = blockstore
.live_slots_iterator(root)
.filter_map(|(slot, slot_meta)| {
if slot_meta.is_full() {
Some(slot)
} else {
None
}
})
.collect();
if !frozen_bank_slots.is_empty() {
cluster_info.push_epoch_slots(&frozen_bank_slots);
while let Ok(mut more) = completed_slots_receiver.try_recv() {
slots.append(&mut more);
}
slots.sort_unstable();
slots.dedup();
if !slots.is_empty() {
cluster_info.push_epoch_slots(&slots);
}
}
}
@@ -180,21 +185,19 @@ impl ClusterSlotsService {
#[cfg(test)]
mod test {
use super::*;
use solana_gossip::{cluster_info::Node, crds_value::CrdsValueLabel};
use crate::cluster_info::Node;
#[test]
pub fn test_update_lowest_slot() {
let pubkey = Pubkey::new_unique();
let node_info = Node::new_localhost_with_pubkey(&pubkey);
let node_info = Node::new_localhost_with_pubkey(&Pubkey::default());
let cluster_info = ClusterInfo::new_with_invalid_keypair(node_info.info);
ClusterSlotsService::update_lowest_slot(&pubkey, 5, &cluster_info);
ClusterSlotsService::update_lowest_slot(&Pubkey::default(), 5, &cluster_info);
cluster_info.flush_push_queue();
let lowest = {
let label = CrdsValueLabel::LowestSlot(pubkey);
let gossip = cluster_info.gossip.read().unwrap();
let entry = gossip.crds.get(&label).unwrap();
entry.value.lowest_slot().unwrap().clone()
};
let lowest = cluster_info
.get_lowest_slot_for_node(&Pubkey::default(), None, |lowest_slot, _| {
lowest_slot.clone()
})
.unwrap();
assert_eq!(lowest.lowest, 5);
}
}

View File

@@ -1,7 +1,6 @@
use crate::consensus::Stake;
use crate::{consensus::Stake, rpc_subscriptions::RpcSubscriptions};
use solana_measure::measure::Measure;
use solana_metrics::datapoint_info;
use solana_rpc::rpc_subscriptions::RpcSubscriptions;
use solana_runtime::{
bank::Bank,
commitment::{BlockCommitment, BlockCommitmentCache, CommitmentSlots, VOTE_THRESHOLD_SIZE},

View File

@@ -1,7 +1,7 @@
use crate::{max_slots::MaxSlots, rpc_subscriptions::RpcSubscriptions};
use crossbeam_channel::{Receiver, RecvTimeoutError, Sender};
use solana_ledger::blockstore::{Blockstore, CompletedDataSetInfo};
use solana_ledger::entry::Entry;
use solana_rpc::{max_slots::MaxSlots, rpc_subscriptions::RpcSubscriptions};
use solana_sdk::signature::Signature;
use std::{
sync::{

View File

@@ -1,5 +1,4 @@
use crate::{
heaviest_subtree_fork_choice::HeaviestSubtreeForkChoice,
latest_validator_votes_for_frozen_banks::LatestValidatorVotesForFrozenBanks,
progress_map::{LockoutIntervals, ProgressMap},
};
@@ -92,8 +91,6 @@ pub type Stake = u64;
pub type VotedStakes = HashMap<Slot, Stake>;
pub type PubkeyVotes = Vec<(Pubkey, Slot)>;
// lint warning "bank_weight is never read"
#[allow(dead_code)]
pub(crate) struct ComputedBankState {
pub voted_stakes: VotedStakes,
pub total_stake: Stake,
@@ -267,7 +264,7 @@ impl Tower {
};
for vote in &vote_state.votes {
lockout_intervals
.entry(vote.last_locked_out_slot())
.entry(vote.expiration_slot())
.or_insert_with(Vec::new)
.push((vote.slot, key));
}
@@ -530,31 +527,31 @@ impl Tower {
false
}
pub fn is_locked_out(&self, slot: Slot, ancestors: &HashSet<Slot>) -> bool {
pub fn is_locked_out(&self, slot: Slot, ancestors: &HashMap<Slot, HashSet<Slot>>) -> bool {
assert!(ancestors.contains_key(&slot));
if !self.is_recent(slot) {
return true;
}
// Check if a slot is locked out by simulating adding a vote for that
// slot to the current lockouts to pop any expired votes. If any of the
// remaining voted slots are on a different fork from the checked slot,
// it's still locked out.
let mut lockouts = self.lockouts.clone();
lockouts.process_slot_vote_unchecked(slot);
for vote in &lockouts.votes {
if slot != vote.slot && !ancestors.contains(&vote.slot) {
if vote.slot == slot {
continue;
}
if !ancestors[&slot].contains(&vote.slot) {
return true;
}
}
if let Some(root_slot) = lockouts.root_slot {
// This case should never happen because bank forks purges all
// non-descendants of the root every time root is set
if slot != root_slot {
// This case should never happen because bank forks purges all
// non-descendants of the root every time root is set
assert!(
ancestors.contains(&root_slot),
ancestors[&slot].contains(&root_slot),
"ancestors: {:?}, slot: {} root: {}",
ancestors,
ancestors[&slot],
slot,
root_slot
);
@@ -564,17 +561,6 @@ impl Tower {
false
}
fn is_candidate_slot_descendant_of_last_vote(
candidate_slot: Slot,
last_voted_slot: Slot,
ancestors: &HashMap<Slot, HashSet<u64>>,
) -> Option<bool> {
ancestors
.get(&candidate_slot)
.map(|candidate_slot_ancestors| candidate_slot_ancestors.contains(&last_voted_slot))
}
#[allow(clippy::too_many_arguments)]
fn make_check_switch_threshold_decision(
&self,
switch_slot: u64,
@@ -583,11 +569,9 @@ impl Tower {
progress: &ProgressMap,
total_stake: u64,
epoch_vote_accounts: &HashMap<Pubkey, (u64, ArcVoteAccount)>,
latest_validator_votes_for_frozen_banks: &LatestValidatorVotesForFrozenBanks,
heaviest_subtree_fork_choice: &HeaviestSubtreeForkChoice,
) -> SwitchForkDecision {
self.last_voted_slot_hash()
.map(|(last_voted_slot, last_voted_hash)| {
self.last_voted_slot()
.map(|last_voted_slot| {
let root = self.root();
let empty_ancestors = HashSet::default();
let empty_ancestors_due_to_minor_unsynced_ledger = || {
@@ -676,7 +660,7 @@ impl Tower {
if last_vote_ancestors.contains(&switch_slot) {
if self.is_stray_last_vote() {
return suspended_decision_due_to_major_unsynced_ledger();
} else if let Some(latest_duplicate_ancestor) = heaviest_subtree_fork_choice.latest_invalid_ancestor(&(last_voted_slot, last_voted_hash)) {
} else if let Some(latest_duplicate_ancestor) = progress.latest_unconfirmed_duplicate_ancestor(last_voted_slot) {
// We're rolling back because one of the ancestors of the last vote was a duplicate. In this
// case, it's acceptable if the switch candidate is one of ancestors of the previous vote,
// just fail the switch check because there's no point in voting on an ancestor. ReplayStage
@@ -718,9 +702,13 @@ impl Tower {
// then use this bank as a representative for the fork.
|| descendants.iter().any(|d| progress.get_fork_stats(*d).map(|stats| stats.computed).unwrap_or(false))
|| *candidate_slot == last_voted_slot
// Ignore if the `candidate_slot` is a descendant of the `last_voted_slot`, since we do not
// want to count votes on the same fork.
|| Self::is_candidate_slot_descendant_of_last_vote(*candidate_slot, last_voted_slot, ancestors).expect("exists in descendants map, so must exist in ancestors map")
|| ancestors
.get(&candidate_slot)
.expect(
"empty descendants implies this is a child, not parent of root, so must
exist in the ancestors map",
)
.contains(&last_voted_slot)
|| *candidate_slot <= root
{
continue;
@@ -740,9 +728,8 @@ impl Tower {
.unwrap()
.fork_stats
.lockout_intervals;
// Find any locked out intervals for vote accounts in this bank with
// `lockout_interval_end` >= `last_vote`, which implies they are locked out at
// `last_vote` on another fork.
// Find any locked out intervals in this bank with endpoint >= last_vote,
// implies they are locked out at last_vote
for (_lockout_interval_end, intervals_keyed_by_end) in lockout_intervals.range((Included(last_voted_slot), Unbounded)) {
for (lockout_interval_start, vote_account_pubkey) in intervals_keyed_by_end {
if locked_out_vote_accounts.contains(vote_account_pubkey) {
@@ -765,66 +752,21 @@ impl Tower {
.map(|(stake, _)| *stake)
.unwrap_or(0);
locked_out_stake += stake;
if (locked_out_stake as f64 / total_stake as f64) > SWITCH_FORK_THRESHOLD {
return SwitchForkDecision::SwitchProof(switch_proof);
}
locked_out_vote_accounts.insert(vote_account_pubkey);
}
}
}
}
// Check the latest votes for potentially gossip votes that haven't landed yet
for (vote_account_pubkey, (candidate_latest_frozen_vote, _candidate_latest_frozen_vote_hash)) in latest_validator_votes_for_frozen_banks.max_gossip_frozen_votes() {
if locked_out_vote_accounts.contains(&vote_account_pubkey) {
continue;
}
if *candidate_latest_frozen_vote > last_voted_slot
&&
// Because `candidate_latest_frozen_vote` is the last vote made by some validator
// in the cluster for a frozen bank `B` observed through gossip, we may have cleared
// that frozen bank `B` because we `set_root(root)` for a `root` on a different fork,
// like so:
//
// |----------X ------candidate_latest_frozen_vote (frozen)
// old root
// |----------new root ----last_voted_slot
//
// In most cases, because `last_voted_slot` must be a descendant of `root`, then
// if `candidate_latest_frozen_vote` is not found in the ancestors/descendants map (recall these
// directly reflect the state of BankForks), this implies that `B` was pruned from BankForks
// because it was on a different fork than `last_voted_slot`, and thus this vote for `candidate_latest_frozen_vote`
// should be safe to count towards the switching proof:
//
// However, there is also the possibility that `last_voted_slot` is a stray, in which
// case we cannot make this conclusion as we do not know the ancestors/descendants
// of strays. Hence we err on the side of caution here and ignore this vote. This
// is ok because validators voting on different unrooted forks should eventually vote
// on some descendant of the root, at which time they can be included in switching proofs.
!Self::is_candidate_slot_descendant_of_last_vote(
*candidate_latest_frozen_vote, last_voted_slot, ancestors)
.unwrap_or(true) {
let stake = epoch_vote_accounts
.get(vote_account_pubkey)
.map(|(stake, _)| *stake)
.unwrap_or(0);
locked_out_stake += stake;
if (locked_out_stake as f64 / total_stake as f64) > SWITCH_FORK_THRESHOLD {
return SwitchForkDecision::SwitchProof(switch_proof);
}
locked_out_vote_accounts.insert(vote_account_pubkey);
}
if (locked_out_stake as f64 / total_stake as f64) > SWITCH_FORK_THRESHOLD {
SwitchForkDecision::SwitchProof(switch_proof)
} else {
SwitchForkDecision::FailedSwitchThreshold(locked_out_stake, total_stake)
}
// We have not detected sufficient lockout past the last voted slot to generate
// a switching proof
SwitchForkDecision::FailedSwitchThreshold(locked_out_stake, total_stake)
})
.unwrap_or(SwitchForkDecision::SameFork)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn check_switch_threshold(
&mut self,
switch_slot: u64,
@@ -833,8 +775,6 @@ impl Tower {
progress: &ProgressMap,
total_stake: u64,
epoch_vote_accounts: &HashMap<Pubkey, (u64, ArcVoteAccount)>,
latest_validator_votes_for_frozen_banks: &LatestValidatorVotesForFrozenBanks,
heaviest_subtree_fork_choice: &HeaviestSubtreeForkChoice,
) -> SwitchForkDecision {
let decision = self.make_check_switch_threshold_decision(
switch_slot,
@@ -843,8 +783,6 @@ impl Tower {
progress,
total_stake,
epoch_vote_accounts,
latest_validator_votes_for_frozen_banks,
heaviest_subtree_fork_choice,
);
let new_check = Some((switch_slot, decision.clone()));
if new_check != self.last_switch_threshold_check {
@@ -1364,11 +1302,11 @@ pub mod test {
use super::*;
use crate::{
cluster_info_vote_listener::VoteTracker,
cluster_slot_state_verifier::{DuplicateSlotsTracker, GossipDuplicateConfirmedSlots},
cluster_slot_state_verifier::GossipDuplicateConfirmedSlots,
cluster_slots::ClusterSlots,
fork_choice::{ForkChoice, SelectVoteAndResetForkResult},
heaviest_subtree_fork_choice::SlotHashKey,
progress_map::ForkProgress,
fork_choice::SelectVoteAndResetForkResult,
heaviest_subtree_fork_choice::{HeaviestSubtreeForkChoice, SlotHashKey},
progress_map::{DuplicateStats, ForkProgress},
replay_stage::{HeaviestForkFailures, ReplayStage},
unfrozen_gossip_verified_vote_hashes::UnfrozenGossipVerifiedVoteHashes,
};
@@ -1382,7 +1320,7 @@ pub mod test {
},
};
use solana_sdk::{
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
account::{Account, AccountSharedData, WritableAccount},
clock::Slot,
hash::Hash,
pubkey::Pubkey,
@@ -1445,9 +1383,9 @@ pub mod test {
while let Some(visit) = walk.get() {
let slot = visit.node().data;
self.progress
.entry(slot)
.or_insert_with(|| ForkProgress::new(Hash::default(), None, None, 0, 0));
self.progress.entry(slot).or_insert_with(|| {
ForkProgress::new(Hash::default(), None, DuplicateStats::default(), None, 0, 0)
});
if self.bank_forks.read().unwrap().get(slot).is_some() {
walk.forward();
continue;
@@ -1535,8 +1473,6 @@ pub mod test {
&descendants,
&self.progress,
tower,
&self.latest_validator_votes_for_frozen_banks,
&self.heaviest_subtree_fork_choice,
);
// Make sure this slot isn't locked out or failing threshold
@@ -1561,7 +1497,6 @@ pub mod test {
&AbsRequestSender::default(),
None,
&mut self.heaviest_subtree_fork_choice,
&mut DuplicateSlotsTracker::default(),
&mut GossipDuplicateConfirmedSlots::default(),
&mut UnfrozenGossipVerifiedVoteHashes::default(),
&mut true,
@@ -1600,7 +1535,9 @@ pub mod test {
) {
self.progress
.entry(slot)
.or_insert_with(|| ForkProgress::new(Hash::default(), None, None, 0, 0))
.or_insert_with(|| {
ForkProgress::new(Hash::default(), None, DuplicateStats::default(), None, 0, 0)
})
.fork_stats
.lockout_intervals
.entry(lockout_interval.1)
@@ -1707,7 +1644,14 @@ pub mod test {
let mut progress = ProgressMap::default();
progress.insert(
0,
ForkProgress::new(bank0.last_blockhash(), None, None, 0, 0),
ForkProgress::new(
bank0.last_blockhash(),
None,
DuplicateStats::default(),
None,
0,
0,
),
);
let bank_forks = BankForks::new(bank0);
let heaviest_subtree_fork_choice =
@@ -1718,11 +1662,11 @@ pub mod test {
fn gen_stakes(stake_votes: &[(u64, &[u64])]) -> Vec<(Pubkey, (u64, ArcVoteAccount))> {
let mut stakes = vec![];
for (lamports, votes) in stake_votes {
let mut account = AccountSharedData::from(Account {
let mut account = AccountSharedData {
data: vec![0; VoteState::size_of()],
lamports: *lamports,
..Account::default()
});
..AccountSharedData::default()
};
let mut vote_state = VoteState::default();
for slot in *votes {
vote_state.process_slot_vote_unchecked(*slot);
@@ -1842,8 +1786,7 @@ pub mod test {
/ (tr(44)
// Minor fork 2
/ (tr(45) / (tr(46) / (tr(47) / (tr(48) / (tr(49) / (tr(50)))))))
/ (tr(110)))
/ tr(112))));
/ (tr(110))))));
// Fill the BankForks according to the above fork structure
vote_simulator.fill_bank_forks(forks, &HashMap::new());
@@ -1866,46 +1809,21 @@ pub mod test {
let mut tower = Tower::new_with_key(&vote_simulator.node_pubkeys[0]);
// Last vote is 47
tower.record_vote(
47,
vote_simulator
.bank_forks
.read()
.unwrap()
.get(47)
.unwrap()
.hash(),
);
tower.record_vote(47, Hash::default());
// Trying to switch to an ancestor of last vote should only not panic
// if the current vote has a duplicate ancestor
let ancestor_of_voted_slot = 43;
let duplicate_ancestor1 = 44;
let duplicate_ancestor2 = 45;
vote_simulator
.heaviest_subtree_fork_choice
.mark_fork_invalid_candidate(&(
duplicate_ancestor1,
vote_simulator
.bank_forks
.read()
.unwrap()
.get(duplicate_ancestor1)
.unwrap()
.hash(),
));
vote_simulator
.heaviest_subtree_fork_choice
.mark_fork_invalid_candidate(&(
duplicate_ancestor2,
vote_simulator
.bank_forks
.read()
.unwrap()
.get(duplicate_ancestor2)
.unwrap()
.hash(),
));
vote_simulator.progress.set_unconfirmed_duplicate_slot(
duplicate_ancestor1,
&descendants.get(&duplicate_ancestor1).unwrap(),
);
vote_simulator.progress.set_unconfirmed_duplicate_slot(
duplicate_ancestor2,
&descendants.get(&duplicate_ancestor2).unwrap(),
);
assert_eq!(
tower.check_switch_threshold(
ancestor_of_voted_slot,
@@ -1914,8 +1832,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchDuplicateRollback(duplicate_ancestor2)
);
@@ -1928,18 +1844,11 @@ pub mod test {
confirm_ancestors.push(duplicate_ancestor2);
}
for (i, duplicate_ancestor) in confirm_ancestors.into_iter().enumerate() {
vote_simulator
.heaviest_subtree_fork_choice
.mark_fork_valid_candidate(&(
duplicate_ancestor,
vote_simulator
.bank_forks
.read()
.unwrap()
.get(duplicate_ancestor)
.unwrap()
.hash(),
));
vote_simulator.progress.set_confirmed_duplicate_slot(
duplicate_ancestor,
ancestors.get(&duplicate_ancestor).unwrap(),
&descendants.get(&duplicate_ancestor).unwrap(),
);
let res = tower.check_switch_threshold(
ancestor_of_voted_slot,
&ancestors,
@@ -1947,8 +1856,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
);
if i == 0 {
assert_eq!(
@@ -1984,8 +1891,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::SameFork
);
@@ -1999,8 +1904,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
@@ -2016,8 +1919,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
@@ -2033,8 +1934,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
@@ -2050,8 +1949,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
@@ -2069,8 +1966,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
@@ -2086,8 +1981,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::SwitchProof(Hash::default())
);
@@ -2104,8 +1997,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::SwitchProof(Hash::default())
);
@@ -2131,115 +2022,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
}
#[test]
fn test_switch_threshold_use_gossip_votes() {
let num_validators = 2;
let (bank0, mut vote_simulator, total_stake) = setup_switch_test(2);
let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
let descendants = vote_simulator
.bank_forks
.read()
.unwrap()
.descendants()
.clone();
let mut tower = Tower::new_with_key(&vote_simulator.node_pubkeys[0]);
let other_vote_account = vote_simulator.vote_pubkeys[1];
// Last vote is 47
tower.record_vote(47, Hash::default());
// Trying to switch to another fork at 110 should fail
assert_eq!(
tower.check_switch_threshold(
110,
&ancestors,
&descendants,
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, num_validators * 10000)
);
// Adding a vote on the descendant shouldn't count toward the switch threshold
vote_simulator.simulate_lockout_interval(50, (49, 100), &other_vote_account);
assert_eq!(
tower.check_switch_threshold(
110,
&ancestors,
&descendants,
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
// Adding a later vote from gossip that isn't on the same fork should count toward the
// switch threshold
vote_simulator
.latest_validator_votes_for_frozen_banks
.check_add_vote(
other_vote_account,
112,
Some(
vote_simulator
.bank_forks
.read()
.unwrap()
.get(112)
.unwrap()
.hash(),
),
false,
);
assert_eq!(
tower.check_switch_threshold(
110,
&ancestors,
&descendants,
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::SwitchProof(Hash::default())
);
// If we now set a root that causes slot 112 to be purged from BankForks, then
// the switch proof will now fail since that validator's vote can no longer be
// included in the switching proof
vote_simulator.set_root(44);
let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
let descendants = vote_simulator
.bank_forks
.read()
.unwrap()
.descendants()
.clone();
assert_eq!(
tower.check_switch_threshold(
110,
&ancestors,
&descendants,
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
@@ -2521,14 +2303,16 @@ pub mod test {
#[test]
fn test_is_locked_out_empty() {
let tower = Tower::new_for_tests(0, 0.67);
let ancestors = HashSet::new();
let ancestors = vec![(0, HashSet::new())].into_iter().collect();
assert!(!tower.is_locked_out(0, &ancestors));
}
#[test]
fn test_is_locked_out_root_slot_child_pass() {
let mut tower = Tower::new_for_tests(0, 0.67);
let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
let ancestors = vec![(1, vec![0].into_iter().collect())]
.into_iter()
.collect();
tower.lockouts.root_slot = Some(0);
assert!(!tower.is_locked_out(1, &ancestors));
}
@@ -2536,7 +2320,9 @@ pub mod test {
#[test]
fn test_is_locked_out_root_slot_sibling_fail() {
let mut tower = Tower::new_for_tests(0, 0.67);
let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
let ancestors = vec![(2, vec![0].into_iter().collect())]
.into_iter()
.collect();
tower.lockouts.root_slot = Some(0);
tower.record_vote(1, Hash::default());
assert!(tower.is_locked_out(2, &ancestors));
@@ -2567,7 +2353,9 @@ pub mod test {
#[test]
fn test_is_locked_out_double_vote() {
let mut tower = Tower::new_for_tests(0, 0.67);
let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
let ancestors = vec![(1, vec![0].into_iter().collect()), (0, HashSet::new())]
.into_iter()
.collect();
tower.record_vote(0, Hash::default());
tower.record_vote(1, Hash::default());
assert!(tower.is_locked_out(0, &ancestors));
@@ -2576,7 +2364,9 @@ pub mod test {
#[test]
fn test_is_locked_out_child() {
let mut tower = Tower::new_for_tests(0, 0.67);
let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
let ancestors = vec![(1, vec![0].into_iter().collect())]
.into_iter()
.collect();
tower.record_vote(0, Hash::default());
assert!(!tower.is_locked_out(1, &ancestors));
}
@@ -2584,7 +2374,13 @@ pub mod test {
#[test]
fn test_is_locked_out_sibling() {
let mut tower = Tower::new_for_tests(0, 0.67);
let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
let ancestors = vec![
(0, HashSet::new()),
(1, vec![0].into_iter().collect()),
(2, vec![0].into_iter().collect()),
]
.into_iter()
.collect();
tower.record_vote(0, Hash::default());
tower.record_vote(1, Hash::default());
assert!(tower.is_locked_out(2, &ancestors));
@@ -2593,7 +2389,13 @@ pub mod test {
#[test]
fn test_is_locked_out_last_vote_expired() {
let mut tower = Tower::new_for_tests(0, 0.67);
let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
let ancestors = vec![
(0, HashSet::new()),
(1, vec![0].into_iter().collect()),
(4, vec![0].into_iter().collect()),
]
.into_iter()
.collect();
tower.record_vote(0, Hash::default());
tower.record_vote(1, Hash::default());
assert!(!tower.is_locked_out(4, &ancestors));
@@ -2657,7 +2459,7 @@ pub mod test {
});
let set: HashSet<u64> = vec![0u64, 1u64].into_iter().collect();
let ancestors: HashMap<u64, HashSet<u64>> = [(2u64, set)].iter().cloned().collect();
Tower::update_ancestor_voted_stakes(&mut voted_stakes, 2, account.lamports(), &ancestors);
Tower::update_ancestor_voted_stakes(&mut voted_stakes, 2, account.lamports, &ancestors);
assert_eq!(voted_stakes[&0], 1);
assert_eq!(voted_stakes[&1], 1);
assert_eq!(voted_stakes[&2], 1);
@@ -2918,8 +2720,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::SameFork
);
@@ -2933,8 +2733,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
@@ -2949,8 +2747,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::SwitchProof(Hash::default())
);
@@ -3020,8 +2816,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
@@ -3036,8 +2830,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
);
@@ -3052,8 +2844,6 @@ pub mod test {
&vote_simulator.progress,
total_stake,
bank0.epoch_vote_accounts(0).unwrap(),
&vote_simulator.latest_validator_votes_for_frozen_banks,
&vote_simulator.heaviest_subtree_fork_choice,
),
SwitchForkDecision::SwitchProof(Hash::default())
);

View File

@@ -1,17 +1,16 @@
use {
crate::crds_value::MAX_WALLCLOCK,
solana_sdk::{
pubkey::Pubkey,
rpc_port,
sanitize::{Sanitize, SanitizeError},
signature::{Keypair, Signer},
timing::timestamp,
},
std::net::{IpAddr, SocketAddr},
};
use crate::crds_value::MAX_WALLCLOCK;
use solana_sdk::pubkey::Pubkey;
#[cfg(test)]
use solana_sdk::rpc_port;
use solana_sdk::sanitize::{Sanitize, SanitizeError};
#[cfg(test)]
use solana_sdk::signature::{Keypair, Signer};
use solana_sdk::timing::timestamp;
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
use std::net::{IpAddr, SocketAddr};
/// Structure representing a node on the network
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, AbiExample, Deserialize, Serialize)]
#[derive(Serialize, Deserialize, Clone, Debug, AbiExample)]
pub struct ContactInfo {
pub id: Pubkey,
/// gossip address
@@ -49,13 +48,34 @@ impl Sanitize for ContactInfo {
}
}
impl Ord for ContactInfo {
fn cmp(&self, other: &Self) -> Ordering {
self.id.cmp(&other.id)
}
}
impl PartialOrd for ContactInfo {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for ContactInfo {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Eq for ContactInfo {}
#[macro_export]
macro_rules! socketaddr {
($ip:expr, $port:expr) => {
std::net::SocketAddr::from((std::net::Ipv4Addr::from($ip), $port))
};
($str:expr) => {{
$str.parse::<std::net::SocketAddr>().unwrap()
let a: std::net::SocketAddr = $str.parse().unwrap();
a
}};
}
#[macro_export]
@@ -134,8 +154,8 @@ impl ContactInfo {
}
}
// Used in tests
pub fn new_with_pubkey_socketaddr(pubkey: &Pubkey, bind_addr: &SocketAddr) -> Self {
#[cfg(test)]
pub(crate) fn new_with_pubkey_socketaddr(pubkey: &Pubkey, bind_addr: &SocketAddr) -> Self {
fn next_port(addr: &SocketAddr, nxt: u16) -> SocketAddr {
let mut nxt_addr = *addr;
nxt_addr.set_port(addr.port() + nxt);
@@ -168,8 +188,8 @@ impl ContactInfo {
}
}
// Used in tests
pub fn new_with_socketaddr(bind_addr: &SocketAddr) -> Self {
#[cfg(test)]
pub(crate) fn new_with_socketaddr(bind_addr: &SocketAddr) -> Self {
let keypair = Keypair::new();
Self::new_with_pubkey_socketaddr(&keypair.pubkey(), bind_addr)
}

File diff suppressed because it is too large Load Diff

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