Compare commits

..

464 Commits
v1.3.1 ... v1.2

Author SHA1 Message Date
Trent Nelson
f55e637796 CI: Drop redundant cargo audit run
There is a Cargo.lock in this dir, so `scripts/cargo-for-all-lock-files.sh ...` covers it
2020-10-02 17:53:45 -07:00
Trent Nelson
7e57c5cefe CI: Split cargo-audit off to its own buildkite job run with cargo 1.46.0
Needed to support new cargo audit advisory format https://github.com/RustSec/advisory-db/issues/414
2020-10-02 17:53:45 -07:00
Michael Vines
f7a87291c3 Expose validator cli arguments for pubsub buffer tuning 2020-10-02 11:53:07 -07:00
Michael Vines
20613d66f0 Bump version to v1.2.33 2020-10-02 08:25:48 -07:00
Michael Vines
90faffdb92 Revert "don't commit! disable audit"
This reverts commit b5305587ea.
2020-10-02 08:20:13 -07:00
Jack May
8c989da683 Fix zero-len slice translations 2020-10-02 08:17:59 -07:00
Jack May
b5305587ea don't commit! disable audit 2020-10-02 08:17:00 -07:00
Jack May
a61d24bfa9 Check CPI program is executable 2020-10-02 08:17:00 -07:00
mergify[bot]
c162ac27dd Add ci env to travis config (#12608) (#12609)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit a17907b9a2)

Co-authored-by: Dan Albert <dan@solana.com>
2020-10-01 06:11:38 +00:00
mergify[bot]
2b22ef1650 Tighten docs publishing flow (#12572) (#12593)
(cherry picked from commit ede19ef33b)

Co-authored-by: Dan Albert <dan@solana.com>
2020-09-30 18:42:27 +00:00
Michael Vines
456e300244 Bump version to v1.2.32 2020-09-29 22:33:41 +00:00
mergify[bot]
27948563f5 Switch get_program_accounts to use base64 (#12558)
(cherry picked from commit 182552c2e7)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-29 20:33:59 +00:00
mergify[bot]
af91768a24 Increase rpc pubsub max payload to unblock large account notifications (#12548) (#12550)
(cherry picked from commit 36d55c0667)

Co-authored-by: Justin Starry <justin@solana.com>
2020-09-29 17:32:29 +00:00
Michael Vines
94102f4501 Cargo.lock 2020-09-28 13:00:46 -07:00
Michael Vines
f53e0af159 Bump version to v1.2.31 2020-09-28 12:59:47 -07:00
mergify[bot]
227804c306 Improve 'Failed to create snapshot archive' warning message (bp #12496) (#12499)
* Improve 'Failed to create snapshot archive' warning message

(cherry picked from commit 5dcf348098)

# Conflicts:
#	ledger/src/snapshot_utils.rs

* Update snapshot_utils.rs

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-26 01:12:39 +00:00
Trent Nelson
4fd298abd5 Bump jsonrpc crates to 15.0.0 (bp #12491) 2020-09-25 20:24:39 +00:00
mergify[bot]
7a33ef1547 Ignore cargo audit RUSTSEC-2020-0008 (bp #12485) (#12488)
* Ignore cargo audit RUSTSEC-2020-0008

(cherry picked from commit cd5c7f30d5)

# Conflicts:
#	ci/test-checks.sh

* conflicts

Co-authored-by: Jack May <jack@solana.com>
2020-09-25 10:06:12 -07:00
Trent Nelson
f4a2045876 CLI: Factor out offline helpers (bp #12382) 2020-09-24 03:10:04 +00:00
mergify[bot]
dfabe35b27 Move dropping AppendVecs outside lock (#12408) (#12428)
* Move drop outside lock

Co-authored-by: Carl Lin <carl@solana.com>
(cherry picked from commit 55be8d4016)

Co-authored-by: carllin <wumu727@gmail.com>
2020-09-23 23:27:56 +00:00
mergify[bot]
75fec798bc patches default impl for crds filter (bp #12199) (#12418)
* patches default impl for crds filter (#12199)

In CrdsFilter.mask all bits after mask_bits are set to 1:
https://github.com/solana-labs/solana/blob/555252f4/core/src/crds_gossip_pull.rs#L65
However the default implementation, sets both mask and mask_bits to zero
which is inconsistent with CrdsFilter::compute_mask for a mask_bits of
zero.

This commit changes the default implementation by setting mask to
`!0u64` (i.e all bits set to one). As a result, for the default crds
filter, `test_mask` will always return true, whereas previously it was
always returning false.
https://github.com/solana-labs/solana/blob/555252f4/core/src/crds_gossip_pull.rs#L85

This is only used in tests and benchmarks, but causes some benchmarks to
be misleading by short circuiting in this line:
https://github.com/solana-labs/solana/blob/555252f4/core/src/crds_gossip_pull.rs#L429

(cherry picked from commit d6ec03f13c)

# Conflicts:
#	core/src/crds_gossip_pull.rs

* resolves mergify merge conflict

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-09-23 22:06:33 +00:00
mergify[bot]
0c4743df03 RpcClient::get_multiple_accounts() now works (#12426)
(cherry picked from commit ff890c173c)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-23 21:58:23 +00:00
mergify[bot]
29f9c1e1f2 uses rust intrinsics to convert hashes to u64 (#12097) (#12379)
(cherry picked from commit 28f2fa3fd5)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-09-23 14:59:12 +00:00
mergify[bot]
c4609d0b6d Fix solana-tokens check_payer_balances for distribute-stake (bp #12380) (#12403) (#12407)
* Fix solana-tokens check_payer_balances for distribute-stake (#12380)

* Handle distribute-stakes properly

* Remove dry-run gating for balance checks

* Reword and simplify InsufficientFunds errors

* Split up test and add helpers

* Rename sol_for_fees -> unlocked_sol

* Refactor distribute_allocations to collect Messages

* Clippy

* Clean up dangling bids

(cherry picked from commit 6563726f22)

# Conflicts:
#	tokens/src/commands.rs

* Fix conflicts

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

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2020-09-23 06:44:55 +00:00
Trent Nelson
3b70849885 validator: Add --require-tower stub arg 2020-09-23 05:06:37 +00:00
mergify[bot]
5979005454 adds new CrdsFilterSet type for Vec<CrdsFilter> (bp #12029) (#12378)
* adds new CrdsFilterSet type for Vec<CrdsFilter> (#12029)

(cherry picked from commit 114c211b66)

# Conflicts:
#	core/src/crds_gossip_pull.rs

* resolves mergify merge conflict

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-09-23 03:59:20 +00:00
mergify[bot]
27c8e7b905 Bump spl-token (bp #12395) (#12399)
* Bump spl-token (#12395)

(cherry picked from commit e1a212fb79)

# Conflicts:
#	Cargo.lock
#	account-decoder/Cargo.toml
#	core/Cargo.toml
#	transaction-status/Cargo.toml

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-09-23 01:17:44 +00:00
Ryo Onodera
3612964a58 Adjust bpf epoch for tests, not effecting prod. (#12387)
* Adjust bpf epoch for tests, not effecting prod.

* Fix local cluster test...
2020-09-23 04:55:08 +09:00
Tyera Eulberg
495e237935 Add PerfSamples column to blockstore (#12377)
* Add blockstore column to store performance sampling data

* Add PerfSamples to purge/compaction
2020-09-22 13:32:16 -06:00
Ryo Onodera
1757cb85a1 Update comment 2020-09-21 18:59:17 -06:00
Ryo Onodera
b10fb46a4b Update test hash to align across branches finally 2020-09-21 18:59:17 -06:00
Ryo Onodera
7045aa9760 Improve pre-operating-mode-based hashing gating 2020-09-21 18:59:17 -06:00
mergify[bot]
e371681f53 CLI: Drop unused runtime dep (#12373)
(cherry picked from commit 6767264aa1)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-09-21 20:50:38 +00:00
mergify[bot]
e972db03bd Add blocktime column to blockstore (bp #12336) (#12341)
* Add blocktime column to blockstore (#12336)

(cherry picked from commit 95ed3641c6)

# Conflicts:
#	ledger/src/blockstore_db.rs

* Fix conflict

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-09-18 23:08:34 +00:00
Justin Starry
a8f7a0c648 Bump version to 1.2.30 (#12301) 2020-09-17 11:25:14 +08:00
mergify[bot]
687254497c Restore --expected-shred-version argument for mainnet-beta (#12299)
(cherry picked from commit 9410eab2af)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-17 01:19:30 +00:00
mergify[bot]
b8932ad0c8 RPC: Limit request payload size to 50kB (#12286)
(cherry picked from commit 32dcce0ac1)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-09-16 23:50:11 +00:00
Tyera Eulberg
1d4dbe0090 v1.2: Remove client resends (#12292)
* Remove resends from client send_tx methods

* Retry status queries until blockhash expires
2020-09-16 17:48:02 -06:00
mergify[bot]
1f8e9c2364 builds crds filters without looping over filters (#11998) (#12291)
(cherry picked from commit bc7adb97ed)

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
2020-09-16 23:35:06 +00:00
mergify[bot]
ac07fb392d Fix off-by-one max payload checks (bp #12230) (#12284)
* Fix off-by-one max payload checks

(cherry picked from commit f6cda2579f)

# Conflicts:
#	faucet/src/faucet.rs

* Update faucet.rs

Co-authored-by: Justin Starry <justin@solana.com>
Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-16 21:09:20 +00:00
Tyera Eulberg
a492357964 v1.2: Backports of solana tokens improvements, including transfer to many arg (#12278)
* Clean up solana-tokens (#10667)

* Use a trait object in solana-tokens' ThinClient

* Inline arg resolution

Not worth the code complexity

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* Add lockups via solana-tokens (bp #11782) (#12263)

* Add lockups via solana-tokens (#11782)

* Allow stake distributions to update lockups

* Reorg

* Add lockup test

* Fix clippy warning

(cherry picked from commit 5553732ae2)

* Fix build

Co-authored-by: Greg Fitzgerald <greg@solana.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>

* Improve solana-tokens UX (#12253) (#12260)

* Fix computed banks port

* Readme incorrect

* Return error if csv cannot be read

* Move column headers over columns

* Add dry-run check for sender/fee-payer balances

* Use clap requires method for paired args

* Write transaction-log anytime outfile is specified

* Replace campaign-name with required db-path

* Remove bids

* Exclude new_stake_account_address from logs for non-stake distributions

* Fix readme

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

* solana-tokens: Add capability to perform the same transfer to a batch of recipients (bp #12259) (#12266)

* solana-tokens: Add capability to perform the same transfer to a batch of recipients (#12259)

* Add transfer-amount argument, use simplified input-csv

* Add transfer-amount to readme

(cherry picked from commit a48cc073cf)

# Conflicts:
#	tokens/src/commands.rs
#	tokens/tests/commands.rs

* Fix build

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

Co-authored-by: Greg Fitzgerald <greg@solana.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2020-09-16 17:42:31 +00:00
mergify[bot]
e0bb26d9db RPC sendTransaction now returns transaction logs on simulation failure (bp #12267) (#12275)
* RPC sendTransaction now returns transaction logs on simulation failure

(cherry picked from commit 749208fa32)

# Conflicts:
#	core/src/rpc.rs

* Remove stale comment

(cherry picked from commit c6eea94edc)

# Conflicts:
#	core/src/rpc.rs

* Resolve merge conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-16 17:32:55 +00:00
mergify[bot]
d687dd9f13 validator-info get/set no longer crash on invalid account data (#12257)
(cherry picked from commit 56282f0c01)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-16 01:18:36 +00:00
mergify[bot]
4b649a71df Drop the recommendation that --expected-shred-version be set by validators (bp #12242) (#12243)
* Drop the recommendation that `--expected-shred-version` be set by validators

`--expected-shred-version` is another knob for users to get wrong and is
documentation that can get stale due to cluster restarts.  Turns out
it's also generally not required anymore either because:
1. The cluster entrypoint can always be expected to be using the correct
   shred version, and that shred version will be adopted by the new node
   (earlier this was not the case when the `solana-gossip spy` node on
   mainnet-beta.solana.com:8001 ran with shred version 0)
2. On a cluster restart, `--expected-bank-hash` is a much stronger
   assertion that the validator is starting from the correct place (and
   didn't exist when `--expected-shred-version` was first recommended)

(cherry picked from commit 4ada4d43f2)

# Conflicts:
#	docs/src/clusters.md
#	docs/src/running-validator/restart-cluster.md

* Update clusters.md

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-15 17:43:00 +00:00
Michael Vines
388a285517 Update Cargo.lock 2020-09-15 09:46:20 -07:00
mergify[bot]
45c368d670 Add new validator options for running in more restrictive environments (bp #12191) (#12217)
* Add --restricted-repair-only-mode flag

(cherry picked from commit 63a67f415e)

# Conflicts:
#	validator/src/main.rs

* Add --gossip-validator argument

(cherry picked from commit daae638781)

# Conflicts:
#	core/src/crds_gossip_pull.rs
#	core/src/crds_gossip_push.rs
#	core/src/gossip_service.rs
#	validator/src/main.rs

* Documenet how to reduce validator port exposure

(cherry picked from commit c8f03c7f6d)

* Resolve conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-15 04:44:04 +00:00
mergify[bot]
bf5609b4fc Fix propagation on startup from snapshot (#12177) (#12198)
(cherry picked from commit 9c490e06b0)

Co-authored-by: carllin <wumu727@gmail.com>
2020-09-12 04:44:00 +00:00
Michael Vines
d8c0633f0f Add bank-hash subcommand
(cherry picked from commit a07980536a)
2020-09-10 10:13:54 -06:00
sakridge
aebb8187a8 Add --print-account-stats/--snapshot-archive-path arguments to ledger-tool (#10945)
Allows for seeing how the accounts are being stored
and specifying a different snapshot source directory.

(cherry picked from commit 6429042b6e)
2020-09-10 10:13:54 -06:00
Trent Nelson
159722a960 genesis: Half-support new --cluster-type on v1.2
Just map these values onto OperatingMode
2020-09-10 05:25:46 +00:00
mergify[bot]
c5b36cf18c Specify loader when bootstrapping bpf programs (#11571) (#12145)
(cherry picked from commit 0a94e7e7fa)

Co-authored-by: Jack May <jack@solana.com>
2020-09-10 03:51:20 +00:00
mergify[bot]
fae90ff397 Program subscriptions now properly check results len and token program id (#12139) (#12140)
(cherry picked from commit 4431080066)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-09-09 22:20:59 +00:00
mergify[bot]
a91a106319 Make ledger-tool accounts print rent_epoch and slot (#11845) (#12125)
(cherry picked from commit 57174cdabe)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-09-09 07:12:35 +00:00
mergify[bot]
7c8debd14a RPC: getMinimumBalanceForRentExemption now only responds to valid account lengths (bp #12113) (#12115)
* getMinimumBalanceForRentExemption now only responds to valid account lengths

(cherry picked from commit 9e96180ce4)

# Conflicts:
#	core/src/rpc.rs

* Update rpc.rs

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-08 19:28:07 +00:00
mergify[bot]
9c64e5e3b1 Fix RPC transaction method options serialization (bp #12100) (#12101)
* Fix RPC transaction method configs serialization (#12100)

(cherry picked from commit 9940870c89)

# Conflicts:
#	core/src/rpc.rs

* Update rpc.rs

Co-authored-by: Justin Starry <justin@solana.com>
2020-09-08 09:40:47 +00:00
mergify[bot]
e48ce1e682 Compress snapshot archive within the validator to reduce system dependencies, and default to zstd compression (bp #12085) (#12086)
* Compress snapshot archive within the validator to reduce system dependencies

(cherry picked from commit d3750b47d2)

* Default snapshot compression to zstd instead of bzip2 for quicker snapshot generation

(cherry picked from commit 9ade73841f)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-07 07:03:59 +00:00
Michael Vines
2c239904cc Bump version to 1.2.29 2020-09-04 22:37:52 -07:00
Michael Vines
9e459f0093 Bump version to 1.2.28 2020-09-04 20:00:27 -07:00
Tyera Eulberg
166251fccd v1.2: Bigtable bug fixes (#12059)
* Accommodate stricted get_bincode_cell in get_confirmed_signatures_for_address

* Sort signatures newest-oldest, even within slot
2020-09-04 20:29:03 -06:00
mergify[bot]
ebbb106fb7 Add unlock epochs for blake3 (bp #12054) (#12055)
* Add unlock epochs for blake3 (#12054)

Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit a13efc52b3)

# Conflicts:
#	runtime/src/accounts_db.rs

* Resolve conflicts

* Bump hash

Co-authored-by: carllin <wumu727@gmail.com>
Co-authored-by: Carl <carl@solana.com>
2020-09-05 00:42:16 +00:00
Michael Vines
a018d78056 Add LARGEST_CONFIRMED_ROOT_UPLOAD_DELAY 2020-09-04 23:42:25 +00:00
Michael Vines
67daa6f01e Request correct access 2020-09-04 23:42:25 +00:00
Michael Vines
d5aa648947 Remove dead code 2020-09-04 23:42:25 +00:00
Michael Vines
acfd72d7c4 Adapt to v1.2 2020-09-04 23:42:25 +00:00
Michael Vines
096d9ce5c7 Cargo.lock 2020-09-04 23:42:25 +00:00
Michael Vines
a8e522702c Add exit flag for bigtable upload operations 2020-09-04 23:42:25 +00:00
Michael Vines
e3753186af Add BigTableUploadService 2020-09-04 23:42:25 +00:00
Michael Vines
82d9624736 Relocate BigTable uploader to ledger/ crate 2020-09-04 23:42:25 +00:00
Michael Vines
6101c1d690 Add --enable-bigtable-ledger-upload flag 2020-09-04 23:42:25 +00:00
carllin
7b7b7be99c Forward transactions to the expected leader instead of your own TPU port (#12012)
Co-authored-by: Carl <carl@solana.com>
2020-09-04 15:22:18 -07:00
mergify[bot]
2b4af48537 Switch account hashing to blake3 (bp #11969) (#11991)
* Switch account hashing to blake3 (#11969)

* Switch account hashing to blake3

Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit af08221aec)

# Conflicts:
#	programs/bpf/Cargo.lock
#	runtime/src/accounts.rs
#	runtime/src/accounts_db.rs
#	runtime/src/serde_snapshot.rs

* Resolve conflicts

Co-authored-by: carllin <wumu727@gmail.com>
Co-authored-by: Carl <carl@solana.com>
2020-09-04 20:47:25 +00:00
mergify[bot]
2a842408bd Bump getMultipleAccounts input limit (#12050) (#12051)
(cherry picked from commit 954b017f85)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-09-04 19:10:12 +00:00
Michael Vines
755ccbc253 Update devnet activation epoch for token2 native mint 2020-09-04 06:55:36 +00:00
mergify[bot]
cf0de48dc0 Mark a withdraw authority as non-circulating (#12033) (#12035)
(cherry picked from commit 2c091e4fca)

Co-authored-by: Greg Fitzgerald <greg@solana.com>
2020-09-04 01:07:53 +00:00
mergify[bot]
d44058edc3 Don't query modern Ledger wallet app version with deprecated payload size (#12030)
(cherry picked from commit dff8242887)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-09-03 22:20:05 +00:00
mergify[bot]
5496d52097 Rpc: add getMultipleAccounts endpoint (bp #12005) (#12023)
* Rpc: add getMultipleAccounts endpoint (#12005)

* Add rpc endpoint to return the state of multiple accounts from the same bank

* Add docs

* Review comments: Dedupe account code, default to base64, add max const

* Add get_multiple_accounts to rpc-client

(cherry picked from commit b22de369b7)

# Conflicts:
#	core/src/rpc.rs

* Fix conflicts

* Use new_response for consistency

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-09-03 19:52:25 +00:00
mergify[bot]
b4da705f97 Update token amounts in parsed instructions to retain full precision (#12020) (#12021)
(cherry picked from commit b940da4040)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-09-03 19:41:20 +00:00
mergify[bot]
75d334147c Fix forwarding calculation (#12014) (#12018)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 3f39ab1e04)

Co-authored-by: carllin <wumu727@gmail.com>
2020-09-03 10:44:19 +00:00
mergify[bot]
006d36dd95 Bigtable method to return a single row of data (#11999) (#12001)
(cherry picked from commit b041afe1be)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-09-02 20:53:44 +00:00
mergify[bot]
8c9e17bbab Docs.rs version replacement (#11981) (#11983)
(cherry picked from commit b720921c83)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-09-01 15:15:08 -06:00
mergify[bot]
42017ebe69 Ensure that the spl-token 2 native mint account is owned by the spl-token 2 program. (#11973)
Workaround for https://github.com/solana-labs/solana-program-library/issues/374 until spl-token 3 is shipped

(cherry picked from commit 7341e60043)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-01 19:32:52 +00:00
mergify[bot]
b34f179546 Update to rayon 1.4.0 (bp #11898) (#11959)
* Update to rayon 1.4.0 (#11898)

Co-authored-by: sakridge <sakridge@gmail.com>
Co-authored-by: Carl <carl@solana.com>
2020-08-31 20:38:33 -07:00
mergify[bot]
1afd1db4fc generate_pull_response optimization (bp #11597) (#11954)
* generate_pull_response optimization (#11597)

(cherry picked from commit f519fdecc2)

# Conflicts:
#	core/src/crds_gossip_pull.rs

* Fix merge conflicts

Co-authored-by: sakridge <sakridge@gmail.com>
Co-authored-by: Carl <carl@solana.com>
2020-09-01 01:21:57 +00:00
mergify[bot]
daba428a3d Remove log (#11949) (#11960)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 7641b60a2b)

Co-authored-by: carllin <wumu727@gmail.com>
2020-09-01 01:13:51 +00:00
mergify[bot]
11f4443a7b Add missing backslash to solana-validator command (#11957)
(cherry picked from commit a19f696a42)

Co-authored-by: Richard Ayotte <rich.ayotte@gmail.com>
2020-08-31 23:41:52 +00:00
mergify[bot]
a8eea4f42d Increase message_processor logging to error level (#11945) (#11947)
(cherry picked from commit 9b9d559312)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-08-31 21:55:07 +00:00
mergify[bot]
18e7112608 Fix get_parsed_token_accounts (#11907) (#11908)
(cherry picked from commit 60c7ac6f95)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-29 20:07:04 +00:00
Michael Vines
857e44c147 Update to spl-token 2 2020-08-29 09:24:35 -07:00
Tyera Eulberg
bd0536c80f Bump spl-token version 2020-08-29 02:22:33 -06:00
Tyera Eulberg
184e4253c7 Update to token pack/unpack changes (#11901) 2020-08-29 04:57:09 +00:00
mergify[bot]
5828d2cff7 Update spl-token to v2.0 (bp #11884) (#11896)
* Update spl-token to v2.0 (#11884)

    * Update account-decoder to spl-token v2.0

    * Update transaction-status to spl-token v2.0

    * Update rpc to spl-token v2.0

    * Update getTokenSupply to pull from Mint directly

    * Fixup to spl-token v2.0.1

    (cherry picked from commit 76be36c9ce)

    # Conflicts:
    #       Cargo.lock
    #       account-decoder/Cargo.toml
    #       core/Cargo.toml
    #       core/src/rpc.rs
    #       transaction-status/Cargo.toml

* Fix non-Cargo.lock conflicts

* Limited Deserialize isn't limiting anything (#10952)

* Add failing test

* Use deserialize_from to enable limit

* Cargo.lock

* chore(deps): bump bincode from 1.2.1 to 1.3.1 (#10867)

* chore(deps): bump bincode from 1.2.1 to 1.3.1

Bumps [bincode](https://github.com/servo/bincode) from 1.2.1 to 1.3.1.
- [Release notes](https://github.com/servo/bincode/releases)
- [Commits](https://github.com/servo/bincode/commits)

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

* [auto-commit] Update all Cargo lock files

* Switch from deprecated method

* Add options to maintain behavior with bincode::options()

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: dependabot-buildkite <dependabot-buildkite@noreply.solana.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>

Co-authored-by: Tyera Eulberg <tyera@solana.com>
Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: dependabot-buildkite <dependabot-buildkite@noreply.solana.com>
2020-08-29 01:27:10 +00:00
Jack May
eeb7503fb6 Revert "Align host addresses (#11384) (#11836)" (#11876)
This reverts commit 3296c13ef2.
2020-08-27 16:19:05 +00:00
Jack May
7e1aa02ce4 Revert "Make BPF Loader static (bp #11516) (#11865)" (#11871)
This reverts commit 81db361d77.
2020-08-27 06:48:21 +00:00
Jack May
734e669581 Revert "cli: Add (hidden) --use-deprecated-loader flag to solana deploy (bp #11675) (#11866)" (#11872)
This reverts commit 97c3ff8a4f.
2020-08-27 06:44:06 +00:00
mergify[bot]
81db361d77 Make BPF Loader static (bp #11516) (#11865)
* Make BPF Loader static (#11516)

(cherry picked from commit 7c736f71fe)

# Conflicts:
#	Cargo.lock
#	core/Cargo.toml
#	core/src/lib.rs
#	core/src/validator.rs
#	genesis/src/main.rs
#	programs/bpf/tests/programs.rs
#	runtime/src/builtin_programs.rs
#	runtime/src/lib.rs

* resolve conflicts

* nudge

Co-authored-by: Jack May <jack@solana.com>
2020-08-27 01:00:24 +00:00
mergify[bot]
97c3ff8a4f cli: Add (hidden) --use-deprecated-loader flag to solana deploy (bp #11675) (#11866)
* Add (hidden) --use-deprecated-loader flag to `solana deploy`

(cherry picked from commit de736e00ad)

# Conflicts:
#	cli/src/cli.rs
#	cli/tests/deploy.rs

* resolve conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
Co-authored-by: Jack May <jack@solana.com>
2020-08-27 00:36:12 +00:00
mergify[bot]
5f85ecd457 Merge pull request #11857 from mvines/cache (#11862)
ci: cargo-target-cache is now channel specific
(cherry picked from commit 5c7080c1f4)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-08-26 19:58:36 +00:00
mergify[bot]
fb1985fe5e Rpc: Filter accounts with invalid mints from get_parsed_token_accounts (#11844) (#11858)
* Filter out accounts with invalid mints from get_parsed_token_accounts

* Explicit docs

(cherry picked from commit 1988ee9cd6)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-26 19:07:23 +00:00
mergify[bot]
3296c13ef2 Align host addresses (#11384) (#11836)
* Align host addresses

* support new program abi

* update epoch rollout

* Enforce aligned pointers in cross-program invocations

(cherry picked from commit 9290e561e1)

# Conflicts:
#	programs/bpf_loader/src/lib.rs

Co-authored-by: Jack May <jack@solana.com>
2020-08-26 00:19:38 +00:00
mergify[bot]
b8cc10749a Re-route program logging (bp #10528) (#11838)
* Route all loader messages to log collector (#10528)

(cherry picked from commit b6a9573748)

# Conflicts:
#	Cargo.lock
#	programs/bpf/Cargo.lock
#	programs/bpf/benches/bpf_loader.rs
#	programs/bpf_loader/Cargo.toml
#	programs/bpf_loader/src/syscalls.rs
#	runtime/src/message_processor.rs
#	sdk/src/entrypoint_native.rs

* resolve conflicts

* nudge

Co-authored-by: Jack May <jack@solana.com>
2020-08-25 21:09:24 +00:00
mergify[bot]
c1f9a9a021 Update system tuning and docs (bp #11680) (#11829)
* Sync FD limit and max maps to 500k

(cherry picked from commit 11951eb009)

* Expand system tuning docs

(cherry picked from commit 5354df8c1c)

* clippy

Co-authored-by: Trent Nelson <trent@solana.com>
2020-08-25 20:39:00 +00:00
mergify[bot]
f88b0c4827 Bump MacOS nofile recommendation message (#11834)
(cherry picked from commit 8841c3398c)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-08-25 19:52:22 +00:00
mergify[bot]
c3564203e9 Document how to validate account pubkey (#11821) (#11832)
(cherry picked from commit 2c5366f259)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-08-25 16:29:20 +00:00
mergify[bot]
de4e548105 sdk: Make PubKey::create_program_address available in program unit tests (bp #11745) (#11809)
* sdk: Make PubKey::create_program_address available in program unit tests (#11745)

* sdk: Make PubKey::create_program_address available in program unit tests

This finishes the work started in #11604 to have
`create_program_address` available when `target_arch` is not `bpf` and
`program` is enabled.  Otherwise, there is an undefined reference error
to `sol_create_program_address`, which is only defined in `bpf`.

A small test to simply call the function has been added in order to catch
the problem in the future.

The default dependency to `solana-sdk/default` doesn't cause a problem with
existing programs since `build.sh` always specifies
`--no-default-features`, and programs in `solana-program-library` all
use it too.

* Add `default-features = false` for inter-program dependencies

Fix the build error found during CI.  The `--no-default-features` flag
only applies to the top-level package, and not to dependencies.  A program that
depends on another program, i.e. `128bit` which depends on `128bit_dep`,
must specify `default-features = false` when including that package,
otherwise the `bpf` build will try to pull in default packages, which
includes `std`.

(cherry picked from commit 9a366281d3)

# Conflicts:
#	programs/bpf/rust/128bit/Cargo.toml
#	programs/bpf/rust/invoke/Cargo.toml
#	programs/bpf/rust/many_args/Cargo.toml
#	programs/bpf/rust/param_passing/Cargo.toml

* Fix merge conflicts

Co-authored-by: Jon Cinque <jon.cinque@gmail.com>
2020-08-24 21:30:15 +00:00
mergify[bot]
8d67204123 Return an error from create_program_address syscall (bp #11658) (#11788)
* Return an error from create_program_address syscall (#11658)

(cherry picked from commit 750e5344f1)

# Conflicts:
#	programs/bpf/rust/invoke/src/lib.rs
#	programs/bpf_loader/src/syscalls.rs

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
2020-08-24 05:03:27 +00:00
mergify[bot]
99a01abfd7 RPC: Allow the sendTransaction preflight commitment level to be configured (bp #11792) (#11793)
* Allow the sendTransaction preflight commitment level to be configured

(cherry picked from commit b660704faa)

# Conflicts:
#	cli/src/cli.rs
#	core/src/rpc.rs

* rebase

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-08-22 17:00:49 +00:00
Michael Vines
973b00debb Fix typo 2020-08-22 09:23:12 -07:00
mergify[bot]
900139da3e Fix region check (bp #11651) (#11784)
* fix region checks (#11651)

(cherry picked from commit 768b386f0a)

# Conflicts:
#	sdk/src/pubkey.rs

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
2020-08-22 03:12:55 +00:00
mergify[bot]
d94ad7523b Unified signature for create_program_address (#11460) (#11783)
(cherry picked from commit 140b2392f6)

Co-authored-by: Jack May <jack@solana.com>
2020-08-22 00:37:31 +00:00
mergify[bot]
4e0dbd6a73 Fix filter_crds_values output alignment with the inputs (bp #11734) (#11780)
* Fix filter_crds_values output alignment with the inputs (#11734)

(cherry picked from commit 418b483af6)

# Conflicts:
#	core/src/crds_gossip_pull.rs

* Resolve conflicts

Co-authored-by: behzad nouri <behzadnouri@gmail.com>
Co-authored-by: Carl <carl@solana.com>
2020-08-21 22:24:48 +00:00
mergify[bot]
9ee69017dc Add option for repairing only from trusted validators (#11752) (#11772)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit c8d67aa8eb)

Co-authored-by: carllin <wumu727@gmail.com>
2020-08-21 09:01:39 +00:00
mergify[bot]
7c956a87e5 Rpc: Return error if block does not exist (#11743) (#11748)
* Return error if block does not exist

* Update docs

(cherry picked from commit 747f8d5877)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-20 22:52:18 +00:00
Trent Nelson
0beb443d44 Bump version to 1.2.27 2020-08-20 13:32:49 -06:00
mergify[bot]
5d8ae9628c Do not delete any ledger when --limit-ledger-size is not provided (#11740)
(cherry picked from commit ea88bbdc33)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-08-20 19:08:21 +00:00
mergify[bot]
de76df0cbb Bump spl-token to clean up magic number (bp #11726) (#11737)
* Bump spl-token to clean up magic number (#11726)

(cherry picked from commit 2fd2aceeb2)

# Conflicts:
#	account-decoder/Cargo.toml
#	core/Cargo.toml
#	transaction-status/Cargo.toml

* Fix conflicts and toml order

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-20 17:35:28 +00:00
Justin Starry
a0190b4105 Hotfix for enabling CPI (#11728) 2020-08-20 15:41:37 +08:00
carllin
5255a6ebd2 Cleanup test utilities (#11725)
Co-authored-by: Carl <carl@solana.com>
2020-08-20 00:10:18 -07:00
mergify[bot]
8575514235 Allow votes to timestamp subsequent slots with the same timestamp (#11715) (#11719)
(cherry picked from commit b1bc901a66)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-20 02:00:32 +00:00
Trent Nelson
2a1946436b Bump version to 1.2.26 2020-08-19 20:33:40 +00:00
Michael Vines
80649a9c3d Revert "Revert "rpc: rework binary encoding. BREAKING CHANGE (bp #11646) (#11673)""
This reverts commit fb90fb3feb.
2020-08-18 21:25:31 -07:00
Michael Vines
ad74ba0eb0 The end_slot argument to purge is now optional 2020-08-19 03:19:02 +00:00
mergify[bot]
fd41ad5d8f Remove old signatureSubscribe info (#11704) (#11705)
(cherry picked from commit 35828e8fe7)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-19 02:43:44 +00:00
mergify[bot]
63855d5c2a Get index (#11694) (#11696)
(cherry picked from commit 55ce2ebd53)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-18 19:12:49 +00:00
Michael Vines
00251f710e Bump version to v1.2.25 2020-08-18 08:40:00 -07:00
Justin Starry
14bc623989 Fully enable cross program support in mainnet-beta 2020-08-18 06:33:12 -07:00
Michael Vines
fb90fb3feb Revert "rpc: rework binary encoding. BREAKING CHANGE (bp #11646) (#11673)"
This reverts commit d6ca879d39.
2020-08-18 06:27:20 -07:00
mergify[bot]
d6ca879d39 rpc: rework binary encoding. BREAKING CHANGE (bp #11646) (#11673)
* Add base64 (binary64) encoding for getConfirmedTransaction/getConfirmedBlock

(cherry picked from commit b5f3ced860)

# Conflicts:
#	transaction-status/Cargo.toml

* decode-transaction now supports binary64

(cherry picked from commit 2ebc68a9e2)

# Conflicts:
#	cli/src/cli.rs

* Rework UiAccountData encode/decode such that it works from Rust

(cherry picked from commit 757e147b3b)

# Conflicts:
#	cli/src/cli.rs

* Rename Binary64 to Base64.  Establish Base58 encoding

(cherry picked from commit adc984a225)

* Remove "binary" encoding. Document "encoding" as required

(cherry picked from commit e5281157fa)

* resolve conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-08-18 04:18:48 +00:00
mergify[bot]
2dcde5281d Faucet: Add per-request cap (#11665) (#11668)
* Add per-request cap; also use clap-utils

* Clean up arg names and take cap inputs as SOL

(cherry picked from commit 71d5409b3b)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-18 01:24:41 +00:00
mergify[bot]
e2626dad83 Re-do rent collection check on rent-exempt account (bp #11349) (#11654)
* Re-do rent collection check on rent-exempt account (#11349)

* wip: re-do rent collection check on rent-exempt account

* Let's see how the ci goes

* Restore previous code

* Well, almost all new changes are revertable

* Update doc

* Add test and gating

* Fix tests

* Fix tests, especially avoid to change abi...

* Fix more tests...

* Fix snapshot restore

* Align to _new_ with better uninitialized detection

(cherry picked from commit 23fa84b322)

# Conflicts:
#	core/src/rpc_subscriptions.rs
#	core/tests/bank_forks.rs
#	runtime/src/bank.rs

* Fix conflicts

* Add missing comment

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-08-17 11:14:56 +00:00
mergify[bot]
070fbeb69a Rpc: Add until parameter for getConfirmedSignaturesForAddress2 (#11644) (#11647)
* Refactor bigtable apis to accept start and end keys

* Make helper fn to deserialize cell data

* Refactor get_confirmed_signatures_for_address to use get_row_data range

* Add until param to get_confirmed_signatures_for_address

* Add until param to blockstore api

* Plumb until through client/cli

* Simplify client params

(cherry picked from commit 6c5b8f324a)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-15 18:04:08 +00:00
mergify[bot]
497ec24754 Bigtable: Use index to filter address-signatures correctly (#11622) (#11642)
* Use index to filter address-signatures correctly

* Pull additional keys to account for filtered records

* Clarify variable name

(cherry picked from commit 820af533a4)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-14 21:08:52 +00:00
Trent Nelson
1bda09bf0e Bump version to 1.2.24 2020-08-14 18:51:08 +00:00
mergify[bot]
7ca7f8604d short_vec::decode_len() returns wrong size for aliased values (bp #11624) (#11630)
* Add failing test for decoding ShortU16 alias values

(cherry picked from commit 338f66f9aa)

* Factor out ShortU16 deser vistor logic to helper

(cherry picked from commit 6222fbcc66)

* Reimplement decode_len() with ShortU16 vistor helper

(cherry picked from commit 30dbe257cf)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-08-14 15:40:12 +00:00
mergify[bot]
e2b5f2dd9c RPC: getConfirmedSignaturesForAddress2 only returns confirmed signatures (#11615) (#11617)
* Add failing test case

* Limit to only rooted slots

(cherry picked from commit 99fb36fe45)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-13 18:31:20 +00:00
mergify[bot]
3652bd57a9 Ensure highest_confirmed_root only grows (bp #11596) (#11607)
* Ensure highest_confirmed_root only grows (#11596)

* Split out commitment-cache update for unit testing

* Add failing test

* Ensure highest_confirmed_root only grows

(cherry picked from commit 4da1e9833c)

# Conflicts:
#	core/src/commitment_service.rs

* Adapt to v1.2

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-13 09:19:14 +00:00
mergify[bot]
5077d6bfb3 Return blockstore signatures-for-address despite bigtable error (#11594) (#11598)
(cherry picked from commit b1e452f876)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-13 01:22:31 +00:00
mergify[bot]
f0ee3e9deb Fix assertion failure (#11572) (#11589)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 473b5249e3)

Co-authored-by: carllin <wumu727@gmail.com>
2020-08-12 20:38:57 +00:00
mergify[bot]
babad39846 Fix typo: epoch => slot... (#11573) (#11579)
(cherry picked from commit 51e818ad64)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-08-12 09:23:05 +00:00
Trent Nelson
c15aa4a968 Bump version to 1.2.23 2020-08-12 00:34:33 +00:00
mergify[bot]
3124a88284 Move cluster slots update to separate thread (bp #11523) (#11557)
* Move cluster slots update to separate thread (#11523)

* Add cluster_slots_service

Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 7ef50a9352)

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

* Fix conflicts

Co-authored-by: carllin <wumu727@gmail.com>
Co-authored-by: Carl <carl@solana.com>
2020-08-11 22:54:29 +00:00
mergify[bot]
e76a2065e3 Gossip log (#11555) (#11561)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 1b238dd63e)

Co-authored-by: carllin <wumu727@gmail.com>
2020-08-11 22:27:35 +00:00
mergify[bot]
45f8e453a9 Add getTokenLargestAccounts to docs (#11560) (#11563)
(cherry picked from commit 697a0e2947)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-11 21:21:44 +00:00
mergify[bot]
20f9c12855 panic on native load failure (#11182) (#11554)
(cherry picked from commit e75f0bdfd3)

Co-authored-by: Jack May <jack@solana.com>
2020-08-11 19:56:23 +00:00
mergify[bot]
4218414c87 filter out old gossip pull requests (#11448) (#11552)
* init

* builds

* stats

* revert

* tests

* clippy

* add some jitter

* shorter jitter timer

* update

* fixup! update

* use saturating_sub

* fix filters

(cherry picked from commit 713851b68d)

Co-authored-by: anatoly yakovenko <anatoly@solana.com>
2020-08-11 19:50:49 +00:00
mergify[bot]
60c91d386f Adapt RpcClient to recent token method changes (bp #11519) (#11547)
* Adapt RpcClient to recent token method changes (#11519)

* Avoid skip_serializing_if since that breaks deserialization

* Adapt RpcClient to recent token method changes

(cherry picked from commit 17645ee20c)

# Conflicts:
#	client/src/rpc_client.rs

* Fix conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-11 18:00:35 +00:00
mergify[bot]
e477501687 Fix bad rent in Bank::deposit as if since epoch 0 (bp #10468) (#11538)
* Fix bad rent in Bank::deposit as if since epoch 0 (#10468)

* Fix bad rent in Bank::deposit as if since epoch 0

* Remove redundant predicate

* Rename

* Start to add tests with some cleanup

* Forgot to add refactor code...

* Enchance test

* Really fix rent timing in deposit with robust test

* Simplify new behavior by disabling rent altogether

(cherry picked from commit 6c242f3fec)

# Conflicts:
#	runtime/src/accounts.rs
#	runtime/src/rent_collector.rs

* Fix conflict

* Fix clippy

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-08-11 16:55:19 +00:00
mergify[bot]
20463e141e Fix simulateTransaction JSON-RPC docs (#11533) (#11534)
(cherry picked from commit f12fc66a69)

Co-authored-by: Justin Starry <justin@solana.com>
2020-08-11 10:24:44 +00:00
mergify[bot]
e699462ed3 Fix solana CLI deploy (bp #11520) (#11529)
* Fix solana CLI deploy (#11520)

* Refresh blockhash for program writes and finalize transactions

* Refactor to use current api, eliminating an rpc call

* Review comment

(cherry picked from commit c0d6761f63)

# Conflicts:
#	cli/src/cli.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-11 10:20:15 +00:00
mergify[bot]
8b345f3258 Add config param to specify offset/length for single and program account info (bp #11515) (#11517)
* Add config param to specify offset/length for single and program account info (#11515)

* Add config param to specify dataSlice for account info and program accounts

* Use match instead of if

(cherry picked from commit 88ca04dbdb)

# Conflicts:
#	core/src/rpc.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-11 00:21:47 +00:00
mergify[bot]
56436a6271 Fix parsing of spl-token Mint (#11512) (#11513)
* Add failing test

* Fix jsonParsed mint

(cherry picked from commit da210ddd51)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-10 22:08:19 +00:00
mergify[bot]
805ea6f469 Return account data size with parsed accounts (#11506) (#11510)
(cherry picked from commit 1925b0bd0b)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-10 20:31:58 +00:00
mergify[bot]
1db1d173fc Blockstore address signatures: handle slots that cross primary indexes, and refactor get_confirmed_signatures_for_address2 (#11497) (#11507)
* Freeze address-signature index in the middle of slot to show failure case

* Secondary filter on signature

* Use AddressSignatures iterator instead of manually decrementing slots

* Remove unused method

* Add metrics

* Add transaction-status-index doccumentation

(cherry picked from commit de5fb3ba0e)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-10 17:50:05 +00:00
sakridge
11476038cd Add db recovery methods (#10838) (#11496) 2020-08-10 08:20:12 -07:00
mergify[bot]
a669ef3abb account subcommand now requests binary64 (#11494)
(cherry picked from commit a4f5f3e978)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-08-09 22:35:19 +00:00
Michael Vines
dbbdfa1dbb Bump version to v1.2.22 2020-08-09 18:02:02 +00:00
Justin Starry
768c6b4bef Fallback to base64 account encoding if json parse fails (#11483)
* Fallback to base64 account encoding if json parse fails

* Remove default binary conversion

(cherry picked from commit ebc45bd73f)
2020-08-09 09:15:21 -07:00
mergify[bot]
8bcc04c275 Decode native-program and sysvar accounts (bp #11463) (#11484)
* Decode native-program and sysvar accounts (#11463)

* Pass pubkey in to account-decoder for sysvars

* Decode sysvar accounts

* Decode config accounts; move validator-info lower

* Decode stake accounts

* Review comments

* Stringify any account lamports and epochs that can be set to u64::MAX

(cherry picked from commit a9f76862fb)

# Conflicts:
#	Cargo.lock
#	account-decoder/Cargo.toml
#	core/src/rpc.rs

* Fix conflicts

* Ignore clippy lint affecting rust <v1.44.0

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-09 09:45:31 +00:00
mergify[bot]
2fd822887f Add Binary64 option for account data (#11474) (#11480)
* Add Binary64 option for account data

* Decode into binary64

* Reword docs

Co-authored-by: sakridge <sakridge@gmail.com>
2020-08-09 07:14:54 +00:00
mergify[bot]
e2c8aa0847 Return delegated amount as UiTokenAmount (#11475) (#11476)
* Return delegated amount as UiTokenAmount

* Omit delegate and delegatedAmount when none

(cherry picked from commit 88d8d3d02a)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-09 00:28:24 +00:00
mergify[bot]
9b049402c9 Token Accounts: return ui_amount, decimals with decoded account (bp #11407) (#11452)
* Token Accounts: return ui_amount, decimals with decoded account (#11407)

* Return ui_amount, decimals from token client methods

* Return ui_amount, decimals in RPC jsonParsed token accounts

* Fixup docs

* Return ui_amount, decimals in pubsub jsonParsed token accounts

* Remove unnecessary duplicate struct

* StringAmount rename

(cherry picked from commit b7c2681903)

# Conflicts:
#	client/src/rpc_client.rs
#	core/src/rpc.rs
#	core/src/rpc_subscriptions.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-07 19:28:25 +00:00
mergify[bot]
d0e1779893 Accounts hash calculation metrics (#11433) (#11438)
(cherry picked from commit 770d3d383c)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-08-07 06:04:50 +00:00
mergify[bot]
929ffc5a4e Fix blockstore empty panic (bp #11423) (#11429)
* Fix blockstore empty panic (#11423)

* Add panicking test

* Add failing test: fresh transaction-status column shouldn't point at valid root 0

* Prevent transaction status match outside of primary-index bounds

* Initialize transaction-status and address-signature primer entries with Slot::MAX

* Revert "Add failing test: fresh transaction-status column shouldn't point at valid root 0"

This reverts commit cbad2a9fae.

* Revert "Initialize transaction-status and address-signature primer entries with Slot::MAX"

This reverts commit ffaeac0669.

(cherry picked from commit 1061b50665)

# Conflicts:
#	ledger/src/blockstore.rs

* Fix conflict

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-07 01:21:24 +00:00
mergify[bot]
1f63fb06f1 Add address-based lower bound to get_confirmed_signatures_for_address2 loop (#11426) (#11431)
(cherry picked from commit 5530ee4c95)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-06 23:56:39 +00:00
Trent Nelson
b49aa125c9 Bump version to 1.2.21 2020-08-06 12:20:56 -07:00
mergify[bot]
55836d133e Realloc not supported (#11417)
(cherry picked from commit bc4c5c5a97)

Co-authored-by: Jack May <jack@solana.com>
2020-08-06 15:00:51 +00:00
Michael Vines
277e402d55 Update lib.rs
(cherry picked from commit 5a63c9d535)
2020-08-06 07:58:01 -07:00
Michael Vines
0ab8312b23 Enable cross program support in mainnet-beta epoch 63
(cherry picked from commit c9b1d08218)
2020-08-06 07:58:01 -07:00
Jack May
bc4c5c5a97 Realloc not supported 2020-08-06 07:57:23 -07:00
mergify[bot]
1a9aa78129 Force program address off the curve (bp #11323) (#11397)
* Force program address off the curve (#11323)

(cherry picked from commit 03263c850a)

* nudge

* trailing whitespace

Co-authored-by: Jack May <jack@solana.com>
Co-authored-by: Trent Nelson <trent@solana.com>
2020-08-06 09:46:35 +00:00
mergify[bot]
798a6db915 RPC: Plug getConfirmedSignaturesForAddress2 into bigtable storage (bp #11395) (#11405)
* Plug getConfirmedSignaturesForAddress2 into bigtable storage

(cherry picked from commit 4222932e08)

# Conflicts:
#	ledger-tool/src/bigtable.rs
#	storage-bigtable/src/lib.rs

* Upgrade help description

(cherry picked from commit 9abb7db5f8)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-08-06 07:49:30 +00:00
Michael Vines
0a4a3fd37e Cargo.lock 2020-08-05 23:15:28 -07:00
Michael Vines
66242eab41 Long-term ledger storage with BigTable (bp #11222) 2020-08-05 23:15:28 -07:00
Trent Nelson
7f0d4f0656 Bump version to 1.2.20 2020-08-05 22:06:02 -06:00
mergify[bot]
acba8d6026 Mark token-specific rpcs as unstable (#11401)
(cherry picked from commit 7430896c79)

Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-06 03:59:28 +00:00
Trent Nelson
1ff9555099 Bump version to 1.2.19
This one has some bonus deltas due to locks not being bumped for v1.2.18 nor
the ed25591-dalek update.
2020-08-06 00:32:08 +00:00
mergify[bot]
72a13e2a72 Add getConfirmedSignaturesForAddress2 RPC method (bp #11259) (#11393)
* Add getConfirmedSignaturesForAddress2 RPC method

(cherry picked from commit 1b2276520b)

# Conflicts:
#	core/src/rpc.rs

* Reimplement transaction-history command with getConfirmedSignaturesForAddress2

(cherry picked from commit 087fd32ce3)

* Rework get_confirmed_signatures_for_address2

(cherry picked from commit a11f137810)

* Rename startAfter to before

(cherry picked from commit 02c0981ecf)

* rebase

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-08-05 23:14:53 +00:00
Tyera Eulberg
74cdfc2213 Fall back to root if highest_confirmed_slot bank does not exist (#11390) 2020-08-05 22:08:20 +00:00
mergify[bot]
7b8e5a9f47 Sanitize preflight (bp #11373) (#11376)
* Add failing test for unsane tx in RPC preflight

(cherry picked from commit e25846e1ad)

* Add From for SanitizeError > TransactionError

(cherry picked from commit 3f73affb2e)

* Sanitize transactions during RPC preflight test

(cherry picked from commit 29b3265dc7)

* Harden RPC preflight test inputs

(cherry picked from commit 14339dec0a)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-08-05 17:03:09 +00:00
mergify[bot]
80525ac862 Return token amounts as floats (bp #11370) (#11378)
* Return token amounts as floats (#11370)

* Return token amounts as floats

* Floating-point equality

* Return float and raw token amounts

* Fix decimals and token rpcs for native-mint tokens

* Fixup docs and review comments

(cherry picked from commit 86e3f96f16)

# Conflicts:
#	core/src/rpc.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-05 08:31:22 +00:00
mergify[bot]
c14f98c6fc Rework parsed account format (#11372) (#11380)
* Rework parsed account format

* Serialize as type

(cherry picked from commit 308186da79)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-05 08:21:08 +00:00
mergify[bot]
c6edfc3944 Update instruction encoding format (#11363) (#11379)
* Rework parsed instruction format

* Rework parsed message accounts

* Review comments

(cherry picked from commit 9d4f9be1fe)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-05 08:21:02 +00:00
mergify[bot]
b95c493d66 get_token_accounts_by_owner now returns UiTokenAccounts (#11367)
(cherry picked from commit b5e03d6df2)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-08-05 00:06:21 +00:00
mergify[bot]
5871462241 Fix token rpc-client methods (bp #11361) (#11362)
* Fix token rpc-client methods (#11361)

* Convert None to error in parse_keyed_accounts

* Allow encoding configuration in getTokenAccounts methods

(cherry picked from commit d0144ce382)

# Conflicts:
#	core/src/rpc.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-04 18:40:39 +00:00
mergify[bot]
53bb826375 Make accounts explicit in unrecognized jsonParsed instructions (#11351) (#11352)
(cherry picked from commit 3f6f1adb5b)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-03 21:50:57 +00:00
mergify[bot]
c769bcc418 Add getTokenLargestAccounts endpoint (bp #11322) (#11338)
* Add getTokenLargestAccounts endpoint (#11322)


(cherry picked from commit d1b2e6cdf2)

* Rebase on v1.2

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-02 17:58:55 +00:00
Michael Vines
f06a4c7861 Update spl-token and spl-memo 2020-08-02 07:53:46 -07:00
Michael Vines
0cae099d12 Bump version to v1.2.18 2020-08-01 21:15:25 -07:00
Michael Vines
4bc3653906 Remove move more 2020-08-01 17:51:59 -07:00
Greg Fitzgerald
3e7050983a Remove move_loader and librapay (#11184)
* Remove move_loader and librapay

* Remove Embedding Move from implemented proposals

* Remove Move variant from CI

* Remove move_loader ID
2020-08-01 17:51:59 -07:00
Greg Fitzgerald
9f1bb75445 Upgrade ed25519-dalek (#11183) 2020-08-01 17:51:59 -07:00
Trent Nelson
139bb32dba Bump version to 1.2.17 2020-08-01 07:14:47 +00:00
mergify[bot]
158f6f3725 Test off curve pubkey (bp #11299) (#11317)
* Allow inspection of signature verification failures

(cherry picked from commit 251f974b50)

* Test that off-curve pubkeys fail signature verify

(cherry picked from commit c421d7f1b8)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-07-31 23:39:56 +00:00
Greg Fitzgerald
e33f9ea6b5 Withdraw authority no longer implies a custodian (#11302)
* Withdraw authority no longer implies a custodian

Before this change, if the withdraw authority and custodian had
the same public key, then a withdraw authority signature would
imply a custodian signature and lockup would be not be enforced.

After this change, the client's withdraw instruction must
explictly reference a custodian account in its optional sixth
account argument.

Likewise, the fee-payer no longer implies either a withdraw
authority or custodian.

* Fix test

The test was configuring the stake account with the fee-payer as
the withdraw authority, but then passing in a different key to
the withdraw instruction's withdraw authority parameter. It only
worked because the second transaction was signed by the fee-payer.
2020-07-31 17:18:23 -06:00
Greg Fitzgerald
473037db86 Remove WithSigner (#10325) 2020-07-31 17:18:23 -06:00
mergify[bot]
b0e14ea83c Add token rpc endpoints to rpc-client (bp #11315) (#11320)
* Add token rpc endpoints to rpc-client (#11315)

(cherry picked from commit 9bcfc51df1)

# Conflicts:
#	client/src/rpc_client.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-07-31 23:10:29 +00:00
mergify[bot]
782a549613 Enable new fork choice on mainnet, 400_000 slots into epoch 61 (#11312) (#11319)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit d7e961dac4)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-31 22:13:23 +00:00
mergify[bot]
c805f7dc4e Decode token instructions (bp #11281) (#11313)
* Decode token instructions (#11281)

* Token->SplToken

* Add spl_token instruction parsing

* Rebase on master

* Gracefully fail key len mismatches

(cherry picked from commit 0f551d4f75)

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

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-07-31 21:11:58 +00:00
mergify[bot]
782829152e Update perf libs to 0.19.1 (#11301) (#11310)
* fix for cuda sigverify check for small order pubkey

(cherry picked from commit 1733f6c9e9)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-07-31 17:27:13 +00:00
mergify[bot]
da6f09afb8 Build programs with --no-default-features --features program to match solana-sdk (#11308)
(cherry picked from commit 52575349dc)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-07-31 17:14:05 +00:00
mergify[bot]
004b1b9c3f Add Vote Account Management Doc (#11278) (#11300)
* Add vote account management doc

* Add links to new doc

* Whitespace

* Fixup language

* Cleaner title

* Apply review feedback

* Apply further feedback

* Fix usage page header

Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit a5b6fd3d9b)

Co-authored-by: Dan Albert <dan@solana.com>
2020-07-31 02:59:07 +00:00
Michael Vines
2f8d0f88d6 Avoid spl-sdk dependency, which inhibits crate publishing 2020-07-31 00:05:13 +00:00
Vladimir Komendantskiy
177d241160 use replace value 2020-07-30 12:22:21 -07:00
Trent Nelson
5323622842 Bump version to 1.2.16 2020-07-30 10:55:09 -06:00
mergify[bot]
c852923347 Reject unsigned transactions sent via RPC (bp #11282) (#11287)
* Add failing test for TX sent via RPC with no signatures

(cherry picked from commit b962b2ce2d)

* Dereplicode send_transaction and request_airdrop RPC handlers

(cherry picked from commit a7079e4dde)

* Add new RPC error for TXs with no signatures

(cherry picked from commit 9778fedd7a)

* Reject TXs sent via RPC with no signatures

(cherry picked from commit a888f2f516)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-07-30 08:17:43 +00:00
mergify[bot]
5dc4410d58 Disable cross-program invocations for OperatingMode::Stable (bp #11272) (#11280)
* Disable cross-program invocations for OperatingMode::Stable (#11272)

(cherry picked from commit 2dbed80e48)

# Conflicts:
#	programs/bpf/benches/bpf_loader.rs
#	programs/bpf_loader/src/lib.rs
#	runtime/src/message_processor.rs
#	sdk/src/entrypoint_native.rs

* fix conflicts

Co-authored-by: Jack May <jack@solana.com>
2020-07-30 05:50:47 +00:00
mergify[bot]
da4642d634 Fix wallet links (#11284) (#11285)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit e8c0ec53e6)

Co-authored-by: Dan Albert <dan@solana.com>
2020-07-30 05:19:33 +00:00
mergify[bot]
a264be1791 Download and install SPL programs in run.sh/multinode-demo/docker (bp #11271) (#11275)
* Add --bpf-program argument

(cherry picked from commit 8eb6cbf784)

* Fetch and install SPL programs by default

(cherry picked from commit 3a1ca4efff)

* .sh

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-07-29 22:42:04 +00:00
mergify[bot]
9aff121949 Add top level link to Clusters page (#11276) (#11277)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit cd043b5d70)

Co-authored-by: Dan Albert <dan@solana.com>
2020-07-29 21:40:55 +00:00
mergify[bot]
a7f4d1487a Add SPL Token-specific rpc endpoints (bp #11231) (#11261)
* Add SPL Token-specific rpc endpoints (#11231)

* Simplify account-decoder program ids + spl_token helper

* Spl program namespace version

* Add getTokenAccountBalance endpoint

* Remove token program id from getTokenAccountBalance request

* Add getTokenSupply endpoint

* Remove token program id from getTokenSupply request

* Add getTokenAccountsByOwner/Delegate endpoints

* Remove token program id from getTokenAccountsByOwner/Delegate requests

* Named parameter

(cherry picked from commit b45ac5d4db)

# Conflicts:
#	Cargo.lock
#	account-decoder/Cargo.toml
#	core/Cargo.toml
#	core/src/rpc.rs
#	transaction-status/Cargo.toml

* Fix backport

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-07-29 17:08:21 +00:00
Trent Nelson
11e43e1654 Bump version to 1.2.15 2020-07-29 06:59:27 +00:00
Jack May
82be47bc18 Revert "Land program addresses on the curve (#11174) (#11226)"
This reverts commit 43e7107f65.
2020-07-28 20:48:57 -06:00
Trent Nelson
6498e4fbf6 Rerere-enable RecentBlockhashes fix on testnet (epoch 76) 2020-07-29 02:32:07 +00:00
Trent Nelson
9978971bd9 Fill out missing RPC request received debug logging 2020-07-29 02:04:34 +00:00
mergify[bot]
e28ac2c377 Fix race condition between shrinking and cleaning (bp #11235) (#11252)
* Fix race condition between shrinking and cleaning (#11235)

* Fix race condition between shrinking and cleaning

* Minor formatting

* fix ci

* Update comments

* More update comment

* Adjust fn naming

(cherry picked from commit 3e4f49f9c9)

# Conflicts:
#	runtime/src/accounts_db.rs

* Fix conflict

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-07-28 22:33:21 +00:00
Dan Albert
ef296aa7db Update non_circulating_supply.rs 2020-07-27 16:39:13 -06:00
mergify[bot]
43e7107f65 Land program addresses on the curve (#11174) (#11226)
(cherry picked from commit f317c362a8)

Co-authored-by: Jack May <jack@solana.com>
2020-07-27 21:21:16 +00:00
mergify[bot]
752fa29390 Designate mainnet-beta epoch 61 as an upgrade epoch (#11229)
(cherry picked from commit ed01591be6)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-07-27 20:08:45 +00:00
mergify[bot]
7bb7b42356 Use &[u8] for program address seeds rather then &str (#10744) (#11227)
(cherry picked from commit 73586c1aad)

Co-authored-by: Jack May <jack@solana.com>
2020-07-27 19:32:21 +00:00
mergify[bot]
2a7fc744f9 Add Docusaurus search (#11135) (#11224)
* Add Docusaurus search

* Add Algolia configuration information

* Trailing whitespace :(

Co-authored-by: Ryan Shea <rmshea@users.noreply.github.com>
(cherry picked from commit cbf0b779d7)

Co-authored-by: R. M. Shea <8948187+rmshea@users.noreply.github.com>
2020-07-27 16:39:56 +00:00
mergify[bot]
90e3da0389 Remove accidental MB activation for RecentBlockhashes consistency fix (#11216)
(cherry picked from commit 7931579610)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-07-26 18:59:07 +00:00
mergify[bot]
1a62bcee42 Windows binaries are now built with the MSVC instead of the GNU toolchain (bp #11208) (#11211)
* Windows binaries are now built with the MSVC instead of the GNU toolchain.

Update `solana-install-init` target info to match

(cherry picked from commit 01ff6846f7)

# Conflicts:
#	ci/publish-tarball.sh

* Update publish-tarball.sh

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-07-25 18:29:35 +00:00
Trent Nelson
b83a4cae90 Bump version to 1.2.14 2020-07-25 04:00:17 +00:00
mergify[bot]
05ef21cd3b Add token account decoding (bp #11136) (#11202)
* Add token account decoding (#11136)

* Add token decoding

* Bump versions

(cherry picked from commit 32fea0496e)

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

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-07-25 01:37:07 +00:00
mergify[bot]
dfa27b04d7 Add package-lock.json to docs (#11200) (#11201)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit eac423f92c)

Co-authored-by: Dan Albert <dan@solana.com>
2020-07-24 20:31:45 +00:00
Dan Albert
880b04906e Restore stake delegation page to sidebar 2020-07-24 13:42:36 -06:00
Trent Nelson
1fe0b1e516 Push back activation epochs redux
Effects:
- Re-enabling inflation
- Nonce FeeCalculator overwrite / RecentBlockhashes sysvar inconsistency fix
2020-07-24 18:09:40 +00:00
mergify[bot]
f9fd4bd24c Test cleanup (#11192) (#11193)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit c0dc21620b)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-24 12:09:39 +00:00
mergify[bot]
c55a11d160 Add encoding and filters parameters to rpc Subscriptions (bp #11065) (#11187)
* Add encoding and filters parameters to rpc Subscriptions (#11065)

* Plumb account configs and enable encoding

* Enable filters for pubsub program accounts

* Update docs

(cherry picked from commit c90de8978d)

* Fix test

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-07-23 21:53:05 +00:00
Tyera Eulberg
92118de0e1 Skip entrypoint in programs (#11175) 2020-07-22 20:59:36 -06:00
Tyera Eulberg
0d9802a2cd Use OrderedIterator in collect_balances (#11173) 2020-07-22 16:59:54 -06:00
Trent Nelson
f6beede01b Push back activation epochs
Effects:
- Re-enabling inflation
- Nonce FeeCalculator overwrite / RecentBlockhashes sysvar inconsistency fix
2020-07-22 16:17:02 -06:00
Trent Nelson
ff48ea20de Bump version to 1.2.13 2020-07-22 06:08:41 +00:00
Trent Nelson
dd9cb18d65 Enable RecentBlockhashes one tick delay fix on testnet
Slot 25_580_256 / Epoch 72
2020-07-22 05:51:47 +00:00
mergify[bot]
71932aed0a Re-enable inflation again for testnet (#11156)
(cherry picked from commit 3fd16cea34)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-07-22 05:14:04 +00:00
mergify[bot]
24dc6680e1 getEpochInfo RPC endpoint now includes the current block height (#11155)
Co-authored-by: Michael Vines <mvines@gmail.com>
2020-07-22 01:53:53 +00:00
mergify[bot]
61d9d40e48 Program feature-flag entrypoint (#11144) (#11152)
(cherry picked from commit 231e2387db)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-07-21 22:02:13 +00:00
mergify[bot]
e9b40db319 Use OrderedIterator in TransactionStatusService (#11149) (#11151)
* Split out get-first-err for unit testing

* Add failing test

* Add missing ordering

(cherry picked from commit 6c38369042)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-07-21 21:36:02 +00:00
mergify[bot]
316356861d Freeze warped bank to show freeze logs (#11141) (#11145)
(cherry picked from commit 6935e88148)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-07-21 08:14:38 +00:00
mergify[bot]
e07c00710a fix rewards points (bp #10914) (#11142)
* fix rewards points (#10914)

* fix rewards points

* fixups

* * verify that we don't spend more in rewards than we've allocated for rewards
* purge f64s from calculations that could be done with integers

* test typical values

* simplify iteration over delegations some

* fixups

* Use try_from

* Add a comment for commission_split()

* Add assertion to detect inconsistent reward dist.

* Fix vote_balance_and_staked

* Don't overwrite accounts with stale copies

* Fix CI...

* Add tests for vote_balance_and_staked

* Add test for the determinism of update_rewards

* Revert "Don't overwrite accounts with stale copies"

This reverts commit 9886d085a6.

* Make stake_delegation_accounts to return hashmap

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

# Conflicts:
#	runtime/src/serde_snapshot/tests.rs

* Fix conflict

Co-authored-by: Rob Walker <rwalker@rwalker.com>
Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-07-21 06:35:20 +00:00
mergify[bot]
bc47c80610 Insubstantial grammar fix (#11133) (#11134)
(cherry picked from commit 0cb422fbbb)

Co-authored-by: Wei Tang <accounts@that.world>
2020-07-20 14:46:51 +00:00
mergify[bot]
14baa511f0 Add --warp-epoch and --enable-inflation to ledger-tool cap. (bp #11107) (#11132)
* Add --warp-epoch and --force-inflation to ledger-tool cap. (#11107)

* Add --warp-epoch and --force-inflation to ledger-tool cap.

* Add more arguments

* Address review comments

* Fix message

* Fix various typos...

(cherry picked from commit 3db246f596)

# Conflicts:
#	ledger-tool/src/main.rs

* Fix conflicts..

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-07-20 12:00:56 +00:00
carllin
e773faeb24 Add replay votes to gossip vote tracking (#11124)
* Plumb replay vote channel

* Don't send redundant slots to repair_service

* Update test

* Keep gossip only for debugging gossip in the future

* Add comments

* Switch to using select()

* Fix replay -> gossip vote not counting toward gossip only stake

* tests

Co-authored-by: Carl <carl@solana.com>
2020-07-19 22:25:16 -07:00
Dan Albert
42847516a2 Update build.sh 2020-07-18 08:32:12 -06:00
mergify[bot]
47e9a1ae4f Remove tictactoe, add Break and Hello World to docs (#11117) (#11118)
* Remove tictactoe, add Break to apps docs

* Add hello world

* fix whitespace

Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit 1ad0d210bc)

Co-authored-by: Dan Albert <dan@solana.com>
2020-07-18 00:21:48 +00:00
mergify[bot]
549a154394 Fix 404 broken links (#11113) (#11114)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit d0d4d9b3d1)

Co-authored-by: Dan Albert <dan@solana.com>
2020-07-17 18:01:50 +00:00
mergify[bot]
dca00d1bde Add Bank support for "upgrade epochs" where all non-vote transactions will be rejected (bp #11082) (#11110)
* Add Bank support for "upgrade epochs" where all non-vote transactions will be rejected

(cherry picked from commit e5d8c4383f)

# Conflicts:
#	runtime/src/bank.rs

* Fix merge conflict

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-07-17 17:29:34 +00:00
mergify[bot]
45ce1b4f96 Always pass affected file check on tagged release (#11089) (#11091)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit 6174cdb579)

Co-authored-by: Dan Albert <dan@solana.com>
2020-07-16 04:29:15 +00:00
Michael Vines
a9232c0633 Update CRATES_IO_TOKEN 2020-07-15 17:53:05 -07:00
carllin
3da254c745 Bump version to 1.2.12 (#11088)
Co-authored-by: Me <carl_solana_com@carl-dev.c.principal-lane-200702.internal>
2020-07-15 23:55:05 +00:00
mergify[bot]
9ba3ee9683 Change transparent .svg to opaque .png (#11084) (#11085)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit fe71f9ad1a)

Co-authored-by: Dan Albert <dan@solana.com>
2020-07-15 21:47:59 +00:00
Tyera Eulberg
b0addba2a9 Gate nonce-overwrite change (#11079) 2020-07-15 21:14:28 +00:00
mergify[bot]
bb59525ff8 Refactor file and URL paths in docusaurus (#11080) (#11083) 2020-07-15 14:35:12 -06:00
mergify[bot]
acd25124d4 Make accounts file clean faster (#11071) (#11077)
(cherry picked from commit 7fe870ba48)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-07-15 18:00:41 +00:00
mergify[bot]
d718ab2491 accounts_clean: Convert stack dependency calculation with iterative (#11067) (#11076)
* accounts_clean: Convert stack dependency calculation with iterative

* optimize clean with by creating a reverse-lookup hashset of the affected
keys

* Add dependency bench

reduce bench

* Huge clean

(cherry picked from commit 8bf3a0aa05)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-07-15 15:13:33 +00:00
mergify[bot]
1860aacd1f Temporalily disable inflation to fix it later (#11072) (#11075)
* Revert get_inflation()

* Temporalily disable inflation to fix it later

* Use match and proper type aliases

(cherry picked from commit d81c7250b0)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-07-15 11:20:02 +00:00
mergify[bot]
d4bbb7f516 Expose TransactionStatusService to the other blockstore_processor path (bp #11070) (#11074)
* Expose tss to the other blockstore_processor path (#11070)

(cherry picked from commit 9a80e31bae)

# Conflicts:
#	core/src/validator.rs
#	ledger/src/blockstore_processor.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-07-15 05:50:45 +00:00
mergify[bot]
d1c0f4b4f1 Fix hygiene issues in declare_program! and declare_loader! (bp #10905) (#11073)
* Fix hygiene issues in `declare_program!` and `declare_loader!`

The `declare_program!` and `declare_loader!` macros both expand to
new macro definitions (based on the `$name` argument). These 'inner'
macros make use of the special `$crate` metavariable to access items in
the crate where the 'inner' macros is defined.

However, this only works due to a bug in rustc. When a macro is
expanded, all `$crate` tokens in its output are 'marked' as being
resolved in the defining crate of that macro. An inner macro (including
the body of its arms) is 'just' another set of tokens that appears in
the body of the outer macro, so any `$crate` identifiers used there are
resolved relative to the 'outer' macro.

For example, consider the following code:

```rust
macro_rules! outer {
    () => {
        macro_rules! inner {
            () => {
                $crate::Foo
            }
        }
    }
}
```

The path `$crate::Foo` will be resolved relative to the crate that defines `outer`,
**not** the crate which defines `inner`.

However, rustc currently loses this extra resolution information
(referred to as 'hygiene' information) when a crate is serialized.
In the above example, this means that the macro `inner` (which gets
defined in whatever crate invokes `outer!`) will behave differently
depending on which crate it is invoked from:

When `inner` is invoked from the same crate in which it is defined,
the hygiene information will still be available,
which will cause `$crate::Foo` to be resolved in the crate which defines 'outer'.

When `inner` is invoked from a different crate, it will be loaded from
the metadata of the crate which defines 'inner'. Since the hygiene
information is currently lost, rust will 'forget' that `$crate::Foo` is
supposed to be resolved in the context of 'outer'. Instead, it will be
resolved relative to the crate which defines 'inner', which can cause
incorrect code to compile.

This bug will soon be fixed in rust (see https://github.com/rust-lang/rust/pull/72121),
which will break `declare_program!` and `declare_loader!`. Fortunately,
it's possible to obtain the desired behavior (`$crate` resolving in the
context of the 'inner' macro) by use of a procedural macro.

This commit adds a `respan!` proc-macro to the `sdk/macro` crate.
Using the newly-stabilized (on Nightly) `Span::resolved_at` method,
the `$crate` identifier can be made to be resolved in the context of the
proper crate.

Since `Span::resolved_at` is only stable on the latest nightly,
referencing it on an earlier version of Rust will cause a compilation error.
This requires the `rustversion` crate to be used, which allows conditionally
compiling code epending on the Rust compiler version in use. Since this method is already
stabilized in the latest nightly, there will never be a situation where
the hygiene bug is fixed (e.g. https://github.com/rust-lang/rust/pull/72121)
is merged but we are unable to call `Span::resolved_at`.

(cherry picked from commit 05445c718e)

# Conflicts:
#	Cargo.lock
#	sdk/Cargo.toml

* Replace FIXME with an issue link

(cherry picked from commit b0cb2b0106)

* Update lock files

(cherry picked from commit 42f88484f4)

# Conflicts:
#	programs/bpf/Cargo.lock
#	programs/librapay/Cargo.lock
#	programs/move_loader/Cargo.lock

* Split comment over multiple lines

Due to https://github.com/rust-lang/rustfmt/issues/4325, leaving this as
one line causes rustfmt to add extra indentation to the surrounding
code.

(cherry picked from commit fed69e96a9)

* Fix clippy lints

(cherry picked from commit e7387f60a7)

* Apply #![feature(proc_macro_hygiene)] when needed

This allows the rust-bpf-builder toolchain to build the sdk

(cherry picked from commit 95490ff56e)

# Conflicts:
#	sdk/build.rs
#	sdk/src/lib.rs

* Update Cargo.toml

* Update lib.rs

* Add rustc_version

* lock file updates

Co-authored-by: Aaron Hill <aa1ronham@gmail.com>
Co-authored-by: Jack May <jack@solana.com>
Co-authored-by: Michael Vines <mvines@gmail.com>
2020-07-15 02:40:36 +00:00
carllin
b72b837ba2 Revert dashboard changes (#11069)
Co-authored-by: Carl <carl@solana.com>
2020-07-15 00:42:39 +00:00
mergify[bot]
fde85c96c0 Add dropped vote metrics (#11009) (#11030)
(cherry picked from commit 1880621740)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-07-14 15:21:49 -07:00
mergify[bot]
121418dad2 CLI: Fix vote blind indexing (bp #11045) (#11050)
* CLI: Fix explicitly plumb withdraw_authority through vote-update-commission

(cherry picked from commit 3392ecc310)

* CLI: Fix explicitly plumb withdraw_authority through vote-update-validator

(cherry picked from commit 2284699889)

* CLI: Fix explicitly plumb vote_account through create-vote-account

(cherry picked from commit 14ac233d01)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-07-14 15:35:46 +00:00
Dan Albert
f44f94fe23 Remove docs step from buildkite flow (#11035) (#11044) 2020-07-14 08:20:58 -06:00
mergify[bot]
55a4481022 Clean up docs publishing flow (#11043) (#11051)
* Clean up publishing flow

* Update README

Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit 303a4df6ef)

Co-authored-by: Dan Albert <dan@solana.com>
2020-07-14 14:09:53 +00:00
mergify[bot]
e859ad37a8 Add TreeDiff trait to reuse tree functions (#11046) (#11048)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit e9cbdf711b)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-14 09:03:53 +00:00
mergify[bot]
1a28c7fc12 Fix recent blockhashes delay (bp #11036) (#11040)
* Add failing test

(cherry picked from commit 942c019d50)

* Factor locked portion of Bank::update_recent_blockhashes() out to helper

(cherry picked from commit 9cc379af6c)

* Synchronize BlockhashQueue and RecentBlockhashes sysvar update

(cherry picked from commit 5357ff6d60)

* Bump goldens

(cherry picked from commit 837ac77c02)

* Fix test advancing banks from incomplete slots

(cherry picked from commit 51283c931c)

* Mode gate RecentBlockhashes/BlockhashQueue sync

(cherry picked from commit 5741002a32)

Co-authored-by: Tyera Eulberg <tyera@solana.com>
Co-authored-by: Trent Nelson <trent@solana.com>
2020-07-14 04:12:37 +00:00
Dan Albert
c706a07764 Fix travis config (#11033)
* Fix travis config

* Remove linux build job from travis
2020-07-13 17:00:18 -06:00
Dan Albert
59568e5776 Move from gitbook to docusaurus - backport (#10970) (#11029)
* Move v1.2 to docusaurus

* Fixup travis conifg

Co-authored-by: publish-docs.sh <maintainers@solana.com>
2020-07-13 14:45:28 -06:00
Dan Albert
33ca8fa72a Fix Travis PR detection environment (#10974) (#11024) 2020-07-13 14:25:40 -06:00
mergify[bot]
4bb66a81fb Check for deleting key, make sure list is empty again (#11007) (#11011)
Co-authored-by: sakridge <sakridge@gmail.com>
2020-07-13 09:00:48 -07:00
Michael Vines
468c14b14f Revert "Add UiTransactionEncoding::Raw"
This reverts commit bcc890e705.
2020-07-12 09:00:11 -07:00
Tyera Eulberg
03e505897a Backport windows build fixes (#11004)
* Bump spl-memo

* spl memo linking windows (#11000)

* Update spl-memo to fix windows linking error

* Only programs need the stubs

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>

Co-authored-by: Jack May <jack@solana.com>
Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-07-10 21:46:11 -06:00
mergify[bot]
5205eb382e Switch to using weighted repair in RepairService (#10735) (#10985)
Co-authored-by: Carl <carl@solana.com>
2020-07-10 16:15:36 -07:00
Michael Vines
b07b6e56fa getConfirmedBlocks now has an upper limit on slot range
(cherry picked from commit aef6bf272e)
2020-07-10 15:40:03 -07:00
Michael Vines
bcc890e705 Add UiTransactionEncoding::Raw
(cherry picked from commit a4a5438b6d)
2020-07-10 14:55:27 -07:00
mergify[bot]
07d14f6f07 Add RepairWeight to track votes seen in gossip for weighted repair (#10903) (#10938)
* Add RepairWeight

Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 3f6042d8b3)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-10 14:13:56 -07:00
mergify[bot]
03b213e296 Add block time placeholder to getConfirmedBlock (#10990)
(cherry picked from commit 491f5ae61a)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-07-10 11:02:27 -07:00
mergify[bot]
1bfce24c9f Fix skipped slot detection for eager rent collect (#10890) (#10978)
(cherry picked from commit f1c1152948)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-07-10 11:59:44 +09:00
mergify[bot]
94b2565969 Fix nonce fee_calculator overwrite (#10973) (#10976)
* Add failing test

* Pass fee_calculator to prepare_if_nonce_account; only overwrite in error case

(cherry picked from commit 25228ca957)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-07-09 16:57:34 -06:00
sakridge
2896fdb603 Update version to v1.2.11 (#10966) 2020-07-09 06:48:30 -07:00
sakridge
50970bc8f9 Update version to v1.2.10 (#10962) 2020-07-08 15:34:19 -07:00
mergify[bot]
10df45b173 update testnet docs (#10954) (#10955)
(cherry picked from commit e50227745d)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-07-08 04:08:16 +00:00
mergify[bot]
d3b8129593 Clean accounts path on validator startup (#10929) (#10944)
Co-authored-by: sakridge <sakridge@gmail.com>
2020-07-07 18:27:49 +00:00
Tyera Eulberg
f7fb5aebac v1.2 instruction and account decoding backports (#10939)
* Revert "Rpc: add filter to getProgramAccounts (#10888) (#10932)"

This reverts commit 9311a6e356.

* Add jsonParsed option for EncodedTransactions; add memo parser (#10711)

* Add jsonParsed option for EncodedTransactions; add memo parser

* Use kebab case for program names

* Add account-key parsing

* Add parse test

* Update transaction encoding docs (#10833)

* Add account-decoder utilities (#10846)

* Fix comment and make less pub

* Add account-decoder crate and use to decode vote and system (nonce) accounts

* Update docs

* Rename RpcAccount struct

* s/Rpc/Display

* Call it jsonParsed and update docs

* Revert "s/Rpc/Display"

This reverts commit 6e7149f503.

* s/Rpc/Ui

* Add tests

* Ui more things

* Comments

* Update struct prefixes to Ui (#10874)

* Update comments

* Use Ui prefix

* Rpc: add filter to getProgramAccounts (#10888)

* Add RpcFilterType, and implement CompareBytes for getProgramAccounts

* Accept bytes in bs58

* Rename to memcmp

* Add Memcmp optional encoding field

* Add dataSize filter

* Update docs

* Clippy

* Simplify tests that don't need to test account contents; add multiple-filter tests
2020-07-07 09:35:35 -06:00
Tyera Eulberg
9311a6e356 Rpc: add filter to getProgramAccounts (#10888) (#10932)
* Add RpcFilterType, and implement CompareBytes for getProgramAccounts

* Accept bytes in bs58

* Rename to memcmp

* Add Memcmp optional encoding field

* Add dataSize filter

* Update docs

* Clippy

* Simplify tests that don't need to test account contents; add multiple-filter tests
2020-07-06 21:45:12 +00:00
mergify[bot]
8c706892df Rpc: Add getStakeActivation endpoint (bp #10902) (#10930)
* Rpc: Add getStakeActivation endpoint (#10902)

* Add getStakeActivation endpoint

* Add docs

* Update docs/src/apps/jsonrpc-api.md

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

* Rework return type

* Update docs

* Rebase

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

* Fix build

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-07-06 21:23:27 +00:00
mergify[bot]
7f2b11756c Fix parsing (#10924) (#10926)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 823126b372)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-06 11:05:17 +00:00
mergify[bot]
f324547600 Skip and warn for hard-forks which are less than the start slot (#10918) (#10920)
* Skip and warn for hard-forks which are less than the start slot

Option is used during a restart, but then after the restart is
complete, then the option is not needed if the starting slot
is past the hard-fork since the hard-fork should already be
in the snapshot it started from.

* Update ledger/src/blockstore_processor.rs

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

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

Co-authored-by: sakridge <sakridge@gmail.com>
2020-07-05 22:15:26 +00:00
mergify[bot]
36e8977f1d Repair timing (#10913) (#10917)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 28e15a63e5)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-04 03:48:29 +00:00
mergify[bot]
b88db2689e Add breakdown of erasure blobs (#10912) (#10915)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit f014c94369)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-04 02:15:03 +00:00
sakridge
1584ec220c Move clean accounts to background service (#10904) 2020-07-02 22:39:22 -07:00
mergify[bot]
fb366a7236 Add weighted traversal (#10877) (#10901)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit f17ac70bb2)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-02 23:52:03 +00:00
mergify[bot]
b903158543 getInflationRate now only supports the current epoch (#10887)
(cherry picked from commit d53228e69d)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-07-02 03:36:47 +00:00
mergify[bot]
9dad9c6333 Prevent stub inclusion when building shared objects (bp #10875) (#10879)
* Prevent stub inclusion when building shared objects (#10875)

(cherry picked from commit 52526a9bc2)

# Conflicts:
#	programs/bpf/rust/128bit/src/lib.rs
#	programs/bpf/rust/alloc/src/lib.rs
#	programs/bpf/rust/dep_crate/src/lib.rs
#	programs/bpf/rust/invoke/src/lib.rs
#	programs/bpf/rust/invoked/src/lib.rs
#	programs/bpf/rust/iter/src/lib.rs
#	programs/bpf/rust/many_args/src/lib.rs
#	programs/bpf/rust/many_args_dep/src/lib.rs
#	programs/bpf/rust/noop/src/lib.rs
#	programs/bpf/rust/param_passing/src/lib.rs
#	programs/bpf/rust/param_passing_dep/src/lib.rs
#	sdk/bpf/rust/test/src/lib.rs

* nudge

Co-authored-by: Jack May <jack@solana.com>
2020-07-01 22:47:17 +00:00
mergify[bot]
a6658b9d75 Add ability to parse logs in ledger-tool (#10840) (#10849)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 2dfa48daf9)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-01 20:30:48 +00:00
mergify[bot]
a97feedcc1 Pull program stubs into SDK (bp #10704) (#10713)
* Pull program stubs into SDK (#10704)

(cherry picked from commit d77818c18b)

# Conflicts:
#	programs/bpf/Cargo.lock
#	programs/bpf/rust/128bit/Cargo.toml
#	programs/bpf/rust/128bit_dep/Cargo.toml
#	programs/bpf/rust/alloc/Cargo.toml
#	programs/bpf/rust/dep_crate/Cargo.toml
#	programs/bpf/rust/dup_accounts/Cargo.toml
#	programs/bpf/rust/error_handling/Cargo.toml
#	programs/bpf/rust/external_spend/Cargo.toml
#	programs/bpf/rust/invoke/Cargo.toml
#	programs/bpf/rust/invoked/Cargo.toml
#	programs/bpf/rust/iter/Cargo.toml
#	programs/bpf/rust/many_args/Cargo.toml
#	programs/bpf/rust/many_args_dep/Cargo.toml
#	programs/bpf/rust/noop/Cargo.toml
#	programs/bpf/rust/panic/Cargo.toml
#	programs/bpf/rust/param_passing/Cargo.toml
#	programs/bpf/rust/param_passing_dep/Cargo.toml
#	programs/bpf/rust/sysval/Cargo.toml
#	sdk/bpf/rust/test/Cargo.toml

* fix conflicts

Co-authored-by: Jack May <jack@solana.com>
2020-07-01 20:17:37 +00:00
mergify[bot]
8021bce41f Instructions for validator logging (#10845) (#10878)
* Instructions for disabling log throttling

* Remove syslog, add logrotate

* Update docs/src/running-validator/validator-start.md

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

Co-authored-by: Carl <carl@solana.com>
Co-authored-by: Trent Nelson <trent.a.b.nelson@gmail.com>
(cherry picked from commit 6b45481bbb)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-01 20:03:27 +00:00
mergify[bot]
d8fa19336c Add heaviest subtree utility functions (#10863) (#10865)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 7a71580d53)

Co-authored-by: carllin <wumu727@gmail.com>
2020-07-01 11:21:22 +00:00
sakridge
191483cf9f Update cargo.* version to 1.2.9 (#10861) 2020-06-30 23:21:10 +00:00
mergify[bot]
1eb8314d42 Update expected shred version for testnet. (#10858) (#10859)
(cherry picked from commit 5adf6f6bde)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-30 21:02:58 +00:00
sakridge
88eeb817e4 More guard rails for restart with ledger procedure (#10854)
* Add expected_bank_hash required for supermajority
* Print snapshot hash in ledger-tool create-snapshot.
2020-06-30 12:55:25 -07:00
Stephen Akridge
b777126bd2 Revert removing -e in cargo-for-all-lock-files 2020-06-30 09:13:03 -07:00
Stephen Akridge
89d78dcfcf Update cargo.* version to 1.2.8 2020-06-30 09:03:28 -07:00
mergify[bot]
1cf142c193 Remove outdated todo comment (#10850) (#10851)
(cherry picked from commit cabedc0f36)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-06-30 15:07:09 +00:00
mergify[bot]
3e29325410 Fix fork detection (#10839) (#10844)
* Fix fork detection

Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 4b93a7c1f6)

Co-authored-by: carllin <wumu727@gmail.com>
2020-06-30 04:16:05 +00:00
mergify[bot]
4dc98c3dbd Reduce logging lines (#10835) (#10841)
(cherry picked from commit d9b389f510)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-30 00:28:58 +00:00
mergify[bot]
9caad645e2 Remove ledger purge batching (#10830) (#10836)
(cherry picked from commit 583cec922b)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-29 23:10:45 +00:00
mergify[bot]
6cb76ac326 More replay stage timing metrics (#10828) (#10829)
(cherry picked from commit 17a2128a8f)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-28 18:27:35 +00:00
mergify[bot]
0001e5c0a1 net.sh: Refactor node initialization wait (#10819) (#10824)
* remote-node.sh: Factor out init wait to own script

* remote-node.sh: Allow nodes to initialize asynchronously

* testnet-automation: Plumb --async-node-init

(cherry picked from commit 7021e1c584)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-06-26 16:28:46 +00:00
carllin
ab32d13da1 Add debugging (#10820)
Co-authored-by: Carl <carl@solana.com>
2020-06-26 08:09:04 +00:00
mergify[bot]
cefe46e981 Clean up rpc module (#10812) (#10815)
* Clean up rpc module

* Simplify getting bank

(cherry picked from commit 62b873b054)

Co-authored-by: Greg Fitzgerald <greg@solana.com>
2020-06-26 01:59:06 +00:00
mergify[bot]
f4d70e78b6 Add ancestor iterator to lib.rs (#10813) (#10817)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 0fde0d7379)

Co-authored-by: carllin <wumu727@gmail.com>
2020-06-26 01:02:51 +00:00
mergify[bot]
d130adf582 Dont skip eager rent collect across gapped epochs (#10206) (#10808)
* Dont skip eager rent collect across gapped epochs

* Adjust style and comment

* Adjust ascii chart and comment a bit

* Moar assert

* Relax the partition_count assert for completeness

* Tweak comment...

* tweak a bit

* Add gating logic

* Address reviews

* small formatting

* Clarify the code by replacing auto_generated...

* small formatting

* small formatting

* small formatting

* small formatting

* Narrow down conditional compilation scope

(cherry picked from commit 50f7ed80c8)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-06-25 15:34:04 +00:00
carllin
1e6285e64e Fix leaf propagation in case of no votes in HeaviestForkChoice (#10807)
* Fix leaf propagation logic

Co-authored-by: Carl <carl@solana.com>
2020-06-25 04:05:26 -07:00
mergify[bot]
e3c90c3807 Add non-circulating withdraw authority (#10798) (#10804)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit b3e382ab3f)

Co-authored-by: Dan Albert <dan@solana.com>
2020-06-25 06:15:24 +00:00
mergify[bot]
85750307aa Rename Client methods to match proposed BanksClient (bp #10793) (#10800)
* Rename Client methods to match proposed BanksClient (#10793)

(cherry picked from commit 7ade330b23)

# Conflicts:
#	programs/bpf/tests/programs.rs
#	runtime/benches/bank.rs

* Fix merge

Co-authored-by: Greg Fitzgerald <greg@solana.com>
2020-06-25 05:33:12 +00:00
mergify[bot]
0ee4a5e799 Fix race in ci/run-sanity.sh (#10796) (#10802)
(cherry picked from commit 4dc9f378b8)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-06-25 04:54:54 +00:00
mergify[bot]
55cb9cf681 Use cargo tree to bump release branch lock files (#10790) (#10792)
(cherry picked from commit 48b846203e)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-06-25 03:04:10 +00:00
mergify[bot]
d3af7e0653 Fix broken image link (#10496) (#10795)
automerge

(cherry picked from commit 75b8c2c4e3)

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-06-25 01:41:53 +00:00
mergify[bot]
729a24d557 Fixup stake doc wording (#10782) (#10784)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit d5d5ad0071)

Co-authored-by: Dan Albert <dan@solana.com>
2020-06-25 01:25:22 +00:00
mergify[bot]
55b92c16da Remove fee-payer guesswork from Message and Transaction (bp #10776) (#10785)
* Remove fee-payer guesswork from Message and Transaction (#10776)

* Make Message::new_with_payer the default constructor

* Remove Transaction::new_[un]signed_instructions

These guess the fee-payer instead of stating it explicitly

(cherry picked from commit 1c498369b5)

# Conflicts:
#	cli/src/nonce.rs
#	core/src/rpc.rs
#	ledger/src/blockstore.rs
#	programs/bpf/tests/programs.rs

* Fix merge

Co-authored-by: Greg Fitzgerald <greg@solana.com>
2020-06-25 01:10:23 +00:00
Trent Nelson
835bacce4f Revert some stowaway changes from ccb7b1a 2020-06-24 16:04:28 -06:00
Stephen Akridge
ccb7b1a698 Bump cargo version to v1.2.7 2020-06-24 09:23:12 -07:00
mergify[bot]
85dbdeb4c3 Add staking guide to docs (#10609) (#10780)
(cherry picked from commit 0b14ae5725)

Co-authored-by: Dan Albert <dan@solana.com>
2020-06-24 09:46:42 -06:00
mergify[bot]
397f9f11c5 Allow for hard fork at last root (#10762) (#10766)
(cherry picked from commit 0e393a5684)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-24 06:10:48 +00:00
mergify[bot]
a11986ad1d Make curl verbose when uploading assets to github (#10757) (#10761)
Debugging silent asset upload failures during release

(cherry picked from commit 3aab13a167)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-06-24 01:35:13 +00:00
mergify[bot]
a4d373f0af Fix plumtree link (#10755) (#10759)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit c52f06a54a)

Co-authored-by: Dan Albert <dan@solana.com>
2020-06-23 23:42:25 +00:00
mergify[bot]
52eea215ce Rework backup and clear function (#10751) (#10754)
(cherry picked from commit a1ef921b88)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-23 22:56:14 +00:00
mergify[bot]
6f48aafd3a Add utility functions for testing (#10749) (#10752)
* Add ancestor iterator

* Add blockstore generation from trees

Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 77b8de193c)

Co-authored-by: carllin <wumu727@gmail.com>
2020-06-23 21:55:09 +00:00
Stephen Akridge
2d94c09aee Bump Cargo.toml version to 1.2.6 2020-06-22 23:23:16 -07:00
mergify[bot]
9699b61679 Remove slots past wait-for-supermajority slot. (#10720) (#10745)
(cherry picked from commit 2ba8fc5243)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-23 04:57:57 +00:00
mergify[bot]
8865bfbd59 Weight repair slots based on vote stake (#10741) (#10746)
* Weight repair slots based on vote stake

* Add test

(cherry picked from commit cabd0a09c3)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-23 04:48:32 +00:00
mergify[bot]
5f80c1d37d Remote Wallet: Stricter derivation path component parsing (#10725) (#10740)
(cherry picked from commit 842cab2739)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-06-22 18:36:12 +00:00
mergify[bot]
f616f5dec6 ledger-tool: Ignore SIGUSR1 (#10730) (#10732)
Prevents warehouse archive calls getting KO'd by logrotate

(cherry picked from commit d42247c652)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-06-21 19:31:38 +00:00
mergify[bot]
db1003b5f8 nit removal (#10721) (#10729)
(cherry picked from commit a87f490b5e)

Co-authored-by: Kristofer Peterson <svenski123@users.noreply.github.com>
2020-06-21 08:36:07 +00:00
mergify[bot]
f52ff777b7 Add repair breakdown by slot and index (#10717) (#10727)
* Slot full logging

* Repair stats logging

Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit a33fef9af2)

Co-authored-by: carllin <wumu727@gmail.com>
2020-06-20 02:52:22 +00:00
mergify[bot]
4314a29953 Fix typo (#10724) (#10726)
(cherry picked from commit cae22efd0e)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-06-20 01:27:20 +00:00
mergify[bot]
e560fff840 Add CLI options and runtime support for selection of output snapshot version (bp #10536) (#10712)
* Add CLI options and runtime support for selection of output snapshot version. (#10536)

(cherry picked from commit 6d81eede93)

# Conflicts:
#	core/src/accounts_hash_verifier.rs
#	core/src/rpc_service.rs
#	core/tests/bank_forks.rs
#	ledger-tool/src/main.rs
#	ledger/src/snapshot_package.rs
#	validator/src/main.rs

* Fix conflicts

Co-authored-by: Kristofer Peterson <svenski123@users.noreply.github.com>
Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-06-19 07:52:09 +00:00
mergify[bot]
5ac747ea7d Reduce responder error prints (#10664) (#10703)
(cherry picked from commit 0a0f17b9d2)

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-19 01:16:43 +00:00
mergify[bot]
f522dc1e18 Don't bother api.github.com on pull requests to avoid getting rate limited (#10710)
(cherry picked from commit c0389ef82f)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-06-18 23:53:32 +00:00
Michael Vines
486812bf54 Only force up-to-date lock files on edge 2020-06-18 18:57:30 +00:00
Michael Vines
7df8f76df1 Add stub address_labels field for 1.3 compatibility 2020-06-18 18:57:30 +00:00
mergify[bot]
bbe4990e80 Move SDK types to more appropriate files (bp #10638) (#10665)
* Move types to more appropriate files (#10638)

(cherry picked from commit dac7dc2f10)

# Conflicts:
#	programs/stake/src/stake_instruction.rs
#	programs/vote/src/vote_instruction.rs
#	sdk/src/system_instruction.rs

* Fix conflicts

* bump lock

Co-authored-by: Jack May <jack@solana.com>
2020-06-18 18:17:43 +00:00
mergify[bot]
a5baaf790d Do not run buildkite tests if gitbook config modified (#10692) (#10694)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
(cherry picked from commit 89e0584250)

# Conflicts:
#	ci/buildkite-pipeline.sh

Co-authored-by: Dan Albert <dan@solana.com>
2020-06-18 17:37:56 +00:00
mergify[bot]
0a36ed1b8c Update testnet shred version (#10684) (#10686)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 9c22a6007d)

Co-authored-by: carllin <wumu727@gmail.com>
2020-06-18 08:58:44 +00:00
mergify[bot]
b7ad240375 Update testnet shred version (#10681) (#10683)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit dae8bc477b)

Co-authored-by: carllin <wumu727@gmail.com>
2020-06-18 07:47:28 +00:00
mergify[bot]
2cc71f2d55 Merge heaviest bank modules (bp #10672) (#10677)
* Merge heaviest bank modules

* Update lockfiles

Co-authored-by: Greg Fitzgerald <greg@solana.com>
2020-06-18 06:14:53 +00:00
Michael Vines
3125c74681 Remove strict from automerge, add rebase opt in 2020-06-17 20:53:38 -07:00
mergify[bot]
d5b1dee8d6 ignore break (#10666) (#10669)
(cherry picked from commit a5f82c995e)

Co-authored-by: anatoly yakovenko <anatoly@solana.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2020-06-17 20:41:35 -07:00
Stephen Akridge
4b33a2a1b8 Update Cargo.toml version from 1.2.4 to 1.2.5 2020-06-17 18:55:20 -07:00
Tyera Eulberg
58e6a5c281 Add docs to declare_id macro (#10673)
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2020-06-17 19:19:06 -06:00
mergify[bot]
7eb61074ab Simd poh (#10604) (#10658)
* Simd poh

* Fix poh verify bench

Co-authored-by: sakridge <sakridge@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2020-06-18 00:34:56 +00:00
mergify[bot]
9b2edbaa9b Plumb --warp-slot through net scripts (bp #10639) (#10643)
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

Co-authored-by: Trent Nelson <trent@solana.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2020-06-17 21:36:04 +00:00
Justin Starry
e8659b45c7 Wait until bank is frozen before sending RPC notifications (#10654)
(cherry picked from commit 39984cdcc3)
2020-06-17 13:05:29 -07:00
mergify[bot]
a9553cb401 Entry verify cleanup and gossip counters (#10632) (#10650)
* Add prune message counter

* Switch to us verification time to match other counters

* Add separate transaction/poh verify timing

Co-authored-by: sakridge <sakridge@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2020-06-17 19:48:05 +00:00
mergify[bot]
800c409698 Factor out testnet automation SW version resolution (#10660)
(cherry picked from commit a15f60a291)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-06-17 17:31:11 +00:00
mergify[bot]
b6f484ddee ClusterInfo cleanup (#10504) (#10657)
automerge

Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-17 15:28:41 +00:00
publish-docs.sh
3c39fee5a8 Add address to non-circulating supply
(cherry picked from commit 5673343f49)
2020-06-16 21:45:51 -07:00
mergify[bot]
560f34d1f6 Fix links in TdS registration docs page (#10641) (#10645)
Co-authored-by: publish-docs.sh <maintainers@solana.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 36ca43e15b)

Co-authored-by: Dan Albert <dan@solana.com>
2020-06-17 02:43:58 +00:00
Stephen Akridge
dbda50941a Bump version to 1.2.4 2020-06-16 17:03:09 -07:00
Trent Nelson
f1e68ac25c Allow pre-existing stake accounts in multinode-demo/delegate-stake.sh
(cherry picked from commit ae0d5ba201)
2020-06-16 15:15:21 -07:00
mergify[bot]
95029b9b05 Enable fork choice and switch votes, devnet => now, testnet => epoch 63 (#10615) (#10624)
* Enable fork choice, devnet => now, testnet => epoch 63

* Set development to 0

* Enable switch vote slot

Co-authored-by: Carl <carl@solana.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit f8b88d717e)

Co-authored-by: carllin <wumu727@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2020-06-16 12:47:58 +00:00
mergify[bot]
a789bf4761 Add generic is_parsable() input validator. (#10621)
Allow input validators to accept &str, &String and String parameters.

(cherry picked from commit daa2e6363f)

Co-authored-by: Kristofer Peterson <kris@tranception.com>
2020-06-16 10:33:13 +00:00
mergify[bot]
d2e7ffa8b9 Fix race in remove_unrooted_slot (#10607) (#10617)
* Fix race

* clippy fixes

* Rename and add comment

Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 8bd62d78eb)

Co-authored-by: carllin <wumu727@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2020-06-16 06:20:48 +00:00
mergify[bot]
0914519f6a Plumb --wait-for-supermajority through scripts (#10611) (#10614)
(cherry picked from commit 348bf78cd1)

Co-authored-by: Trent Nelson <trent@solana.com>
2020-06-16 03:09:29 +00:00
carllin
43cd5f3730 Disable repeated slot dumping (#10606)
* Disable repeated slot dumping

* Disable entire codepath

Co-authored-by: Carl <carl@solana.com>
2020-06-15 18:00:23 -07:00
Michael Vines
d396a5f45a |solana withdraw-from-vote-account| now supports ALL, and refuses to deallocate the vote account (#10602)
(cherry picked from commit 296ac10b3a)
2020-06-15 17:17:43 -07:00
Michael Vines
76a7071dba Add mergify automerge rules 2020-06-15 09:10:42 -07:00
mergify[bot]
133baa8ce6 Fix udp port check retry and check all udp ports (#10385) (#10577)
automerge
2020-06-14 18:16:15 -07:00
mergify[bot]
5df3510fde Fix perf-libs version detection (#10571) (#10574)
automerge
2020-06-14 13:50:29 -07:00
Stephen Akridge
357339273f Revert "Look at repair peers"
This reverts commit 0013bfff4e.
2020-06-14 09:58:21 -07:00
Stephen Akridge
2500881e0b Bump version to v1.2.3 2020-06-14 09:58:10 -07:00
Stephen Akridge
0013bfff4e Look at repair peers 2020-06-14 09:09:57 -07:00
mergify[bot]
f13498b428 Fix fannout gossip bench (bp #10509) (#10556)
automerge
2020-06-14 08:52:00 -07:00
Ryo Onodera
b567138170 Use git diff instead of git show for --check (#10566) (#10568)
automerge
2020-06-14 07:41:48 -07:00
mergify[bot]
653982cae5 Check the whole range of commits in the topic branch (bp #10560) (#10564)
automerge
2020-06-14 04:53:08 -07:00
mergify[bot]
605f4906ba Revert "Gossip PullRequests tend to return a lot of duplicates. (#10326)" (#10455) (#10557)
automerge
2020-06-13 23:41:06 -07:00
Michael Vines
d27f24e312 Add merge-stake subcommmand
(cherry picked from commit 0510b6e336)
2020-06-13 09:50:34 -07:00
Dan Albert
c9c1cb5c9c Add Trust Wallet security info (#10516)
automerge

(cherry picked from commit 914f285914)
2020-06-12 22:14:30 -07:00
mergify[bot]
1cc6493ccf Split commitment module (#10541) (#10547)
automerge
2020-06-12 20:59:25 -07:00
Michael Vines
ae47862be2 Add FdGYQ... to non-circulation withdrawer authority list (#10542)
automerge

(cherry picked from commit f54c049b43)
2020-06-12 18:35:07 -07:00
Michael Vines
8590184df7 Refine build condition 2020-06-12 17:02:50 -07:00
Michael Vines
d840bbab08 Disable PR builds 2020-06-12 16:51:37 -07:00
mergify[bot]
63314de516 Remove redundant BankForks parameter (#10537) (#10538)
automerge
2020-06-12 16:41:21 -07:00
mergify[bot]
c47a6e12c7 Improve BPF SDK dependency caching (#10434) (#10513)
(cherry picked from commit 97f9b63507)

Co-authored-by: Jack May <jack@solana.com>
2020-06-12 15:36:35 -07:00
mergify[bot]
7937c45ba4 Adopt heaviest subtree fork choice rule (#10441) (#10515)
automerge
2020-06-12 01:25:47 -07:00
mergify[bot]
813b11ac56 Optimize stale slot shrinking for previously cleaned roots (#10099) (#10534)
automerge
2020-06-12 00:18:40 -07:00
Michael Vines
ad6883b66a ./scripts/cargo-for-all-lock-files.sh update 2020-06-11 20:48:23 -07:00
Michael Vines
a8f4c4e297 Bump version to 1.2.2 2020-06-11 20:45:13 -07:00
mergify[bot]
6d68e94e4e Add operating mode gating (#10332) (#10531)
automerge
2020-06-11 20:05:58 -07:00
mergify[bot]
5dd40d7d88 Enable jsonrpc client (#10522) (#10525)
automerge
2020-06-11 17:19:26 -07:00
mergify[bot]
3f58177670 Update non-circulating pubkeys (#10524) (#10527)
automerge

(cherry picked from commit fb8612be49)

Co-authored-by: Greg Fitzgerald <greg@solana.com>
2020-06-11 16:58:49 -07:00
mergify[bot]
edfd65b115 Distinguish switch/non-switching votes in ReplayStage (#10218) (#10523)
automerge
2020-06-11 16:43:40 -07:00
Michael Vines
51da66ec84 Force CI_REPO_SLUG 2020-06-11 13:14:07 -07:00
mergify[bot]
ba36308d69 Add StakeInstruction::Merge (#10503) (#10507)
automerge
2020-06-10 19:08:56 -07:00
mergify[bot]
ee450b2dd0 More reliable way to detect expired transactions (#10482) (#10505)
automerge
2020-06-10 17:24:47 -07:00
mergify[bot]
84b28fb261 Add back missing pull_response success counter (#10491) (#10501)
Co-authored-by: sakridge <sakridge@gmail.com>
2020-06-10 15:11:13 -07:00
mergify[bot]
1586b86797 Optimize process pull responses (#10460) (#10484) (#10490)
automerge
2020-06-10 11:17:46 -07:00
mergify[bot]
8f065e487e Add ability to change the commission of a vote account (bp #10493) (#10498)
automerge
2020-06-10 10:09:04 -07:00
mergify[bot]
953eadd983 Expose last-valid-slot to BankClient and ThinClient users (#10478) (#10483)
automerge
2020-06-10 08:43:37 -07:00
mergify[bot]
a4a792facd Update docs for eager rent collection (#10348) (#10489)
automerge
2020-06-09 21:12:23 -07:00
mergify[bot]
055f808f98 Clean up delinquency slot distance computation (#10479)
automerge
2020-06-09 14:22:37 -07:00
mergify[bot]
0404878445 Add SendTransactionService (#10471)
automerge
2020-06-09 12:25:05 -07:00
mergify[bot]
053907f8a4 Add --warp-slot argument to |solana-ledger-tool create-snapshot| (#10474)
automerge
2020-06-09 10:49:27 -07:00
Michael Vines
f76dcc1f05 Add missing " 2020-06-08 17:44:27 -07:00
Michael Vines
823bc138cd Bump new_system_program_activation_epoch by 2 2020-06-08 09:40:12 -07:00
mergify[bot]
18f746b025 Add Algo|Stake as a recommended trusted testnet validator (#10452) (#10453)
automerge
2020-06-08 08:23:40 -07:00
mergify[bot]
c81adaf901 Remove lock around JsonRpcRequestProcessor (#10417) (#10451)
automerge
2020-06-07 23:04:56 -07:00
mergify[bot]
2d12ddd0f6 Gossip cleanup remove duplicate gossip metrics and name worker threads (#10435) (#10448)
automerge
2020-06-06 16:46:36 -07:00
mergify[bot]
bee36cc8d0 Enable and add tick rate to metrics (#10430) (#10447)
automerge
2020-06-06 13:47:16 -07:00
mergify[bot]
f7aee67023 RPC simulateTransaction endpoint now returns program log output (#10432) (#10444)
automerge
2020-06-06 11:57:24 -07:00
mergify[bot]
c021727009 Lower counter level (#10428) (#10436)
automerge
2020-06-05 17:40:59 -07:00
mergify[bot]
6653136e1d Add Certus One as a trusted validator for testnet (#10433) (#10438)
automerge
2020-06-05 16:54:38 -07:00
mergify[bot]
06c40c807c Gossip PullRequests tend to return a lot of duplicates. (#10326) (#10429)
automerge
2020-06-05 11:51:48 -07:00
mergify[bot]
9b262b4915 Add pull request count metrics (#10421) (#10427)
automerge
2020-06-05 11:25:26 -07:00
mergify[bot]
cc2d3ecfd7 More cluster stats and add epoch stakes cache in retransmit stage (#10345) (#10351)
automerge
2020-06-05 10:01:42 -07:00
mergify[bot]
92743499bf Enable more fine-grained control in partition tests (#10418) (#10423)
automerge
2020-06-05 00:55:14 -07:00
mergify[bot]
aa6a00a03e ledger_cleanup_service: compact at a slower rate than purging (#10414) (#10422)
automerge
2020-06-04 22:56:32 -07:00
mergify[bot]
bd19f7c4cb Avoid AccountInUse errors when simulating transactions (#10391) (#10420)
automerge
2020-06-04 20:54:08 -07:00
mergify[bot]
988bf65ba4 Deactivate legacy_system_instruction_processor at epoch 58/38 (preview/stable) (#10406) (#10408)
automerge
2020-06-04 01:33:09 -07:00
mergify[bot]
d5b03bd824 Don't reuse executable accounts between instructions (#10403) (#10405)
automerge
2020-06-03 23:36:14 -07:00
mergify[bot]
6a72dab111 Enable rolling update of "Permit paying oneself" / "No longer allow create-account to add funds to an existing account" (bp #10375) (#10404)
automerge
2020-06-03 18:22:03 -07:00
mergify[bot]
56e8319a6d Add built-in programs to InvokeContext (#10383) (#10402)
automerge
2020-06-03 14:25:16 -07:00
mergify[bot]
aed1e51ef1 Throw error if no release version (#10396) (#10397)
automerge
2020-06-03 11:15:39 -07:00
mergify[bot]
f4278d61df Cache tvu peers for broadcast (#10373) (#10393)
automerge
2020-06-03 10:15:47 -07:00
mergify[bot]
a5c3ae3cef Don't share same snapshot dir for secondary access (#10384) (#10387)
automerge
2020-06-03 04:12:51 -07:00
mergify[bot]
05c052e212 Support opening an in-use rocksdb as secondary (#10209) (#10382)
automerge
2020-06-02 23:09:22 -07:00
mergify[bot]
dc05bb648a Purge TransactionStatus and AddressSignatures exactly from ledger-tool (#10358) (#10376)
automerge
2020-06-02 20:12:46 -07:00
mergify[bot]
800b65b2f6 Cleanup program docs (#10283) (#10360)
automerge
2020-06-02 03:32:09 -07:00
mergify[bot]
ae1a0f57c5 Add preflight checks to sendTransaction RPC method (bp #10338) (#10363)
automerge
2020-06-01 22:27:30 -07:00
mergify[bot]
df7c44bd0c Add docs for the builtin programs (#10359) (#10365)
automerge
2020-06-01 20:17:01 -07:00
Tyera Eulberg
3e29cfd712 v1.2: backport exchange doc fmt (#10357)
* Exchange doc reformat (#10353)

* Exchange doc reformat pt2 (#10355)
2020-06-01 15:17:23 -06:00
mergify[bot]
202031538f Restore archiver design document (#10352) (#10354)
automerge
2020-06-01 09:55:36 -07:00
mergify[bot]
29ff1b925d Reduce stable jobs (#10344) (#10347)
automerge
2020-05-31 22:49:56 -07:00
mergify[bot]
5a91db6e62 Program address nits (bp #10261) (#10262)
automerge
2020-05-31 09:05:37 -07:00
mergify[bot]
94ba700e58 Permit paying oneself (#10337) (#10342)
automerge
2020-05-31 08:50:42 -07:00
mergify[bot]
1964c6ec29 Don't attempt to resolve mainnet-beta in the test suite (#10328) (#10334)
automerge
2020-05-29 20:01:26 -07:00
mergify[bot]
4dd6591bfd Added --health-check-slot-distance (#10324) (#10331)
automerge
2020-05-29 17:10:46 -07:00
mergify[bot]
163217815b Improve Rpc inflation tooling (bp #10309) (#10322)
automerge
2020-05-29 14:09:41 -07:00
mergify[bot]
37c182cd5d log leader (#10280) (#10315)
automerge
2020-05-29 13:38:46 -07:00
mergify[bot]
0c68f27ac3 Fix repair dos (#10299) (#10303)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit e68621b8bb)

Co-authored-by: carllin <wumu727@gmail.com>
2020-05-28 21:48:29 -07:00
mergify[bot]
5fb8da9b35 Feign RPC health while in a --wait-for-supermajority holding pattern (#10295) (#10301)
(cherry picked from commit 0442c45d5b)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-05-28 21:46:38 -07:00
mergify[bot]
74d9fd1e4f verify_reachable_ports: Handle errors without expect() (#10298) (#10305)
automerge
2020-05-28 17:11:34 -07:00
mergify[bot]
e71206c578 Add more logging while unpacking snapshots (#10266) (#10270)
automerge
2020-05-28 13:47:58 -07:00
mergify[bot]
0141c80238 Skip gossip requests with different shred version and split lock (#10240) (#10297)
automerge
2020-05-28 13:24:56 -07:00
Michael Vines
ed928cfdf7 Add commitment parameter to getFeeCalculatorForBlockhash (#10255) (#10296)
automerge
2020-05-28 13:22:46 -07:00
mergify[bot]
2fd319ab7a Verify TPU and serve repair ports are reachable (#10291) (#10294)
automerge
2020-05-28 10:14:14 -07:00
mergify[bot]
7813a1decd Purge next slots to avoid a blockstore_processor panic on restart (#10281) (#10285)
(cherry picked from commit 5ac2ae1178)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-05-28 08:40:41 -07:00
mergify[bot]
93e4ed1f75 Include GenesisConfig inflation in Display (#10282) (#10289)
automerge
2020-05-28 00:21:58 -07:00
mergify[bot]
a70f31b3da Use correct --url (#10284) (#10287)
automerge
2020-05-27 22:12:47 -07:00
Michael Vines
2d25227d0a Adjust mainnet-beta shred version 2020-05-27 17:11:34 -07:00
mergify[bot]
fc7bfd0f67 Cleanup programming model doc (#10274) (#10276)
automerge
2020-05-27 15:31:40 -07:00
mergify[bot]
2996291b37 CLI: Improve stake (de)activation display (#10273)
automerge
2020-05-27 14:45:20 -07:00
mergify[bot]
3e80b9231c Add exchange integration docs (#10054) (#10267)
automerge
2020-05-27 12:18:24 -07:00
Tyera Eulberg
78231a8682 Update Cargo.lock files (#10271)
automerge
2020-05-27 12:09:48 -07:00
Michael Vines
ace711e7f1 Bump version to 1.2.1 2020-05-26 19:07:35 -07:00
Michael Vines
c9cbc39ec9 Wait for one slot to be produced (#10257)
automerge

(cherry picked from commit 22a98bd27a)
2020-05-26 17:58:45 -07:00
mergify[bot]
606a392d50 Cli: expose last-valid-slot in solana fees (#10254) (#10256)
automerge

(cherry picked from commit b6083ca107)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-05-26 17:38:14 -06:00
mergify[bot]
c67596ceb4 Add mechanism to get blockhash's last valid slot (#10239) (#10253)
automerge
2020-05-26 14:33:11 -07:00
Ryo Onodera
9a42cc7555 Lower owner hashing activation slot for devnet (#10244)
automerge
2020-05-26 12:08:22 -07:00
mergify[bot]
2e5ef2a802 Update cross-program and program address proposals (bp #10234) (#10241)
automerge
2020-05-26 08:51:16 -07:00
mergify[bot]
8c8e2c4b2b Prevent privilege escalation (#10232) (#10247)
automerge
2020-05-26 02:39:28 -07:00
mergify[bot]
0578801f99 Remove storage rpc docs (#10238) (#10242)
automerge
2020-05-25 22:45:18 -07:00
mergify[bot]
6141e1410a Cluster info metrics (#10215) (#10236)
automerge
2020-05-25 16:39:08 -07:00
mergify[bot]
4fc86807ff Re-enable move in docker-solana (#10214) (#10228)
automerge
2020-05-25 01:32:54 -07:00
Michael Vines
d2a2eba69e v1.2: Include account.owner into account hash (#9918) (#10222)
automerge
2020-05-25 00:34:54 -07:00
1416 changed files with 18952 additions and 106332 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -3,16 +3,19 @@
#
# Save target/ for the next CI build on this machine
#
(
set -x
d=$HOME/cargo-target-cache/"$BUILDKITE_LABEL"
mkdir -p "$d"
set -x
rsync -a --delete --link-dest="$PWD" target "$d"
du -hs "$d"
read -r cacheSizeInGB _ < <(du -s --block-size=1800000000 "$d")
echo "--- ${cacheSizeInGB}GB: $d"
)
if [[ -z $CARGO_TARGET_CACHE ]]; then
echo "+++ CARGO_TARGET_CACHE not defined" # pre-command should have defined it
else
(
set -x
mkdir -p "$CARGO_TARGET_CACHE"
set -x
rsync -a --delete --link-dest="$PWD" target "$CARGO_TARGET_CACHE"
du -hs "$CARGO_TARGET_CACHE"
read -r cacheSizeInGB _ < <(du -s --block-size=1800000000 "$CARGO_TARGET_CACHE")
echo "--- ${cacheSizeInGB}GB: $CARGO_TARGET_CACHE"
)
fi
#
# Add job_stats data point

View File

@@ -11,23 +11,24 @@ export PS4="++"
#
# Restore target/ from the previous CI build on this machine
#
eval "$(ci/channel-info.sh)"
export CARGO_TARGET_CACHE=$HOME/cargo-target-cache/"$CHANNEL"-"$BUILDKITE_LABEL"
(
set -x
d=$HOME/cargo-target-cache/"$BUILDKITE_LABEL"
MAX_CACHE_SIZE=18 # gigabytes
if [[ -d $d ]]; then
du -hs "$d"
read -r cacheSizeInGB _ < <(du -s --block-size=1800000000 "$d")
echo "--- ${cacheSizeInGB}GB: $d"
if [[ -d $CARGO_TARGET_CACHE ]]; then
du -hs "$CARGO_TARGET_CACHE"
read -r cacheSizeInGB _ < <(du -s --block-size=1800000000 "$CARGO_TARGET_CACHE")
echo "--- ${cacheSizeInGB}GB: $CARGO_TARGET_CACHE"
if [[ $cacheSizeInGB -gt $MAX_CACHE_SIZE ]]; then
echo "--- $d is too large, removing it"
rm -rf "$d"
echo "--- $CARGO_TARGET_CACHE is too large, removing it"
rm -rf "$CARGO_TARGET_CACHE"
fi
else
echo "--- $d not present"
echo "--- $CARGO_TARGET_CACHE not present"
fi
mkdir -p "$d"/target
rsync -a --delete --link-dest="$d" "$d"/target .
mkdir -p "$CARGO_TARGET_CACHE"/target
rsync -a --delete --link-dest="$CARGO_TARGET_CACHE" "$CARGO_TARGET_CACHE"/target .
)

View File

@@ -9,10 +9,23 @@
set -e
cd "$(dirname "$0")"/..
source ci/_
_ ci/buildkite-pipeline.sh pipeline.yml
echo +++ pipeline
cat pipeline.yml
if [[ -n $BUILDKITE_TAG ]]; then
buildkite-agent annotate --style info --context release-tag \
"https://github.com/solana-labs/solana/releases/$BUILDKITE_TAG"
buildkite-agent pipeline upload ci/buildkite-release.yml
else
if [[ $BUILDKITE_BRANCH =~ ^pull ]]; then
# Add helpful link back to the corresponding Github Pull Request
buildkite-agent annotate --style info --context pr-backlink \
"Github Pull Request: https://github.com/solana-labs/solana/$BUILDKITE_BRANCH"
fi
_ buildkite-agent pipeline upload pipeline.yml
if [[ $BUILDKITE_MESSAGE =~ GitBook: ]]; then
buildkite-agent annotate --style info --context gitbook-ci-skip \
"GitBook commit detected, CI skipped"
exit
fi
buildkite-agent pipeline upload ci/buildkite.yml
fi

View File

@@ -1,41 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: cargo
directory: "/"
schedule:
interval: daily
time: "01:00"
timezone: America/Los_Angeles
#labels:
# - "automerge"
open-pull-requests-limit: 3
- package-ecosystem: npm
directory: "/web3.js"
schedule:
interval: daily
time: "01:00"
timezone: America/Los_Angeles
labels:
- "automerge"
commit-message:
prefix: "chore:"
open-pull-requests-limit: 3
- package-ecosystem: npm
directory: "/explorer"
schedule:
interval: daily
time: "01:00"
timezone: America/Los_Angeles
labels:
- "automerge"
commit-message:
prefix: "chore:"
include: "scope"
open-pull-requests-limit: 3

1
.github/stale.yml vendored
View File

@@ -9,7 +9,6 @@ daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- security
- blocked
# Label to use when marking a pull request as stale
staleLabel: stale

2
.gitignore vendored
View File

@@ -27,5 +27,3 @@ log-*/
# fetch-spl.sh artifacts
/spl-genesis-args.sh
/spl_*.so
.DS_Store

View File

@@ -7,7 +7,7 @@ pull_request_rules:
- name: automatic merge (squash) on CI success
conditions:
- status-success=buildkite/solana
- status-success=Travis CI - Pull Request
#- status-success=Travis CI - Pull Request
- status-success=ci-gate
- label=automerge
- author≠@dont-squash-my-commits
@@ -18,7 +18,7 @@ pull_request_rules:
- name: automatic merge (rebase) on CI success
conditions:
- status-success=buildkite/solana
- status-success=Travis CI - Pull Request
#- status-success=Travis CI - Pull Request
- status-success=ci-gate
- label=automerge
- author=@dont-squash-my-commits
@@ -50,6 +50,14 @@ pull_request_rules:
label:
add:
- automerge
- name: v1.0 backport
conditions:
- label=v1.0
actions:
backport:
ignore_conflicts: true
branches:
- v1.0
- name: v1.1 backport
conditions:
- label=v1.1
@@ -66,11 +74,3 @@ pull_request_rules:
ignore_conflicts: true
branches:
- v1.2
- name: v1.3 backport
conditions:
- label=v1.3
actions:
backport:
ignore_conflicts: true
branches:
- v1.3

View File

@@ -4,10 +4,8 @@ branches:
- /^v\d+\.\d+/
notifications:
email: false
slack:
on_success: change
if: NOT type = pull_request
secure: F4IjOE05MyaMOdPRL+r8qhs7jBvv4yDM3RmFKE1zNXnfUOqV4X38oQM1EI+YVsgpMQLj/pxnEB7wcTE4Bf86N6moLssEULCpvAuMVoXj4QbWdomLX+01WbFa6fLVeNQIg45NHrz2XzVBhoKOrMNnl+QI5mbR2AlS5oqsudHsXDnyLzZtd4Y5SDMdYG1zVWM01+oNNjgNfjcCGmOE/K0CnOMl6GPi3X9C34tJ19P2XT7MTDsz1/IfEF7fro2Q8DHEYL9dchJMoisXSkem5z7IDQkGzXsWdWT4NnndUvmd1MlTCE9qgoXDqRf95Qh8sB1Dz08HtvgfaosP2XjtNTfDI9BBYS15Ibw9y7PchAJE1luteNjF35EOy6OgmCLw/YpnweqfuNViBZz+yOPWXVC0kxnPIXKZ1wyH9ibeH6E4hr7a8o9SV/6SiWIlbYF+IR9jPXyTCLP/cc3sYljPWxDnhWFwFdRVIi3PbVAhVu7uWtVUO17Oc9gtGPgs/GrhOMkJfwQPXaudRJDpVZowxTX4x9kefNotlMAMRgq+Drbmgt4eEBiCNp0ITWgh17BiE1U09WS3myuduhoct85+FoVeaUkp1sxzHVtGsNQH0hcz7WcpZyOM+AwistJA/qzeEDQao5zi1eKWPbO2xAhi2rV1bDH6bPf/4lDBwLRqSiwvlWU=
os: linux
@@ -16,17 +14,8 @@ language: minimal
jobs:
include:
- name: "Export Github Repositories"
if: type IN (push, cron) AND branch = master
language: python
git:
depth: false
script:
- .travis/export-github-repo.sh web3.js/ solana-web3.js
- .travis/export-github-repo.sh explorer/ explorer
- &release-artifacts
if: type IN (api, cron) OR tag IS present
if: type = push
name: "macOS release artifacts"
os: osx
language: rust
@@ -58,58 +47,8 @@ jobs:
- <<: *release-artifacts
name: "Windows release artifacts"
os: windows
# Linux release artifacts are still built by ci/buildkite-secondary.yml
#- <<: *release-artifacts
# name: "Linux release artifacts"
# os: linux
# before_install:
# - sudo apt-get install libssl-dev libudev-dev
# explorer pull request
- name: "explorer"
if: type = pull_request AND branch = master
language: node_js
node_js:
- "node"
cache:
directories:
- ~/.npm
before_install:
- .travis/affects.sh explorer/ .travis || travis_terminate 0
- cd explorer
script:
- npm run build
- npm run format
# web3.js pull request
- name: "web3.js"
if: type = pull_request AND branch = master
language: node_js
node_js:
- "lts/*"
services:
- docker
cache:
directories:
- ~/.npm
before_install:
- .travis/affects.sh web3.js/ .travis || travis_terminate 0
- cd web3.js/
- source .travis/before_install.sh
script:
- ../.travis/commitlint.sh
- source .travis/script.sh
# docs pull request
# docs pull request or commit
- name: "docs"
if: type IN (push, pull_request) OR tag IS present
language: node_js
@@ -124,6 +63,8 @@ jobs:
- ~/.npm
before_install:
- source ci/env.sh
- .travis/channel_restriction.sh edge beta || travis_terminate 0
- .travis/affects.sh docs/ .travis || travis_terminate 0
- cd docs/
- source .travis/before_install.sh

17
.travis/channel_restriction.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/env bash
#
# Only proceed if we are on one of the channels passed in when calling this file
#
set -ex
eval "$(ci/channel-info.sh)"
for acceptable_channel in "$@"; do
if [[ "$CHANNEL" == "$acceptable_channel" ]]; then
exit 0
fi
done
echo "Not running from one of the following channels: $*"
exit 1

View File

@@ -1,32 +0,0 @@
#!/usr/bin/env bash
#
# Runs commitlint in the provided subdirectory
#
set -e
basedir=$1
if [[ -z "$basedir" ]]; then
basedir=.
fi
if [[ ! -d "$basedir" ]]; then
echo "Error: not a directory: $basedir"
exit 1
fi
if [[ ! -f "$basedir"/commitlint.config.js ]]; then
echo "Error: No commitlint configuration found"
exit 1
fi
if [[ -z $TRAVIS_COMMIT_RANGE ]]; then
echo "Error: TRAVIS_COMMIT_RANGE not defined"
exit 1
fi
cd "$basedir"
echo "Checking commits in TRAVIS_COMMIT_RANGE: $TRAVIS_COMMIT_RANGE"
while IFS= read -r line; do
echo "$line" | npx commitlint
done < <(git log "$TRAVIS_COMMIT_RANGE" --format=%s -- .)

View File

@@ -1,34 +0,0 @@
#!/usr/bin/env bash
#
# Exports a subdirectory into another github repository
#
set -e
if [[ -z $GITHUB_TOKEN ]]; then
echo GITHUB_TOKEN not defined
exit 1
fi
cd "$(dirname "$0")/.."
pip3 install git-filter-repo
declare subdir=$1
declare repo_name=$2
[[ -n "$subdir" ]] || {
echo "Error: subdir not specified"
exit 1
}
[[ -n "$repo_name" ]] || {
echo "Error: repo_name not specified"
exit 1
}
echo "Exporting $subdir"
set -x
rm -rf .github_export/"$repo_name"
git clone https://"$GITHUB_TOKEN"@github.com/solana-labs/"$repo_name" .github_export/"$repo_name"
git filter-repo --subdirectory-filter "$subdir" --target .github_export/"$repo_name"
git -C .github_export/"$repo_name" push https://"$GITHUB_TOKEN"@github.com/solana-labs/"$repo_name"

1162
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,8 @@ members = [
"bench-tps",
"accounts-bench",
"banking-bench",
"clap-utils",
"cli-config",
"cli-output",
"client",
"core",
"dos",
@@ -32,9 +32,10 @@ members = [
"metrics",
"net-shaper",
"notifier",
"poh-bench",
"programs/bpf_loader",
"programs/budget",
"programs/btc_spv",
"programs/btc_spv_bin",
"programs/config",
"programs/exchange",
"programs/failure",

View File

@@ -1,4 +1,4 @@
Copyright 2020 Solana Foundation.
Copyright 2018 Solana Labs, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -76,20 +76,21 @@ There are three release channels that map to branches as follows:
git push -u origin <branchname>
```
Alternatively use the Github UI.
### Update master branch to the next release minor version
### Update master branch with the next version
1. After the new branch has been created and pushed, update the Cargo.toml files on **master** to the next semantic version (e.g. 0.9.0 -> 0.10.0) with:
```
$ scripts/increment-cargo-version.sh minor
$ ./scripts/cargo-for-all-lock-files.sh update
scripts/increment-cargo-version.sh minor
```
1. Rebuild to get an updated version of `Cargo.lock`:
```
cargo build
```
1. Push all the changed Cargo.toml and Cargo.lock files to the `master` branch with something like:
```
git co -b version_update
git ls-files -m | xargs git add
git commit -m 'Bump version to X.Y+1.0'
git commit -m 'Update Cargo.toml versions from X.Y to X.Y+1'
git push -u origin version_update
```
1. Confirm that your freshly cut release branch is shown as `BETA_CHANNEL` and the previous release branch as `STABLE_CHANNEL`:
@@ -101,18 +102,15 @@ Alternatively use the Github UI.
### Create the Release Tag on GitHub
1. Go to [GitHub Releases](https://github.com/solana-labs/solana/releases) for tagging a release.
1. Go to [GitHub's Releases UI](https://github.com/solana-labs/solana/releases) for tagging a release.
1. Click "Draft new release". The release tag must exactly match the `version`
field in `/Cargo.toml` prefixed by `v`.
1. If the Cargo.toml version field is **0.12.3**, then the release tag must be **v0.12.3**
1. If the Cargo.toml verion field is **0.12.3**, then the release tag must be **v0.12.3**
1. Make sure the Target Branch field matches the branch you want to make a release on.
1. If you want to release v0.12.0, the target branch must be v0.12
1. If this is the first release on the branch (e.g. v0.13.**0**), paste in [this
template](https://raw.githubusercontent.com/solana-labs/solana/master/.github/RELEASE_TEMPLATE.md). Engineering Lead can provide summary contents for release notes if needed. If this is a patch release, review all the commits since the previous release on this branch and add details as needed.
1. Click "Save Draft", then confirm the release notes look good and the tag name and branch are correct.
1. Ensure the release is marked **"This is a pre-release"**. This flag will then need to be be removed once the the Linux binary artifacts appear later.
1. Go back into edit the release and click "Publish release" when ready.
template](https://raw.githubusercontent.com/solana-labs/solana/master/.github/RELEASE_TEMPLATE.md). Engineering Lead can provide summary contents for release notes if needed.
1. Click "Save Draft", then confirm the release notes look good and the tag name and branch are correct. Go back into edit the release and click "Publish release" when ready.
### Update release branch with the next patch version
@@ -121,31 +119,68 @@ Alternatively use the Github UI.
$ scripts/increment-cargo-version.sh patch
$ ./scripts/cargo-for-all-lock-files.sh tree
```
1. Rebuild to get an updated version of `Cargo.lock`:
```
cargo build
```
1. Push all the changed Cargo.toml and Cargo.lock files to the **release branch** with something like:
```
git co -b version_update origin/vX.Y
git add -u
git commit -m 'Bump version to X.Y.Z+1'
git push -u <user-remote> version_update
git co -b version_update
git ls-files -m | xargs git add
git commit -m 'Update Cargo.toml versions from X.Y.Z to X.Y.Z+1'
git push -u origin version_update
```
1. Open a PR against origin/vX.Y and then merge the PR after passing CI.
### Prepare for the next release
1. Go to [GitHub Releases](https://github.com/solana-labs/solana/releases) and create a new draft release for `X.Y.Z+1` with empty release nodes. This allows people to incrementally add new release notes until it's time for the next release
1. Go to the [Github Milestones](https://github.com/solana-labs/solana/milestones). Create a new milestone for the `X.Y.Z+1`, move over
unresolved issues still in the `X.Y.Z` milestone, then close the `X.Y.Z` milestone.
### Verify release automation success
Go to [Solana Releases](https://github.com/solana-labs/solana/releases) and click on the latest release that you just published.
Verify that all of the build artifacts are present, then the uncheck **"This is a pre-release"** for the release.
1. Go to [Solana Releases](https://github.com/solana-labs/solana/releases) and click on the latest release that you just published. Verify that all of the build artifacts are present. This can take up to 90 minutes after creating the tag.
1. The `solana-secondary` Buildkite pipeline handles creating the binary tarballs and updated crates. Look for a job under the tag name of the release: https://buildkite.com/solana-labs/solana-secondary
1. [Crates.io](https://crates.io/crates/solana) should have an updated Solana version.
Build artifacts can take up to 60 minutes after creating the tag before
appearing. To check for progress:
* The `solana-secondary` Buildkite pipeline handles creating the Linux release artifacts and updated crates. Look for a job under the tag name of the release: https://buildkite.com/solana-labs/solana-secondary.
* The macOS and Windows release artifacts are produced by Travis CI: https://travis-ci.com/github/solana-labs/solana/branches
### Update documentation
TODO: Documentation update procedure is WIP as we move to gitbook
[Crates.io](https://crates.io/crates/solana) should have an updated Solana version. This can take 2-3 hours, and sometimes fails in the `solana-secondary` job.
If this happens and the error is non-fatal, click "Retry" on the "publish crate" job
Document the new recommended version by updating `docs/src/running-archiver.md` and `docs/src/validator-testnet.md` on the release (beta) branch to point at the `solana-install` for the upcoming release version.
### Update software on devnet.solana.com/testnet.solama.com/mainnet-beta.solana.com
See the documentation at https://github.com/solana-labs/cluster-ops/
### Update software on devnet.solana.com
The testnet running on devnet.solana.com is set to use a fixed release tag
which is set in the Buildkite testnet-management pipeline.
This tag needs to be updated and the testnet restarted after a new release
tag is created.
#### Update testnet schedules
Go to https://buildkite.com/solana-labs and click through: Pipelines ->
testnet-management -> Pipeline Settings -> Schedules
Or just click here:
https://buildkite.com/solana-labs/testnet-management/settings/schedules
There are two scheduled jobs for testnet: a daily restart and an hourly sanity-or-restart. \
https://buildkite.com/solana-labs/testnet-management/settings/schedules/0efd7856-7143-4713-8817-47e6bdb05387
https://buildkite.com/solana-labs/testnet-management/settings/schedules/2a926646-d972-42b5-aeb9-bb6759592a53
On each schedule:
1. Set TESTNET_TAG environment variable to the desired release tag.
1. Example, TESTNET_TAG=v0.13.2
1. Set the Build Branch to the branch that TESTNET_TAG is from.
1. Example: v0.13
#### Restart the testnet
Trigger a TESTNET_OP=create-and-start to refresh the cluster with the new version
1. Go to https://buildkite.com/solana-labs/testnet-management
2. Click "New Build" and use the following settings, then click "Create Build"
1. Commit: HEAD
1. Branch: [channel branch as set in the schedules]
1. Environment Variables:
```
TESTNET=testnet
TESTNET_TAG=[same value as used in TESTNET_TAG in the schedules]
TESTNET_OP=create-and-start
```
### Alert the community
Notify Discord users on #validator-support that a new release for
devnet.solana.com is available

View File

@@ -1,6 +1,6 @@
[package]
name = "solana-account-decoder"
version = "1.3.1"
version = "1.2.33"
description = "Solana account decoder"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -10,15 +10,19 @@ edition = "2018"
[dependencies]
bincode = "1.3.1"
base64 = "0.12.3"
bs58 = "0.3.1"
bv = "0.11.1"
Inflector = "0.11.4"
lazy_static = "1.4.0"
solana-sdk = { path = "../sdk", version = "1.3.1" }
solana-vote-program = { path = "../programs/vote", version = "1.3.1" }
spl-token-v1-0 = { package = "spl-token", version = "1.0.6", features = ["skip-no-mangle"] }
serde = "1.0.112"
serde_derive = "1.0.103"
serde_json = "1.0.56"
serde_json = "1.0.54"
solana-config-program = { path = "../programs/config", version = "1.2.33" }
solana-sdk = { path = "../sdk", version = "1.2.33" }
solana-stake-program = { path = "../programs/stake", version = "1.2.33" }
solana-vote-program = { path = "../programs/vote", version = "1.2.33" }
spl-token-v2-0 = { package = "spl-token", version = "2.0.6", features = ["skip-no-mangle"] }
thiserror = "1.0"
[package.metadata.docs.rs]

View File

@@ -4,12 +4,16 @@ extern crate lazy_static;
extern crate serde_derive;
pub mod parse_account_data;
pub mod parse_config;
pub mod parse_nonce;
pub mod parse_stake;
pub mod parse_sysvar;
pub mod parse_token;
pub mod parse_vote;
pub mod validator_info;
use crate::parse_account_data::{parse_account_data, AccountAdditionalData, ParsedAccount};
use solana_sdk::{account::Account, clock::Epoch, pubkey::Pubkey};
use solana_sdk::{account::Account, clock::Epoch, fee_calculator::FeeCalculator, pubkey::Pubkey};
use std::str::FromStr;
pub type StringAmount = String;
@@ -28,38 +32,47 @@ pub struct UiAccount {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", untagged)]
pub enum UiAccountData {
Binary(String),
LegacyBinary(String), // Legacy. Retained for RPC backwards compatibility
Json(ParsedAccount),
}
impl From<Vec<u8>> for UiAccountData {
fn from(data: Vec<u8>) -> Self {
Self::Binary(bs58::encode(data).into_string())
}
Binary(String, UiAccountEncoding),
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum UiAccountEncoding {
Binary,
Binary, // Legacy. Retained for RPC backwards compatibility
Base58,
Base64,
JsonParsed,
}
impl UiAccount {
pub fn encode(
pubkey: &Pubkey,
account: Account,
encoding: UiAccountEncoding,
additional_data: Option<AccountAdditionalData>,
data_slice_config: Option<UiDataSliceConfig>,
) -> Self {
let data = match encoding {
UiAccountEncoding::Binary => account.data.into(),
UiAccountEncoding::Binary => UiAccountData::LegacyBinary(
bs58::encode(slice_data(&account.data, data_slice_config)).into_string(),
),
UiAccountEncoding::Base58 => UiAccountData::Binary(
bs58::encode(slice_data(&account.data, data_slice_config)).into_string(),
encoding,
),
UiAccountEncoding::Base64 => UiAccountData::Binary(
base64::encode(slice_data(&account.data, data_slice_config)),
encoding,
),
UiAccountEncoding::JsonParsed => {
if let Ok(parsed_data) =
parse_account_data(&account.owner, &account.data, additional_data)
parse_account_data(pubkey, &account.owner, &account.data, additional_data)
{
UiAccountData::Json(parsed_data)
} else {
account.data.into()
UiAccountData::Binary(base64::encode(&account.data), UiAccountEncoding::Base64)
}
}
};
@@ -75,7 +88,12 @@ impl UiAccount {
pub fn decode(&self) -> Option<Account> {
let data = match &self.data {
UiAccountData::Json(_) => None,
UiAccountData::Binary(blob) => bs58::decode(blob).into_vec().ok(),
UiAccountData::LegacyBinary(blob) => bs58::decode(blob).into_vec().ok(),
UiAccountData::Binary(blob, encoding) => match encoding {
UiAccountEncoding::Base58 => bs58::decode(blob).into_vec().ok(),
UiAccountEncoding::Base64 => base64::decode(blob).ok(),
UiAccountEncoding::Binary | UiAccountEncoding::JsonParsed => None,
},
}?;
Some(Account {
lamports: self.lamports,
@@ -86,3 +104,79 @@ impl UiAccount {
})
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiFeeCalculator {
pub lamports_per_signature: StringAmount,
}
impl From<FeeCalculator> for UiFeeCalculator {
fn from(fee_calculator: FeeCalculator) -> Self {
Self {
lamports_per_signature: fee_calculator.lamports_per_signature.to_string(),
}
}
}
impl Default for UiFeeCalculator {
fn default() -> Self {
Self {
lamports_per_signature: "0".to_string(),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UiDataSliceConfig {
pub offset: usize,
pub length: usize,
}
fn slice_data(data: &[u8], data_slice_config: Option<UiDataSliceConfig>) -> &[u8] {
if let Some(UiDataSliceConfig { offset, length }) = data_slice_config {
if offset >= data.len() {
&[]
} else if length > data.len() - offset {
&data[offset..]
} else {
&data[offset..offset + length]
}
} else {
data
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_slice_data() {
let data = vec![1, 2, 3, 4, 5];
let slice_config = Some(UiDataSliceConfig {
offset: 0,
length: 5,
});
assert_eq!(slice_data(&data, slice_config), &data[..]);
let slice_config = Some(UiDataSliceConfig {
offset: 0,
length: 10,
});
assert_eq!(slice_data(&data, slice_config), &data[..]);
let slice_config = Some(UiDataSliceConfig {
offset: 1,
length: 2,
});
assert_eq!(slice_data(&data, slice_config), &data[1..3]);
let slice_config = Some(UiDataSliceConfig {
offset: 10,
length: 2,
});
assert_eq!(slice_data(&data, slice_config), &[] as &[u8]);
}
}

View File

@@ -1,22 +1,31 @@
use crate::{
parse_config::parse_config,
parse_nonce::parse_nonce,
parse_token::{parse_token, spl_token_id_v1_0},
parse_stake::parse_stake,
parse_sysvar::parse_sysvar,
parse_token::{parse_token, spl_token_id_v2_0},
parse_vote::parse_vote,
};
use inflector::Inflector;
use serde_json::Value;
use solana_sdk::{instruction::InstructionError, pubkey::Pubkey, system_program};
use solana_sdk::{instruction::InstructionError, pubkey::Pubkey, system_program, sysvar};
use std::collections::HashMap;
use thiserror::Error;
lazy_static! {
static ref CONFIG_PROGRAM_ID: Pubkey = solana_config_program::id();
static ref STAKE_PROGRAM_ID: Pubkey = solana_stake_program::id();
static ref SYSTEM_PROGRAM_ID: Pubkey = system_program::id();
static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v1_0();
static ref SYSVAR_PROGRAM_ID: Pubkey = sysvar::id();
static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v2_0();
static ref VOTE_PROGRAM_ID: Pubkey = solana_vote_program::id();
pub static ref PARSABLE_PROGRAM_IDS: HashMap<Pubkey, ParsableAccount> = {
let mut m = HashMap::new();
m.insert(*CONFIG_PROGRAM_ID, ParsableAccount::Config);
m.insert(*SYSTEM_PROGRAM_ID, ParsableAccount::Nonce);
m.insert(*TOKEN_PROGRAM_ID, ParsableAccount::SplToken);
m.insert(*STAKE_PROGRAM_ID, ParsableAccount::Stake);
m.insert(*SYSVAR_PROGRAM_ID, ParsableAccount::Sysvar);
m.insert(*VOTE_PROGRAM_ID, ParsableAccount::Vote);
m
};
@@ -45,13 +54,17 @@ pub enum ParseAccountError {
pub struct ParsedAccount {
pub program: String,
pub parsed: Value,
pub space: u64,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ParsableAccount {
Config,
Nonce,
SplToken,
Stake,
Sysvar,
Vote,
}
@@ -61,6 +74,7 @@ pub struct AccountAdditionalData {
}
pub fn parse_account_data(
pubkey: &Pubkey,
program_id: &Pubkey,
data: &[u8],
additional_data: Option<AccountAdditionalData>,
@@ -70,15 +84,19 @@ pub fn parse_account_data(
.ok_or_else(|| ParseAccountError::ProgramNotParsable)?;
let additional_data = additional_data.unwrap_or_default();
let parsed_json = match program_name {
ParsableAccount::Config => serde_json::to_value(parse_config(data, pubkey)?)?,
ParsableAccount::Nonce => serde_json::to_value(parse_nonce(data)?)?,
ParsableAccount::SplToken => {
serde_json::to_value(parse_token(data, additional_data.spl_token_decimals)?)?
}
ParsableAccount::Stake => serde_json::to_value(parse_stake(data)?)?,
ParsableAccount::Sysvar => serde_json::to_value(parse_sysvar(data, pubkey)?)?,
ParsableAccount::Vote => serde_json::to_value(parse_vote(data)?)?,
};
Ok(ParsedAccount {
program: format!("{:?}", program_name).to_kebab_case(),
parsed: parsed_json,
space: data.len() as u64,
})
}
@@ -93,21 +111,35 @@ mod test {
#[test]
fn test_parse_account_data() {
let account_pubkey = Pubkey::new_rand();
let other_program = Pubkey::new_rand();
let data = vec![0; 4];
assert!(parse_account_data(&other_program, &data, None).is_err());
assert!(parse_account_data(&account_pubkey, &other_program, &data, None).is_err());
let vote_state = VoteState::default();
let mut vote_account_data: Vec<u8> = vec![0; VoteState::size_of()];
let versioned = VoteStateVersions::Current(Box::new(vote_state));
VoteState::serialize(&versioned, &mut vote_account_data).unwrap();
let parsed =
parse_account_data(&solana_vote_program::id(), &vote_account_data, None).unwrap();
let parsed = parse_account_data(
&account_pubkey,
&solana_vote_program::id(),
&vote_account_data,
None,
)
.unwrap();
assert_eq!(parsed.program, "vote".to_string());
assert_eq!(parsed.space, VoteState::size_of() as u64);
let nonce_data = Versions::new_current(State::Initialized(Data::default()));
let nonce_account_data = bincode::serialize(&nonce_data).unwrap();
let parsed = parse_account_data(&system_program::id(), &nonce_account_data, None).unwrap();
let parsed = parse_account_data(
&account_pubkey,
&system_program::id(),
&nonce_account_data,
None,
)
.unwrap();
assert_eq!(parsed.program, "nonce".to_string());
assert_eq!(parsed.space, State::size() as u64);
}
}

View File

@@ -0,0 +1,146 @@
use crate::{
parse_account_data::{ParsableAccount, ParseAccountError},
validator_info,
};
use bincode::deserialize;
use serde_json::Value;
use solana_config_program::{get_config_data, ConfigKeys};
use solana_sdk::pubkey::Pubkey;
use solana_stake_program::config::Config as StakeConfig;
pub fn parse_config(data: &[u8], pubkey: &Pubkey) -> Result<ConfigAccountType, ParseAccountError> {
let parsed_account = if pubkey == &solana_stake_program::config::id() {
get_config_data(data)
.ok()
.and_then(|data| deserialize::<StakeConfig>(data).ok())
.map(|config| ConfigAccountType::StakeConfig(config.into()))
} else {
deserialize::<ConfigKeys>(data).ok().and_then(|key_list| {
if !key_list.keys.is_empty() && key_list.keys[0].0 == validator_info::id() {
parse_config_data::<String>(data, key_list.keys).and_then(|validator_info| {
Some(ConfigAccountType::ValidatorInfo(UiConfig {
keys: validator_info.keys,
config_data: serde_json::from_str(&validator_info.config_data).ok()?,
}))
})
} else {
None
}
})
};
parsed_account.ok_or(ParseAccountError::AccountNotParsable(
ParsableAccount::Config,
))
}
fn parse_config_data<T>(data: &[u8], keys: Vec<(Pubkey, bool)>) -> Option<UiConfig<T>>
where
T: serde::de::DeserializeOwned,
{
let config_data: T = deserialize(&get_config_data(data).ok()?).ok()?;
let keys = keys
.iter()
.map(|key| UiConfigKey {
pubkey: key.0.to_string(),
signer: key.1,
})
.collect();
Some(UiConfig { keys, config_data })
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase", tag = "type", content = "info")]
pub enum ConfigAccountType {
StakeConfig(UiStakeConfig),
ValidatorInfo(UiConfig<Value>),
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiConfigKey {
pub pubkey: String,
pub signer: bool,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiStakeConfig {
pub warmup_cooldown_rate: f64,
pub slash_penalty: u8,
}
impl From<StakeConfig> for UiStakeConfig {
fn from(config: StakeConfig) -> Self {
Self {
warmup_cooldown_rate: config.warmup_cooldown_rate,
slash_penalty: config.slash_penalty,
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiConfig<T> {
pub keys: Vec<UiConfigKey>,
pub config_data: T,
}
#[cfg(test)]
mod test {
use super::*;
use crate::validator_info::ValidatorInfo;
use serde_json::json;
use solana_config_program::create_config_account;
#[test]
fn test_parse_config() {
let stake_config = StakeConfig {
warmup_cooldown_rate: 0.25,
slash_penalty: 50,
};
let stake_config_account = create_config_account(vec![], &stake_config, 10);
assert_eq!(
parse_config(
&stake_config_account.data,
&solana_stake_program::config::id()
)
.unwrap(),
ConfigAccountType::StakeConfig(UiStakeConfig {
warmup_cooldown_rate: 0.25,
slash_penalty: 50,
}),
);
let validator_info = ValidatorInfo {
info: serde_json::to_string(&json!({
"name": "Solana",
}))
.unwrap(),
};
let info_pubkey = Pubkey::new_rand();
let validator_info_config_account = create_config_account(
vec![(validator_info::id(), false), (info_pubkey, true)],
&validator_info,
10,
);
assert_eq!(
parse_config(&validator_info_config_account.data, &info_pubkey).unwrap(),
ConfigAccountType::ValidatorInfo(UiConfig {
keys: vec![
UiConfigKey {
pubkey: validator_info::id().to_string(),
signer: false,
},
UiConfigKey {
pubkey: info_pubkey.to_string(),
signer: true,
}
],
config_data: serde_json::from_str(r#"{"name":"Solana"}"#).unwrap(),
}),
);
let bad_data = vec![0; 4];
assert!(parse_config(&bad_data, &info_pubkey).is_err());
}
}

View File

@@ -1,6 +1,5 @@
use crate::parse_account_data::ParseAccountError;
use crate::{parse_account_data::ParseAccountError, UiFeeCalculator};
use solana_sdk::{
fee_calculator::FeeCalculator,
instruction::InstructionError,
nonce::{state::Versions, State},
};
@@ -14,7 +13,7 @@ pub fn parse_nonce(data: &[u8]) -> Result<UiNonceState, ParseAccountError> {
State::Initialized(data) => Ok(UiNonceState::Initialized(UiNonceData {
authority: data.authority.to_string(),
blockhash: data.blockhash.to_string(),
fee_calculator: data.fee_calculator,
fee_calculator: data.fee_calculator.into(),
})),
}
}
@@ -32,7 +31,7 @@ pub enum UiNonceState {
pub struct UiNonceData {
pub authority: String,
pub blockhash: String,
pub fee_calculator: FeeCalculator,
pub fee_calculator: UiFeeCalculator,
}
#[cfg(test)]
@@ -56,7 +55,9 @@ mod test {
UiNonceState::Initialized(UiNonceData {
authority: Pubkey::default().to_string(),
blockhash: Hash::default().to_string(),
fee_calculator: FeeCalculator::default(),
fee_calculator: UiFeeCalculator {
lamports_per_signature: 0.to_string(),
},
}),
);

View File

@@ -0,0 +1,236 @@
use crate::{
parse_account_data::{ParsableAccount, ParseAccountError},
StringAmount,
};
use bincode::deserialize;
use solana_sdk::clock::{Epoch, UnixTimestamp};
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)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::Stake))?;
let parsed_account = match stake_state {
StakeState::Uninitialized => StakeAccountType::Uninitialized,
StakeState::Initialized(meta) => StakeAccountType::Initialized(UiStakeAccount {
meta: meta.into(),
stake: None,
}),
StakeState::Stake(meta, stake) => StakeAccountType::Delegated(UiStakeAccount {
meta: meta.into(),
stake: Some(stake.into()),
}),
StakeState::RewardsPool => StakeAccountType::RewardsPool,
};
Ok(parsed_account)
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase", tag = "type", content = "info")]
#[allow(clippy::large_enum_variant)]
pub enum StakeAccountType {
Uninitialized,
Initialized(UiStakeAccount),
Delegated(UiStakeAccount),
RewardsPool,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiStakeAccount {
pub meta: UiMeta,
pub stake: Option<UiStake>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiMeta {
pub rent_exempt_reserve: StringAmount,
pub authorized: UiAuthorized,
pub lockup: UiLockup,
}
impl From<Meta> for UiMeta {
fn from(meta: Meta) -> Self {
Self {
rent_exempt_reserve: meta.rent_exempt_reserve.to_string(),
authorized: meta.authorized.into(),
lockup: meta.lockup.into(),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiLockup {
pub unix_timestamp: UnixTimestamp,
pub epoch: Epoch,
pub custodian: String,
}
impl From<Lockup> for UiLockup {
fn from(lockup: Lockup) -> Self {
Self {
unix_timestamp: lockup.unix_timestamp,
epoch: lockup.epoch,
custodian: lockup.custodian.to_string(),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiAuthorized {
pub staker: String,
pub withdrawer: String,
}
impl From<Authorized> for UiAuthorized {
fn from(authorized: Authorized) -> Self {
Self {
staker: authorized.staker.to_string(),
withdrawer: authorized.withdrawer.to_string(),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiStake {
pub delegation: UiDelegation,
pub credits_observed: u64,
}
impl From<Stake> for UiStake {
fn from(stake: Stake) -> Self {
Self {
delegation: stake.delegation.into(),
credits_observed: stake.credits_observed,
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiDelegation {
pub voter: String,
pub stake: StringAmount,
pub activation_epoch: StringAmount,
pub deactivation_epoch: StringAmount,
pub warmup_cooldown_rate: f64,
}
impl From<Delegation> for UiDelegation {
fn from(delegation: Delegation) -> Self {
Self {
voter: delegation.voter_pubkey.to_string(),
stake: delegation.stake.to_string(),
activation_epoch: delegation.activation_epoch.to_string(),
deactivation_epoch: delegation.deactivation_epoch.to_string(),
warmup_cooldown_rate: delegation.warmup_cooldown_rate,
}
}
}
#[cfg(test)]
mod test {
use super::*;
use bincode::serialize;
use solana_sdk::pubkey::Pubkey;
#[test]
fn test_parse_stake() {
let stake_state = StakeState::Uninitialized;
let stake_data = serialize(&stake_state).unwrap();
assert_eq!(
parse_stake(&stake_data).unwrap(),
StakeAccountType::Uninitialized
);
let pubkey = Pubkey::new_rand();
let custodian = Pubkey::new_rand();
let authorized = Authorized::auto(&pubkey);
let lockup = Lockup {
unix_timestamp: 0,
epoch: 1,
custodian,
};
let meta = Meta {
rent_exempt_reserve: 42,
authorized,
lockup,
};
let stake_state = StakeState::Initialized(meta);
let stake_data = serialize(&stake_state).unwrap();
assert_eq!(
parse_stake(&stake_data).unwrap(),
StakeAccountType::Initialized(UiStakeAccount {
meta: UiMeta {
rent_exempt_reserve: 42.to_string(),
authorized: UiAuthorized {
staker: pubkey.to_string(),
withdrawer: pubkey.to_string(),
},
lockup: UiLockup {
unix_timestamp: 0,
epoch: 1,
custodian: custodian.to_string(),
}
},
stake: None,
})
);
let voter_pubkey = Pubkey::new_rand();
let stake = Stake {
delegation: Delegation {
voter_pubkey,
stake: 20,
activation_epoch: 2,
deactivation_epoch: std::u64::MAX,
warmup_cooldown_rate: 0.25,
},
credits_observed: 10,
};
let stake_state = StakeState::Stake(meta, stake);
let stake_data = serialize(&stake_state).unwrap();
assert_eq!(
parse_stake(&stake_data).unwrap(),
StakeAccountType::Delegated(UiStakeAccount {
meta: UiMeta {
rent_exempt_reserve: 42.to_string(),
authorized: UiAuthorized {
staker: pubkey.to_string(),
withdrawer: pubkey.to_string(),
},
lockup: UiLockup {
unix_timestamp: 0,
epoch: 1,
custodian: custodian.to_string(),
}
},
stake: Some(UiStake {
delegation: UiDelegation {
voter: voter_pubkey.to_string(),
stake: 20.to_string(),
activation_epoch: 2.to_string(),
deactivation_epoch: std::u64::MAX.to_string(),
warmup_cooldown_rate: 0.25,
},
credits_observed: 10,
})
})
);
let stake_state = StakeState::RewardsPool;
let stake_data = serialize(&stake_state).unwrap();
assert_eq!(
parse_stake(&stake_data).unwrap(),
StakeAccountType::RewardsPool
);
let bad_data = vec![1, 2, 3, 4];
assert!(parse_stake(&bad_data).is_err());
}
}

View File

@@ -0,0 +1,328 @@
use crate::{
parse_account_data::{ParsableAccount, ParseAccountError},
StringAmount, UiFeeCalculator,
};
use bincode::deserialize;
use bv::BitVec;
use solana_sdk::{
clock::{Clock, Epoch, Slot, UnixTimestamp},
epoch_schedule::EpochSchedule,
pubkey::Pubkey,
rent::Rent,
slot_hashes::SlotHashes,
slot_history::{self, SlotHistory},
stake_history::{StakeHistory, StakeHistoryEntry},
sysvar::{self, fees::Fees, recent_blockhashes::RecentBlockhashes, rewards::Rewards},
};
pub fn parse_sysvar(data: &[u8], pubkey: &Pubkey) -> Result<SysvarAccountType, ParseAccountError> {
let parsed_account = {
if pubkey == &sysvar::clock::id() {
deserialize::<Clock>(data)
.ok()
.map(|clock| SysvarAccountType::Clock(clock.into()))
} else if pubkey == &sysvar::epoch_schedule::id() {
deserialize(data).ok().map(SysvarAccountType::EpochSchedule)
} else if pubkey == &sysvar::fees::id() {
deserialize::<Fees>(data)
.ok()
.map(|fees| SysvarAccountType::Fees(fees.into()))
} else if pubkey == &sysvar::recent_blockhashes::id() {
deserialize::<RecentBlockhashes>(data)
.ok()
.map(|recent_blockhashes| {
let recent_blockhashes = recent_blockhashes
.iter()
.map(|entry| UiRecentBlockhashesEntry {
blockhash: entry.blockhash.to_string(),
fee_calculator: entry.fee_calculator.clone().into(),
})
.collect();
SysvarAccountType::RecentBlockhashes(recent_blockhashes)
})
} else if pubkey == &sysvar::rent::id() {
deserialize::<Rent>(data)
.ok()
.map(|rent| SysvarAccountType::Rent(rent.into()))
} else if pubkey == &sysvar::rewards::id() {
deserialize::<Rewards>(data)
.ok()
.map(|rewards| SysvarAccountType::Rewards(rewards.into()))
} else if pubkey == &sysvar::slot_hashes::id() {
deserialize::<SlotHashes>(data).ok().map(|slot_hashes| {
let slot_hashes = slot_hashes
.iter()
.map(|slot_hash| UiSlotHashEntry {
slot: slot_hash.0,
hash: slot_hash.1.to_string(),
})
.collect();
SysvarAccountType::SlotHashes(slot_hashes)
})
} else if pubkey == &sysvar::slot_history::id() {
deserialize::<SlotHistory>(data).ok().map(|slot_history| {
SysvarAccountType::SlotHistory(UiSlotHistory {
next_slot: slot_history.next_slot,
bits: format!("{:?}", SlotHistoryBits(slot_history.bits)),
})
})
} else if pubkey == &sysvar::stake_history::id() {
deserialize::<StakeHistory>(data).ok().map(|stake_history| {
let stake_history = stake_history
.iter()
.map(|entry| UiStakeHistoryEntry {
epoch: entry.0,
stake_history: entry.1.clone(),
})
.collect();
SysvarAccountType::StakeHistory(stake_history)
})
} else {
None
}
};
parsed_account.ok_or(ParseAccountError::AccountNotParsable(
ParsableAccount::Sysvar,
))
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase", tag = "type", content = "info")]
pub enum SysvarAccountType {
Clock(UiClock),
EpochSchedule(EpochSchedule),
Fees(UiFees),
RecentBlockhashes(Vec<UiRecentBlockhashesEntry>),
Rent(UiRent),
Rewards(UiRewards),
SlotHashes(Vec<UiSlotHashEntry>),
SlotHistory(UiSlotHistory),
StakeHistory(Vec<UiStakeHistoryEntry>),
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
pub struct UiClock {
pub slot: Slot,
pub epoch: Epoch,
pub leader_schedule_epoch: Epoch,
pub unix_timestamp: UnixTimestamp,
}
impl From<Clock> for UiClock {
fn from(clock: Clock) -> Self {
Self {
slot: clock.slot,
epoch: clock.epoch,
leader_schedule_epoch: clock.leader_schedule_epoch,
unix_timestamp: clock.unix_timestamp,
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
pub struct UiFees {
pub fee_calculator: UiFeeCalculator,
}
impl From<Fees> for UiFees {
fn from(fees: Fees) -> Self {
Self {
fee_calculator: fees.fee_calculator.into(),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
pub struct UiRent {
pub lamports_per_byte_year: StringAmount,
pub exemption_threshold: f64,
pub burn_percent: u8,
}
impl From<Rent> for UiRent {
fn from(rent: Rent) -> Self {
Self {
lamports_per_byte_year: rent.lamports_per_byte_year.to_string(),
exemption_threshold: rent.exemption_threshold,
burn_percent: rent.burn_percent,
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
pub struct UiRewards {
pub validator_point_value: f64,
}
impl From<Rewards> for UiRewards {
fn from(rewards: Rewards) -> Self {
Self {
validator_point_value: rewards.validator_point_value,
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiRecentBlockhashesEntry {
pub blockhash: String,
pub fee_calculator: UiFeeCalculator,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiSlotHashEntry {
pub slot: Slot,
pub hash: String,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiSlotHistory {
pub next_slot: Slot,
pub bits: String,
}
struct SlotHistoryBits(BitVec<u64>);
impl std::fmt::Debug for SlotHistoryBits {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for i in 0..slot_history::MAX_ENTRIES {
if self.0.get(i) {
write!(f, "1")?;
} else {
write!(f, "0")?;
}
}
Ok(())
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiStakeHistoryEntry {
pub epoch: Epoch,
pub stake_history: StakeHistoryEntry,
}
#[cfg(test)]
mod test {
use super::*;
use solana_sdk::{
fee_calculator::FeeCalculator,
hash::Hash,
sysvar::{recent_blockhashes::IterItem, Sysvar},
};
use std::iter::FromIterator;
#[test]
fn test_parse_sysvars() {
let clock_sysvar = Clock::default().create_account(1);
assert_eq!(
parse_sysvar(&clock_sysvar.data, &sysvar::clock::id()).unwrap(),
SysvarAccountType::Clock(UiClock::default()),
);
let epoch_schedule = EpochSchedule {
slots_per_epoch: 12,
leader_schedule_slot_offset: 0,
warmup: false,
first_normal_epoch: 1,
first_normal_slot: 12,
};
let epoch_schedule_sysvar = epoch_schedule.create_account(1);
assert_eq!(
parse_sysvar(&epoch_schedule_sysvar.data, &sysvar::epoch_schedule::id()).unwrap(),
SysvarAccountType::EpochSchedule(epoch_schedule),
);
let fees_sysvar = Fees::default().create_account(1);
assert_eq!(
parse_sysvar(&fees_sysvar.data, &sysvar::fees::id()).unwrap(),
SysvarAccountType::Fees(UiFees::default()),
);
let hash = Hash::new(&[1; 32]);
let fee_calculator = FeeCalculator {
lamports_per_signature: 10,
};
let recent_blockhashes =
RecentBlockhashes::from_iter(vec![IterItem(0, &hash, &fee_calculator)].into_iter());
let recent_blockhashes_sysvar = recent_blockhashes.create_account(1);
assert_eq!(
parse_sysvar(
&recent_blockhashes_sysvar.data,
&sysvar::recent_blockhashes::id()
)
.unwrap(),
SysvarAccountType::RecentBlockhashes(vec![UiRecentBlockhashesEntry {
blockhash: hash.to_string(),
fee_calculator: fee_calculator.into(),
}]),
);
let rent = Rent {
lamports_per_byte_year: 10,
exemption_threshold: 2.0,
burn_percent: 5,
};
let rent_sysvar = rent.create_account(1);
assert_eq!(
parse_sysvar(&rent_sysvar.data, &sysvar::rent::id()).unwrap(),
SysvarAccountType::Rent(rent.into()),
);
let rewards_sysvar = Rewards::default().create_account(1);
assert_eq!(
parse_sysvar(&rewards_sysvar.data, &sysvar::rewards::id()).unwrap(),
SysvarAccountType::Rewards(UiRewards::default()),
);
let mut slot_hashes = SlotHashes::default();
slot_hashes.add(1, hash);
let slot_hashes_sysvar = slot_hashes.create_account(1);
assert_eq!(
parse_sysvar(&slot_hashes_sysvar.data, &sysvar::slot_hashes::id()).unwrap(),
SysvarAccountType::SlotHashes(vec![UiSlotHashEntry {
slot: 1,
hash: hash.to_string(),
}]),
);
let mut slot_history = SlotHistory::default();
slot_history.add(42);
let slot_history_sysvar = slot_history.create_account(1);
assert_eq!(
parse_sysvar(&slot_history_sysvar.data, &sysvar::slot_history::id()).unwrap(),
SysvarAccountType::SlotHistory(UiSlotHistory {
next_slot: slot_history.next_slot,
bits: format!("{:?}", SlotHistoryBits(slot_history.bits)),
}),
);
let mut stake_history = StakeHistory::default();
let stake_history_entry = StakeHistoryEntry {
effective: 10,
activating: 2,
deactivating: 3,
};
stake_history.add(1, stake_history_entry.clone());
let stake_history_sysvar = stake_history.create_account(1);
assert_eq!(
parse_sysvar(&stake_history_sysvar.data, &sysvar::stake_history::id()).unwrap(),
SysvarAccountType::StakeHistory(vec![UiStakeHistoryEntry {
epoch: 1,
stake_history: stake_history_entry,
}]),
);
let bad_pubkey = Pubkey::new_rand();
assert!(parse_sysvar(&stake_history_sysvar.data, &bad_pubkey).is_err());
let bad_data = vec![0; 4];
assert!(parse_sysvar(&bad_data, &sysvar::stake_history::id()).is_err());
}
}

View File

@@ -3,64 +3,81 @@ use crate::{
StringAmount,
};
use solana_sdk::pubkey::Pubkey;
use spl_token_v1_0::{
option::COption,
solana_sdk::pubkey::Pubkey as SplTokenPubkey,
state::{unpack, Account, Mint, Multisig},
use spl_token_v2_0::{
solana_sdk::{program_option::COption, program_pack::Pack, pubkey::Pubkey as SplTokenPubkey},
state::{Account, AccountState, Mint, Multisig},
};
use std::{mem::size_of, str::FromStr};
use std::str::FromStr;
// A helper function to convert spl_token_v1_0::id() as spl_sdk::pubkey::Pubkey to
// 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_v1_0() -> Pubkey {
Pubkey::from_str(&spl_token_v1_0::id().to_string()).unwrap()
pub fn spl_token_id_v2_0() -> Pubkey {
Pubkey::from_str(&spl_token_v2_0::id().to_string()).unwrap()
}
// A helper function to convert spl_token_v1_0::native_mint::id() as spl_sdk::pubkey::Pubkey to
// 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_v1_0_native_mint() -> Pubkey {
Pubkey::from_str(&spl_token_v1_0::native_mint::id().to_string()).unwrap()
pub fn spl_token_v2_0_native_mint() -> Pubkey {
Pubkey::from_str(&spl_token_v2_0::native_mint::id().to_string()).unwrap()
}
pub fn parse_token(
data: &[u8],
mint_decimals: Option<u8>,
) -> Result<TokenAccountType, ParseAccountError> {
let mut data = data.to_vec();
if data.len() == size_of::<Account>() {
let account: Account = *unpack(&mut data)
if data.len() == Account::get_packed_len() {
let account = Account::unpack(data)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
let decimals = mint_decimals.ok_or_else(|| {
ParseAccountError::AdditionalDataMissing(
"no mint_decimals provided to parse spl-token account".to_string(),
)
})?;
let ui_token_amount = token_amount_to_ui_amount(account.amount, decimals);
Ok(TokenAccountType::Account(UiTokenAccount {
mint: account.mint.to_string(),
owner: account.owner.to_string(),
token_amount: ui_token_amount,
token_amount: token_amount_to_ui_amount(account.amount, decimals),
delegate: match account.delegate {
COption::Some(pubkey) => Some(pubkey.to_string()),
COption::None => None,
},
is_initialized: account.is_initialized,
is_native: account.is_native,
delegated_amount: account.delegated_amount,
}))
} else if data.len() == size_of::<Mint>() {
let mint: Mint = *unpack(&mut data)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
Ok(TokenAccountType::Mint(UiMint {
owner: match mint.owner {
state: account.state.into(),
is_native: account.is_native(),
rent_exempt_reserve: match account.is_native {
COption::Some(reserve) => Some(token_amount_to_ui_amount(reserve, decimals)),
COption::None => None,
},
delegated_amount: if account.delegate.is_none() {
None
} else {
Some(token_amount_to_ui_amount(
account.delegated_amount,
decimals,
))
},
close_authority: match account.close_authority {
COption::Some(pubkey) => Some(pubkey.to_string()),
COption::None => None,
},
}))
} else if data.len() == Mint::get_packed_len() {
let mint = Mint::unpack(data)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
Ok(TokenAccountType::Mint(UiMint {
mint_authority: match mint.mint_authority {
COption::Some(pubkey) => Some(pubkey.to_string()),
COption::None => None,
},
supply: mint.supply.to_string(),
decimals: mint.decimals,
is_initialized: mint.is_initialized,
freeze_authority: match mint.freeze_authority {
COption::Some(pubkey) => Some(pubkey.to_string()),
COption::None => None,
},
}))
} else if data.len() == size_of::<Multisig>() {
let multisig: Multisig = *unpack(&mut data)
} else if data.len() == Multisig::get_packed_len() {
let multisig = Multisig::unpack(data)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
Ok(TokenAccountType::Multisig(UiMultisig {
num_required_signers: multisig.m,
@@ -99,10 +116,34 @@ pub struct UiTokenAccount {
pub mint: String,
pub owner: String,
pub token_amount: UiTokenAmount,
#[serde(skip_serializing_if = "Option::is_none")]
pub delegate: Option<String>,
pub is_initialized: bool,
pub state: UiAccountState,
pub is_native: bool,
pub delegated_amount: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub rent_exempt_reserve: Option<UiTokenAmount>,
#[serde(skip_serializing_if = "Option::is_none")]
pub delegated_amount: Option<UiTokenAmount>,
#[serde(skip_serializing_if = "Option::is_none")]
pub close_authority: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum UiAccountState {
Uninitialized,
Initialized,
Frozen,
}
impl From<AccountState> for UiAccountState {
fn from(state: AccountState) -> Self {
match state {
AccountState::Uninitialized => UiAccountState::Uninitialized,
AccountState::Initialized => UiAccountState::Initialized,
AccountState::Frozen => UiAccountState::Frozen,
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
@@ -126,9 +167,11 @@ pub fn token_amount_to_ui_amount(amount: u64, decimals: u8) -> UiTokenAmount {
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiMint {
pub owner: Option<String>,
pub mint_authority: Option<String>,
pub supply: StringAmount,
pub decimals: u8,
pub is_initialized: bool,
pub freeze_authority: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
@@ -141,7 +184,7 @@ pub struct UiMultisig {
}
pub fn get_token_account_mint(data: &[u8]) -> Option<Pubkey> {
if data.len() == size_of::<Account>() {
if data.len() == Account::get_packed_len() {
Some(Pubkey::new(&data[0..32]))
} else {
None
@@ -151,18 +194,21 @@ pub fn get_token_account_mint(data: &[u8]) -> Option<Pubkey> {
#[cfg(test)]
mod test {
use super::*;
use spl_token_v1_0::state::unpack_unchecked;
#[test]
fn test_parse_token() {
let mint_pubkey = SplTokenPubkey::new(&[2; 32]);
let owner_pubkey = SplTokenPubkey::new(&[3; 32]);
let mut account_data = [0; size_of::<Account>()];
let mut account: &mut Account = unpack_unchecked(&mut account_data).unwrap();
let mut account_data = vec![0; Account::get_packed_len()];
let mut account = Account::unpack_unchecked(&account_data).unwrap();
account.mint = mint_pubkey;
account.owner = owner_pubkey;
account.amount = 42;
account.is_initialized = true;
account.state = AccountState::Initialized;
account.is_native = COption::None;
account.close_authority = COption::Some(owner_pubkey);
Account::pack(account, &mut account_data).unwrap();
assert!(parse_token(&account_data, None).is_err());
assert_eq!(
parse_token(&account_data, Some(2)).unwrap(),
@@ -175,39 +221,49 @@ mod test {
amount: "42".to_string()
},
delegate: None,
is_initialized: true,
state: UiAccountState::Initialized,
is_native: false,
delegated_amount: 0,
rent_exempt_reserve: None,
delegated_amount: None,
close_authority: Some(owner_pubkey.to_string()),
}),
);
let mut mint_data = [0; size_of::<Mint>()];
let mut mint: &mut Mint = unpack_unchecked(&mut mint_data).unwrap();
mint.owner = COption::Some(owner_pubkey);
let mut mint_data = vec![0; Mint::get_packed_len()];
let mut mint = Mint::unpack_unchecked(&mint_data).unwrap();
mint.mint_authority = COption::Some(owner_pubkey);
mint.supply = 42;
mint.decimals = 3;
mint.is_initialized = true;
mint.freeze_authority = COption::Some(owner_pubkey);
Mint::pack(mint, &mut mint_data).unwrap();
assert_eq!(
parse_token(&mint_data, None).unwrap(),
TokenAccountType::Mint(UiMint {
owner: Some(owner_pubkey.to_string()),
mint_authority: Some(owner_pubkey.to_string()),
supply: 42.to_string(),
decimals: 3,
is_initialized: true,
freeze_authority: Some(owner_pubkey.to_string()),
}),
);
let signer1 = SplTokenPubkey::new(&[1; 32]);
let signer2 = SplTokenPubkey::new(&[2; 32]);
let signer3 = SplTokenPubkey::new(&[3; 32]);
let mut multisig_data = [0; size_of::<Multisig>()];
let mut multisig: &mut Multisig = unpack_unchecked(&mut multisig_data).unwrap();
let mut multisig_data = vec![0; Multisig::get_packed_len()];
let mut signers = [SplTokenPubkey::default(); 11];
signers[0] = signer1;
signers[1] = signer2;
signers[2] = signer3;
let mut multisig = Multisig::unpack_unchecked(&multisig_data).unwrap();
multisig.m = 2;
multisig.n = 3;
multisig.is_initialized = true;
multisig.signers = signers;
Multisig::pack(multisig, &mut multisig_data).unwrap();
assert_eq!(
parse_token(&multisig_data, None).unwrap(),
TokenAccountType::Multisig(UiMultisig {
@@ -229,9 +285,10 @@ mod test {
#[test]
fn test_get_token_account_mint() {
let mint_pubkey = SplTokenPubkey::new(&[2; 32]);
let mut account_data = [0; size_of::<Account>()];
let mut account: &mut Account = unpack_unchecked(&mut account_data).unwrap();
let mut account_data = vec![0; Account::get_packed_len()];
let mut account = Account::unpack_unchecked(&account_data).unwrap();
account.mint = mint_pubkey;
Account::pack(account, &mut account_data).unwrap();
let expected_mint_pubkey = Pubkey::new(&[2; 32]);
assert_eq!(

View File

@@ -1,4 +1,4 @@
use crate::parse_account_data::ParseAccountError;
use crate::{parse_account_data::ParseAccountError, StringAmount};
use solana_sdk::{
clock::{Epoch, Slot},
pubkey::Pubkey,
@@ -12,8 +12,8 @@ pub fn parse_vote(data: &[u8]) -> Result<VoteAccountType, ParseAccountError> {
.iter()
.map(|(epoch, credits, previous_credits)| UiEpochCredits {
epoch: *epoch,
credits: *credits,
previous_credits: *previous_credits,
credits: credits.to_string(),
previous_credits: previous_credits.to_string(),
})
.collect();
let votes = vote_state
@@ -115,8 +115,8 @@ struct UiPriorVoters {
#[serde(rename_all = "camelCase")]
struct UiEpochCredits {
epoch: Epoch,
credits: u64,
previous_credits: u64,
credits: StringAmount,
previous_credits: StringAmount,
}
#[cfg(test)]

View File

@@ -0,0 +1,18 @@
use solana_config_program::ConfigState;
pub const MAX_SHORT_FIELD_LENGTH: usize = 70;
pub const MAX_LONG_FIELD_LENGTH: usize = 300;
pub const MAX_VALIDATOR_INFO: u64 = 576;
solana_sdk::declare_id!("Va1idator1nfo111111111111111111111111111111");
#[derive(Debug, Deserialize, PartialEq, Serialize, Default)]
pub struct ValidatorInfo {
pub info: String,
}
impl ConfigState for ValidatorInfo {
fn max_space() -> u64 {
MAX_VALIDATOR_INFO
}
}

View File

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

View File

@@ -5,7 +5,7 @@ use solana_runtime::{
accounts::{create_test_accounts, update_accounts, Accounts},
accounts_index::Ancestors,
};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::{genesis_config::OperatingMode, pubkey::Pubkey};
use std::fs;
use std::path::PathBuf;
@@ -54,7 +54,7 @@ fn main() {
if fs::remove_dir_all(path.clone()).is_err() {
println!("Warning: Couldn't remove {:?}", path);
}
let accounts = Accounts::new(vec![path]);
let accounts = Accounts::new(vec![path], OperatingMode::Preview);
println!("Creating {} accounts", num_accounts);
let mut create_time = Measure::start("create accounts");
let pubkeys: Vec<_> = (0..num_slots)

View File

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

View File

@@ -11,13 +11,14 @@ use solana_core::{
poh_recorder::WorkingBankEntry,
};
use solana_ledger::{
bank_forks::BankForks,
blockstore::Blockstore,
genesis_utils::{create_genesis_config, GenesisConfigInfo},
get_tmp_ledger_path,
};
use solana_measure::measure::Measure;
use solana_perf::packet::to_packets_chunked;
use solana_runtime::{bank::Bank, bank_forks::BankForks};
use solana_runtime::bank::Bank;
use solana_sdk::{
hash::Hash,
pubkey::Pubkey,
@@ -167,7 +168,6 @@ fn main() {
let (verified_sender, verified_receiver) = unbounded();
let (vote_sender, vote_receiver) = unbounded();
let (replay_vote_sender, _replay_vote_receiver) = unbounded();
let bank0 = Bank::new(&genesis_config);
let mut bank_forks = BankForks::new(bank0);
let mut bank = bank_forks.working_bank();
@@ -209,7 +209,7 @@ fn main() {
bank.clear_signatures();
}
let mut verified: Vec<_> = to_packets_chunked(&transactions, packets_per_chunk);
let mut verified: Vec<_> = to_packets_chunked(&transactions.clone(), packets_per_chunk);
let ledger_path = get_tmp_ledger_path!();
{
let blockstore = Arc::new(
@@ -225,7 +225,6 @@ fn main() {
verified_receiver,
vote_receiver,
None,
replay_vote_sender,
);
poh_recorder.lock().unwrap().set_bank(&bank);

View File

@@ -1,8 +1,8 @@
[package]
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
authors = ["Solana Maintainers <maintainers@solana.com>"]
edition = "2018"
name = "solana-bench-exchange"
version = "1.3.1"
version = "1.2.33"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -15,24 +15,24 @@ log = "0.4.8"
num-derive = "0.3"
num-traits = "0.2"
rand = "0.7.0"
rayon = "1.3.1"
serde_json = "1.0.56"
serde_yaml = "0.8.13"
solana-clap-utils = { path = "../clap-utils", version = "1.3.1" }
solana-core = { path = "../core", version = "1.3.1" }
solana-genesis = { path = "../genesis", version = "1.3.1" }
solana-client = { path = "../client", version = "1.3.1" }
solana-faucet = { path = "../faucet", version = "1.3.1" }
solana-exchange-program = { path = "../programs/exchange", version = "1.3.1" }
solana-logger = { path = "../logger", version = "1.3.1" }
solana-metrics = { path = "../metrics", version = "1.3.1" }
solana-net-utils = { path = "../net-utils", version = "1.3.1" }
solana-runtime = { path = "../runtime", version = "1.3.1" }
solana-sdk = { path = "../sdk", version = "1.3.1" }
solana-version = { path = "../version", version = "1.3.1" }
rayon = "1.4.0"
serde_json = "1.0.53"
serde_yaml = "0.8.12"
solana-clap-utils = { path = "../clap-utils", version = "1.2.33" }
solana-core = { path = "../core", version = "1.2.33" }
solana-genesis = { path = "../genesis", version = "1.2.33" }
solana-client = { path = "../client", version = "1.2.33" }
solana-faucet = { path = "../faucet", version = "1.2.33" }
solana-exchange-program = { path = "../programs/exchange", version = "1.2.33" }
solana-logger = { path = "../logger", version = "1.2.33" }
solana-metrics = { path = "../metrics", version = "1.2.33" }
solana-net-utils = { path = "../net-utils", version = "1.2.33" }
solana-runtime = { path = "../runtime", version = "1.2.33" }
solana-sdk = { path = "../sdk", version = "1.2.33" }
solana-version = { path = "../version", version = "1.2.33" }
[dev-dependencies]
solana-local-cluster = { path = "../local-cluster", version = "1.3.1" }
solana-local-cluster = { path = "../local-cluster", version = "1.2.33" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -179,13 +179,19 @@ where
info!("Generating {:?} account keys", total_keys);
let mut account_keypairs = generate_keypairs(total_keys);
let src_keypairs: Vec<_> = account_keypairs.drain(0..accounts_in_groups).collect();
let src_keypairs: Vec<_> = account_keypairs
.drain(0..accounts_in_groups)
.map(|keypair| keypair)
.collect();
let src_pubkeys: Vec<Pubkey> = src_keypairs
.iter()
.map(|keypair| keypair.pubkey())
.collect();
let profit_keypairs: Vec<_> = account_keypairs.drain(0..accounts_in_groups).collect();
let profit_keypairs: Vec<_> = account_keypairs
.drain(0..accounts_in_groups)
.map(|keypair| keypair)
.collect();
let profit_pubkeys: Vec<Pubkey> = profit_keypairs
.iter()
.map(|keypair| keypair.pubkey())

View File

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

View File

@@ -27,7 +27,7 @@ fn producer(addr: &SocketAddr, exit: Arc<AtomicBool>) -> JoinHandle<()> {
let mut num = 0;
for p in &msgs.packets {
let a = p.meta.addr();
assert!(p.meta.size < PACKET_DATA_SIZE);
assert!(p.meta.size <= PACKET_DATA_SIZE);
send.send_to(&p.data[..p.meta.size], &a).unwrap();
num += 1;
}

View File

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

View File

@@ -1,10 +1,7 @@
use clap::{crate_description, crate_name, App, Arg, ArgMatches};
use solana_faucet::faucet::FAUCET_PORT;
use solana_sdk::fee_calculator::FeeRateGovernor;
use solana_sdk::{
pubkey::Pubkey,
signature::{read_keypair_file, Keypair},
};
use solana_sdk::signature::{read_keypair_file, Keypair};
use std::{net::SocketAddr, process::exit, time::Duration};
const NUM_LAMPORTS_PER_ACCOUNT_DEFAULT: u64 = solana_sdk::native_token::LAMPORTS_PER_SOL;
@@ -28,7 +25,6 @@ pub struct Config {
pub multi_client: bool,
pub num_lamports_per_account: u64,
pub target_slots_per_epoch: u64,
pub target_node: Option<Pubkey>,
}
impl Default for Config {
@@ -51,7 +47,6 @@ impl Default for Config {
multi_client: true,
num_lamports_per_account: NUM_LAMPORTS_PER_ACCOUNT_DEFAULT,
target_slots_per_epoch: 0,
target_node: None,
}
}
}
@@ -117,14 +112,6 @@ pub fn build_args<'a, 'b>(version: &'b str) -> App<'a, 'b> {
.long("no-multi-client")
.help("Disable multi-client support, only transact with the entrypoint."),
)
.arg(
Arg::with_name("target_node")
.long("target-node")
.requires("no-multi-client")
.takes_value(true)
.value_name("PUBKEY")
.help("Specify an exact node to send transactions to."),
)
.arg(
Arg::with_name("tx_count")
.long("tx_count")
@@ -270,9 +257,6 @@ pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
}
args.multi_client = !matches.is_present("no-multi-client");
args.target_node = matches
.value_of("target_node")
.map(|target_str| target_str.parse().unwrap());
if let Some(v) = matches.value_of("num_lamports_per_account") {
args.num_lamports_per_account = v.to_string().parse().expect("can't parse lamports");

View File

@@ -31,7 +31,6 @@ fn main() {
target_lamports_per_signature,
multi_client,
num_lamports_per_account,
target_node,
..
} = &cli_config;
@@ -82,19 +81,6 @@ fn main() {
exit(1);
}
Arc::new(client)
} else if let Some(target_node) = target_node {
info!("Searching for target_node: {:?}", target_node);
let mut target_client = None;
for node in nodes {
if node.id == *target_node {
target_client = Some(Arc::new(get_client(&[node])));
break;
}
}
target_client.unwrap_or_else(|| {
eprintln!("Target node {} not found", target_node);
exit(1);
})
} else {
Arc::new(get_client(&nodes))
};

43
ci/affects-files.sh Executable file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
#
# Checks if a CI build affects one or more path patterns. Each command-line
# argument is checked in series.
#
# Bash regular expressions are permitted in the pattern:
# ./affects-files.sh .rs$ -- any file or directory ending in .rs
# ./affects-files.sh .rs -- also matches foo.rs.bar
# ./affects-files.sh ^snap/ -- anything under the snap/ subdirectory
# ./affects-files.sh snap/ -- also matches foo/snap/
# Any pattern starting with the ! character will be negated:
# ./affects-files.sh !^docs/ -- anything *not* under the docs/ subdirectory
#
set -e
cd "$(dirname "$0")"/..
if [[ -n $CI_PULL_REQUEST ]]; then
affectedFiles="$(buildkite-agent meta-data get affected_files)"
echo "Affected files in this PR: $affectedFiles"
IFS=':' read -ra files <<< "$affectedFiles"
for pattern in "$@"; do
if [[ ${pattern:0:1} = "!" ]]; then
for file in "${files[@]}"; do
if [[ ! $file =~ ${pattern:1} ]]; then
exit 0
fi
done
else
for file in "${files[@]}"; do
if [[ $file =~ $pattern ]]; then
exit 0
fi
done
fi
done
exit 1
fi
# affected_files metadata is not currently available for non-PR builds, so assume
# the worse (affected)
exit 0

View File

@@ -207,7 +207,7 @@ pull_or_push_steps() {
# Run the full test suite by default, skipping only if modifications are local
# to some particular areas of the tree
if affects_other_than ^.buildkite ^.mergify .md$ ^docs/ ^web3.js/ ^explorer/ ^.gitbook; then
if affects_other_than ^.buildkite ^.travis .md$ ^docs/ ^web3.js/ ^explorer/ ^.gitbook; then
all_test_steps
fi

15
ci/buildkite-release.yml Normal file
View File

@@ -0,0 +1,15 @@
# Build steps that run on a release tag
#
# All the steps in `buildkite.yml` are skipped and we jump directly to the
# secondary build steps since it's assumed the commit that was tagged is known
# to be good so there's no need to rebuild and retest it.
steps:
- trigger: "solana-secondary"
branches: "!pull/*"
async: true
build:
message: "${BUILDKITE_MESSAGE}"
commit: "${BUILDKITE_COMMIT}"
branch: "${BUILDKITE_BRANCH}"
env:
TRIGGERED_BUILDKITE_TAG: "${BUILDKITE_TAG}"

26
ci/buildkite-tests.yml Normal file
View File

@@ -0,0 +1,26 @@
# These steps are conditionally triggered by ci/buildkite.yml when files
# other than those in docs/ are modified
steps:
- command: ". ci/rust-version.sh; ci/docker-run.sh $$rust_nightly_docker_image ci/test-coverage.sh"
name: "coverage"
timeout_in_minutes: 30
- wait
- command: ". ci/rust-version.sh; ci/docker-run.sh $$rust_stable_docker_image ci/test-stable.sh"
name: "stable"
timeout_in_minutes: 60
artifact_paths: "log-*.txt"
- wait
- command: "ci/test-stable-perf.sh"
name: "stable-perf"
timeout_in_minutes: 40
artifact_paths: "log-*.txt"
agents:
- "queue=cuda"
- command: "ci/test-bench.sh"
name: "bench"
timeout_in_minutes: 30
- command: ". ci/rust-version.sh; ci/docker-run.sh $$rust_stable_docker_image ci/test-local-cluster.sh"
name: "local-cluster"
timeout_in_minutes: 45
artifact_paths: "log-*.txt"

47
ci/buildkite.yml Normal file
View File

@@ -0,0 +1,47 @@
# Build steps that run on pushes and pull requests.
# If files other than those in docs/ were modified, this will be followed up by
# ci/buildkite-tests.yml
#
# Release tags use buildkite-release.yml instead
steps:
- command: "ci/test-sanity.sh"
name: "sanity"
timeout_in_minutes: 5
- command: "ci/dependabot-pr.sh"
name: "dependabot"
timeout_in_minutes: 5
if: build.env("GITHUB_USER") == "dependabot-preview[bot]"
- wait
- command: ". ci/rust-version.sh; ci/docker-run.sh $$rust_audit_docker_image ci/test-audit.sh"
name: "audit"
timeout_in_minutes: 20
- wait
- command: ". ci/rust-version.sh; ci/docker-run.sh $$rust_nightly_docker_image ci/test-checks.sh"
name: "checks"
timeout_in_minutes: 20
- command: "ci/shellcheck.sh"
name: "shellcheck"
timeout_in_minutes: 5
- wait
- command: "ci/maybe-trigger-tests.sh"
name: "maybe-trigger-tests"
timeout_in_minutes: 2
- wait
- trigger: "solana-secondary"
branches: "!pull/*"
async: true
build:
message: "${BUILDKITE_MESSAGE}"
commit: "${BUILDKITE_COMMIT}"
branch: "${BUILDKITE_BRANCH}"
env:
TRIGGERED_BUILDKITE_TAG: "${BUILDKITE_TAG}"

View File

@@ -89,11 +89,17 @@ BETA_CHANNEL_LATEST_TAG=${beta_tag:+v$beta_tag}
STABLE_CHANNEL_LATEST_TAG=${stable_tag:+v$stable_tag}
if [[ $CI_BRANCH = "$STABLE_CHANNEL" ]]; then
if [[ -n $CI_BASE_BRANCH ]]; then
BRANCH="$CI_BASE_BRANCH"
elif [[ -n $CI_BRANCH ]]; then
BRANCH="$CI_BRANCH"
fi
if [[ $BRANCH = "$STABLE_CHANNEL" ]]; then
CHANNEL=stable
elif [[ $CI_BRANCH = "$EDGE_CHANNEL" ]]; then
elif [[ $BRANCH = "$EDGE_CHANNEL" ]]; then
CHANNEL=edge
elif [[ $CI_BRANCH = "$BETA_CHANNEL" ]]; then
elif [[ $BRANCH = "$BETA_CHANNEL" ]]; then
CHANNEL=beta
fi

View File

@@ -7,14 +7,14 @@ source ci/_
commit_range="$(git merge-base HEAD origin/master)..HEAD"
parsed_update_args="$(
git log "$commit_range" --author "dependabot-preview" --oneline -n1 |
grep -o '[Bb]ump.*$' |
sed -r 's/[Bb]ump ([^ ]+) from ([^ ]+) to ([^ ]+)/-p \1:\2 --precise \3/'
grep -o 'Bump.*$' |
sed -r 's/Bump ([^ ]+) from ([^ ]+) to ([^ ]+)/-p \1:\2 --precise \3/'
)"
# relaxed_parsed_update_args is temporal measure...
relaxed_parsed_update_args="$(
git log "$commit_range" --author "dependabot-preview" --oneline -n1 |
grep -o '[Bb]ump.*$' |
sed -r 's/[Bb]ump ([^ ]+) from [^ ]+ to ([^ ]+)/-p \1 --precise \2/'
grep -o 'Bump.*$' |
sed -r 's/Bump ([^ ]+) from [^ ]+ to ([^ ]+)/-p \1 --precise \2/'
)"
package=$(echo "$parsed_update_args" | awk '{print $2}' | grep -o "^[^:]*")
if [[ -n $parsed_update_args ]]; then

View File

@@ -60,12 +60,6 @@ if [[ -z "$SOLANA_DOCKER_RUN_NOSETUID" ]]; then
ARGS+=(--user "$(id -u):$(id -g)")
fi
if [[ -n $SOLANA_ALLOCATE_TTY ]]; then
# Colored output, progress bar and Ctrl-C:
# https://stackoverflow.com/a/41099052/10242004
ARGS+=(--interactive --tty)
fi
# Environment variables to propagate into the container
ARGS+=(
--env BUILDKITE

View File

@@ -1,10 +1,9 @@
FROM solanalabs/rust:1.45.1
FROM solanalabs/rust:1.43.0
ARG date
RUN set -x \
&& rustup install nightly-$date \
&& rustup component add clippy --toolchain=nightly-$date \
&& rustup component add rustfmt --toolchain=nightly-$date \
&& rustup show \
&& rustc --version \
&& cargo --version \

View File

@@ -2,27 +2,23 @@ Docker image containing rust nightly and some preinstalled crates used in CI.
This image may be manually updated by running `CI=true ./build.sh` if you are a member
of the [Solana Labs](https://hub.docker.com/u/solanalabs/) Docker Hub
organization.
organization, but it is also automatically updated periodically by
[this automation](https://buildkite.com/solana-labs/solana-ci-docker-rust-nightly).
## Moving to a newer nightly
NOTE: Follow instructions in docker-rust/README.md before this when updating the stable
rust version as well.
We pin the version of nightly (see the `ARG nightly=xyz` line in `Dockerfile`)
to avoid the build breaking at unexpected times, as occasionally nightly will
introduce breaking changes.
To update the pinned version:
1. Edit `Dockerfile` to match the desired stable rust version to base on if needed.
1. Run `ci/docker-rust-nightly/build.sh` to rebuild the nightly image locally,
or potentially `ci/docker-rust-nightly/build.sh YYYY-MM-DD` if there's a
specific YYYY-MM-DD that is desired (default is today's build).
Check https://rust-lang.github.io/rustup-components-history/ for build
status
1. Update `ci/rust-version.sh` to reflect the new nightly `YYY-MM-DD`
1. Run `SOLANA_ALLOCATE_TTY=1 SOLANA_DOCKER_RUN_NOSETUID=1 ci/docker-run.sh --nopull solanalabs/rust-nightly:YYYY-MM-DD ci/test-checks.sh`
and `SOLANA_ALLOCATE_TTY=1 SOLANA_DOCKER_RUN_NOSETUID=1 ci/docker-run.sh --nopull solanalabs/rust-nightly:YYYY-MM-DD ci/test-coverage.sh [args]...`
1. Run `SOLANA_DOCKER_RUN_NOSETUID=1 ci/docker-run.sh --nopull solanalabs/rust-nightly:YYYY-MM-DD ci/test-coverage.sh`
to confirm the new nightly image builds. Fix any issues as needed
1. Run `docker login` to enable pushing images to Docker Hub, if you're authorized.
1. Run `CI=true ci/docker-rust-nightly/build.sh YYYY-MM-DD` to push the new nightly image to dockerhub.com.

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.45.1
FROM rust:1.43.0
# Add Google Protocol Buffers for Libra's metrics library.
ENV PROTOC_VERSION 3.8.0

View File

@@ -1,11 +1,7 @@
Docker image containing rust and some preinstalled packages used in CI.
NOTE: Recreate rust-nightly docker image after this when updating the stable rust
version! Both of docker images must be updated in tandem.
This image manually maintained:
1. Edit `Dockerfile` to match the desired rust version
1. Run `docker login` to enable pushing images to Docker Hub, if you're authorized.
1. Run `./build.sh` to publish the new image, if you are a member of the [Solana
2. Run `./build.sh` to publish the new image, if you are a member of the [Solana
Labs](https://hub.docker.com/u/solanalabs/) Docker Hub organization.

21
ci/maybe-trigger-tests.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -e
cd "$(dirname "$0")/.."
annotate() {
${BUILDKITE:-false} && {
buildkite-agent annotate "$@"
}
}
# Skip if only the docs have been modified
ci/affects-files.sh \
\!^docs/ \
|| {
annotate --style info \
"Skipping all further tests as only docs/ files were modified"
exit 0
}
annotate --style info "Triggering tests"
buildkite-agent pipeline upload ci/buildkite-tests.yml

View File

@@ -46,15 +46,6 @@ linux)
;;
windows)
TARGET=x86_64-pc-windows-msvc
# Enable symlinks used by some build.rs files
# source: https://stackoverflow.com/a/52097145/10242004
(
set -x
git --version
git config core.symlinks true
find . -type l -delete
git reset --hard
)
;;
*)
echo CI_OS_NAME unset
@@ -62,14 +53,11 @@ windows)
;;
esac
RELEASE_BASENAME="${RELEASE_BASENAME:=solana-release}"
TARBALL_BASENAME="${TARBALL_BASENAME:="$RELEASE_BASENAME"}"
echo --- Creating release tarball
(
set -x
rm -rf "${RELEASE_BASENAME:?}"/
mkdir "${RELEASE_BASENAME}"/
rm -rf solana-release/
mkdir solana-release/
COMMIT="$(git rev-parse HEAD)"
@@ -77,18 +65,18 @@ echo --- Creating release tarball
echo "channel: $CHANNEL_OR_TAG"
echo "commit: $COMMIT"
echo "target: $TARGET"
) > "${RELEASE_BASENAME}"/version.yml
) > solana-release/version.yml
# Make CHANNEL available to include in the software version information
export CHANNEL
source ci/rust-version.sh stable
scripts/cargo-install-all.sh +"$rust_stable" "${RELEASE_BASENAME}"
scripts/cargo-install-all.sh +"$rust_stable" solana-release
tar cvf "${TARBALL_BASENAME}"-$TARGET.tar "${RELEASE_BASENAME}"
bzip2 "${TARBALL_BASENAME}"-$TARGET.tar
cp "${RELEASE_BASENAME}"/bin/solana-install-init solana-install-init-$TARGET
cp "${RELEASE_BASENAME}"/version.yml "${TARBALL_BASENAME}"-$TARGET.yml
tar cvf solana-release-$TARGET.tar solana-release
bzip2 solana-release-$TARGET.tar
cp solana-release/bin/solana-install-init solana-install-init-$TARGET
cp solana-release/version.yml solana-release-$TARGET.yml
)
# Metrics tarball is platform agnostic, only publish it from Linux
@@ -106,7 +94,7 @@ fi
source ci/upload-ci-artifact.sh
for file in "${TARBALL_BASENAME}"-$TARGET.tar.bz2 "${TARBALL_BASENAME}"-$TARGET.yml solana-install-init-"$TARGET"* $MAYBE_TARBALLS; do
for file in solana-release-$TARGET.tar.bz2 solana-release-$TARGET.yml solana-install-init-"$TARGET"* $MAYBE_TARBALLS; do
if [[ -n $DO_NOT_PUBLISH_TAR ]]; then
upload-ci-artifact "$file"
echo "Skipped $file due to DO_NOT_PUBLISH_TAR"

View File

@@ -18,13 +18,13 @@
if [[ -n $RUST_STABLE_VERSION ]]; then
stable_version="$RUST_STABLE_VERSION"
else
stable_version=1.45.1
stable_version=1.43.0
fi
if [[ -n $RUST_NIGHTLY_VERSION ]]; then
nightly_version="$RUST_NIGHTLY_VERSION"
else
nightly_version=2020-07-27
nightly_version=2020-04-23
fi
@@ -34,12 +34,14 @@ export rust_stable_docker_image=solanalabs/rust:"$stable_version"
export rust_nightly=nightly-"$nightly_version"
export rust_nightly_docker_image=solanalabs/rust-nightly:"$nightly_version"
export rust_audit="1.46.0"
export rust_audit_docker_image=solanalabs/rust-nightly:2020-08-17
[[ -z $1 ]] || (
rustup_install() {
declare toolchain=$1
if ! cargo +"$toolchain" -V > /dev/null; then
echo "$0: Missing toolchain? Installing...: $toolchain" >&2
if ! cargo +"$toolchain" -V; then
rustup install "$toolchain"
cargo +"$toolchain" -V
fi
@@ -48,6 +50,9 @@ export rust_nightly_docker_image=solanalabs/rust-nightly:"$nightly_version"
set -e
cd "$(dirname "${BASH_SOURCE[0]}")"
case $1 in
audit)
rustup_install "$rust_audit"
;;
stable)
rustup_install "$rust_stable"
;;
@@ -57,9 +62,10 @@ export rust_nightly_docker_image=solanalabs/rust-nightly:"$nightly_version"
all)
rustup_install "$rust_stable"
rustup_install "$rust_nightly"
rustup_install "$rust_audit"
;;
*)
echo "$0: Note: ignoring unknown argument: $1" >&2
echo "Note: ignoring unknown argument: $1"
;;
esac
)

View File

@@ -27,5 +27,5 @@ Alternatively, you can source it from within a script:
local PATCH=0
local SPECIAL=""
semverParseInto "1.2.3" MAJOR MINOR PATCH SPECIAL
semverParseInto "3.2.1" MAJOR MINOR PATCH SPECIAL
semverParseInto "1.2.33" MAJOR MINOR PATCH SPECIAL
semverParseInto "3.2.1" MAJOR MINOR PATCH SPECIAL

View File

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

View File

@@ -8,5 +8,5 @@ source "$HERE"/utils.sh
ensure_env || exit 1
# Allow more files to be opened by a user
sed -i 's/^\(# End of file\)/* soft nofile 65535\n\n\1/' /etc/security/limits.conf
echo "* - nofile 500000" > /etc/security/limits.d/90-solana-nofiles.conf

11
ci/test-audit.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -e
source ci/_
source ci/rust-version.sh audit
export RUST_BACKTRACE=1
export RUSTFLAGS="-D warnings"
_ cargo +"$rust_audit" audit --version
_ scripts/cargo-for-all-lock-files.sh +"$rust_audit" audit --ignore RUSTSEC-2020-0002 --ignore RUSTSEC-2020-0008

View File

@@ -2,6 +2,25 @@
set -e
cd "$(dirname "$0")/.."
annotate() {
${BUILDKITE:-false} && {
buildkite-agent annotate "$@"
}
}
ci/affects-files.sh \
.rs$ \
Cargo.lock$ \
Cargo.toml$ \
^ci/rust-version.sh \
^ci/test-bench.sh \
|| {
annotate --style info --context test-bench \
"Bench skipped as no .rs files were modified"
exit 0
}
source ci/_
source ci/upload-ci-artifact.sh

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env bash
set -e
cd "$(dirname "$0")/.."
@@ -9,63 +8,40 @@ source ci/rust-version.sh stable
source ci/rust-version.sh nightly
eval "$(ci/channel-info.sh)"
echo --- build environment
(
set -x
rustup run "$rust_stable" rustc --version --verbose
rustup run "$rust_nightly" rustc --version --verbose
cargo +"$rust_stable" --version --verbose
cargo +"$rust_nightly" --version --verbose
cargo +"$rust_stable" clippy --version --verbose
cargo +"$rust_nightly" clippy --version --verbose
# audit is done only with stable
cargo +"$rust_stable" audit --version
)
export RUST_BACKTRACE=1
export RUSTFLAGS="-D warnings -A incomplete_features"
export RUSTFLAGS="-D warnings"
# Only force up-to-date lock files on edge
if [[ $CI_BASE_BRANCH = "$EDGE_CHANNEL" ]]; then
# Exclude --benches as it's not available in rust stable yet
if _ scripts/cargo-for-all-lock-files.sh +"$rust_stable" check --locked --tests --bins --examples; then
if _ scripts/cargo-for-all-lock-files.sh +"$rust_nightly" check --locked --all-targets; then
true
else
check_status=$?
echo "$0: Some Cargo.lock might be outdated; sync them (or just be a compilation error?)" >&2
echo "$0: protip: $ ./scripts/cargo-for-all-lock-files.sh [--ignore-exit-code] ... \\" >&2
echo "$0: [tree (for outdated Cargo.lock sync)|check (for compilation error)|update -p foo --precise x.y.z (for your Cargo.toml update)] ..." >&2
echo "Some Cargo.lock is outdated; please update them as well"
echo "protip: you can use ./scripts/cargo-for-all-lock-files.sh update ..."
exit "$check_status"
fi
else
echo "Note: cargo-for-all-lock-files.sh skipped because $CI_BASE_BRANCH != $EDGE_CHANNEL"
fi
# Ensure nightly and --benches
_ scripts/cargo-for-all-lock-files.sh +"$rust_nightly" check --locked --all-targets
_ ci/order-crates-for-publishing.py
_ cargo +"$rust_stable" fmt --all -- --check
# -Z... is needed because of clippy bug: https://github.com/rust-lang/rust-clippy/issues/4612
# run nightly clippy for `sdk/` as there's a moderate amount of nightly-only code there
_ cargo +"$rust_nightly" clippy -Zunstable-options --workspace --all-targets -- --deny=warnings
_ cargo +"$rust_stable" clippy --version
_ cargo +"$rust_stable" clippy --workspace -- --deny=warnings
_ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit --ignore RUSTSEC-2020-0002 --ignore RUSTSEC-2020-0008
_ ci/order-crates-for-publishing.py
{
cd programs/bpf
_ cargo +"$rust_stable" audit
for project in rust/*/ ; do
echo "+++ do_bpf_checks $project"
(
cd "$project"
_ cargo +"$rust_stable" fmt -- --check
_ cargo +"$rust_nightly" test
_ cargo +"$rust_nightly" clippy --version
_ cargo +"$rust_nightly" clippy -- --deny=warnings --allow=clippy::missing_safety_doc
)
done

View File

@@ -8,14 +8,23 @@ annotate() {
}
}
ci/affects-files.sh \
.rs$ \
Cargo.lock$ \
Cargo.toml$ \
^ci/rust-version.sh \
^ci/test-coverage.sh \
^scripts/coverage.sh \
|| {
annotate --style info --context test-coverage \
"Coverage skipped as no .rs files were modified"
exit 0
}
source ci/upload-ci-artifact.sh
source scripts/ulimit-n.sh
scripts/coverage.sh "$@"
if [[ -z $CI ]]; then
exit
fi
scripts/coverage.sh
report=coverage-"${CI_COMMIT:0:9}".tar.gz
mv target/cov/report.tar.gz "$report"

View File

@@ -13,6 +13,15 @@ annotate() {
# Run the appropriate test based on entrypoint
testName=$(basename "$0" .sh)
# Skip if only the docs have been modified
ci/affects-files.sh \
\!^docs/ \
|| {
annotate --style info \
"Skipped $testName as only docs/ files were modified"
exit 0
}
source ci/rust-version.sh stable
export RUST_BACKTRACE=1
@@ -40,6 +49,24 @@ test-stable)
_ cargo +"$rust_stable" test --jobs "$NPROC" --all --exclude solana-local-cluster ${V:+--verbose} -- --nocapture
;;
test-stable-perf)
ci/affects-files.sh \
.rs$ \
Cargo.lock$ \
Cargo.toml$ \
^ci/rust-version.sh \
^ci/test-stable-perf.sh \
^ci/test-stable.sh \
^ci/test-local-cluster.sh \
^core/build.rs \
^fetch-perf-libs.sh \
^programs/ \
^sdk/ \
|| {
annotate --style info \
"Skipped $testName as no relevant files were modified"
exit 0
}
# BPF program tests
_ make -C programs/bpf/c tests
_ cargo +"$rust_stable" test \
@@ -64,7 +91,6 @@ test-stable-perf)
_ cargo +"$rust_stable" build --bins ${V:+--verbose}
_ cargo +"$rust_stable" test --package solana-perf --package solana-ledger --package solana-core --lib ${V:+--verbose} -- --nocapture
_ cargo +"$rust_stable" run --manifest-path poh-bench/Cargo.toml ${V:+--verbose} -- --hashes-per-tick 10
;;
test-local-cluster)
_ cargo +"$rust_stable" build --release --bins ${V:+--verbose}

View File

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

View File

@@ -0,0 +1,19 @@
use crate::{input_validators, ArgConstant};
use clap::Arg;
pub const FEE_PAYER_ARG: ArgConstant<'static> = ArgConstant {
name: "fee_payer",
long: "fee-payer",
help: "Specify the fee-payer account. This may be a keypair file, the ASK keyword \n\
or the pubkey of an offline signer, provided an appropriate --signer argument \n\
is also passed. Defaults to the client keypair.",
};
pub fn fee_payer_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(FEE_PAYER_ARG.name)
.long(FEE_PAYER_ARG.long)
.takes_value(true)
.value_name("KEYPAIR")
.validator(input_validators::is_valid_signer)
.help(FEE_PAYER_ARG.help)
}

View File

@@ -11,6 +11,7 @@ use solana_remote_wallet::{
remote_wallet::{maybe_wallet_manager, RemoteWalletError, RemoteWalletManager},
};
use solana_sdk::{
hash::Hash,
pubkey::Pubkey,
signature::{
keypair_from_seed, keypair_from_seed_phrase_and_passphrase, read_keypair,
@@ -25,6 +26,81 @@ use std::{
sync::Arc,
};
pub struct SignOnly {
pub blockhash: Hash,
pub present_signers: Vec<(Pubkey, Signature)>,
pub absent_signers: Vec<Pubkey>,
pub bad_signers: Vec<Pubkey>,
}
impl SignOnly {
pub fn has_all_signers(&self) -> bool {
self.absent_signers.is_empty() && self.bad_signers.is_empty()
}
pub fn presigner_of(&self, pubkey: &Pubkey) -> Option<Presigner> {
presigner_from_pubkey_sigs(pubkey, &self.present_signers)
}
}
pub type CliSigners = Vec<Box<dyn Signer>>;
pub type SignerIndex = usize;
pub struct CliSignerInfo {
pub signers: CliSigners,
}
impl CliSignerInfo {
pub fn index_of(&self, pubkey: Option<Pubkey>) -> Option<usize> {
if let Some(pubkey) = pubkey {
self.signers
.iter()
.position(|signer| signer.pubkey() == pubkey)
} else {
Some(0)
}
}
}
pub struct DefaultSigner {
pub arg_name: String,
pub path: String,
}
impl DefaultSigner {
pub fn generate_unique_signers(
&self,
bulk_signers: Vec<Option<Box<dyn Signer>>>,
matches: &ArgMatches<'_>,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliSignerInfo, Box<dyn error::Error>> {
let mut unique_signers = vec![];
// Determine if the default signer is needed
if bulk_signers.iter().any(|signer| signer.is_none()) {
let default_signer = self.signer_from_path(matches, wallet_manager)?;
unique_signers.push(default_signer);
}
for signer in bulk_signers.into_iter() {
if let Some(signer) = signer {
if !unique_signers.iter().any(|s| s == &signer) {
unique_signers.push(signer);
}
}
}
Ok(CliSignerInfo {
signers: unique_signers,
})
}
pub fn signer_from_path(
&self,
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)
}
}
pub enum KeypairUrl {
Ask,
Filepath(String),

View File

@@ -24,7 +24,9 @@ impl std::fmt::Debug for DisplayError {
}
pub mod commitment;
pub mod fee_payer;
pub mod input_parsers;
pub mod input_validators;
pub mod keypair;
pub mod nonce;
pub mod offline;

47
clap-utils/src/nonce.rs Normal file
View File

@@ -0,0 +1,47 @@
use crate::{input_validators::*, offline::BLOCKHASH_ARG, ArgConstant};
use clap::{App, Arg};
pub const NONCE_ARG: ArgConstant<'static> = ArgConstant {
name: "nonce",
long: "nonce",
help: "Provide the nonce account to use when creating a nonced \n\
transaction. Nonced transactions are useful when a transaction \n\
requires a lengthy signing process. Learn more about nonced \n\
transactions at https://docs.solana.com/offline-signing/durable-nonce",
};
pub const NONCE_AUTHORITY_ARG: ArgConstant<'static> = ArgConstant {
name: "nonce_authority",
long: "nonce-authority",
help: "Provide the nonce authority keypair to use when signing a nonced transaction",
};
fn nonce_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(NONCE_ARG.name)
.long(NONCE_ARG.long)
.takes_value(true)
.value_name("PUBKEY")
.requires(BLOCKHASH_ARG.name)
.validator(is_valid_pubkey)
.help(NONCE_ARG.help)
}
pub fn nonce_authority_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(NONCE_AUTHORITY_ARG.name)
.long(NONCE_AUTHORITY_ARG.long)
.takes_value(true)
.value_name("KEYPAIR")
.validator(is_valid_signer)
.help(NONCE_AUTHORITY_ARG.help)
}
pub trait NonceArgs {
fn nonce_args(self) -> Self;
}
impl NonceArgs for App<'_, '_> {
fn nonce_args(self) -> Self {
self.arg(nonce_arg())
.arg(nonce_authority_arg().requires(NONCE_ARG.name))
}
}

View File

@@ -1,4 +1,5 @@
use crate::ArgConstant;
use crate::{input_validators::*, ArgConstant};
use clap::{App, Arg};
pub const BLOCKHASH_ARG: ArgConstant<'static> = ArgConstant {
name: "blockhash",
@@ -17,3 +18,43 @@ pub const SIGNER_ARG: ArgConstant<'static> = ArgConstant {
long: "signer",
help: "Provide a public-key/signature pair for the transaction",
};
pub fn blockhash_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(BLOCKHASH_ARG.name)
.long(BLOCKHASH_ARG.long)
.takes_value(true)
.value_name("BLOCKHASH")
.validator(is_hash)
.help(BLOCKHASH_ARG.help)
}
pub fn sign_only_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(SIGN_ONLY_ARG.name)
.long(SIGN_ONLY_ARG.long)
.takes_value(false)
.requires(BLOCKHASH_ARG.name)
.help(SIGN_ONLY_ARG.help)
}
fn signer_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(SIGNER_ARG.name)
.long(SIGNER_ARG.long)
.takes_value(true)
.value_name("PUBKEY=SIGNATURE")
.validator(is_pubkey_sig)
.requires(BLOCKHASH_ARG.name)
.multiple(true)
.help(SIGNER_ARG.help)
}
pub trait OfflineArgs {
fn offline_args(self) -> Self;
}
impl OfflineArgs for App<'_, '_> {
fn offline_args(self) -> Self {
self.arg(blockhash_arg())
.arg(sign_only_arg())
.arg(signer_arg())
}
}

View File

@@ -1,9 +1,9 @@
[package]
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
authors = ["Solana Maintainers <maintainers@solana.com>"]
edition = "2018"
name = "solana-cli-config"
description = "Blockchain, Rebuilt for Scale"
version = "1.3.1"
version = "1.2.33"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -11,9 +11,9 @@ homepage = "https://solana.com/"
[dependencies]
dirs = "2.0.2"
lazy_static = "1.4.0"
serde = "1.0.112"
serde = "1.0.110"
serde_derive = "1.0.103"
serde_yaml = "0.8.13"
serde_yaml = "0.8.12"
url = "2.1.1"
[package.metadata.docs.rs]

View File

@@ -1,6 +1,6 @@
// Wallet settings that can be configured for long-term use
use serde_derive::{Deserialize, Serialize};
use std::{collections::HashMap, io, path::Path};
use std::{collections::HashMap, io};
use url::Url;
lazy_static! {
@@ -17,7 +17,6 @@ pub struct Config {
pub json_rpc_url: String,
pub websocket_url: String,
pub keypair_path: String,
#[serde(default)]
pub address_labels: HashMap<String, String>,
}
@@ -35,17 +34,11 @@ impl Default for Config {
// `Config::compute_websocket_url(&json_rpc_url)`
let websocket_url = "".to_string();
let mut address_labels = HashMap::new();
address_labels.insert(
"11111111111111111111111111111111".to_string(),
"System Program".to_string(),
);
Self {
json_rpc_url,
websocket_url,
keypair_path,
address_labels,
address_labels: HashMap::new(),
}
}
}
@@ -75,24 +68,6 @@ impl Config {
}
ws_url.to_string()
}
pub fn import_address_labels<P>(&mut self, filename: P) -> Result<(), io::Error>
where
P: AsRef<Path>,
{
let imports: HashMap<String, String> = crate::load_config_file(filename)?;
for (address, label) in imports.into_iter() {
self.address_labels.insert(address, label);
}
Ok(())
}
pub fn export_address_labels<P>(&self, filename: P) -> Result<(), io::Error>
where
P: AsRef<Path>,
{
crate::save_config_file(&self.address_labels, filename)
}
}
#[cfg(test)]

28
cli-output/Cargo.toml Normal file
View File

@@ -0,0 +1,28 @@
[package]
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
edition = "2018"
name = "solana-cli-output"
description = "Blockchain, Rebuilt for Scale"
version = "1.2.33"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
[dependencies]
chrono = { version = "0.4.11", features = ["serde"] }
console = "0.10.1"
humantime = "2.0.0"
Inflector = "0.11.4"
indicatif = "0.14.0"
serde = "1.0.110"
serde_derive = "1.0.103"
serde_json = "1.0.53"
solana-clap-utils = { path = "../clap-utils", version = "1.2.33" }
solana-client = { path = "../client", version = "1.2.33" }
solana-sdk = { path = "../sdk", version = "1.2.33" }
solana-stake-program = { path = "../programs/stake", version = "1.2.33" }
solana-transaction-status = { path = "../transaction-status", version = "1.2.33" }
solana-vote-program = { path = "../programs/vote", version = "1.2.33" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,31 +1,29 @@
use crate::{
cli::build_balance_message,
display::{format_labeled_address, writeln_name_value},
};
use crate::display::{build_balance_message, writeln_name_value};
use chrono::{DateTime, NaiveDateTime, SecondsFormat, Utc};
use console::{style, Emoji};
use inflector::cases::titlecase::to_title_case;
use serde::Serialize;
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use solana_clap_utils::keypair::SignOnly;
use solana_client::rpc_response::{
RpcAccountBalance, RpcKeyedAccount, RpcSupply, RpcVoteAccountInfo,
};
use solana_sdk::{
clock::{self, Epoch, Slot, UnixTimestamp},
epoch_info::EpochInfo,
hash::Hash,
native_token::lamports_to_sol,
pubkey::Pubkey,
signature::Signature,
stake_history::StakeHistoryEntry,
transaction::Transaction,
};
use solana_stake_program::stake_state::{Authorized, Lockup};
use solana_vote_program::{
authorized_voters::AuthorizedVoters,
vote_state::{BlockTimestamp, Lockout},
};
use std::{
collections::{BTreeMap, HashMap},
fmt,
time::Duration,
};
use std::{collections::BTreeMap, fmt, str::FromStr, time::Duration};
static WARNING: Emoji = Emoji("⚠️", "!");
@@ -206,11 +204,6 @@ impl From<EpochInfo> for CliEpochInfo {
impl fmt::Display for CliEpochInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f)?;
writeln_name_value(
f,
"Block height:",
&self.epoch_info.block_height.to_string(),
)?;
writeln_name_value(f, "Slot:", &self.epoch_info.absolute_slot.to_string())?;
writeln_name_value(f, "Epoch:", &self.epoch_info.epoch.to_string())?;
let start_slot = self.epoch_info.absolute_slot - self.epoch_info.slot_index;
@@ -259,15 +252,6 @@ fn slot_to_human_time(slot: Slot) -> String {
.to_string()
}
#[derive(Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct CliValidatorsStakeByVersion {
pub current_validators: usize,
pub delinquent_validators: usize,
pub current_active_stake: u64,
pub delinquent_active_stake: u64,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CliValidators {
@@ -276,7 +260,6 @@ pub struct CliValidators {
pub total_deliquent_stake: u64,
pub current_validators: Vec<CliValidator>,
pub delinquent_validators: Vec<CliValidator>,
pub stake_by_version: BTreeMap<String, CliValidatorsStakeByVersion>,
#[serde(skip_serializing)]
pub use_lamports_unit: bool,
}
@@ -300,7 +283,7 @@ impl fmt::Display for CliValidators {
writeln!(
f,
"{} {:<44} {:<44} {:>3}% {:>8} {:>10} {:>10} {:>17} {}",
"{} {:<44} {:<44} {:>9}% {:>8} {:>10} {:>7} {}",
if delinquent {
WARNING.to_string()
} else {
@@ -312,12 +295,11 @@ impl fmt::Display for CliValidators {
non_zero_or_dash(validator.last_vote),
non_zero_or_dash(validator.root_slot),
validator.credits,
validator.version,
if validator.activated_stake > 0 {
format!(
"{} ({:.2}%)",
build_balance_message(validator.activated_stake, use_lamports_unit, true),
100. * validator.activated_stake as f64 / total_active_stake as f64,
100. * validator.activated_stake as f64 / total_active_stake as f64
)
} else {
"-".into()
@@ -353,41 +335,18 @@ impl fmt::Display for CliValidators {
),
)?;
}
writeln!(f)?;
writeln!(f, "{}", style("Stake By Version:").bold())?;
for (version, info) in self.stake_by_version.iter() {
writeln!(
f,
"{:<16} - {:3} current validators ({:>5.2}%){}",
version,
info.current_validators,
100. * info.current_active_stake as f64 / self.total_active_stake as f64,
if info.delinquent_validators > 0 {
format!(
", {:3} delinquent validators ({:>5.2}%)",
info.delinquent_validators,
100. * info.delinquent_active_stake as f64 / self.total_active_stake as f64
)
} else {
"".to_string()
},
)?;
}
writeln!(f)?;
writeln!(
f,
"{}",
style(format!(
" {:<44} {:<38} {} {} {} {:>10} {:^17} {}",
" {:<44} {:<44} {} {} {} {:>7} {}",
"Identity Pubkey",
"Vote Account Pubkey",
"Commission",
"Last Vote",
"Root Block",
"Credits",
"Version",
"Active Stake",
))
.bold()
@@ -424,19 +383,13 @@ pub struct CliValidator {
pub root_slot: u64,
pub credits: u64,
pub activated_stake: u64,
pub version: String,
}
impl CliValidator {
pub fn new(
vote_account: &RpcVoteAccountInfo,
current_epoch: Epoch,
version: String,
address_labels: &HashMap<String, String>,
) -> Self {
pub fn new(vote_account: &RpcVoteAccountInfo, current_epoch: Epoch) -> Self {
Self {
identity_pubkey: format_labeled_address(&vote_account.node_pubkey, address_labels),
vote_account_pubkey: format_labeled_address(&vote_account.vote_pubkey, address_labels),
identity_pubkey: vote_account.node_pubkey.to_string(),
vote_account_pubkey: vote_account.vote_pubkey.to_string(),
commission: vote_account.commission,
last_vote: vote_account.last_vote,
root_slot: vote_account.root_slot,
@@ -452,7 +405,6 @@ impl CliValidator {
})
.unwrap_or(0),
activated_stake: vote_account.activated_stake,
version,
}
}
}
@@ -569,25 +521,19 @@ impl fmt::Display for CliStakeState {
writeln!(f, "Withdraw Authority: {}", authorized.withdrawer)?;
Ok(())
}
fn show_lockup(f: &mut fmt::Formatter, lockup: Option<&CliLockup>) -> fmt::Result {
if let Some(lockup) = lockup {
if lockup.unix_timestamp != UnixTimestamp::default() {
writeln!(
f,
"Lockup Timestamp: {} (UnixTimestamp: {})",
DateTime::<Utc>::from_utc(
NaiveDateTime::from_timestamp(lockup.unix_timestamp, 0),
Utc
)
.to_rfc3339_opts(SecondsFormat::Secs, true),
lockup.unix_timestamp
)?;
}
if lockup.epoch != Epoch::default() {
writeln!(f, "Lockup Epoch: {}", lockup.epoch)?;
}
writeln!(f, "Lockup Custodian: {}", lockup.custodian)?;
}
fn show_lockup(f: &mut fmt::Formatter, lockup: &CliLockup) -> fmt::Result {
writeln!(
f,
"Lockup Timestamp: {} (UnixTimestamp: {})",
DateTime::<Utc>::from_utc(
NaiveDateTime::from_timestamp(lockup.unix_timestamp, 0),
Utc
)
.to_rfc3339_opts(SecondsFormat::Secs, true),
lockup.unix_timestamp
)?;
writeln!(f, "Lockup Epoch: {}", lockup.epoch)?;
writeln!(f, "Lockup Custodian: {}", lockup.custodian)?;
Ok(())
}
@@ -611,7 +557,7 @@ impl fmt::Display for CliStakeState {
CliStakeType::Initialized => {
writeln!(f, "Stake account is undelegated")?;
show_authorized(f, self.authorized.as_ref().unwrap())?;
show_lockup(f, self.lockup.as_ref())?;
show_lockup(f, self.lockup.as_ref().unwrap())?;
}
CliStakeType::Stake => {
let show_delegation = {
@@ -709,7 +655,7 @@ impl fmt::Display for CliStakeState {
writeln!(f, "Stake account is undelegated")?;
}
show_authorized(f, self.authorized.as_ref().unwrap())?;
show_lockup(f, self.lockup.as_ref())?;
show_lockup(f, self.lockup.as_ref().unwrap())?;
}
}
Ok(())
@@ -1145,3 +1091,149 @@ impl fmt::Display for CliFees {
Ok(())
}
}
pub fn return_signers(
tx: &Transaction,
output_format: &OutputFormat,
) -> Result<String, Box<dyn std::error::Error>> {
let verify_results = tx.verify_with_results();
let mut signers = Vec::new();
let mut absent = Vec::new();
let mut bad_sig = Vec::new();
tx.signatures
.iter()
.zip(tx.message.account_keys.iter())
.zip(verify_results.into_iter())
.for_each(|((sig, key), res)| {
if res {
signers.push(format!("{}={}", key, sig))
} else if *sig == Signature::default() {
absent.push(key.to_string());
} else {
bad_sig.push(key.to_string());
}
});
let cli_command = CliSignOnlyData {
blockhash: tx.message.recent_blockhash.to_string(),
signers,
absent,
bad_sig,
};
Ok(output_format.formatted_string(&cli_command))
}
pub fn parse_sign_only_reply_string(reply: &str) -> SignOnly {
let object: Value = serde_json::from_str(&reply).unwrap();
let blockhash_str = object.get("blockhash").unwrap().as_str().unwrap();
let blockhash = blockhash_str.parse::<Hash>().unwrap();
let mut present_signers: Vec<(Pubkey, Signature)> = Vec::new();
let signer_strings = object.get("signers");
if let Some(sig_strings) = signer_strings {
present_signers = sig_strings
.as_array()
.unwrap()
.iter()
.map(|signer_string| {
let mut signer = signer_string.as_str().unwrap().split('=');
let key = Pubkey::from_str(signer.next().unwrap()).unwrap();
let sig = Signature::from_str(signer.next().unwrap()).unwrap();
(key, sig)
})
.collect();
}
let mut absent_signers: Vec<Pubkey> = Vec::new();
let signer_strings = object.get("absent");
if let Some(sig_strings) = signer_strings {
absent_signers = sig_strings
.as_array()
.unwrap()
.iter()
.map(|val| {
let s = val.as_str().unwrap();
Pubkey::from_str(s).unwrap()
})
.collect();
}
let mut bad_signers: Vec<Pubkey> = Vec::new();
let signer_strings = object.get("badSig");
if let Some(sig_strings) = signer_strings {
bad_signers = sig_strings
.as_array()
.unwrap()
.iter()
.map(|val| {
let s = val.as_str().unwrap();
Pubkey::from_str(s).unwrap()
})
.collect();
}
SignOnly {
blockhash,
present_signers,
absent_signers,
bad_signers,
}
}
#[cfg(test)]
mod tests {
use super::*;
use solana_sdk::{
message::Message,
pubkey::Pubkey,
signature::{keypair_from_seed, NullSigner, Signature, Signer, SignerError},
system_instruction,
transaction::Transaction,
};
#[test]
fn test_return_signers() {
struct BadSigner {
pubkey: Pubkey,
}
impl BadSigner {
pub fn new(pubkey: Pubkey) -> Self {
Self { pubkey }
}
}
impl Signer for BadSigner {
fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
Ok(self.pubkey)
}
fn try_sign_message(&self, _message: &[u8]) -> Result<Signature, SignerError> {
Ok(Signature::new(&[1u8; 64]))
}
}
let present: Box<dyn Signer> = Box::new(keypair_from_seed(&[2u8; 32]).unwrap());
let absent: Box<dyn Signer> = Box::new(NullSigner::new(&Pubkey::new(&[3u8; 32])));
let bad: Box<dyn Signer> = Box::new(BadSigner::new(Pubkey::new(&[4u8; 32])));
let to = Pubkey::new(&[5u8; 32]);
let nonce = Pubkey::new(&[6u8; 32]);
let from = present.pubkey();
let fee_payer = absent.pubkey();
let nonce_auth = bad.pubkey();
let mut tx = Transaction::new_unsigned(Message::new_with_nonce(
vec![system_instruction::transfer(&from, &to, 42)],
Some(&fee_payer),
&nonce,
&nonce_auth,
));
let signers = vec![present.as_ref(), absent.as_ref(), bad.as_ref()];
let blockhash = Hash::new(&[7u8; 32]);
tx.try_partial_sign(&signers, blockhash).unwrap();
let res = return_signers(&tx, &OutputFormat::JsonCompact).unwrap();
let sign_only = parse_sign_only_reply_string(&res);
assert_eq!(sign_only.blockhash, blockhash);
assert_eq!(sign_only.present_signers[0].0, present.pubkey());
assert_eq!(sign_only.absent_signers[0], absent.pubkey());
assert_eq!(sign_only.bad_signers[0], bad.pubkey());
}
}

View File

@@ -1,4 +1,3 @@
use crate::cli::SettingType;
use console::style;
use indicatif::{ProgressBar, ProgressStyle};
use solana_sdk::{
@@ -6,7 +5,25 @@ use solana_sdk::{
transaction::Transaction,
};
use solana_transaction_status::UiTransactionStatusMeta;
use std::{collections::HashMap, fmt, io};
use std::{fmt, io};
pub fn build_balance_message(lamports: u64, use_lamports_unit: bool, show_unit: bool) -> String {
if use_lamports_unit {
let ess = if lamports == 1 { "" } else { "s" };
let unit = if show_unit {
format!(" lamport{}", ess)
} else {
"".to_string()
};
format!("{:?}{}", lamports, unit)
} else {
let sol = lamports_to_sol(lamports);
let sol_str = format!("{:.9}", sol);
let pretty_sol = sol_str.trim_end_matches('0').trim_end_matches('.');
let unit = if show_unit { " SOL" } else { "" };
format!("{}{}", pretty_sol, unit)
}
}
// Pretty print a "name value"
pub fn println_name_value(name: &str, value: &str) {
@@ -27,34 +44,6 @@ pub fn writeln_name_value(f: &mut fmt::Formatter, name: &str, value: &str) -> fm
writeln!(f, "{} {}", style(name).bold(), styled_value)
}
pub fn format_labeled_address(pubkey: &str, address_labels: &HashMap<String, String>) -> String {
let label = address_labels.get(pubkey);
match label {
Some(label) => format!(
"{:.31} ({:.4}..{})",
label,
pubkey,
pubkey.split_at(pubkey.len() - 4).1
),
None => pubkey.to_string(),
}
}
pub fn println_name_value_or(name: &str, value: &str, setting_type: SettingType) {
let description = match setting_type {
SettingType::Explicit => "",
SettingType::Computed => "(computed)",
SettingType::SystemDefault => "(default)",
};
println!(
"{} {} {}",
style(name).bold(),
style(value),
style(description).italic(),
);
}
pub fn println_signers(
blockhash: &Hash,
signers: &[String],
@@ -223,32 +212,3 @@ pub fn new_spinner_progress_bar() -> ProgressBar {
progress_bar.enable_steady_tick(100);
progress_bar
}
#[cfg(test)]
mod test {
use super::*;
use solana_sdk::pubkey::Pubkey;
#[test]
fn test_format_labeled_address() {
let pubkey = Pubkey::default().to_string();
let mut address_labels = HashMap::new();
assert_eq!(format_labeled_address(&pubkey, &address_labels), pubkey);
address_labels.insert(pubkey.to_string(), "Default Address".to_string());
assert_eq!(
&format_labeled_address(&pubkey, &address_labels),
"Default Address (1111..1111)"
);
address_labels.insert(
pubkey.to_string(),
"abcdefghijklmnopqrstuvwxyz1234567890".to_string(),
);
assert_eq!(
&format_labeled_address(&pubkey, &address_labels),
"abcdefghijklmnopqrstuvwxyz12345 (1111..1111)"
);
}
}

3
cli-output/src/lib.rs Normal file
View File

@@ -0,0 +1,3 @@
mod cli_output;
pub mod display;
pub use cli_output::*;

View File

@@ -1,9 +1,9 @@
[package]
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
authors = ["Solana Maintainers <maintainers@solana.com>"]
edition = "2018"
name = "solana-cli"
description = "Blockchain, Rebuilt for Scale"
version = "1.3.1"
version = "1.2.33"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
@@ -14,42 +14,42 @@ bs58 = "0.3.1"
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.11.3"
ctrlc = { version = "3.1.4", features = ["termination"] }
console = "0.10.1"
dirs = "2.0.2"
log = "0.4.8"
Inflector = "0.11.4"
indicatif = "0.15.0"
humantime = "2.0.1"
indicatif = "0.14.0"
humantime = "2.0.0"
num-traits = "0.2"
pretty-hex = "0.1.1"
reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde = "1.0.112"
reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde = "1.0.110"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "1.3.1" }
solana-budget-program = { path = "../programs/budget", version = "1.3.1" }
solana-clap-utils = { path = "../clap-utils", version = "1.3.1" }
solana-cli-config = { path = "../cli-config", version = "1.3.1" }
solana-client = { path = "../client", version = "1.3.1" }
solana-config-program = { path = "../programs/config", version = "1.3.1" }
solana-faucet = { path = "../faucet", version = "1.3.1" }
solana-logger = { path = "../logger", version = "1.3.1" }
solana-net-utils = { path = "../net-utils", version = "1.3.1" }
solana-remote-wallet = { path = "../remote-wallet", version = "1.3.1" }
solana-runtime = { path = "../runtime", version = "1.3.1" }
solana-sdk = { path = "../sdk", version = "1.3.1" }
solana-stake-program = { path = "../programs/stake", version = "1.3.1" }
solana-transaction-status = { path = "../transaction-status", version = "1.3.1" }
solana-version = { path = "../version", version = "1.3.1" }
solana-vote-program = { path = "../programs/vote", version = "1.3.1" }
solana-vote-signer = { path = "../vote-signer", version = "1.3.1" }
thiserror = "1.0.20"
serde_json = "1.0.53"
solana-account-decoder = { path = "../account-decoder", version = "1.2.33" }
solana-budget-program = { path = "../programs/budget", version = "1.2.33" }
solana-clap-utils = { path = "../clap-utils", version = "1.2.33" }
solana-cli-config = { path = "../cli-config", version = "1.2.33" }
solana-cli-output = { path = "../cli-output", version = "1.2.33" }
solana-client = { path = "../client", version = "1.2.33" }
solana-config-program = { path = "../programs/config", version = "1.2.33" }
solana-faucet = { path = "../faucet", version = "1.2.33" }
solana-logger = { path = "../logger", version = "1.2.33" }
solana-net-utils = { path = "../net-utils", version = "1.2.33" }
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.33" }
solana-sdk = { path = "../sdk", version = "1.2.33" }
solana-stake-program = { path = "../programs/stake", version = "1.2.33" }
solana-transaction-status = { path = "../transaction-status", version = "1.2.33" }
solana-version = { path = "../version", version = "1.2.33" }
solana-vote-program = { path = "../programs/vote", version = "1.2.33" }
solana-vote-signer = { path = "../vote-signer", version = "1.2.33" }
thiserror = "1.0.19"
url = "2.1.1"
[dev-dependencies]
solana-core = { path = "../core", version = "1.3.1" }
solana-budget-program = { path = "../programs/budget", version = "1.3.1" }
solana-core = { path = "../core", version = "1.2.33" }
solana-budget-program = { path = "../programs/budget", version = "1.2.33" }
tempfile = "3.1.0"
[[bin]]

View File

@@ -4,8 +4,7 @@ use solana_client::{
rpc_client::RpcClient,
};
use solana_sdk::{
commitment_config::CommitmentConfig, fee_calculator::FeeCalculator, message::Message,
native_token::lamports_to_sol, pubkey::Pubkey,
fee_calculator::FeeCalculator, message::Message, native_token::lamports_to_sol, pubkey::Pubkey,
};
pub fn check_account_for_fee(
@@ -17,46 +16,14 @@ pub fn check_account_for_fee(
check_account_for_multiple_fees(rpc_client, account_pubkey, fee_calculator, &[message])
}
pub fn check_account_for_fee_with_commitment(
rpc_client: &RpcClient,
account_pubkey: &Pubkey,
fee_calculator: &FeeCalculator,
message: &Message,
commitment: CommitmentConfig,
) -> Result<(), CliError> {
check_account_for_multiple_fees_with_commitment(
rpc_client,
account_pubkey,
fee_calculator,
&[message],
commitment,
)
}
pub fn check_account_for_multiple_fees(
rpc_client: &RpcClient,
account_pubkey: &Pubkey,
fee_calculator: &FeeCalculator,
messages: &[&Message],
) -> Result<(), CliError> {
check_account_for_multiple_fees_with_commitment(
rpc_client,
account_pubkey,
fee_calculator,
messages,
CommitmentConfig::default(),
)
}
pub fn check_account_for_multiple_fees_with_commitment(
rpc_client: &RpcClient,
account_pubkey: &Pubkey,
fee_calculator: &FeeCalculator,
messages: &[&Message],
commitment: CommitmentConfig,
) -> Result<(), CliError> {
let fee = calculate_fee(fee_calculator, messages);
if !check_account_for_balance_with_commitment(rpc_client, account_pubkey, fee, commitment)
if !check_account_for_balance(rpc_client, account_pubkey, fee)
.map_err(Into::<ClientError>::into)?
{
return Err(CliError::InsufficientFundsForFee(lamports_to_sol(fee)));
@@ -76,23 +43,7 @@ pub fn check_account_for_balance(
account_pubkey: &Pubkey,
balance: u64,
) -> ClientResult<bool> {
check_account_for_balance_with_commitment(
rpc_client,
account_pubkey,
balance,
CommitmentConfig::default(),
)
}
pub fn check_account_for_balance_with_commitment(
rpc_client: &RpcClient,
account_pubkey: &Pubkey,
balance: u64,
commitment: CommitmentConfig,
) -> ClientResult<bool> {
let lamports = rpc_client
.get_balance_with_commitment(account_pubkey, commitment)?
.value;
let lamports = rpc_client.get_balance(account_pubkey)?;
if lamports != 0 && lamports >= balance {
return Ok(true);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,22 @@
use crate::{
cli::{CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult},
cli_output::*,
display::{format_labeled_address, new_spinner_progress_bar, println_name_value},
spend_utils::{resolve_spend_tx_and_check_account_balance, SpendAmount},
};
use clap::{value_t, value_t_or_exit, App, AppSettings, Arg, ArgMatches, SubCommand};
use console::{style, Emoji};
use solana_clap_utils::{
commitment::commitment_arg, input_parsers::*, input_validators::*, keypair::signer_from_path,
commitment::{commitment_arg, COMMITMENT_ARG},
input_parsers::*,
input_validators::*,
keypair::DefaultSigner,
};
use solana_cli_output::{
display::{new_spinner_progress_bar, println_name_value},
*,
};
use solana_client::{
pubsub_client::{PubsubClient, SlotInfoMessage},
rpc_client::RpcClient,
rpc_client::{GetConfirmedSignaturesForAddress2Config, RpcClient},
rpc_config::{RpcLargestAccountsConfig, RpcLargestAccountsFilter},
};
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
@@ -33,7 +38,7 @@ use solana_sdk::{
transaction::Transaction,
};
use std::{
collections::{BTreeMap, HashMap, VecDeque},
collections::{HashMap, VecDeque},
net::SocketAddr,
sync::{
atomic::{AtomicBool, Ordering},
@@ -115,10 +120,6 @@ impl ClusterQuerySubCommands for App<'_, '_> {
.alias("get-slot")
.arg(commitment_arg()),
)
.subcommand(
SubCommand::with_name("block-height").about("Get current block height")
.arg(commitment_arg()),
)
.subcommand(
SubCommand::with_name("epoch").about("Get current epoch")
.arg(commitment_arg()),
@@ -292,11 +293,13 @@ pub fn parse_catchup(
) -> Result<CliCommandInfo, CliError> {
let node_pubkey = pubkey_of_signer(matches, "node_pubkey", wallet_manager)?.unwrap();
let node_json_rpc_url = value_t!(matches, "node_json_rpc_url", String).ok();
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
let follow = matches.is_present("follow");
Ok(CliCommandInfo {
command: CliCommand::Catchup {
node_pubkey,
node_json_rpc_url,
commitment_config,
follow,
},
signers: vec![],
@@ -305,7 +308,7 @@ pub fn parse_catchup(
pub fn parse_cluster_ping(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let lamports = value_t_or_exit!(matches, "lamports", u64);
@@ -316,19 +319,16 @@ pub fn parse_cluster_ping(
None
};
let timeout = Duration::from_secs(value_t_or_exit!(matches, "timeout", u64));
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
Ok(CliCommandInfo {
command: CliCommand::Ping {
lamports,
interval,
count,
timeout,
commitment_config,
},
signers: vec![signer_from_path(
matches,
default_signer_path,
"keypair",
wallet_manager,
)?],
signers: vec![default_signer.signer_from_path(matches, wallet_manager)?],
})
}
@@ -340,35 +340,32 @@ pub fn parse_get_block_time(matches: &ArgMatches<'_>) -> Result<CliCommandInfo,
})
}
pub fn parse_get_epoch(_matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
pub fn parse_get_epoch_info(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
Ok(CliCommandInfo {
command: CliCommand::GetEpoch,
command: CliCommand::GetEpochInfo { commitment_config },
signers: vec![],
})
}
pub fn parse_get_epoch_info(_matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
pub fn parse_get_slot(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
Ok(CliCommandInfo {
command: CliCommand::GetEpochInfo,
command: CliCommand::GetSlot { commitment_config },
signers: vec![],
})
}
pub fn parse_get_slot(_matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
pub fn parse_get_epoch(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
Ok(CliCommandInfo {
command: CliCommand::GetSlot,
signers: vec![],
})
}
pub fn parse_get_block_height(_matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
Ok(CliCommandInfo {
command: CliCommand::GetBlockHeight,
command: CliCommand::GetEpoch { commitment_config },
signers: vec![],
})
}
pub fn parse_largest_accounts(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
let filter = if matches.is_present("circulating") {
Some(RpcLargestAccountsFilter::Circulating)
} else if matches.is_present("non_circulating") {
@@ -377,29 +374,38 @@ pub fn parse_largest_accounts(matches: &ArgMatches<'_>) -> Result<CliCommandInfo
None
};
Ok(CliCommandInfo {
command: CliCommand::LargestAccounts { filter },
command: CliCommand::LargestAccounts {
commitment_config,
filter,
},
signers: vec![],
})
}
pub fn parse_supply(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
let print_accounts = matches.is_present("print_accounts");
Ok(CliCommandInfo {
command: CliCommand::Supply { print_accounts },
command: CliCommand::Supply {
commitment_config,
print_accounts,
},
signers: vec![],
})
}
pub fn parse_total_supply(_matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
pub fn parse_total_supply(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
Ok(CliCommandInfo {
command: CliCommand::TotalSupply,
command: CliCommand::TotalSupply { commitment_config },
signers: vec![],
})
}
pub fn parse_get_transaction_count(_matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
pub fn parse_get_transaction_count(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
Ok(CliCommandInfo {
command: CliCommand::GetTransactionCount,
command: CliCommand::GetTransactionCount { commitment_config },
signers: vec![],
})
}
@@ -423,9 +429,13 @@ pub fn parse_show_stakes(
pub fn parse_show_validators(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let use_lamports_unit = matches.is_present("lamports");
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
Ok(CliCommandInfo {
command: CliCommand::ShowValidators { use_lamports_unit },
command: CliCommand::ShowValidators {
use_lamports_unit,
commitment_config,
},
signers: vec![],
})
}
@@ -444,12 +454,21 @@ pub fn parse_transaction_history(
),
None => None,
};
let until = match matches.value_of("until") {
Some(signature) => Some(
signature
.parse()
.map_err(|err| CliError::BadParameter(format!("Invalid signature: {}", err)))?,
),
None => None,
};
let limit = value_t_or_exit!(matches, "limit", usize);
Ok(CliCommandInfo {
command: CliCommand::TransactionHistory {
address,
before,
until,
limit,
},
signers: vec![],
@@ -458,9 +477,9 @@ pub fn parse_transaction_history(
pub fn process_catchup(
rpc_client: &RpcClient,
config: &CliConfig,
node_pubkey: &Pubkey,
node_json_rpc_url: &Option<String>,
commitment_config: CommitmentConfig,
follow: bool,
) -> ProcessResult {
let sleep_interval = 5;
@@ -509,8 +528,8 @@ pub fn process_catchup(
let mut previous_rpc_slot = std::u64::MAX;
let mut previous_slot_distance = 0;
loop {
let rpc_slot = rpc_client.get_slot_with_commitment(config.commitment)?;
let node_slot = node_client.get_slot_with_commitment(config.commitment)?;
let rpc_slot = rpc_client.get_slot_with_commitment(commitment_config)?;
let node_slot = node_client.get_slot_with_commitment(commitment_config)?;
if !follow && node_slot > std::cmp::min(previous_rpc_slot, rpc_slot) {
progress_bar.finish_and_clear();
return Ok(format!(
@@ -643,14 +662,13 @@ pub fn process_get_block_time(
Ok(config.output_format.formatted_string(&block_time))
}
pub fn process_get_epoch(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
let epoch_info = rpc_client.get_epoch_info_with_commitment(config.commitment)?;
Ok(epoch_info.epoch.to_string())
}
pub fn process_get_epoch_info(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
pub fn process_get_epoch_info(
rpc_client: &RpcClient,
config: &CliConfig,
commitment_config: CommitmentConfig,
) -> ProcessResult {
let epoch_info: CliEpochInfo = rpc_client
.get_epoch_info_with_commitment(config.commitment)?
.get_epoch_info_with_commitment(commitment_config.clone())?
.into();
Ok(config.output_format.formatted_string(&epoch_info))
}
@@ -660,16 +678,20 @@ pub fn process_get_genesis_hash(rpc_client: &RpcClient) -> ProcessResult {
Ok(genesis_hash.to_string())
}
pub fn process_get_slot(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
let slot = rpc_client.get_slot_with_commitment(config.commitment)?;
pub fn process_get_slot(
rpc_client: &RpcClient,
commitment_config: CommitmentConfig,
) -> ProcessResult {
let slot = rpc_client.get_slot_with_commitment(commitment_config.clone())?;
Ok(slot.to_string())
}
pub fn process_get_block_height(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
let epoch_info: CliEpochInfo = rpc_client
.get_epoch_info_with_commitment(config.commitment)?
.into();
Ok(epoch_info.epoch_info.block_height.to_string())
pub fn process_get_epoch(
rpc_client: &RpcClient,
commitment_config: CommitmentConfig,
) -> ProcessResult {
let epoch_info = rpc_client.get_epoch_info_with_commitment(commitment_config.clone())?;
Ok(epoch_info.epoch.to_string())
}
pub fn parse_show_block_production(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
@@ -755,12 +777,11 @@ pub fn process_show_block_production(
let leader_schedule = leader_schedule.unwrap();
let mut leader_per_slot_index = Vec::new();
leader_per_slot_index.resize(total_slots, "?".to_string());
leader_per_slot_index.resize(total_slots, "?");
for (pubkey, leader_slots) in leader_schedule.iter() {
let pubkey = format_labeled_address(pubkey, &config.address_labels);
for slot_index in leader_slots.iter() {
if *slot_index >= start_slot_index && *slot_index <= end_slot_index {
leader_per_slot_index[*slot_index - start_slot_index] = pubkey.clone();
leader_per_slot_index[*slot_index - start_slot_index] = pubkey;
}
}
}
@@ -837,11 +858,12 @@ pub fn process_show_block_production(
pub fn process_largest_accounts(
rpc_client: &RpcClient,
config: &CliConfig,
commitment_config: CommitmentConfig,
filter: Option<RpcLargestAccountsFilter>,
) -> ProcessResult {
let accounts = rpc_client
.get_largest_accounts_with_config(RpcLargestAccountsConfig {
commitment: Some(config.commitment),
commitment: Some(commitment_config),
filter,
})?
.value;
@@ -852,21 +874,29 @@ pub fn process_largest_accounts(
pub fn process_supply(
rpc_client: &RpcClient,
config: &CliConfig,
commitment_config: CommitmentConfig,
print_accounts: bool,
) -> ProcessResult {
let supply_response = rpc_client.supply_with_commitment(config.commitment)?;
let supply_response = rpc_client.supply_with_commitment(commitment_config.clone())?;
let mut supply: CliSupply = supply_response.value.into();
supply.print_accounts = print_accounts;
Ok(config.output_format.formatted_string(&supply))
}
pub fn process_total_supply(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
let total_supply = rpc_client.total_supply_with_commitment(config.commitment)?;
pub fn process_total_supply(
rpc_client: &RpcClient,
commitment_config: CommitmentConfig,
) -> ProcessResult {
let total_supply = rpc_client.total_supply_with_commitment(commitment_config.clone())?;
Ok(format!("{} SOL", lamports_to_sol(total_supply)))
}
pub fn process_get_transaction_count(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
let transaction_count = rpc_client.get_transaction_count_with_commitment(config.commitment)?;
pub fn process_get_transaction_count(
rpc_client: &RpcClient,
commitment_config: CommitmentConfig,
) -> ProcessResult {
let transaction_count =
rpc_client.get_transaction_count_with_commitment(commitment_config.clone())?;
Ok(transaction_count.to_string())
}
@@ -877,6 +907,7 @@ pub fn process_ping(
interval: &Duration,
count: &Option<u64>,
timeout: &Duration,
commitment_config: CommitmentConfig,
) -> ProcessResult {
println_name_value("Source Account:", &config.signers[0].pubkey().to_string());
println!();
@@ -922,7 +953,6 @@ pub fn process_ping(
&fee_calculator,
&config.signers[0].pubkey(),
build_message,
config.commitment,
)?;
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, blockhash)?;
@@ -931,8 +961,10 @@ pub fn process_ping(
Ok(signature) => {
let transaction_sent = Instant::now();
loop {
let signature_status = rpc_client
.get_signature_status_with_commitment(&signature, config.commitment)?;
let signature_status = rpc_client.get_signature_status_with_commitment(
&signature,
commitment_config.clone(),
)?;
let elapsed_time = Instant::now().duration_since(transaction_sent);
if let Some(transaction_status) = signature_status {
match transaction_status {
@@ -1107,7 +1139,7 @@ pub fn process_live_slots(url: &str) -> ProcessResult {
Ok("".to_string())
}
pub fn process_show_gossip(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
pub fn process_show_gossip(rpc_client: &RpcClient) -> ProcessResult {
let cluster_nodes = rpc_client.get_cluster_nodes()?;
fn format_port(addr: Option<SocketAddr>) -> String {
@@ -1116,27 +1148,26 @@ pub fn process_show_gossip(rpc_client: &RpcClient, config: &CliConfig) -> Proces
}
let s: Vec<_> = cluster_nodes
.into_iter()
.iter()
.map(|node| {
format!(
"{:15} | {:44} | {:6} | {:5} | {:5} | {}",
"{:15} | {:44} | {:6} | {:5} | {:5}",
node.gossip
.map(|addr| addr.ip().to_string())
.unwrap_or_else(|| "none".to_string()),
format_labeled_address(&node.pubkey, &config.address_labels),
node.pubkey,
format_port(node.gossip),
format_port(node.tpu),
format_port(node.rpc),
node.version.unwrap_or_else(|| "unknown".to_string()),
)
})
.collect();
Ok(format!(
"IP Address | Node identifier \
| Gossip | TPU | RPC | Version\n\
| Gossip | TPU | RPC\n\
----------------+----------------------------------------------+\
--------+-------+-------+----------------\n\
--------+-------+-------\n\
{}\n\
Nodes: {}",
s.join("\n"),
@@ -1158,14 +1189,10 @@ pub fn process_show_stakes(
let all_stake_accounts = rpc_client.get_program_accounts(&solana_stake_program::id())?;
let stake_history_account = rpc_client.get_account(&stake_history::id())?;
progress_bar.finish_and_clear();
let clock_account = rpc_client.get_account(&sysvar::clock::id())?;
let stake_history = StakeHistory::from_account(&stake_history_account).ok_or_else(|| {
CliError::RpcRequestError("Failed to deserialize stake history".to_string())
})?;
let clock: Clock = Sysvar::from_account(&clock_account).ok_or_else(|| {
CliError::RpcRequestError("Failed to deserialize clock sysvar".to_string())
})?;
let mut stake_accounts: Vec<CliKeyedStakeState> = vec![];
for (stake_pubkey, stake_account) in all_stake_accounts {
@@ -1180,7 +1207,6 @@ pub fn process_show_stakes(
&stake_state,
use_lamports_unit,
&stake_history,
&clock,
),
});
}
@@ -1198,7 +1224,6 @@ pub fn process_show_stakes(
&stake_state,
use_lamports_unit,
&stake_history,
&clock,
),
});
}
@@ -1216,21 +1241,10 @@ pub fn process_show_validators(
rpc_client: &RpcClient,
config: &CliConfig,
use_lamports_unit: bool,
commitment_config: CommitmentConfig,
) -> ProcessResult {
let epoch_info = rpc_client.get_epoch_info_with_commitment(config.commitment)?;
let vote_accounts = rpc_client.get_vote_accounts_with_commitment(config.commitment)?;
let mut node_version = HashMap::new();
let unknown_version = "unknown".to_string();
for contact_info in rpc_client.get_cluster_nodes()? {
node_version.insert(
contact_info.pubkey,
contact_info
.version
.unwrap_or_else(|| unknown_version.clone()),
);
}
let epoch_info = rpc_client.get_epoch_info_with_commitment(commitment_config)?;
let vote_accounts = rpc_client.get_vote_accounts_with_commitment(commitment_config)?;
let total_active_stake = vote_accounts
.current
.iter()
@@ -1249,58 +1263,21 @@ pub fn process_show_validators(
current.sort_by(|a, b| b.activated_stake.cmp(&a.activated_stake));
let current_validators: Vec<CliValidator> = current
.iter()
.map(|vote_account| {
CliValidator::new(
vote_account,
epoch_info.epoch,
node_version
.get(&vote_account.node_pubkey)
.unwrap_or(&unknown_version)
.clone(),
&config.address_labels,
)
})
.map(|vote_account| CliValidator::new(vote_account, epoch_info.epoch))
.collect();
let mut delinquent = vote_accounts.delinquent;
delinquent.sort_by(|a, b| b.activated_stake.cmp(&a.activated_stake));
let delinquent_validators: Vec<CliValidator> = delinquent
.iter()
.map(|vote_account| {
CliValidator::new(
vote_account,
epoch_info.epoch,
node_version
.get(&vote_account.node_pubkey)
.unwrap_or(&unknown_version)
.clone(),
&config.address_labels,
)
})
.map(|vote_account| CliValidator::new(vote_account, epoch_info.epoch))
.collect();
let mut stake_by_version: BTreeMap<_, CliValidatorsStakeByVersion> = BTreeMap::new();
for validator in current_validators.iter() {
let mut entry = stake_by_version
.entry(validator.version.clone())
.or_default();
entry.current_validators += 1;
entry.current_active_stake += validator.activated_stake;
}
for validator in delinquent_validators.iter() {
let mut entry = stake_by_version
.entry(validator.version.clone())
.or_default();
entry.delinquent_validators += 1;
entry.delinquent_active_stake += validator.activated_stake;
}
let cli_validators = CliValidators {
total_active_stake,
total_current_stake,
total_deliquent_stake,
current_validators,
delinquent_validators,
stake_by_version,
use_lamports_unit,
};
Ok(config.output_format.formatted_string(&cli_validators))
@@ -1311,12 +1288,16 @@ pub fn process_transaction_history(
config: &CliConfig,
address: &Pubkey,
before: Option<Signature>,
until: Option<Signature>,
limit: usize,
) -> ProcessResult {
let results = rpc_client.get_confirmed_signatures_for_address2_with_config(
address,
before,
Some(limit),
GetConfirmedSignaturesForAddress2Config {
before,
until,
limit: Some(limit),
},
)?;
let transactions_found = format!("{} transactions found", results.len());
@@ -1358,12 +1339,16 @@ 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 {
path: default_keypair_file,
arg_name: String::new(),
};
let test_cluster_version = test_commands
.clone()
.get_matches_from(vec!["test", "cluster-date"]);
assert_eq!(
parse_command(&test_cluster_version, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_cluster_version, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::ClusterDate,
signers: vec![],
@@ -1374,7 +1359,7 @@ mod tests {
.clone()
.get_matches_from(vec!["test", "cluster-version"]);
assert_eq!(
parse_command(&test_cluster_version, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_cluster_version, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::ClusterVersion,
signers: vec![],
@@ -1383,7 +1368,7 @@ mod tests {
let test_fees = test_commands.clone().get_matches_from(vec!["test", "fees"]);
assert_eq!(
parse_command(&test_fees, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_fees, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::Fees,
signers: vec![],
@@ -1396,31 +1381,22 @@ mod tests {
.clone()
.get_matches_from(vec!["test", "block-time", &slot.to_string()]);
assert_eq!(
parse_command(&test_get_block_time, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_get_block_time, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetBlockTime { slot: Some(slot) },
signers: vec![],
}
);
let test_get_epoch = test_commands
.clone()
.get_matches_from(vec!["test", "epoch"]);
assert_eq!(
parse_command(&test_get_epoch, &default_keypair_file, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetEpoch,
signers: vec![],
}
);
let test_get_epoch_info = test_commands
.clone()
.get_matches_from(vec!["test", "epoch-info"]);
assert_eq!(
parse_command(&test_get_epoch_info, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_get_epoch_info, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetEpochInfo,
command: CliCommand::GetEpochInfo {
commitment_config: CommitmentConfig::recent(),
},
signers: vec![],
}
);
@@ -1429,7 +1405,7 @@ mod tests {
.clone()
.get_matches_from(vec!["test", "genesis-hash"]);
assert_eq!(
parse_command(&test_get_genesis_hash, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_get_genesis_hash, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetGenesisHash,
signers: vec![],
@@ -1438,9 +1414,24 @@ mod tests {
let test_get_slot = test_commands.clone().get_matches_from(vec!["test", "slot"]);
assert_eq!(
parse_command(&test_get_slot, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_get_slot, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetSlot,
command: CliCommand::GetSlot {
commitment_config: CommitmentConfig::recent(),
},
signers: vec![],
}
);
let test_get_epoch = test_commands
.clone()
.get_matches_from(vec!["test", "epoch"]);
assert_eq!(
parse_command(&test_get_epoch, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetEpoch {
commitment_config: CommitmentConfig::recent(),
},
signers: vec![],
}
);
@@ -1449,9 +1440,11 @@ mod tests {
.clone()
.get_matches_from(vec!["test", "total-supply"]);
assert_eq!(
parse_command(&test_total_supply, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_total_supply, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::TotalSupply,
command: CliCommand::TotalSupply {
commitment_config: CommitmentConfig::recent(),
},
signers: vec![],
}
);
@@ -1460,9 +1453,11 @@ mod tests {
.clone()
.get_matches_from(vec!["test", "transaction-count"]);
assert_eq!(
parse_command(&test_transaction_count, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_transaction_count, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetTransactionCount,
command: CliCommand::GetTransactionCount {
commitment_config: CommitmentConfig::recent(),
},
signers: vec![],
}
);
@@ -1480,13 +1475,14 @@ mod tests {
"max",
]);
assert_eq!(
parse_command(&test_ping, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_ping, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::Ping {
lamports: 1,
interval: Duration::from_secs(1),
count: Some(2),
timeout: Duration::from_secs(3),
commitment_config: CommitmentConfig::max(),
},
signers: vec![default_keypair.into()],
}

View File

@@ -18,16 +18,12 @@ macro_rules! pubkey {
};
}
#[macro_use]
extern crate serde_derive;
pub mod checks;
pub mod cli;
pub mod cli_output;
pub mod cluster_query;
pub mod display;
pub mod nonce;
pub mod offline;
pub mod spend_utils;
pub mod stake;
pub mod test_utils;

View File

@@ -1,43 +1,41 @@
use clap::{
crate_description, crate_name, value_t_or_exit, AppSettings, Arg, ArgGroup, ArgMatches,
SubCommand,
};
use clap::{crate_description, crate_name, AppSettings, Arg, ArgGroup, ArgMatches, SubCommand};
use console::style;
use solana_clap_utils::{
commitment::COMMITMENT_ARG, input_parsers::commitment_of, input_validators::is_url,
keypair::SKIP_SEED_PHRASE_VALIDATION_ARG, DisplayError,
input_validators::is_url,
keypair::{CliSigners, DefaultSigner, SKIP_SEED_PHRASE_VALIDATION_ARG},
DisplayError,
};
use solana_cli::{
cli::{
app, parse_command, process_command, CliCommandInfo, CliConfig, CliSigners,
DEFAULT_RPC_TIMEOUT_SECONDS,
},
cli_output::OutputFormat,
display::{println_name_value, println_name_value_or},
use solana_cli::cli::{
app, parse_command, process_command, CliCommandInfo, CliConfig, SettingType,
};
use solana_cli_config::{Config, CONFIG_FILE};
use solana_client::rpc_config::RpcSendTransactionConfig;
use solana_cli_output::{display::println_name_value, OutputFormat};
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use std::{collections::HashMap, error, path::PathBuf, sync::Arc, time::Duration};
use std::{error, sync::Arc};
pub fn println_name_value_or(name: &str, value: &str, setting_type: SettingType) {
let description = match setting_type {
SettingType::Explicit => "",
SettingType::Computed => "(computed)",
SettingType::SystemDefault => "(default)",
};
println!(
"{} {} {}",
style(name).bold(),
style(value),
style(description).italic(),
);
}
fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error>> {
let parse_args = match matches.subcommand() {
("config", Some(matches)) => {
let config_file = match matches.value_of("config_file") {
None => {
println!(
"{} Either provide the `--config` arg or ensure home directory exists to use the default config location",
style("No config file found.").bold()
);
return Ok(false);
}
Some(config_file) => config_file,
};
let mut config = Config::load(config_file).unwrap_or_default();
("config", Some(matches)) => match matches.subcommand() {
("get", Some(subcommand_matches)) => {
if let Some(config_file) = matches.value_of("config_file") {
let config = Config::load(config_file).unwrap_or_default();
match matches.subcommand() {
("get", Some(subcommand_matches)) => {
let (url_setting_type, json_rpc_url) =
CliConfig::compute_json_rpc_url_setting("", &config.json_rpc_url);
let (ws_setting_type, websocket_url) = CliConfig::compute_websocket_url_setting(
@@ -63,8 +61,17 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
println_name_value_or("WebSocket URL:", &websocket_url, ws_setting_type);
println_name_value_or("Keypair Path:", &keypair_path, keypair_setting_type);
}
} else {
println!(
"{} Either provide the `--config` arg or ensure home directory exists to use the default config location",
style("No config file found.").bold()
);
}
("set", Some(subcommand_matches)) => {
false
}
("set", Some(subcommand_matches)) => {
if let Some(config_file) = matches.value_of("config_file") {
let mut config = Config::load(config_file).unwrap_or_default();
if let Some(url) = subcommand_matches.value_of("json_rpc_url") {
config.json_rpc_url = url.to_string();
// Revert to a computed `websocket_url` value when `json_rpc_url` is
@@ -77,7 +84,6 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
if let Some(keypair) = subcommand_matches.value_of("keypair") {
config.keypair_path = keypair.to_string();
}
config.save(config_file)?;
let (url_setting_type, json_rpc_url) =
@@ -95,22 +101,16 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
println_name_value_or("RPC URL:", &json_rpc_url, url_setting_type);
println_name_value_or("WebSocket URL:", &websocket_url, ws_setting_type);
println_name_value_or("Keypair Path:", &keypair_path, keypair_setting_type);
} else {
println!(
"{} Either provide the `--config` arg or ensure home directory exists to use the default config location",
style("No config file found.").bold()
);
}
("import-address-labels", Some(subcommand_matches)) => {
let filename = value_t_or_exit!(subcommand_matches, "filename", PathBuf);
config.import_address_labels(&filename)?;
config.save(config_file)?;
println!("Address labels imported from {:?}", filename);
}
("export-address-labels", Some(subcommand_matches)) => {
let filename = value_t_or_exit!(subcommand_matches, "filename", PathBuf);
config.export_address_labels(&filename)?;
println!("Address labels exported to {:?}", filename);
}
_ => unreachable!(),
false
}
false
}
_ => unreachable!(),
},
_ => true,
};
Ok(parse_args)
@@ -129,23 +129,25 @@ pub fn parse_args<'a>(
matches.value_of("json_rpc_url").unwrap_or(""),
&config.json_rpc_url,
);
let rpc_timeout = value_t_or_exit!(matches, "rpc_timeout", u64);
let rpc_timeout = Duration::from_secs(rpc_timeout);
let (_, websocket_url) = CliConfig::compute_websocket_url_setting(
matches.value_of("websocket_url").unwrap_or(""),
&config.websocket_url,
matches.value_of("json_rpc_url").unwrap_or(""),
&config.json_rpc_url,
);
let default_signer_arg_name = "keypair".to_string();
let (_, default_signer_path) = CliConfig::compute_keypair_path_setting(
matches.value_of("keypair").unwrap_or(""),
matches.value_of(&default_signer_arg_name).unwrap_or(""),
&config.keypair_path,
);
let default_signer = DefaultSigner {
arg_name: default_signer_arg_name,
path: default_signer_path.clone(),
};
let CliCommandInfo { command, signers } =
parse_command(&matches, &default_signer_path, &mut wallet_manager)?;
parse_command(&matches, &default_signer, &mut wallet_manager)?;
let output_format = matches
.value_of("output_format")
@@ -156,18 +158,6 @@ pub fn parse_args<'a>(
})
.unwrap_or(OutputFormat::Display);
let commitment = matches
.subcommand_name()
.and_then(|name| matches.subcommand_matches(name))
.and_then(|sub_matches| commitment_of(sub_matches, COMMITMENT_ARG.long))
.unwrap_or_default();
let address_labels = if matches.is_present("no_address_labels") {
HashMap::new()
} else {
config.address_labels
};
Ok((
CliConfig {
command,
@@ -176,12 +166,8 @@ pub fn parse_args<'a>(
signers: vec![],
keypair_path: default_signer_path,
rpc_client: None,
rpc_timeout,
verbose: matches.is_present("verbose"),
output_format,
commitment,
send_transaction_config: RpcSendTransactionConfig::default(),
address_labels,
},
signers,
))
@@ -243,12 +229,6 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.global(true)
.help("Show additional information"),
)
.arg(
Arg::with_name("no_address_labels")
.long("no-address-labels")
.global(true)
.help("Do not use address labels in the output"),
)
.arg(
Arg::with_name("output_format")
.long("output")
@@ -264,16 +244,6 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.global(true)
.help(SKIP_SEED_PHRASE_VALIDATION_ARG.help),
)
.arg(
Arg::with_name("rpc_timeout")
.long("rpc-timeout")
.value_name("SECONDS")
.takes_value(true)
.default_value(DEFAULT_RPC_TIMEOUT_SECONDS)
.global(true)
.hidden(true)
.help("Timeout value for RPC requests"),
)
.subcommand(
SubCommand::with_name("config")
.about("Solana command-line tool configuration settings")
@@ -300,28 +270,6 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.multiple(true)
.required(true),
),
)
.subcommand(
SubCommand::with_name("import-address-labels")
.about("Import a list of address labels")
.arg(
Arg::with_name("filename")
.index(1)
.value_name("FILENAME")
.takes_value(true)
.help("YAML file of address labels"),
),
)
.subcommand(
SubCommand::with_name("export-address-labels")
.about("Export the current address labels")
.arg(
Arg::with_name("filename")
.index(1)
.value_name("FILENAME")
.takes_value(true)
.help("YAML file to receive the current address labels"),
),
),
)
.get_matches();

View File

@@ -1,29 +1,26 @@
use crate::{
checks::{check_account_for_fee_with_commitment, check_unique_pubkeys},
checks::{check_account_for_fee, check_unique_pubkeys},
cli::{
generate_unique_signers, log_instruction_custom_error, CliCommand, CliCommandInfo,
CliConfig, CliError, ProcessResult, SignerIndex,
log_instruction_custom_error, CliCommand, CliCommandInfo, CliConfig, CliError,
ProcessResult,
},
cli_output::CliNonceAccount,
spend_utils::{resolve_spend_tx_and_check_account_balance, SpendAmount},
};
use clap::{App, Arg, ArgMatches, SubCommand};
use solana_clap_utils::{
input_parsers::*, input_validators::*, offline::BLOCKHASH_ARG, ArgConstant,
input_parsers::*,
input_validators::*,
keypair::{DefaultSigner, SignerIndex},
nonce::*,
};
use solana_client::rpc_client::RpcClient;
use solana_cli_output::CliNonceAccount;
use solana_client::{nonce_utils::*, rpc_client::RpcClient};
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
account::Account,
account_utils::StateMut,
commitment_config::CommitmentConfig,
hash::Hash,
message::Message,
nonce::{
self,
state::{Data, Versions},
State,
},
nonce::{self, State},
pubkey::Pubkey,
system_instruction::{
advance_nonce_account, authorize_nonce_account, create_nonce_account,
@@ -33,64 +30,11 @@ use solana_sdk::{
transaction::Transaction,
};
use std::sync::Arc;
use thiserror::Error;
#[derive(Debug, Error, PartialEq)]
pub enum CliNonceError {
#[error("invalid account owner")]
InvalidAccountOwner,
#[error("invalid account data")]
InvalidAccountData,
#[error("unexpected account data size")]
UnexpectedDataSize,
#[error("query hash does not match stored hash")]
InvalidHash,
#[error("query authority does not match account authority")]
InvalidAuthority,
#[error("invalid state for requested operation")]
InvalidStateForOperation,
#[error("client error: {0}")]
Client(String),
}
pub const NONCE_ARG: ArgConstant<'static> = ArgConstant {
name: "nonce",
long: "nonce",
help: "Provide the nonce account to use when creating a nonced \n\
transaction. Nonced transactions are useful when a transaction \n\
requires a lengthy signing process. Learn more about nonced \n\
transactions at https://docs.solana.com/offline-signing/durable-nonce",
};
pub const NONCE_AUTHORITY_ARG: ArgConstant<'static> = ArgConstant {
name: "nonce_authority",
long: "nonce-authority",
help: "Provide the nonce authority keypair to use when signing a nonced transaction",
};
pub trait NonceSubCommands {
fn nonce_subcommands(self) -> Self;
}
pub fn nonce_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(NONCE_ARG.name)
.long(NONCE_ARG.long)
.takes_value(true)
.value_name("PUBKEY")
.requires(BLOCKHASH_ARG.name)
.validator(is_valid_pubkey)
.help(NONCE_ARG.help)
}
pub fn nonce_authority_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(NONCE_AUTHORITY_ARG.name)
.long(NONCE_AUTHORITY_ARG.long)
.takes_value(true)
.value_name("KEYPAIR")
.validator(is_valid_signer)
.help(NONCE_AUTHORITY_ARG.help)
}
impl NonceSubCommands for App<'_, '_> {
fn nonce_subcommands(self) -> Self {
self.subcommand(
@@ -220,64 +164,9 @@ impl NonceSubCommands for App<'_, '_> {
}
}
pub fn get_account(
rpc_client: &RpcClient,
nonce_pubkey: &Pubkey,
) -> Result<Account, CliNonceError> {
get_account_with_commitment(rpc_client, nonce_pubkey, CommitmentConfig::default())
}
pub fn get_account_with_commitment(
rpc_client: &RpcClient,
nonce_pubkey: &Pubkey,
commitment: CommitmentConfig,
) -> Result<Account, CliNonceError> {
rpc_client
.get_account_with_commitment(nonce_pubkey, commitment)
.map_err(|e| CliNonceError::Client(format!("{}", e)))
.and_then(|result| {
result.value.ok_or_else(|| {
CliNonceError::Client(format!("AccountNotFound: pubkey={}", nonce_pubkey))
})
})
.and_then(|a| match account_identity_ok(&a) {
Ok(()) => Ok(a),
Err(e) => Err(e),
})
}
pub fn account_identity_ok(account: &Account) -> Result<(), CliNonceError> {
if account.owner != system_program::id() {
Err(CliNonceError::InvalidAccountOwner)
} else if account.data.is_empty() {
Err(CliNonceError::UnexpectedDataSize)
} else {
Ok(())
}
}
pub fn state_from_account(account: &Account) -> Result<State, CliNonceError> {
account_identity_ok(account)?;
StateMut::<Versions>::state(account)
.map_err(|_| CliNonceError::InvalidAccountData)
.map(|v| v.convert_to_current())
}
pub fn data_from_account(account: &Account) -> Result<Data, CliNonceError> {
account_identity_ok(account)?;
state_from_account(account).and_then(|ref s| data_from_state(s).map(|d| d.clone()))
}
pub fn data_from_state(state: &State) -> Result<&Data, CliNonceError> {
match state {
State::Uninitialized => Err(CliNonceError::InvalidStateForOperation),
State::Initialized(data) => Ok(data),
}
}
pub fn parse_authorize_nonce_account(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let nonce_account = pubkey_of_signer(matches, "nonce_account_pubkey", wallet_manager)?.unwrap();
@@ -286,10 +175,9 @@ pub fn parse_authorize_nonce_account(
signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?;
let payer_provided = None;
let signer_info = generate_unique_signers(
let signer_info = default_signer.generate_unique_signers(
vec![payer_provided, nonce_authority],
matches,
default_signer_path,
wallet_manager,
)?;
@@ -305,7 +193,7 @@ pub fn parse_authorize_nonce_account(
pub fn parse_nonce_create_account(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let (nonce_account, nonce_account_pubkey) =
@@ -315,10 +203,9 @@ pub fn parse_nonce_create_account(
let nonce_authority = pubkey_of_signer(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?;
let payer_provided = None;
let signer_info = generate_unique_signers(
let signer_info = default_signer.generate_unique_signers(
vec![payer_provided, nonce_account],
matches,
default_signer_path,
wallet_manager,
)?;
@@ -348,7 +235,7 @@ pub fn parse_get_nonce(
pub fn parse_new_nonce(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let nonce_account = pubkey_of_signer(matches, "nonce_account_pubkey", wallet_manager)?.unwrap();
@@ -356,10 +243,9 @@ pub fn parse_new_nonce(
signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?;
let payer_provided = None;
let signer_info = generate_unique_signers(
let signer_info = default_signer.generate_unique_signers(
vec![payer_provided, nonce_authority],
matches,
default_signer_path,
wallet_manager,
)?;
@@ -391,7 +277,7 @@ pub fn parse_show_nonce_account(
pub fn parse_withdraw_from_nonce_account(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let nonce_account = pubkey_of_signer(matches, "nonce_account_pubkey", wallet_manager)?.unwrap();
@@ -402,10 +288,9 @@ pub fn parse_withdraw_from_nonce_account(
signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?;
let payer_provided = None;
let signer_info = generate_unique_signers(
let signer_info = default_signer.generate_unique_signers(
vec![payer_provided, nonce_authority],
matches,
default_signer_path,
wallet_manager,
)?;
@@ -429,14 +314,14 @@ pub fn check_nonce_account(
match state_from_account(nonce_account)? {
State::Initialized(ref data) => {
if &data.blockhash != nonce_hash {
Err(CliNonceError::InvalidHash.into())
Err(Error::InvalidHash.into())
} else if nonce_authority != &data.authority {
Err(CliNonceError::InvalidAuthority.into())
Err(Error::InvalidAuthority.into())
} else {
Ok(())
}
}
State::Uninitialized => Err(CliNonceError::InvalidStateForOperation.into()),
State::Uninitialized => Err(Error::InvalidStateForOperation.into()),
}
}
@@ -447,9 +332,7 @@ pub fn process_authorize_nonce_account(
nonce_authority: SignerIndex,
new_authority: &Pubkey,
) -> ProcessResult {
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let nonce_authority = config.signers[nonce_authority];
let ix = authorize_nonce_account(nonce_account, &nonce_authority.pubkey(), new_authority);
@@ -457,18 +340,13 @@ pub fn process_authorize_nonce_account(
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<NonceError>(result, &config)
}
@@ -515,9 +393,7 @@ pub fn process_create_nonce_account(
Message::new(&ixs, Some(&config.signers[0].pubkey()))
};
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (message, lamports) = resolve_spend_tx_and_check_account_balance(
rpc_client,
@@ -526,12 +402,9 @@ pub fn process_create_nonce_account(
&fee_calculator,
&config.signers[0].pubkey(),
build_message,
config.commitment,
)?;
if let Ok(nonce_account) =
get_account_with_commitment(rpc_client, &nonce_account_address, config.commitment)
{
if let Ok(nonce_account) = get_account(rpc_client, &nonce_account_address) {
let err_msg = if state_from_account(&nonce_account).is_ok() {
format!("Nonce account {} already exists", nonce_account_address)
} else {
@@ -554,22 +427,12 @@ pub fn process_create_nonce_account(
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<SystemError>(result, &config)
}
pub fn process_get_nonce(
rpc_client: &RpcClient,
config: &CliConfig,
nonce_account_pubkey: &Pubkey,
) -> ProcessResult {
match get_account_with_commitment(rpc_client, nonce_account_pubkey, config.commitment)
.and_then(|ref a| state_from_account(a))?
{
pub fn process_get_nonce(rpc_client: &RpcClient, nonce_account_pubkey: &Pubkey) -> ProcessResult {
match get_account(rpc_client, nonce_account_pubkey).and_then(|ref a| state_from_account(a))? {
State::Uninitialized => Ok("Nonce account is uninitialized".to_string()),
State::Initialized(ref data) => Ok(format!("{:?}", data.blockhash)),
}
@@ -586,9 +449,7 @@ pub fn process_new_nonce(
(&nonce_account, "nonce_account_pubkey".to_string()),
)?;
let nonce_account_check =
rpc_client.get_account_with_commitment(&nonce_account, config.commitment);
if nonce_account_check.is_err() || nonce_account_check.unwrap().value.is_none() {
if rpc_client.get_account(&nonce_account).is_err() {
return Err(CliError::BadParameter(
"Unable to create new nonce, no nonce account found".to_string(),
)
@@ -597,24 +458,17 @@ pub fn process_new_nonce(
let nonce_authority = config.signers[nonce_authority];
let ix = advance_nonce_account(&nonce_account, &nonce_authority.pubkey());
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let message = Message::new(&[ix], Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<SystemError>(result, &config)
}
@@ -624,8 +478,7 @@ pub fn process_show_nonce_account(
nonce_account_pubkey: &Pubkey,
use_lamports_unit: bool,
) -> ProcessResult {
let nonce_account =
get_account_with_commitment(rpc_client, nonce_account_pubkey, config.commitment)?;
let nonce_account = get_account(rpc_client, nonce_account_pubkey)?;
let print_account = |data: Option<&nonce::state::Data>| {
let mut nonce_account = CliNonceAccount {
balance: nonce_account.lamports,
@@ -656,9 +509,7 @@ pub fn process_withdraw_from_nonce_account(
destination_account_pubkey: &Pubkey,
lamports: u64,
) -> ProcessResult {
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let nonce_authority = config.signers[nonce_authority];
let ix = withdraw_nonce_account(
@@ -670,18 +521,13 @@ pub fn process_withdraw_from_nonce_account(
let message = Message::new(&[ix], Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<NonceError>(result, &config)
}
@@ -691,9 +537,10 @@ mod tests {
use crate::cli::{app, parse_command};
use solana_sdk::{
account::Account,
account_utils::StateMut,
fee_calculator::FeeCalculator,
hash::hash,
nonce::{self, State},
nonce::{self, state::Versions, State},
signature::{read_keypair_file, write_keypair, Keypair, Signer},
system_program,
};
@@ -710,6 +557,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 {
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();
@@ -728,12 +579,7 @@ mod tests {
&Pubkey::default().to_string(),
]);
assert_eq!(
parse_command(
&test_authorize_nonce_account,
&default_keypair_file,
&mut None
)
.unwrap(),
parse_command(&test_authorize_nonce_account, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::AuthorizeNonceAccount {
nonce_account: nonce_account_pubkey,
@@ -754,12 +600,7 @@ mod tests {
&authority_keypair_file,
]);
assert_eq!(
parse_command(
&test_authorize_nonce_account,
&default_keypair_file,
&mut None
)
.unwrap(),
parse_command(&test_authorize_nonce_account, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::AuthorizeNonceAccount {
nonce_account: read_keypair_file(&keypair_file).unwrap().pubkey(),
@@ -781,7 +622,7 @@ mod tests {
"50",
]);
assert_eq!(
parse_command(&test_create_nonce_account, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_create_nonce_account, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::CreateNonceAccount {
nonce_account: 1,
@@ -806,7 +647,7 @@ mod tests {
&authority_keypair_file,
]);
assert_eq!(
parse_command(&test_create_nonce_account, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_create_nonce_account, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::CreateNonceAccount {
nonce_account: 1,
@@ -828,7 +669,7 @@ mod tests {
&nonce_account_string,
]);
assert_eq!(
parse_command(&test_get_nonce, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_get_nonce, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetNonce(nonce_account_keypair.pubkey()),
signers: vec![],
@@ -842,7 +683,7 @@ mod tests {
.get_matches_from(vec!["test", "new-nonce", &keypair_file]);
let nonce_account = read_keypair_file(&keypair_file).unwrap();
assert_eq!(
parse_command(&test_new_nonce, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_new_nonce, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::NewNonce {
nonce_account: nonce_account.pubkey(),
@@ -862,7 +703,7 @@ mod tests {
]);
let nonce_account = read_keypair_file(&keypair_file).unwrap();
assert_eq!(
parse_command(&test_new_nonce, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_new_nonce, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::NewNonce {
nonce_account: nonce_account.pubkey(),
@@ -882,7 +723,7 @@ mod tests {
&nonce_account_string,
]);
assert_eq!(
parse_command(&test_show_nonce_account, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_show_nonce_account, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::ShowNonceAccount {
nonce_account_pubkey: nonce_account_keypair.pubkey(),
@@ -903,7 +744,7 @@ mod tests {
assert_eq!(
parse_command(
&test_withdraw_from_nonce_account,
&default_keypair_file,
&default_signer,
&mut None
)
.unwrap(),
@@ -931,7 +772,7 @@ mod tests {
assert_eq!(
parse_command(
&test_withdraw_from_nonce_account,
&default_keypair_file,
&default_signer,
&mut None
)
.unwrap(),
@@ -966,14 +807,14 @@ mod tests {
if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_owner.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{
assert_eq!(err, CliNonceError::InvalidAccountOwner,);
assert_eq!(err, Error::InvalidAccountOwner,);
}
let invalid_data = Account::new_data(1, &"invalid", &system_program::ID);
if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_data.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{
assert_eq!(err, CliNonceError::InvalidAccountData,);
assert_eq!(err, Error::InvalidAccountData,);
}
let data = Versions::new_current(State::Initialized(nonce::state::Data {
@@ -985,7 +826,7 @@ mod tests {
if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_hash.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{
assert_eq!(err, CliNonceError::InvalidHash,);
assert_eq!(err, Error::InvalidHash,);
}
let data = Versions::new_current(State::Initialized(nonce::state::Data {
@@ -997,7 +838,7 @@ mod tests {
if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_authority.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{
assert_eq!(err, CliNonceError::InvalidAuthority,);
assert_eq!(err, Error::InvalidAuthority,);
}
let data = Versions::new_current(State::Uninitialized);
@@ -1005,7 +846,7 @@ mod tests {
if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_state.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{
assert_eq!(err, CliNonceError::InvalidStateForOperation,);
assert_eq!(err, Error::InvalidStateForOperation,);
}
}
@@ -1017,14 +858,14 @@ mod tests {
let system_account = Account::new(1, 0, &system_program::id());
assert_eq!(
account_identity_ok(&system_account),
Err(CliNonceError::UnexpectedDataSize),
Err(Error::UnexpectedDataSize),
);
let other_program = Pubkey::new(&[1u8; 32]);
let other_account_no_data = Account::new(1, 0, &other_program);
assert_eq!(
account_identity_ok(&other_account_no_data),
Err(CliNonceError::InvalidAccountOwner),
Err(Error::InvalidAccountOwner),
);
}
@@ -1049,7 +890,7 @@ mod tests {
let wrong_data_size_account = Account::new(1, 1, &system_program::id());
assert_eq!(
state_from_account(&wrong_data_size_account),
Err(CliNonceError::InvalidAccountData),
Err(Error::InvalidAccountData),
);
}
@@ -1059,11 +900,11 @@ mod tests {
let state = state_from_account(&nonce_account).unwrap();
assert_eq!(
data_from_state(&state),
Err(CliNonceError::InvalidStateForOperation)
Err(Error::InvalidStateForOperation)
);
assert_eq!(
data_from_account(&nonce_account),
Err(CliNonceError::InvalidStateForOperation)
Err(Error::InvalidStateForOperation)
);
let data = nonce::state::Data {

View File

@@ -1,129 +0,0 @@
pub mod blockhash_query;
use crate::nonce;
use clap::{App, Arg, ArgMatches};
use serde_json::Value;
use solana_clap_utils::{
input_parsers::{pubkey_of, value_of},
input_validators::{is_hash, is_pubkey_sig},
keypair::presigner_from_pubkey_sigs,
offline::{BLOCKHASH_ARG, SIGNER_ARG, SIGN_ONLY_ARG},
};
use solana_client::rpc_client::RpcClient;
use solana_sdk::{
fee_calculator::FeeCalculator,
hash::Hash,
pubkey::Pubkey,
signature::{Presigner, Signature},
};
use std::str::FromStr;
fn blockhash_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(BLOCKHASH_ARG.name)
.long(BLOCKHASH_ARG.long)
.takes_value(true)
.value_name("BLOCKHASH")
.validator(is_hash)
.help(BLOCKHASH_ARG.help)
}
fn sign_only_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(SIGN_ONLY_ARG.name)
.long(SIGN_ONLY_ARG.long)
.takes_value(false)
.requires(BLOCKHASH_ARG.name)
.help(SIGN_ONLY_ARG.help)
}
fn signer_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(SIGNER_ARG.name)
.long(SIGNER_ARG.long)
.takes_value(true)
.value_name("PUBKEY=SIGNATURE")
.validator(is_pubkey_sig)
.requires(BLOCKHASH_ARG.name)
.multiple(true)
.help(SIGNER_ARG.help)
}
pub trait OfflineArgs {
fn offline_args(self) -> Self;
}
impl OfflineArgs for App<'_, '_> {
fn offline_args(self) -> Self {
self.arg(blockhash_arg())
.arg(sign_only_arg())
.arg(signer_arg())
}
}
pub struct SignOnly {
pub blockhash: Hash,
pub present_signers: Vec<(Pubkey, Signature)>,
pub absent_signers: Vec<Pubkey>,
pub bad_signers: Vec<Pubkey>,
}
impl SignOnly {
pub fn has_all_signers(&self) -> bool {
self.absent_signers.is_empty() && self.bad_signers.is_empty()
}
pub fn presigner_of(&self, pubkey: &Pubkey) -> Option<Presigner> {
presigner_from_pubkey_sigs(pubkey, &self.present_signers)
}
}
pub fn parse_sign_only_reply_string(reply: &str) -> SignOnly {
let object: Value = serde_json::from_str(&reply).unwrap();
let blockhash_str = object.get("blockhash").unwrap().as_str().unwrap();
let blockhash = blockhash_str.parse::<Hash>().unwrap();
let mut present_signers: Vec<(Pubkey, Signature)> = Vec::new();
let signer_strings = object.get("signers");
if let Some(sig_strings) = signer_strings {
present_signers = sig_strings
.as_array()
.unwrap()
.iter()
.map(|signer_string| {
let mut signer = signer_string.as_str().unwrap().split('=');
let key = Pubkey::from_str(signer.next().unwrap()).unwrap();
let sig = Signature::from_str(signer.next().unwrap()).unwrap();
(key, sig)
})
.collect();
}
let mut absent_signers: Vec<Pubkey> = Vec::new();
let signer_strings = object.get("absent");
if let Some(sig_strings) = signer_strings {
absent_signers = sig_strings
.as_array()
.unwrap()
.iter()
.map(|val| {
let s = val.as_str().unwrap();
Pubkey::from_str(s).unwrap()
})
.collect();
}
let mut bad_signers: Vec<Pubkey> = Vec::new();
let signer_strings = object.get("badSig");
if let Some(sig_strings) = signer_strings {
bad_signers = sig_strings
.as_array()
.unwrap()
.iter()
.map(|val| {
let s = val.as_str().unwrap();
Pubkey::from_str(s).unwrap()
})
.collect();
}
SignOnly {
blockhash,
present_signers,
absent_signers,
bad_signers,
}
}

View File

@@ -1,13 +1,12 @@
use crate::{
checks::{calculate_fee, check_account_for_balance_with_commitment},
checks::{calculate_fee, check_account_for_balance},
cli::CliError,
};
use clap::ArgMatches;
use solana_clap_utils::{input_parsers::lamports_of_sol, offline::SIGN_ONLY_ARG};
use solana_client::rpc_client::RpcClient;
use solana_sdk::{
commitment_config::CommitmentConfig, fee_calculator::FeeCalculator, message::Message,
native_token::lamports_to_sol, pubkey::Pubkey,
fee_calculator::FeeCalculator, message::Message, native_token::lamports_to_sol, pubkey::Pubkey,
};
#[derive(Debug, PartialEq, Clone, Copy)]
@@ -50,7 +49,6 @@ pub fn resolve_spend_tx_and_check_account_balance<F>(
fee_calculator: &FeeCalculator,
from_pubkey: &Pubkey,
build_message: F,
commitment: CommitmentConfig,
) -> Result<(Message, u64), CliError>
where
F: Fn(u64) -> Message,
@@ -63,7 +61,6 @@ where
from_pubkey,
from_pubkey,
build_message,
commitment,
)
}
@@ -75,7 +72,6 @@ pub fn resolve_spend_tx_and_check_account_balances<F>(
from_pubkey: &Pubkey,
fee_pubkey: &Pubkey,
build_message: F,
commitment: CommitmentConfig,
) -> Result<(Message, u64), CliError>
where
F: Fn(u64) -> Message,
@@ -91,9 +87,7 @@ where
);
Ok((message, spend))
} else {
let from_balance = rpc_client
.get_balance_with_commitment(&from_pubkey, commitment)?
.value;
let from_balance = rpc_client.get_balance(&from_pubkey)?;
let (message, SpendAndFee { spend, fee }) = resolve_spend_message(
amount,
fee_calculator,
@@ -113,8 +107,7 @@ where
if from_balance < spend {
return Err(CliError::InsufficientFundsForSpend(lamports_to_sol(spend)));
}
if !check_account_for_balance_with_commitment(rpc_client, fee_pubkey, fee, commitment)?
{
if !check_account_for_balance(rpc_client, fee_pubkey, fee)? {
return Err(CliError::InsufficientFundsForFee(lamports_to_sol(fee)));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,10 @@
use solana_client::rpc_client::RpcClient;
use solana_sdk::{clock::DEFAULT_MS_PER_SLOT, commitment_config::CommitmentConfig, pubkey::Pubkey};
use solana_sdk::pubkey::Pubkey;
use std::{thread::sleep, time::Duration};
pub fn check_recent_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) {
pub fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) {
(0..5).for_each(|tries| {
let balance = client
.get_balance_with_commitment(pubkey, CommitmentConfig::recent())
.unwrap()
.value;
let balance = client.get_balance(pubkey).unwrap();
if balance == expected_balance {
return;
}
@@ -17,13 +14,3 @@ pub fn check_recent_balance(expected_balance: u64, client: &RpcClient, pubkey: &
sleep(Duration::from_millis(500));
});
}
pub fn check_ready(rpc_client: &RpcClient) {
while rpc_client
.get_slot_with_commitment(CommitmentConfig::recent())
.unwrap()
< 5
{
sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT));
}
}

View File

@@ -1,19 +1,20 @@
use crate::{
cli::{CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult},
cli_output::{CliValidatorInfo, CliValidatorInfoVec},
spend_utils::{resolve_spend_tx_and_check_account_balance, SpendAmount},
};
use bincode::deserialize;
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use reqwest::blocking::Client;
use serde_derive::{Deserialize, Serialize};
use serde_json::{Map, Value};
use solana_account_decoder::validator_info::{
self, ValidatorInfo, MAX_LONG_FIELD_LENGTH, MAX_SHORT_FIELD_LENGTH,
};
use solana_clap_utils::{
input_parsers::pubkey_of,
input_validators::{is_pubkey, is_url},
keypair::signer_from_path,
keypair::DefaultSigner,
};
use solana_cli_output::{CliValidatorInfo, CliValidatorInfoVec};
use solana_client::rpc_client::RpcClient;
use solana_config_program::{config_instruction, get_config_data, ConfigKeys, ConfigState};
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
@@ -27,23 +28,6 @@ use solana_sdk::{
};
use std::{error, sync::Arc};
pub const MAX_SHORT_FIELD_LENGTH: usize = 70;
pub const MAX_LONG_FIELD_LENGTH: usize = 300;
pub const MAX_VALIDATOR_INFO: u64 = 576;
solana_sdk::declare_id!("Va1idator1nfo111111111111111111111111111111");
#[derive(Debug, Deserialize, PartialEq, Serialize, Default)]
pub struct ValidatorInfo {
info: String,
}
impl ConfigState for ValidatorInfo {
fn max_space() -> u64 {
MAX_VALIDATOR_INFO
}
}
// Return an error if a validator details are longer than the max length.
pub fn check_details_length(string: String) -> Result<(), String> {
if string.len() > MAX_LONG_FIELD_LENGTH {
@@ -228,7 +212,7 @@ impl ValidatorInfoSubCommands for App<'_, '_> {
pub fn parse_validator_info_command(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let info_pubkey = pubkey_of(matches, "info_pubkey");
@@ -240,12 +224,7 @@ pub fn parse_validator_info_command(
force_keybase: matches.is_present("force"),
info_pubkey,
},
signers: vec![signer_from_path(
matches,
default_signer_path,
"keypair",
wallet_manager,
)?],
signers: vec![default_signer.signer_from_path(matches, wallet_manager)?],
})
}
@@ -287,10 +266,12 @@ pub fn process_set_validator_info(
let all_config = rpc_client.get_program_accounts(&solana_config_program::id())?;
let existing_account = all_config
.iter()
.filter(|(_, account)| {
let key_list: ConfigKeys = deserialize(&account.data).map_err(|_| false).unwrap();
key_list.keys.contains(&(id(), false))
})
.filter(
|(_, account)| match deserialize::<ConfigKeys>(&account.data) {
Ok(key_list) => key_list.keys.contains(&(validator_info::id(), false)),
Err(_) => false,
},
)
.find(|(pubkey, account)| {
let (validator_pubkey, _) = parse_validator_info(&pubkey, &account).unwrap();
validator_pubkey == config.signers[0].pubkey()
@@ -328,7 +309,10 @@ pub fn process_set_validator_info(
};
let build_message = |lamports| {
let keys = vec![(id(), false), (config.signers[0].pubkey(), true)];
let keys = vec![
(validator_info::id(), false),
(config.signers[0].pubkey(), true),
];
if balance == 0 {
println!(
"Publishing info for Validator {:?}",
@@ -372,7 +356,6 @@ pub fn process_set_validator_info(
&fee_calculator,
&config.signers[0].pubkey(),
build_message,
config.commitment,
)?;
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&signers, recent_blockhash)?;
@@ -398,10 +381,10 @@ pub fn process_get_validator_info(
all_config
.into_iter()
.filter(|(_, validator_info_account)| {
let key_list: ConfigKeys = deserialize(&validator_info_account.data)
.map_err(|_| false)
.unwrap();
key_list.keys.contains(&(id(), false))
match deserialize::<ConfigKeys>(&validator_info_account.data) {
Ok(key_list) => key_list.keys.contains(&(validator_info::id(), false)),
Err(_) => false,
}
})
.collect()
};
@@ -503,7 +486,7 @@ mod tests {
#[test]
fn test_parse_validator_info() {
let pubkey = Pubkey::new_rand();
let keys = vec![(id(), false), (pubkey, true)];
let keys = vec![(validator_info::id(), false), (pubkey, true)];
let config = ConfigKeys { keys };
let mut info = Map::new();

View File

@@ -1,14 +1,19 @@
use crate::{
checks::{check_account_for_fee_with_commitment, check_unique_pubkeys},
checks::{check_account_for_fee, check_unique_pubkeys},
cli::{
generate_unique_signers, log_instruction_custom_error, CliCommand, CliCommandInfo,
CliConfig, CliError, ProcessResult, SignerIndex,
log_instruction_custom_error, CliCommand, CliCommandInfo, CliConfig, CliError,
ProcessResult,
},
cli_output::{CliEpochVotingHistory, CliLockout, CliVoteAccount},
spend_utils::{resolve_spend_tx_and_check_account_balance, SpendAmount},
};
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
use solana_clap_utils::{commitment::commitment_arg, input_parsers::*, input_validators::*};
use solana_clap_utils::{
commitment::{commitment_arg, COMMITMENT_ARG},
input_parsers::*,
input_validators::*,
keypair::{DefaultSigner, SignerIndex},
};
use solana_cli_output::{CliEpochVotingHistory, CliLockout, CliVoteAccount};
use solana_client::rpc_client::RpcClient;
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
@@ -246,7 +251,7 @@ impl VoteSubCommands for App<'_, '_> {
pub fn parse_create_vote_account(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let (vote_account, vote_account_pubkey) = signer_of(matches, "vote_account", wallet_manager)?;
@@ -258,10 +263,9 @@ pub fn parse_create_vote_account(
let authorized_withdrawer = pubkey_of_signer(matches, "authorized_withdrawer", wallet_manager)?;
let payer_provided = None;
let signer_info = generate_unique_signers(
let signer_info = default_signer.generate_unique_signers(
vec![payer_provided, vote_account, identity_account],
matches,
default_signer_path,
wallet_manager,
)?;
@@ -280,7 +284,7 @@ pub fn parse_create_vote_account(
pub fn parse_vote_authorize(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
vote_authorize: VoteAuthorize,
) -> Result<CliCommandInfo, CliError> {
@@ -291,10 +295,9 @@ pub fn parse_vote_authorize(
let (authorized, _) = signer_of(matches, "authorized", wallet_manager)?;
let payer_provided = None;
let signer_info = generate_unique_signers(
let signer_info = default_signer.generate_unique_signers(
vec![payer_provided, authorized],
matches,
default_signer_path,
wallet_manager,
)?;
@@ -310,7 +313,7 @@ pub fn parse_vote_authorize(
pub fn parse_vote_update_validator(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let vote_account_pubkey =
@@ -321,10 +324,9 @@ pub fn parse_vote_update_validator(
signer_of(matches, "authorized_withdrawer", wallet_manager)?;
let payer_provided = None;
let signer_info = generate_unique_signers(
let signer_info = default_signer.generate_unique_signers(
vec![payer_provided, authorized_withdrawer, new_identity_account],
matches,
default_signer_path,
wallet_manager,
)?;
@@ -340,7 +342,7 @@ pub fn parse_vote_update_validator(
pub fn parse_vote_update_commission(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let vote_account_pubkey =
@@ -350,10 +352,9 @@ pub fn parse_vote_update_commission(
let commission = value_t_or_exit!(matches, "commission", u8);
let payer_provided = None;
let signer_info = generate_unique_signers(
let signer_info = default_signer.generate_unique_signers(
vec![payer_provided, authorized_withdrawer],
matches,
default_signer_path,
wallet_manager,
)?;
@@ -374,10 +375,12 @@ pub fn parse_vote_get_account_command(
let vote_account_pubkey =
pubkey_of_signer(matches, "vote_account_pubkey", wallet_manager)?.unwrap();
let use_lamports_unit = matches.is_present("lamports");
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
Ok(CliCommandInfo {
command: CliCommand::ShowVoteAccount {
pubkey: vote_account_pubkey,
use_lamports_unit,
commitment_config,
},
signers: vec![],
})
@@ -385,7 +388,7 @@ pub fn parse_vote_get_account_command(
pub fn parse_withdraw_from_vote_account(
matches: &ArgMatches<'_>,
default_signer_path: &str,
default_signer: &DefaultSigner,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let vote_account_pubkey =
@@ -398,10 +401,9 @@ pub fn parse_withdraw_from_vote_account(
signer_of(matches, "authorized_withdrawer", wallet_manager)?;
let payer_provided = None;
let signer_info = generate_unique_signers(
let signer_info = default_signer.generate_unique_signers(
vec![payer_provided, withdraw_authority],
matches,
default_signer_path,
wallet_manager,
)?;
@@ -478,25 +480,19 @@ pub fn process_create_vote_account(
Message::new(&ixs, Some(&config.signers[0].pubkey()))
};
if let Ok(response) =
rpc_client.get_account_with_commitment(&vote_account_address, config.commitment)
{
if let Some(vote_account) = response.value {
let err_msg = if vote_account.owner == solana_vote_program::id() {
format!("Vote account {} already exists", vote_account_address)
} else {
format!(
"Account {} already exists and is not a vote account",
vote_account_address
)
};
return Err(CliError::BadParameter(err_msg).into());
}
if let Ok(vote_account) = rpc_client.get_account(&vote_account_address) {
let err_msg = if vote_account.owner == solana_vote_program::id() {
format!("Vote account {} already exists", vote_account_address)
} else {
format!(
"Account {} already exists and is not a vote account",
vote_account_address
)
};
return Err(CliError::BadParameter(err_msg).into());
}
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (message, _) = resolve_spend_tx_and_check_account_balance(
rpc_client,
@@ -505,15 +501,10 @@ pub fn process_create_vote_account(
&fee_calculator,
&config.signers[0].pubkey(),
build_message,
config.commitment,
)?;
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<SystemError>(result, &config)
}
@@ -536,9 +527,7 @@ pub fn process_vote_authorize(
(&authorized.pubkey(), "authorized_account".to_string()),
(new_authorized_pubkey, "new_authorized_pubkey".to_string()),
)?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let ixs = vec![vote_instruction::authorize(
vote_account_pubkey, // vote account to update
&authorized.pubkey(), // current authorized
@@ -549,18 +538,13 @@ pub fn process_vote_authorize(
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<VoteError>(result, &config)
}
@@ -578,9 +562,7 @@ pub fn process_vote_update_validator(
(vote_account_pubkey, "vote_account_pubkey".to_string()),
(&new_identity_pubkey, "new_identity_account".to_string()),
)?;
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let ixs = vec![vote_instruction::update_validator_identity(
vote_account_pubkey,
&authorized_withdrawer.pubkey(),
@@ -590,18 +572,13 @@ pub fn process_vote_update_validator(
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<VoteError>(result, &config)
}
@@ -613,9 +590,7 @@ pub fn process_vote_update_commission(
withdraw_authority: SignerIndex,
) -> ProcessResult {
let authorized_withdrawer = config.signers[withdraw_authority];
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let ixs = vec![vote_instruction::update_commission(
vote_account_pubkey,
&authorized_withdrawer.pubkey(),
@@ -625,18 +600,13 @@ pub fn process_vote_update_commission(
let message = Message::new(&ixs, Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, recent_blockhash)?;
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&tx.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<VoteError>(result, &config)
}
@@ -673,9 +643,10 @@ pub fn process_show_vote_account(
config: &CliConfig,
vote_account_pubkey: &Pubkey,
use_lamports_unit: bool,
commitment_config: CommitmentConfig,
) -> ProcessResult {
let (vote_account, vote_state) =
get_vote_account(rpc_client, vote_account_pubkey, config.commitment)?;
get_vote_account(rpc_client, vote_account_pubkey, commitment_config)?;
let epoch_schedule = rpc_client.get_epoch_schedule()?;
@@ -721,14 +692,10 @@ pub fn process_withdraw_from_vote_account(
withdraw_amount: SpendAmount,
destination_account_pubkey: &Pubkey,
) -> ProcessResult {
let (recent_blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let withdraw_authority = config.signers[withdraw_authority];
let current_balance = rpc_client
.get_balance_with_commitment(&vote_account_pubkey, config.commitment)?
.value;
let current_balance = rpc_client.get_balance(&vote_account_pubkey)?;
let minimum_balance = rpc_client.get_minimum_balance_for_rent_exemption(VoteState::size_of())?;
let lamports = match withdraw_amount {
@@ -754,18 +721,13 @@ pub fn process_withdraw_from_vote_account(
let message = Message::new(&[ix], Some(&config.signers[0].pubkey()));
let mut transaction = Transaction::new_unsigned(message);
transaction.try_sign(&config.signers, recent_blockhash)?;
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&transaction.message,
config.commitment,
)?;
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&transaction,
config.commitment,
config.send_transaction_config,
);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&transaction);
log_instruction_custom_error::<VoteError>(result, &config)
}
@@ -794,6 +756,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 {
path: default_keypair_file.clone(),
arg_name: String::new(),
};
let test_authorize_voter = test_commands.clone().get_matches_from(vec![
"test",
@@ -803,7 +769,7 @@ mod tests {
&pubkey2_string,
]);
assert_eq!(
parse_command(&test_authorize_voter, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_authorize_voter, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::VoteAuthorize {
vote_account_pubkey: pubkey,
@@ -826,7 +792,7 @@ mod tests {
&pubkey2_string,
]);
assert_eq!(
parse_command(&test_authorize_voter, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_authorize_voter, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::VoteAuthorize {
vote_account_pubkey: pubkey,
@@ -856,7 +822,7 @@ mod tests {
"10",
]);
assert_eq!(
parse_command(&test_create_vote_account, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_create_vote_account, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::CreateVoteAccount {
vote_account: 1,
@@ -885,7 +851,7 @@ mod tests {
&identity_keypair_file,
]);
assert_eq!(
parse_command(&test_create_vote_account2, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_create_vote_account2, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::CreateVoteAccount {
vote_account: 1,
@@ -918,7 +884,7 @@ mod tests {
&authed.to_string(),
]);
assert_eq!(
parse_command(&test_create_vote_account3, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_create_vote_account3, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::CreateVoteAccount {
vote_account: 1,
@@ -949,7 +915,7 @@ mod tests {
&authed.to_string(),
]);
assert_eq!(
parse_command(&test_create_vote_account4, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_create_vote_account4, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::CreateVoteAccount {
vote_account: 1,
@@ -975,7 +941,7 @@ mod tests {
&keypair_file,
]);
assert_eq!(
parse_command(&test_update_validator, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_update_validator, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::VoteUpdateValidator {
vote_account_pubkey: pubkey,
@@ -998,7 +964,7 @@ mod tests {
&keypair_file,
]);
assert_eq!(
parse_command(&test_update_commission, &default_keypair_file, &mut None).unwrap(),
parse_command(&test_update_commission, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::VoteUpdateCommission {
vote_account_pubkey: pubkey,
@@ -1021,12 +987,7 @@ mod tests {
"42",
]);
assert_eq!(
parse_command(
&test_withdraw_from_vote_account,
&default_keypair_file,
&mut None
)
.unwrap(),
parse_command(&test_withdraw_from_vote_account, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::WithdrawFromVoteAccount {
vote_account_pubkey: read_keypair_file(&keypair_file).unwrap().pubkey(),
@@ -1047,12 +1008,7 @@ mod tests {
"ALL",
]);
assert_eq!(
parse_command(
&test_withdraw_from_vote_account,
&default_keypair_file,
&mut None
)
.unwrap(),
parse_command(&test_withdraw_from_vote_account, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::WithdrawFromVoteAccount {
vote_account_pubkey: read_keypair_file(&keypair_file).unwrap().pubkey(),
@@ -1078,12 +1034,7 @@ mod tests {
&withdraw_authority_file,
]);
assert_eq!(
parse_command(
&test_withdraw_from_vote_account,
&default_keypair_file,
&mut None
)
.unwrap(),
parse_command(&test_withdraw_from_vote_account, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::WithdrawFromVoteAccount {
vote_account_pubkey: read_keypair_file(&keypair_file).unwrap().pubkey(),

View File

@@ -3,12 +3,7 @@ use solana_cli::cli::{process_command, CliCommand, CliConfig};
use solana_client::rpc_client::RpcClient;
use solana_core::validator::TestValidator;
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
bpf_loader,
commitment_config::CommitmentConfig,
pubkey::Pubkey,
signature::{Keypair, Signer},
};
use solana_sdk::{bpf_loader, pubkey::Pubkey, signature::Keypair};
use std::{
fs::{remove_dir_all, File},
io::Read,
@@ -48,22 +43,19 @@ fn test_cli_deploy_program() {
.get_minimum_balance_for_rent_exemption(program_data.len())
.unwrap();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
let keypair = Keypair::new();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.command = CliCommand::Airdrop {
faucet_host: None,
faucet_port: faucet_addr.port(),
pubkey: None,
lamports: 3 * minimum_balance_for_rent_exemption, // min balance for rent exemption for two programs + leftover for tx processing
lamports: minimum_balance_for_rent_exemption + 1, // min balance for rent exemption + leftover for tx processing
};
config.signers = vec![&keypair];
process_command(&config).unwrap();
config.command = CliCommand::Deploy {
program_location: pathbuf.to_str().unwrap().to_string(),
address: None,
};
config.command = CliCommand::Deploy(pathbuf.to_str().unwrap().to_string());
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -75,41 +67,16 @@ fn test_cli_deploy_program() {
.as_str()
.unwrap();
let program_id = Pubkey::from_str(&program_id_str).unwrap();
let account0 = rpc_client
.get_account_with_commitment(&program_id, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
assert_eq!(account0.lamports, minimum_balance_for_rent_exemption);
assert_eq!(account0.owner, bpf_loader::id());
assert_eq!(account0.executable, true);
let account = rpc_client.get_account(&program_id).unwrap();
assert_eq!(account.lamports, minimum_balance_for_rent_exemption);
assert_eq!(account.owner, bpf_loader::id());
assert_eq!(account.executable, true);
let mut file = File::open(pathbuf.to_str().unwrap().to_string()).unwrap();
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
assert_eq!(account0.data, elf);
// Test custom address
let custom_address_keypair = Keypair::new();
config.signers = vec![&keypair, &custom_address_keypair];
config.command = CliCommand::Deploy {
program_location: pathbuf.to_str().unwrap().to_string(),
address: Some(1),
};
process_command(&config).unwrap();
let account1 = rpc_client
.get_account_with_commitment(&custom_address_keypair.pubkey(), CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
assert_eq!(account1.lamports, minimum_balance_for_rent_exemption);
assert_eq!(account1.owner, bpf_loader::id());
assert_eq!(account1.executable, true);
assert_eq!(account0.data, account1.data);
// Attempt to redeploy to the same address
process_command(&config).unwrap_err();
assert_eq!(account.data, elf);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();

View File

@@ -1,20 +1,18 @@
use solana_cli::test_utils::check_balance;
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
cli_output::OutputFormat,
nonce,
offline::{
blockhash_query::{self, BlockhashQuery},
parse_sign_only_reply_string,
},
spend_utils::SpendAmount,
test_utils::{check_ready, check_recent_balance},
};
use solana_client::rpc_client::RpcClient;
use solana_cli_output::{parse_sign_only_reply_string, OutputFormat};
use solana_client::{
blockhash_query::{self, BlockhashQuery},
nonce_utils,
rpc_client::RpcClient,
};
use solana_core::contact_info::ContactInfo;
use solana_core::validator::{TestValidator, TestValidatorOptions};
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
commitment_config::CommitmentConfig,
hash::Hash,
pubkey::Pubkey,
signature::{keypair_from_seed, Keypair, Signer},
@@ -84,7 +82,7 @@ fn full_battery_tests(
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
let mut config_payer = CliConfig::recent_for_tests();
let mut config_payer = CliConfig::default();
config_payer.json_rpc_url = json_rpc_url.clone();
let payer = Keypair::new();
config_payer.signers = vec![&payer];
@@ -97,9 +95,9 @@ fn full_battery_tests(
&config_payer,
)
.unwrap();
check_recent_balance(2000, &rpc_client, &config_payer.signers[0].pubkey());
check_balance(2000, &rpc_client, &config_payer.signers[0].pubkey());
let mut config_nonce = CliConfig::recent_for_tests();
let mut config_nonce = CliConfig::default();
config_nonce.json_rpc_url = json_rpc_url;
let nonce_keypair = keypair_from_seed(&[0u8; 32]).unwrap();
config_nonce.signers = vec![&nonce_keypair];
@@ -132,8 +130,8 @@ fn full_battery_tests(
};
process_command(&config_payer).unwrap();
check_recent_balance(1000, &rpc_client, &config_payer.signers[0].pubkey());
check_recent_balance(1000, &rpc_client, &nonce_account);
check_balance(1000, &rpc_client, &config_payer.signers[0].pubkey());
check_balance(1000, &rpc_client, &nonce_account);
// Get nonce
config_payer.signers.pop();
@@ -182,9 +180,9 @@ fn full_battery_tests(
lamports: 100,
};
process_command(&config_payer).unwrap();
check_recent_balance(1000, &rpc_client, &config_payer.signers[0].pubkey());
check_recent_balance(900, &rpc_client, &nonce_account);
check_recent_balance(100, &rpc_client, &payee_pubkey);
check_balance(1000, &rpc_client, &config_payer.signers[0].pubkey());
check_balance(900, &rpc_client, &nonce_account);
check_balance(100, &rpc_client, &payee_pubkey);
// Show nonce account
config_payer.command = CliCommand::ShowNonceAccount {
@@ -225,9 +223,9 @@ fn full_battery_tests(
lamports: 100,
};
process_command(&config_payer).unwrap();
check_recent_balance(1000, &rpc_client, &config_payer.signers[0].pubkey());
check_recent_balance(800, &rpc_client, &nonce_account);
check_recent_balance(200, &rpc_client, &payee_pubkey);
check_balance(1000, &rpc_client, &config_payer.signers[0].pubkey());
check_balance(800, &rpc_client, &nonce_account);
check_balance(200, &rpc_client, &payee_pubkey);
}
#[test]
@@ -251,7 +249,7 @@ fn test_create_account_with_seed() {
let offline_nonce_authority_signer = keypair_from_seed(&[1u8; 32]).unwrap();
let online_nonce_creator_signer = keypair_from_seed(&[2u8; 32]).unwrap();
let to_address = Pubkey::new(&[3u8; 32]);
let config = CliConfig::recent_for_tests();
let config = CliConfig::default();
// Setup accounts
let rpc_client = RpcClient::new_socket(leader_data.rpc);
@@ -271,11 +269,9 @@ fn test_create_account_with_seed() {
&config,
)
.unwrap();
check_recent_balance(42, &rpc_client, &offline_nonce_authority_signer.pubkey());
check_recent_balance(4242, &rpc_client, &online_nonce_creator_signer.pubkey());
check_recent_balance(0, &rpc_client, &to_address);
check_ready(&rpc_client);
check_balance(42, &rpc_client, &offline_nonce_authority_signer.pubkey());
check_balance(4242, &rpc_client, &online_nonce_creator_signer.pubkey());
check_balance(0, &rpc_client, &to_address);
// Create nonce account
let creator_pubkey = online_nonce_creator_signer.pubkey();
@@ -283,9 +279,9 @@ fn test_create_account_with_seed() {
let seed = authority_pubkey.to_string()[0..32].to_string();
let nonce_address =
Pubkey::create_with_seed(&creator_pubkey, &seed, &system_program::id()).unwrap();
check_recent_balance(0, &rpc_client, &nonce_address);
check_balance(0, &rpc_client, &nonce_address);
let mut creator_config = CliConfig::recent_for_tests();
let mut creator_config = CliConfig::default();
creator_config.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
creator_config.signers = vec![&online_nonce_creator_signer];
@@ -296,20 +292,19 @@ fn test_create_account_with_seed() {
amount: SpendAmount::Some(241),
};
process_command(&creator_config).unwrap();
check_recent_balance(241, &rpc_client, &nonce_address);
check_recent_balance(42, &rpc_client, &offline_nonce_authority_signer.pubkey());
check_recent_balance(4000, &rpc_client, &online_nonce_creator_signer.pubkey());
check_recent_balance(0, &rpc_client, &to_address);
check_balance(241, &rpc_client, &nonce_address);
check_balance(42, &rpc_client, &offline_nonce_authority_signer.pubkey());
check_balance(4000, &rpc_client, &online_nonce_creator_signer.pubkey());
check_balance(0, &rpc_client, &to_address);
// Fetch nonce hash
let nonce_hash =
nonce::get_account_with_commitment(&rpc_client, &nonce_address, CommitmentConfig::recent())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_address)
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Test by creating transfer TX with nonce, fully offline
let mut authority_config = CliConfig::recent_for_tests();
let mut authority_config = CliConfig::default();
authority_config.json_rpc_url = String::default();
authority_config.signers = vec![&offline_nonce_authority_signer];
// Verify we cannot contact the cluster
@@ -333,7 +328,7 @@ fn test_create_account_with_seed() {
assert_eq!(sign_only.blockhash, nonce_hash);
// And submit it
let mut submit_config = CliConfig::recent_for_tests();
let mut submit_config = CliConfig::default();
submit_config.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
submit_config.signers = vec![&authority_presigner];
@@ -352,10 +347,10 @@ fn test_create_account_with_seed() {
fee_payer: 0,
};
process_command(&submit_config).unwrap();
check_recent_balance(241, &rpc_client, &nonce_address);
check_recent_balance(31, &rpc_client, &offline_nonce_authority_signer.pubkey());
check_recent_balance(4000, &rpc_client, &online_nonce_creator_signer.pubkey());
check_recent_balance(10, &rpc_client, &to_address);
check_balance(241, &rpc_client, &nonce_address);
check_balance(31, &rpc_client, &offline_nonce_authority_signer.pubkey());
check_balance(4000, &rpc_client, &online_nonce_creator_signer.pubkey());
check_balance(10, &rpc_client, &to_address);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();

View File

@@ -1,21 +1,19 @@
use chrono::prelude::*;
use serde_json::Value;
use solana_cli::test_utils::check_balance;
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig, PayCommand},
cli_output::OutputFormat,
nonce,
offline::{
blockhash_query::{self, BlockhashQuery},
parse_sign_only_reply_string,
},
spend_utils::SpendAmount,
test_utils::check_recent_balance,
};
use solana_client::rpc_client::RpcClient;
use solana_cli_output::{parse_sign_only_reply_string, OutputFormat};
use solana_client::{
blockhash_query::{self, BlockhashQuery},
nonce_utils,
rpc_client::RpcClient,
};
use solana_core::validator::TestValidator;
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
commitment_config::CommitmentConfig,
nonce::State as NonceState,
pubkey::Pubkey,
signature::{Keypair, Signer},
@@ -41,12 +39,12 @@ fn test_cli_timestamp_tx() {
let default_signer0 = Keypair::new();
let default_signer1 = Keypair::new();
let mut config_payer = CliConfig::recent_for_tests();
let mut config_payer = CliConfig::default();
config_payer.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config_payer.signers = vec![&default_signer0];
let mut config_witness = CliConfig::recent_for_tests();
let mut config_witness = CliConfig::default();
config_witness.json_rpc_url = config_payer.json_rpc_url.clone();
config_witness.signers = vec![&default_signer1];
@@ -63,7 +61,7 @@ fn test_cli_timestamp_tx() {
&config_witness,
)
.unwrap();
check_recent_balance(50, &rpc_client, &config_payer.signers[0].pubkey());
check_balance(50, &rpc_client, &config_payer.signers[0].pubkey());
request_and_confirm_airdrop(
&rpc_client,
@@ -93,17 +91,17 @@ fn test_cli_timestamp_tx() {
.expect("base58-encoded public key");
let process_id = Pubkey::new(&process_id_vec);
check_recent_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_recent_balance(10, &rpc_client, &process_id); // contract balance
check_recent_balance(0, &rpc_client, &bob_pubkey); // recipient balance
check_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_balance(10, &rpc_client, &process_id); // contract balance
check_balance(0, &rpc_client, &bob_pubkey); // recipient balance
// Sign transaction by config_witness
config_witness.command = CliCommand::TimeElapsed(bob_pubkey, process_id, dt);
process_command(&config_witness).unwrap();
check_recent_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_recent_balance(0, &rpc_client, &process_id); // contract balance
check_recent_balance(10, &rpc_client, &bob_pubkey); // recipient balance
check_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_balance(0, &rpc_client, &process_id); // contract balance
check_balance(10, &rpc_client, &bob_pubkey); // recipient balance
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
@@ -128,12 +126,12 @@ fn test_cli_witness_tx() {
let default_signer0 = Keypair::new();
let default_signer1 = Keypair::new();
let mut config_payer = CliConfig::recent_for_tests();
let mut config_payer = CliConfig::default();
config_payer.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config_payer.signers = vec![&default_signer0];
let mut config_witness = CliConfig::recent_for_tests();
let mut config_witness = CliConfig::default();
config_witness.json_rpc_url = config_payer.json_rpc_url.clone();
config_witness.signers = vec![&default_signer1];
@@ -175,17 +173,17 @@ fn test_cli_witness_tx() {
.expect("base58-encoded public key");
let process_id = Pubkey::new(&process_id_vec);
check_recent_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_recent_balance(10, &rpc_client, &process_id); // contract balance
check_recent_balance(0, &rpc_client, &bob_pubkey); // recipient balance
check_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_balance(10, &rpc_client, &process_id); // contract balance
check_balance(0, &rpc_client, &bob_pubkey); // recipient balance
// Sign transaction by config_witness
config_witness.command = CliCommand::Witness(bob_pubkey, process_id);
process_command(&config_witness).unwrap();
check_recent_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_recent_balance(0, &rpc_client, &process_id); // contract balance
check_recent_balance(10, &rpc_client, &bob_pubkey); // recipient balance
check_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_balance(0, &rpc_client, &process_id); // contract balance
check_balance(10, &rpc_client, &bob_pubkey); // recipient balance
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
@@ -210,12 +208,12 @@ fn test_cli_cancel_tx() {
let default_signer0 = Keypair::new();
let default_signer1 = Keypair::new();
let mut config_payer = CliConfig::recent_for_tests();
let mut config_payer = CliConfig::default();
config_payer.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config_payer.signers = vec![&default_signer0];
let mut config_witness = CliConfig::recent_for_tests();
let mut config_witness = CliConfig::default();
config_witness.json_rpc_url = config_payer.json_rpc_url.clone();
config_witness.signers = vec![&default_signer1];
@@ -250,17 +248,17 @@ fn test_cli_cancel_tx() {
.expect("base58-encoded public key");
let process_id = Pubkey::new(&process_id_vec);
check_recent_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_recent_balance(10, &rpc_client, &process_id); // contract balance
check_recent_balance(0, &rpc_client, &bob_pubkey); // recipient balance
check_balance(40, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_balance(10, &rpc_client, &process_id); // contract balance
check_balance(0, &rpc_client, &bob_pubkey); // recipient balance
// Sign transaction by config_witness
config_payer.command = CliCommand::Cancel(process_id);
process_command(&config_payer).unwrap();
check_recent_balance(50, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_recent_balance(0, &rpc_client, &process_id); // contract balance
check_recent_balance(0, &rpc_client, &bob_pubkey); // recipient balance
check_balance(50, &rpc_client, &config_payer.signers[0].pubkey()); // config_payer balance
check_balance(0, &rpc_client, &process_id); // contract balance
check_balance(0, &rpc_client, &bob_pubkey); // recipient balance
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
@@ -285,11 +283,11 @@ fn test_offline_pay_tx() {
let default_signer = Keypair::new();
let default_offline_signer = Keypair::new();
let mut config_offline = CliConfig::recent_for_tests();
let mut config_offline = CliConfig::default();
config_offline.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config_offline.signers = vec![&default_offline_signer];
let mut config_online = CliConfig::recent_for_tests();
let mut config_online = CliConfig::default();
config_online.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config_online.signers = vec![&default_signer];
@@ -315,8 +313,8 @@ fn test_offline_pay_tx() {
&config_offline,
)
.unwrap();
check_recent_balance(50, &rpc_client, &config_offline.signers[0].pubkey());
check_recent_balance(50, &rpc_client, &config_online.signers[0].pubkey());
check_balance(50, &rpc_client, &config_offline.signers[0].pubkey());
check_balance(50, &rpc_client, &config_online.signers[0].pubkey());
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
config_offline.command = CliCommand::Pay(PayCommand {
@@ -329,9 +327,9 @@ fn test_offline_pay_tx() {
config_offline.output_format = OutputFormat::JsonCompact;
let sig_response = process_command(&config_offline).unwrap();
check_recent_balance(50, &rpc_client, &config_offline.signers[0].pubkey());
check_recent_balance(50, &rpc_client, &config_online.signers[0].pubkey());
check_recent_balance(0, &rpc_client, &bob_pubkey);
check_balance(50, &rpc_client, &config_offline.signers[0].pubkey());
check_balance(50, &rpc_client, &config_online.signers[0].pubkey());
check_balance(0, &rpc_client, &bob_pubkey);
let sign_only = parse_sign_only_reply_string(&sig_response);
assert!(sign_only.has_all_signers());
@@ -348,9 +346,9 @@ fn test_offline_pay_tx() {
});
process_command(&config_online).unwrap();
check_recent_balance(40, &rpc_client, &config_offline.signers[0].pubkey());
check_recent_balance(50, &rpc_client, &online_pubkey);
check_recent_balance(10, &rpc_client, &bob_pubkey);
check_balance(40, &rpc_client, &config_offline.signers[0].pubkey());
check_balance(50, &rpc_client, &online_pubkey);
check_balance(10, &rpc_client, &bob_pubkey);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
@@ -374,7 +372,7 @@ fn test_nonced_pay_tx() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let default_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
@@ -390,7 +388,7 @@ fn test_nonced_pay_tx() {
&config,
)
.unwrap();
check_recent_balance(
check_balance(
50 + minimum_nonce_balance,
&rpc_client,
&config.signers[0].pubkey(),
@@ -407,18 +405,14 @@ fn test_nonced_pay_tx() {
config.signers.push(&nonce_account);
process_command(&config).unwrap();
check_recent_balance(50, &rpc_client, &config.signers[0].pubkey());
check_recent_balance(minimum_nonce_balance, &rpc_client, &nonce_account.pubkey());
check_balance(50, &rpc_client, &config.signers[0].pubkey());
check_balance(minimum_nonce_balance, &rpc_client, &nonce_account.pubkey());
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
let bob_pubkey = Pubkey::new_rand();
config.signers = vec![&default_signer];
@@ -434,18 +428,14 @@ fn test_nonced_pay_tx() {
});
process_command(&config).expect("failed to process pay command");
check_recent_balance(40, &rpc_client, &config.signers[0].pubkey());
check_recent_balance(10, &rpc_client, &bob_pubkey);
check_balance(40, &rpc_client, &config.signers[0].pubkey());
check_balance(10, &rpc_client, &bob_pubkey);
// Verify that nonce has been used
let nonce_hash2 = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash2 = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
assert_ne!(nonce_hash, nonce_hash2);
server.close().unwrap();

View File

@@ -2,7 +2,7 @@ use solana_cli::cli::{process_command, CliCommand, CliConfig};
use solana_client::rpc_client::RpcClient;
use solana_core::validator::TestValidator;
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair};
use solana_sdk::signature::Keypair;
use std::{fs::remove_dir_all, sync::mpsc::channel};
#[test]
@@ -18,7 +18,7 @@ fn test_cli_request_airdrop() {
run_local_faucet(alice, sender, None);
let faucet_addr = receiver.recv().unwrap();
let mut bob_config = CliConfig::recent_for_tests();
let mut bob_config = CliConfig::default();
bob_config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
bob_config.command = CliCommand::Airdrop {
faucet_host: None,
@@ -35,9 +35,8 @@ fn test_cli_request_airdrop() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let balance = rpc_client
.get_balance_with_commitment(&bob_config.signers[0].pubkey(), CommitmentConfig::recent())
.unwrap()
.value;
.get_balance(&bob_config.signers[0].pubkey())
.unwrap();
assert_eq!(balance, 50);
server.close().unwrap();

View File

@@ -1,20 +1,18 @@
use solana_cli::test_utils::check_balance;
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
cli_output::OutputFormat,
nonce,
offline::{
blockhash_query::{self, BlockhashQuery},
parse_sign_only_reply_string,
},
spend_utils::SpendAmount,
test_utils::{check_ready, check_recent_balance},
};
use solana_client::rpc_client::RpcClient;
use solana_cli_output::{parse_sign_only_reply_string, OutputFormat};
use solana_client::{
blockhash_query::{self, BlockhashQuery},
nonce_utils,
rpc_client::RpcClient,
};
use solana_core::validator::{TestValidator, TestValidatorOptions};
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
account_utils::StateMut,
commitment_config::CommitmentConfig,
nonce::State as NonceState,
pubkey::Pubkey,
signature::{keypair_from_seed, Keypair, Signer},
@@ -41,7 +39,7 @@ fn test_stake_delegation_force() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let default_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
@@ -138,7 +136,7 @@ fn test_seed_stake_delegation_and_deactivation() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let validator_keypair = keypair_from_seed(&[0u8; 32]).unwrap();
let mut config_validator = CliConfig::recent_for_tests();
let mut config_validator = CliConfig::default();
config_validator.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config_validator.signers = vec![&validator_keypair];
@@ -151,7 +149,7 @@ fn test_seed_stake_delegation_and_deactivation() {
&config_validator,
)
.unwrap();
check_recent_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
check_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
let stake_address = Pubkey::create_with_seed(
&config_validator.signers[0].pubkey(),
@@ -183,7 +181,7 @@ fn test_seed_stake_delegation_and_deactivation() {
stake_account_pubkey: stake_address,
vote_account_pubkey: vote_pubkey,
stake_authority: 0,
force: true,
force: false,
sign_only: false,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
@@ -227,7 +225,7 @@ fn test_stake_delegation_and_deactivation() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let validator_keypair = Keypair::new();
let mut config_validator = CliConfig::recent_for_tests();
let mut config_validator = CliConfig::default();
config_validator.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config_validator.signers = vec![&validator_keypair];
@@ -242,7 +240,7 @@ fn test_stake_delegation_and_deactivation() {
&config_validator,
)
.unwrap();
check_recent_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
check_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
// Create stake account
config_validator.signers.push(&stake_keypair);
@@ -268,7 +266,7 @@ fn test_stake_delegation_and_deactivation() {
stake_account_pubkey: stake_keypair.pubkey(),
vote_account_pubkey: vote_pubkey,
stake_authority: 0,
force: true,
force: false,
sign_only: false,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
@@ -311,19 +309,19 @@ fn test_offline_stake_delegation_and_deactivation() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let mut config_validator = CliConfig::recent_for_tests();
let mut config_validator = CliConfig::default();
config_validator.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
let validator_keypair = Keypair::new();
config_validator.signers = vec![&validator_keypair];
let mut config_payer = CliConfig::recent_for_tests();
let mut config_payer = CliConfig::default();
config_payer.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
let stake_keypair = keypair_from_seed(&[0u8; 32]).unwrap();
let mut config_offline = CliConfig::recent_for_tests();
let mut config_offline = CliConfig::default();
config_offline.json_rpc_url = String::default();
config_offline.command = CliCommand::ClusterVersion;
let offline_keypair = Keypair::new();
@@ -339,7 +337,7 @@ fn test_offline_stake_delegation_and_deactivation() {
&config_offline,
)
.unwrap();
check_recent_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
check_balance(100_000, &rpc_client, &config_validator.signers[0].pubkey());
request_and_confirm_airdrop(
&rpc_client,
@@ -349,7 +347,7 @@ fn test_offline_stake_delegation_and_deactivation() {
&config_validator,
)
.unwrap();
check_recent_balance(100_000, &rpc_client, &config_offline.signers[0].pubkey());
check_balance(100_000, &rpc_client, &config_offline.signers[0].pubkey());
// Create stake account
config_validator.signers.push(&stake_keypair);
@@ -375,7 +373,7 @@ fn test_offline_stake_delegation_and_deactivation() {
stake_account_pubkey: stake_keypair.pubkey(),
vote_account_pubkey: vote_pubkey,
stake_authority: 0,
force: true,
force: false,
sign_only: true,
blockhash_query: BlockhashQuery::None(blockhash),
nonce_account: None,
@@ -394,7 +392,7 @@ fn test_offline_stake_delegation_and_deactivation() {
stake_account_pubkey: stake_keypair.pubkey(),
vote_account_pubkey: vote_pubkey,
stake_authority: 0,
force: true,
force: false,
sign_only: false,
blockhash_query: BlockhashQuery::FeeCalculator(blockhash_query::Source::Cluster, blockhash),
nonce_account: None,
@@ -455,7 +453,7 @@ fn test_nonced_stake_delegation_and_deactivation() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let config_keypair = keypair_from_seed(&[0u8; 32]).unwrap();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.signers = vec![&config_keypair];
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
@@ -503,14 +501,10 @@ fn test_nonced_stake_delegation_and_deactivation() {
process_command(&config).unwrap();
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Delegate stake
config.signers = vec![&config_keypair];
@@ -518,7 +512,7 @@ fn test_nonced_stake_delegation_and_deactivation() {
stake_account_pubkey: stake_keypair.pubkey(),
vote_account_pubkey: vote_pubkey,
stake_authority: 0,
force: true,
force: false,
sign_only: false,
blockhash_query: BlockhashQuery::FeeCalculator(
blockhash_query::Source::NonceAccount(nonce_account.pubkey()),
@@ -531,14 +525,10 @@ fn test_nonced_stake_delegation_and_deactivation() {
process_command(&config).unwrap();
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Deactivate stake
config.command = CliCommand::DeactivateStake {
@@ -577,7 +567,7 @@ fn test_stake_authorize() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let default_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
@@ -591,7 +581,7 @@ fn test_stake_authorize() {
.unwrap();
let offline_keypair = keypair_from_seed(&[0u8; 32]).unwrap();
let mut config_offline = CliConfig::recent_for_tests();
let mut config_offline = CliConfig::default();
config_offline.signers = vec![&offline_keypair];
config_offline.json_rpc_url = String::default();
let offline_authority_pubkey = config_offline.signers[0].pubkey();
@@ -642,11 +632,7 @@ fn test_stake_authorize() {
fee_payer: 0,
};
process_command(&config).unwrap();
let stake_account = rpc_client
.get_account_with_commitment(&stake_account_pubkey, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
let stake_state: StakeState = stake_account.state().unwrap();
let current_authority = match stake_state {
StakeState::Initialized(meta) => meta.authorized.staker,
@@ -673,11 +659,7 @@ fn test_stake_authorize() {
fee_payer: 0,
};
process_command(&config).unwrap();
let stake_account = rpc_client
.get_account_with_commitment(&stake_account_pubkey, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
let stake_state: StakeState = stake_account.state().unwrap();
let (current_staker, current_withdrawer) = match stake_state {
StakeState::Initialized(meta) => (meta.authorized.staker, meta.authorized.withdrawer),
@@ -699,11 +681,7 @@ fn test_stake_authorize() {
fee_payer: 0,
};
process_command(&config).unwrap();
let stake_account = rpc_client
.get_account_with_commitment(&stake_account_pubkey, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
let stake_state: StakeState = stake_account.state().unwrap();
let current_authority = match stake_state {
StakeState::Initialized(meta) => meta.authorized.staker,
@@ -714,10 +692,7 @@ fn test_stake_authorize() {
// Offline assignment of new nonced stake authority
let nonced_authority = Keypair::new();
let nonced_authority_pubkey = nonced_authority.pubkey();
let (blockhash, _, _) = rpc_client
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.unwrap()
.value;
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
config_offline.command = CliCommand::StakeAuthorize {
stake_account_pubkey,
new_authorizations: vec![(StakeAuthorize::Staker, nonced_authority_pubkey, 0)],
@@ -743,11 +718,7 @@ fn test_stake_authorize() {
fee_payer: 0,
};
process_command(&config).unwrap();
let stake_account = rpc_client
.get_account_with_commitment(&stake_account_pubkey, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
let stake_state: StakeState = stake_account.state().unwrap();
let current_authority = match stake_state {
StakeState::Initialized(meta) => meta.authorized.staker,
@@ -770,14 +741,10 @@ fn test_stake_authorize() {
process_command(&config).unwrap();
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Nonced assignment of new online stake authority
let online_authority = Keypair::new();
@@ -812,11 +779,7 @@ fn test_stake_authorize() {
fee_payer: 0,
};
process_command(&config).unwrap();
let stake_account = rpc_client
.get_account_with_commitment(&stake_account_pubkey, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
let stake_state: StakeState = stake_account.state().unwrap();
let current_authority = match stake_state {
StakeState::Initialized(meta) => meta.authorized.staker,
@@ -824,14 +787,10 @@ fn test_stake_authorize() {
};
assert_eq!(current_authority, online_authority_pubkey);
let new_nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let new_nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
assert_ne!(nonce_hash, new_nonce_hash);
server.close().unwrap();
@@ -862,18 +821,18 @@ fn test_stake_authorize_with_fee_payer() {
let default_signer = Keypair::new();
let default_pubkey = default_signer.pubkey();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
let payer_keypair = keypair_from_seed(&[0u8; 32]).unwrap();
let mut config_payer = CliConfig::recent_for_tests();
let mut config_payer = CliConfig::default();
config_payer.signers = vec![&payer_keypair];
config_payer.json_rpc_url =
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
let payer_pubkey = config_payer.signers[0].pubkey();
let mut config_offline = CliConfig::recent_for_tests();
let mut config_offline = CliConfig::default();
let offline_signer = Keypair::new();
config_offline.signers = vec![&offline_signer];
config_offline.json_rpc_url = String::new();
@@ -884,17 +843,15 @@ fn test_stake_authorize_with_fee_payer() {
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &default_pubkey, 100_000, &config)
.unwrap();
check_recent_balance(100_000, &rpc_client, &config.signers[0].pubkey());
check_balance(100_000, &rpc_client, &config.signers[0].pubkey());
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &payer_pubkey, 100_000, &config)
.unwrap();
check_recent_balance(100_000, &rpc_client, &payer_pubkey);
check_balance(100_000, &rpc_client, &payer_pubkey);
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000, &config)
.unwrap();
check_recent_balance(100_000, &rpc_client, &offline_pubkey);
check_ready(&rpc_client);
check_balance(100_000, &rpc_client, &offline_pubkey);
// Create stake account, identity is authority
let stake_keypair = Keypair::new();
@@ -916,7 +873,7 @@ fn test_stake_authorize_with_fee_payer() {
};
process_command(&config).unwrap();
// `config` balance should be 50,000 - 1 stake account sig - 1 fee sig
check_recent_balance(50_000 - SIG_FEE - SIG_FEE, &rpc_client, &default_pubkey);
check_balance(50_000 - SIG_FEE - SIG_FEE, &rpc_client, &default_pubkey);
// Assign authority with separate fee payer
config.signers = vec![&default_signer, &payer_keypair];
@@ -931,16 +888,13 @@ fn test_stake_authorize_with_fee_payer() {
};
process_command(&config).unwrap();
// `config` balance has not changed, despite submitting the TX
check_recent_balance(50_000 - SIG_FEE - SIG_FEE, &rpc_client, &default_pubkey);
check_balance(50_000 - SIG_FEE - SIG_FEE, &rpc_client, &default_pubkey);
// `config_payer` however has paid `config`'s authority sig
// and `config_payer`'s fee sig
check_recent_balance(100_000 - SIG_FEE - SIG_FEE, &rpc_client, &payer_pubkey);
check_balance(100_000 - SIG_FEE - SIG_FEE, &rpc_client, &payer_pubkey);
// Assign authority with offline fee payer
let (blockhash, _, _) = rpc_client
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.unwrap()
.value;
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
config_offline.command = CliCommand::StakeAuthorize {
stake_account_pubkey,
new_authorizations: vec![(StakeAuthorize::Staker, payer_pubkey, 0)],
@@ -967,10 +921,10 @@ fn test_stake_authorize_with_fee_payer() {
};
process_command(&config).unwrap();
// `config`'s balance again has not changed
check_recent_balance(50_000 - SIG_FEE - SIG_FEE, &rpc_client, &default_pubkey);
check_balance(50_000 - SIG_FEE - SIG_FEE, &rpc_client, &default_pubkey);
// `config_offline` however has paid 1 sig due to being both authority
// and fee payer
check_recent_balance(100_000 - SIG_FEE, &rpc_client, &offline_pubkey);
check_balance(100_000 - SIG_FEE, &rpc_client, &offline_pubkey);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
@@ -999,11 +953,11 @@ fn test_stake_split() {
let default_signer = Keypair::new();
let offline_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
let mut config_offline = CliConfig::recent_for_tests();
let mut config_offline = CliConfig::default();
config_offline.json_rpc_url = String::default();
config_offline.signers = vec![&offline_signer];
let offline_pubkey = config_offline.signers[0].pubkey();
@@ -1019,11 +973,11 @@ fn test_stake_split() {
&config,
)
.unwrap();
check_recent_balance(500_000, &rpc_client, &config.signers[0].pubkey());
check_balance(500_000, &rpc_client, &config.signers[0].pubkey());
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000, &config)
.unwrap();
check_recent_balance(100_000, &rpc_client, &offline_pubkey);
check_balance(100_000, &rpc_client, &offline_pubkey);
// Create stake account, identity is authority
let minimum_stake_balance = rpc_client
@@ -1047,7 +1001,7 @@ fn test_stake_split() {
from: 0,
};
process_command(&config).unwrap();
check_recent_balance(
check_balance(
10 * minimum_stake_balance,
&rpc_client,
&stake_account_pubkey,
@@ -1066,21 +1020,17 @@ fn test_stake_split() {
amount: SpendAmount::Some(minimum_nonce_balance),
};
process_command(&config).unwrap();
check_recent_balance(minimum_nonce_balance, &rpc_client, &nonce_account.pubkey());
check_balance(minimum_nonce_balance, &rpc_client, &nonce_account.pubkey());
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Nonced offline split
let split_account = keypair_from_seed(&[2u8; 32]).unwrap();
check_recent_balance(0, &rpc_client, &split_account.pubkey());
check_balance(0, &rpc_client, &split_account.pubkey());
config_offline.signers.push(&split_account);
config_offline.command = CliCommand::SplitStake {
stake_account_pubkey,
@@ -1116,12 +1066,12 @@ fn test_stake_split() {
fee_payer: 0,
};
process_command(&config).unwrap();
check_recent_balance(
check_balance(
8 * minimum_stake_balance,
&rpc_client,
&stake_account_pubkey,
);
check_recent_balance(
check_balance(
2 * minimum_stake_balance,
&rpc_client,
&split_account.pubkey(),
@@ -1154,11 +1104,11 @@ fn test_stake_set_lockup() {
let default_signer = Keypair::new();
let offline_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
let mut config_offline = CliConfig::recent_for_tests();
let mut config_offline = CliConfig::default();
config_offline.json_rpc_url = String::default();
config_offline.signers = vec![&offline_signer];
let offline_pubkey = config_offline.signers[0].pubkey();
@@ -1174,11 +1124,11 @@ fn test_stake_set_lockup() {
&config,
)
.unwrap();
check_recent_balance(500_000, &rpc_client, &config.signers[0].pubkey());
check_balance(500_000, &rpc_client, &config.signers[0].pubkey());
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000, &config)
.unwrap();
check_recent_balance(100_000, &rpc_client, &offline_pubkey);
check_balance(100_000, &rpc_client, &offline_pubkey);
// Create stake account, identity is authority
let minimum_stake_balance = rpc_client
@@ -1207,7 +1157,7 @@ fn test_stake_set_lockup() {
from: 0,
};
process_command(&config).unwrap();
check_recent_balance(
check_balance(
10 * minimum_stake_balance,
&rpc_client,
&stake_account_pubkey,
@@ -1231,11 +1181,7 @@ fn test_stake_set_lockup() {
fee_payer: 0,
};
process_command(&config).unwrap();
let stake_account = rpc_client
.get_account_with_commitment(&stake_account_pubkey, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
let stake_state: StakeState = stake_account.state().unwrap();
let current_lockup = match stake_state {
StakeState::Initialized(meta) => meta.lockup,
@@ -1286,11 +1232,7 @@ fn test_stake_set_lockup() {
fee_payer: 0,
};
process_command(&config).unwrap();
let stake_account = rpc_client
.get_account_with_commitment(&stake_account_pubkey, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
let stake_state: StakeState = stake_account.state().unwrap();
let current_lockup = match stake_state {
StakeState::Initialized(meta) => meta.lockup,
@@ -1335,17 +1277,13 @@ fn test_stake_set_lockup() {
amount: SpendAmount::Some(minimum_nonce_balance),
};
process_command(&config).unwrap();
check_recent_balance(minimum_nonce_balance, &rpc_client, &nonce_account_pubkey);
check_balance(minimum_nonce_balance, &rpc_client, &nonce_account_pubkey);
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Nonced offline set lockup
let lockup = LockupArgs {
@@ -1383,11 +1321,7 @@ fn test_stake_set_lockup() {
fee_payer: 0,
};
process_command(&config).unwrap();
let stake_account = rpc_client
.get_account_with_commitment(&stake_account_pubkey, CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap();
let stake_state: StakeState = stake_account.state().unwrap();
let current_lockup = match stake_state {
StakeState::Initialized(meta) => meta.lockup,
@@ -1421,12 +1355,12 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
let default_signer = keypair_from_seed(&[1u8; 32]).unwrap();
config.signers = vec![&default_signer];
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
let mut config_offline = CliConfig::recent_for_tests();
let mut config_offline = CliConfig::default();
let offline_signer = keypair_from_seed(&[2u8; 32]).unwrap();
config_offline.signers = vec![&offline_signer];
let offline_pubkey = config_offline.signers[0].pubkey();
@@ -1443,11 +1377,11 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
&config,
)
.unwrap();
check_recent_balance(200_000, &rpc_client, &config.signers[0].pubkey());
check_balance(200_000, &rpc_client, &config.signers[0].pubkey());
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 100_000, &config)
.unwrap();
check_recent_balance(100_000, &rpc_client, &offline_pubkey);
check_balance(100_000, &rpc_client, &offline_pubkey);
// Create nonce account
let minimum_nonce_balance = rpc_client
@@ -1465,14 +1399,10 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
process_command(&config).unwrap();
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Create stake account offline
let stake_keypair = keypair_from_seed(&[4u8; 32]).unwrap();
@@ -1517,17 +1447,13 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
from: 0,
};
process_command(&config).unwrap();
check_recent_balance(50_000, &rpc_client, &stake_pubkey);
check_balance(50_000, &rpc_client, &stake_pubkey);
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Offline, nonced stake-withdraw
let recipient = keypair_from_seed(&[5u8; 32]).unwrap();
@@ -1565,17 +1491,13 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
fee_payer: 0,
};
process_command(&config).unwrap();
check_recent_balance(42, &rpc_client, &recipient_pubkey);
check_balance(42, &rpc_client, &recipient_pubkey);
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Create another stake account. This time with seed
let seed = "seedy";
@@ -1619,7 +1541,7 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
process_command(&config).unwrap();
let seed_address =
Pubkey::create_with_seed(&stake_pubkey, seed, &solana_stake_program::id()).unwrap();
check_recent_balance(50_000, &rpc_client, &seed_address);
check_balance(50_000, &rpc_client, &seed_address);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();

View File

@@ -1,19 +1,17 @@
use solana_cli::test_utils::check_balance;
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
cli_output::OutputFormat,
nonce,
offline::{
blockhash_query::{self, BlockhashQuery},
parse_sign_only_reply_string,
},
spend_utils::SpendAmount,
test_utils::{check_ready, check_recent_balance},
};
use solana_client::rpc_client::RpcClient;
use solana_cli_output::{parse_sign_only_reply_string, OutputFormat};
use solana_client::{
blockhash_query::{self, BlockhashQuery},
nonce_utils,
rpc_client::RpcClient,
};
use solana_core::validator::{TestValidator, TestValidatorOptions};
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
commitment_config::CommitmentConfig,
nonce::State as NonceState,
pubkey::Pubkey,
signature::{keypair_from_seed, Keypair, NullSigner, Signer},
@@ -43,7 +41,7 @@ fn test_transfer() {
let default_signer = Keypair::new();
let default_offline_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
@@ -52,10 +50,8 @@ fn test_transfer() {
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &sender_pubkey, 50_000, &config)
.unwrap();
check_recent_balance(50_000, &rpc_client, &sender_pubkey);
check_recent_balance(0, &rpc_client, &recipient_pubkey);
check_ready(&rpc_client);
check_balance(50_000, &rpc_client, &sender_pubkey);
check_balance(0, &rpc_client, &recipient_pubkey);
// Plain ole transfer
config.command = CliCommand::Transfer {
@@ -70,8 +66,8 @@ fn test_transfer() {
fee_payer: 0,
};
process_command(&config).unwrap();
check_recent_balance(49_989, &rpc_client, &sender_pubkey);
check_recent_balance(10, &rpc_client, &recipient_pubkey);
check_balance(49_989, &rpc_client, &sender_pubkey);
check_balance(10, &rpc_client, &recipient_pubkey);
// Plain ole transfer, failure due to InsufficientFundsForSpendAndFee
config.command = CliCommand::Transfer {
@@ -86,10 +82,10 @@ fn test_transfer() {
fee_payer: 0,
};
assert!(process_command(&config).is_err());
check_recent_balance(49_989, &rpc_client, &sender_pubkey);
check_recent_balance(10, &rpc_client, &recipient_pubkey);
check_balance(49_989, &rpc_client, &sender_pubkey);
check_balance(10, &rpc_client, &recipient_pubkey);
let mut offline = CliConfig::recent_for_tests();
let mut offline = CliConfig::default();
offline.json_rpc_url = String::default();
offline.signers = vec![&default_offline_signer];
// Verify we cannot contact the cluster
@@ -98,13 +94,10 @@ fn test_transfer() {
let offline_pubkey = offline.signers[0].pubkey();
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &offline_pubkey, 50, &config).unwrap();
check_recent_balance(50, &rpc_client, &offline_pubkey);
check_balance(50, &rpc_client, &offline_pubkey);
// Offline transfer
let (blockhash, _, _) = rpc_client
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.unwrap()
.value;
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
offline.command = CliCommand::Transfer {
amount: SpendAmount::Some(10),
to: recipient_pubkey,
@@ -134,8 +127,8 @@ fn test_transfer() {
fee_payer: 0,
};
process_command(&config).unwrap();
check_recent_balance(39, &rpc_client, &offline_pubkey);
check_recent_balance(20, &rpc_client, &recipient_pubkey);
check_balance(39, &rpc_client, &offline_pubkey);
check_balance(20, &rpc_client, &recipient_pubkey);
// Create nonce account
let nonce_account = keypair_from_seed(&[3u8; 32]).unwrap();
@@ -150,17 +143,13 @@ fn test_transfer() {
amount: SpendAmount::Some(minimum_nonce_balance),
};
process_command(&config).unwrap();
check_recent_balance(49_987 - minimum_nonce_balance, &rpc_client, &sender_pubkey);
check_balance(49_987 - minimum_nonce_balance, &rpc_client, &sender_pubkey);
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Nonced transfer
config.signers = vec![&default_signer];
@@ -179,16 +168,12 @@ fn test_transfer() {
fee_payer: 0,
};
process_command(&config).unwrap();
check_recent_balance(49_976 - minimum_nonce_balance, &rpc_client, &sender_pubkey);
check_recent_balance(30, &rpc_client, &recipient_pubkey);
let new_nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
check_balance(49_976 - minimum_nonce_balance, &rpc_client, &sender_pubkey);
check_balance(30, &rpc_client, &recipient_pubkey);
let new_nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
assert_ne!(nonce_hash, new_nonce_hash);
// Assign nonce authority to offline
@@ -199,17 +184,13 @@ fn test_transfer() {
new_authority: offline_pubkey,
};
process_command(&config).unwrap();
check_recent_balance(49_975 - minimum_nonce_balance, &rpc_client, &sender_pubkey);
check_balance(49_975 - minimum_nonce_balance, &rpc_client, &sender_pubkey);
// Fetch nonce hash
let nonce_hash = nonce::get_account_with_commitment(
&rpc_client,
&nonce_account.pubkey(),
CommitmentConfig::recent(),
)
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let nonce_hash = nonce_utils::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce_utils::data_from_account(a))
.unwrap()
.blockhash;
// Offline, nonced transfer
offline.signers = vec![&default_offline_signer];
@@ -244,8 +225,8 @@ fn test_transfer() {
fee_payer: 0,
};
process_command(&config).unwrap();
check_recent_balance(28, &rpc_client, &offline_pubkey);
check_recent_balance(40, &rpc_client, &recipient_pubkey);
check_balance(28, &rpc_client, &offline_pubkey);
check_balance(40, &rpc_client, &recipient_pubkey);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
@@ -273,7 +254,7 @@ fn test_transfer_multisession_signing() {
let offline_from_signer = keypair_from_seed(&[2u8; 32]).unwrap();
let offline_fee_payer_signer = keypair_from_seed(&[3u8; 32]).unwrap();
let from_null_signer = NullSigner::new(&offline_from_signer.pubkey());
let config = CliConfig::recent_for_tests();
let config = CliConfig::default();
// Setup accounts
let rpc_client = RpcClient::new_socket(leader_data.rpc);
@@ -293,19 +274,14 @@ fn test_transfer_multisession_signing() {
&config,
)
.unwrap();
check_recent_balance(43, &rpc_client, &offline_from_signer.pubkey());
check_recent_balance(3, &rpc_client, &offline_fee_payer_signer.pubkey());
check_recent_balance(0, &rpc_client, &to_pubkey);
check_balance(43, &rpc_client, &offline_from_signer.pubkey());
check_balance(3, &rpc_client, &offline_fee_payer_signer.pubkey());
check_balance(0, &rpc_client, &to_pubkey);
check_ready(&rpc_client);
let (blockhash, _, _) = rpc_client
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())
.unwrap()
.value;
let (blockhash, _) = rpc_client.get_recent_blockhash().unwrap();
// Offline fee-payer signs first
let mut fee_payer_config = CliConfig::recent_for_tests();
let mut fee_payer_config = CliConfig::default();
fee_payer_config.json_rpc_url = String::default();
fee_payer_config.signers = vec![&offline_fee_payer_signer, &from_null_signer];
// Verify we cannot contact the cluster
@@ -331,7 +307,7 @@ fn test_transfer_multisession_signing() {
.unwrap();
// Now the offline fund source
let mut from_config = CliConfig::recent_for_tests();
let mut from_config = CliConfig::default();
from_config.json_rpc_url = String::default();
from_config.signers = vec![&fee_payer_presigner, &offline_from_signer];
// Verify we cannot contact the cluster
@@ -357,7 +333,7 @@ fn test_transfer_multisession_signing() {
.unwrap();
// Finally submit to the cluster
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&fee_payer_presigner, &from_presigner];
config.command = CliCommand::Transfer {
@@ -373,9 +349,9 @@ fn test_transfer_multisession_signing() {
};
process_command(&config).unwrap();
check_recent_balance(1, &rpc_client, &offline_from_signer.pubkey());
check_recent_balance(1, &rpc_client, &offline_fee_payer_signer.pubkey());
check_recent_balance(42, &rpc_client, &to_pubkey);
check_balance(1, &rpc_client, &offline_from_signer.pubkey());
check_balance(1, &rpc_client, &offline_fee_payer_signer.pubkey());
check_balance(42, &rpc_client, &to_pubkey);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
@@ -403,7 +379,7 @@ fn test_transfer_all() {
let default_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
@@ -412,10 +388,8 @@ fn test_transfer_all() {
request_and_confirm_airdrop(&rpc_client, &faucet_addr, &sender_pubkey, 50_000, &config)
.unwrap();
check_recent_balance(50_000, &rpc_client, &sender_pubkey);
check_recent_balance(0, &rpc_client, &recipient_pubkey);
check_ready(&rpc_client);
check_balance(50_000, &rpc_client, &sender_pubkey);
check_balance(0, &rpc_client, &recipient_pubkey);
// Plain ole transfer
config.command = CliCommand::Transfer {
@@ -430,8 +404,8 @@ fn test_transfer_all() {
fee_payer: 0,
};
process_command(&config).unwrap();
check_recent_balance(0, &rpc_client, &sender_pubkey);
check_recent_balance(49_999, &rpc_client, &recipient_pubkey);
check_balance(0, &rpc_client, &sender_pubkey);
check_balance(49_999, &rpc_client, &recipient_pubkey);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();

View File

@@ -1,15 +1,16 @@
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
offline::{blockhash_query::BlockhashQuery, *},
spend_utils::SpendAmount,
test_utils::check_recent_balance,
test_utils::check_balance,
};
use solana_client::{
blockhash_query::{self, BlockhashQuery},
rpc_client::RpcClient,
};
use solana_client::rpc_client::RpcClient;
use solana_core::validator::TestValidator;
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
account_utils::StateMut,
commitment_config::CommitmentConfig,
pubkey::Pubkey,
signature::{Keypair, Signer},
};
@@ -32,7 +33,7 @@ fn test_vote_authorize_and_withdraw() {
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let default_signer = Keypair::new();
let mut config = CliConfig::recent_for_tests();
let mut config = CliConfig::default();
config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
config.signers = vec![&default_signer];
@@ -59,9 +60,7 @@ fn test_vote_authorize_and_withdraw() {
};
process_command(&config).unwrap();
let vote_account = rpc_client
.get_account_with_commitment(&vote_account_keypair.pubkey(), CommitmentConfig::recent())
.unwrap()
.value
.get_account(&vote_account_keypair.pubkey())
.unwrap();
let vote_state: VoteStateVersions = vote_account.state().unwrap();
let authorized_withdrawer = vote_state.convert_to_current().authorized_withdrawer;
@@ -70,7 +69,7 @@ fn test_vote_authorize_and_withdraw() {
.get_minimum_balance_for_rent_exemption(VoteState::size_of())
.unwrap()
.max(1);
check_recent_balance(expected_balance, &rpc_client, &vote_account_pubkey);
check_balance(expected_balance, &rpc_client, &vote_account_pubkey);
// Transfer in some more SOL
config.signers = vec![&default_signer];
@@ -87,7 +86,7 @@ fn test_vote_authorize_and_withdraw() {
};
process_command(&config).unwrap();
let expected_balance = expected_balance + 1_000;
check_recent_balance(expected_balance, &rpc_client, &vote_account_pubkey);
check_balance(expected_balance, &rpc_client, &vote_account_pubkey);
// Authorize vote account withdrawal to another signer
let withdraw_authority = Keypair::new();
@@ -99,9 +98,7 @@ fn test_vote_authorize_and_withdraw() {
};
process_command(&config).unwrap();
let vote_account = rpc_client
.get_account_with_commitment(&vote_account_keypair.pubkey(), CommitmentConfig::recent())
.unwrap()
.value
.get_account(&vote_account_keypair.pubkey())
.unwrap();
let vote_state: VoteStateVersions = vote_account.state().unwrap();
let authorized_withdrawer = vote_state.convert_to_current().authorized_withdrawer;
@@ -117,8 +114,8 @@ fn test_vote_authorize_and_withdraw() {
destination_account_pubkey: destination_account,
};
process_command(&config).unwrap();
check_recent_balance(expected_balance - 100, &rpc_client, &vote_account_pubkey);
check_recent_balance(100, &rpc_client, &destination_account);
check_balance(expected_balance - 100, &rpc_client, &vote_account_pubkey);
check_balance(100, &rpc_client, &destination_account);
// Re-assign validator identity
let new_identity_keypair = Keypair::new();

View File

@@ -1,8 +1,8 @@
[package]
name = "solana-client"
version = "1.3.1"
version = "1.2.33"
description = "Solana Client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
authors = ["Solana Maintainers <maintainers@solana.com>"]
repository = "https://github.com/solana-labs/solana"
homepage = "https://solana.com/"
license = "Apache-2.0"
@@ -11,28 +11,30 @@ edition = "2018"
[dependencies]
bincode = "1.3.1"
bs58 = "0.3.1"
indicatif = "0.15.0"
jsonrpc-core = "14.2.0"
clap = "2.33.0"
indicatif = "0.14.0"
jsonrpc-core = "15.0.0"
log = "0.4.8"
rayon = "1.3.1"
reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde = "1.0.112"
rayon = "1.4.0"
reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde = "1.0.110"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "1.3.1" }
solana-net-utils = { path = "../net-utils", version = "1.3.1" }
solana-sdk = { path = "../sdk", version = "1.3.1" }
solana-transaction-status = { path = "../transaction-status", version = "1.3.1" }
solana-vote-program = { path = "../programs/vote", version = "1.3.1" }
serde_json = "1.0.53"
solana-account-decoder = { path = "../account-decoder", version = "1.2.33" }
solana-clap-utils = { path = "../clap-utils", version = "1.2.33" }
solana-net-utils = { path = "../net-utils", version = "1.2.33" }
solana-sdk = { path = "../sdk", version = "1.2.33" }
solana-transaction-status = { path = "../transaction-status", version = "1.2.33" }
solana-vote-program = { path = "../programs/vote", version = "1.2.33" }
thiserror = "1.0"
tungstenite = "0.10.1"
url = "2.1.1"
[dev-dependencies]
assert_matches = "1.3.0"
jsonrpc-core = "14.2.0"
jsonrpc-http-server = "14.2.0"
solana-logger = { path = "../logger", version = "1.3.1" }
jsonrpc-core = "15.0.0"
jsonrpc-http-server = "15.0.0"
solana-logger = { path = "../logger", version = "1.2.33" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,5 +1,11 @@
use super::*;
use solana_sdk::commitment_config::CommitmentConfig;
use crate::{nonce_utils, rpc_client::RpcClient};
use clap::ArgMatches;
use solana_clap_utils::{
input_parsers::{pubkey_of, value_of},
nonce::*,
offline::*,
};
use solana_sdk::{fee_calculator::FeeCalculator, hash::Hash, pubkey::Pubkey};
#[derive(Debug, PartialEq)]
pub enum Source {
@@ -11,18 +17,15 @@ impl Source {
pub fn get_blockhash_and_fee_calculator(
&self,
rpc_client: &RpcClient,
commitment: CommitmentConfig,
) -> Result<(Hash, FeeCalculator), Box<dyn std::error::Error>> {
match self {
Self::Cluster => {
let res = rpc_client
.get_recent_blockhash_with_commitment(commitment)?
.value;
Ok((res.0, res.1))
let res = rpc_client.get_recent_blockhash()?;
Ok(res)
}
Self::NonceAccount(ref pubkey) => {
let data = nonce::get_account_with_commitment(rpc_client, pubkey, commitment)
.and_then(|ref a| nonce::data_from_account(a))?;
let data = nonce_utils::get_account(rpc_client, pubkey)
.and_then(|ref a| nonce_utils::data_from_account(a))?;
Ok((data.blockhash, data.fee_calculator))
}
}
@@ -32,21 +35,23 @@ impl Source {
&self,
rpc_client: &RpcClient,
blockhash: &Hash,
commitment: CommitmentConfig,
) -> Result<Option<FeeCalculator>, Box<dyn std::error::Error>> {
match self {
Self::Cluster => {
let res = rpc_client
.get_fee_calculator_for_blockhash_with_commitment(blockhash, commitment)?
.value;
let res = rpc_client.get_fee_calculator_for_blockhash(blockhash)?;
Ok(res)
}
Self::NonceAccount(ref pubkey) => {
let res = nonce::get_account_with_commitment(rpc_client, pubkey, commitment)?;
let res = nonce::data_from_account(&res)?;
Ok(Some(res)
.filter(|d| d.blockhash == *blockhash)
.map(|d| d.fee_calculator))
let res = nonce_utils::get_account(rpc_client, pubkey)
.and_then(|ref a| nonce_utils::data_from_account(a))
.and_then(|d| {
if d.blockhash == *blockhash {
Ok(Some(d.fee_calculator))
} else {
Ok(None)
}
})?;
Ok(res)
}
}
}
@@ -75,26 +80,23 @@ impl BlockhashQuery {
pub fn new_from_matches(matches: &ArgMatches<'_>) -> Self {
let blockhash = value_of(matches, BLOCKHASH_ARG.name);
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
let nonce_account = pubkey_of(matches, nonce::NONCE_ARG.name);
let nonce_account = pubkey_of(matches, NONCE_ARG.name);
BlockhashQuery::new(blockhash, sign_only, nonce_account)
}
pub fn get_blockhash_and_fee_calculator(
&self,
rpc_client: &RpcClient,
commitment: CommitmentConfig,
) -> Result<(Hash, FeeCalculator), Box<dyn std::error::Error>> {
match self {
BlockhashQuery::None(hash) => Ok((*hash, FeeCalculator::default())),
BlockhashQuery::FeeCalculator(source, hash) => {
let fee_calculator = source
.get_fee_calculator(rpc_client, hash, commitment)?
.get_fee_calculator(rpc_client, hash)?
.ok_or(format!("Hash has expired {:?}", hash))?;
Ok((*hash, fee_calculator))
}
BlockhashQuery::All(source) => {
source.get_blockhash_and_fee_calculator(rpc_client, commitment)
}
BlockhashQuery::All(source) => source.get_blockhash_and_fee_calculator(rpc_client),
}
}
}
@@ -108,17 +110,15 @@ impl Default for BlockhashQuery {
#[cfg(test)]
mod tests {
use super::*;
use crate::{nonce::nonce_arg, offline::blockhash_query::BlockhashQuery};
use clap::App;
use serde_json::{self, json, Value};
use solana_account_decoder::{UiAccount, UiAccountEncoding};
use solana_client::{
use crate::{
blockhash_query,
rpc_request::RpcRequest,
rpc_response::{Response, RpcFeeCalculator, RpcResponseContext},
};
use solana_sdk::{
account::Account, fee_calculator::FeeCalculator, hash::hash, nonce, system_program,
};
use clap::App;
use serde_json::{self, json, Value};
use solana_account_decoder::{UiAccount, UiAccountEncoding};
use solana_sdk::{account::Account, hash::hash, nonce, system_program};
use std::collections::HashMap;
#[test]
@@ -171,9 +171,7 @@ mod tests {
#[test]
fn test_blockhash_query_new_from_matches_ok() {
let test_commands = App::new("blockhash_query_test")
.arg(nonce_arg())
.offline_args();
let test_commands = App::new("blockhash_query_test").nonce_args().offline_args();
let blockhash = hash(&[1u8]);
let blockhash_string = blockhash.to_string();
@@ -298,7 +296,7 @@ mod tests {
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::default()
.get_blockhash_and_fee_calculator(&rpc_client, CommitmentConfig::default())
.get_blockhash_and_fee_calculator(&rpc_client)
.unwrap(),
(rpc_blockhash, rpc_fee_calc.clone()),
);
@@ -314,7 +312,7 @@ mod tests {
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::FeeCalculator(Source::Cluster, test_blockhash)
.get_blockhash_and_fee_calculator(&rpc_client, CommitmentConfig::default())
.get_blockhash_and_fee_calculator(&rpc_client)
.unwrap(),
(test_blockhash, rpc_fee_calc),
);
@@ -326,13 +324,13 @@ mod tests {
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::None(test_blockhash)
.get_blockhash_and_fee_calculator(&rpc_client, CommitmentConfig::default())
.get_blockhash_and_fee_calculator(&rpc_client)
.unwrap(),
(test_blockhash, FeeCalculator::default()),
);
let rpc_client = RpcClient::new_mock("fails".to_string());
assert!(BlockhashQuery::default()
.get_blockhash_and_fee_calculator(&rpc_client, CommitmentConfig::default())
.get_blockhash_and_fee_calculator(&rpc_client)
.is_err());
let nonce_blockhash = Hash::new(&[2u8; 32]);
@@ -350,7 +348,13 @@ mod tests {
)
.unwrap();
let nonce_pubkey = Pubkey::new(&[4u8; 32]);
let rpc_nonce_account = UiAccount::encode(nonce_account, UiAccountEncoding::Binary, None);
let rpc_nonce_account = UiAccount::encode(
&nonce_pubkey,
nonce_account,
UiAccountEncoding::Base64,
None,
None,
);
let get_account_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!(Some(rpc_nonce_account)),
@@ -361,7 +365,7 @@ mod tests {
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::All(Source::NonceAccount(nonce_pubkey))
.get_blockhash_and_fee_calculator(&rpc_client, CommitmentConfig::default())
.get_blockhash_and_fee_calculator(&rpc_client)
.unwrap(),
(nonce_blockhash, nonce_fee_calc.clone()),
);
@@ -370,7 +374,7 @@ mod tests {
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::FeeCalculator(Source::NonceAccount(nonce_pubkey), nonce_blockhash)
.get_blockhash_and_fee_calculator(&rpc_client, CommitmentConfig::default())
.get_blockhash_and_fee_calculator(&rpc_client)
.unwrap(),
(nonce_blockhash, nonce_fee_calc),
);
@@ -379,7 +383,7 @@ mod tests {
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert!(
BlockhashQuery::FeeCalculator(Source::NonceAccount(nonce_pubkey), test_blockhash)
.get_blockhash_and_fee_calculator(&rpc_client, CommitmentConfig::default())
.get_blockhash_and_fee_calculator(&rpc_client)
.is_err()
);
let mut mocks = HashMap::new();
@@ -387,14 +391,14 @@ mod tests {
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::None(nonce_blockhash)
.get_blockhash_and_fee_calculator(&rpc_client, CommitmentConfig::default())
.get_blockhash_and_fee_calculator(&rpc_client)
.unwrap(),
(nonce_blockhash, FeeCalculator::default()),
);
let rpc_client = RpcClient::new_mock("fails".to_string());
assert!(BlockhashQuery::All(Source::NonceAccount(nonce_pubkey))
.get_blockhash_and_fee_calculator(&rpc_client, CommitmentConfig::default())
.get_blockhash_and_fee_calculator(&rpc_client)
.is_err());
}
}

View File

@@ -1,9 +1,11 @@
#[macro_use]
extern crate serde_derive;
pub mod blockhash_query;
pub mod client_error;
pub mod http_sender;
pub mod mock_sender;
pub mod nonce_utils;
pub mod perf_utils;
pub mod pubsub_client;
pub mod rpc_client;

68
client/src/nonce_utils.rs Normal file
View File

@@ -0,0 +1,68 @@
use crate::rpc_client::RpcClient;
use solana_sdk::{
account::Account,
account_utils::StateMut,
nonce::{
state::{Data, Versions},
State,
},
pubkey::Pubkey,
system_program,
};
#[derive(Debug, thiserror::Error, PartialEq)]
pub enum Error {
#[error("invalid account owner")]
InvalidAccountOwner,
#[error("invalid account data")]
InvalidAccountData,
#[error("unexpected account data size")]
UnexpectedDataSize,
#[error("query hash does not match stored hash")]
InvalidHash,
#[error("query authority does not match account authority")]
InvalidAuthority,
#[error("invalid state for requested operation")]
InvalidStateForOperation,
#[error("client error: {0}")]
Client(String),
}
pub fn get_account(rpc_client: &RpcClient, nonce_pubkey: &Pubkey) -> Result<Account, Error> {
rpc_client
.get_account(nonce_pubkey)
.map_err(|e| Error::Client(format!("{}", e)))
.and_then(|a| match account_identity_ok(&a) {
Ok(()) => Ok(a),
Err(e) => Err(e),
})
}
pub fn account_identity_ok(account: &Account) -> Result<(), Error> {
if account.owner != system_program::id() {
Err(Error::InvalidAccountOwner)
} else if account.data.is_empty() {
Err(Error::UnexpectedDataSize)
} else {
Ok(())
}
}
pub fn state_from_account(account: &Account) -> Result<State, Error> {
account_identity_ok(account)?;
StateMut::<Versions>::state(account)
.map_err(|_| Error::InvalidAccountData)
.map(|v| v.convert_to_current())
}
pub fn data_from_account(account: &Account) -> Result<Data, Error> {
account_identity_ok(account)?;
state_from_account(account).and_then(|ref s| data_from_state(s).map(|d| d.clone()))
}
pub fn data_from_state(state: &State) -> Result<&Data, Error> {
match state {
State::Uninitialized => Err(Error::InvalidStateForOperation),
State::Initialized(data) => Ok(data),
}
}

View File

@@ -2,6 +2,7 @@ use crate::{
client_error::{ClientError, ClientErrorKind, Result as ClientResult},
http_sender::HttpSender,
mock_sender::{MockSender, Mocks},
rpc_config::RpcAccountInfoConfig,
rpc_config::{
RpcGetConfirmedSignaturesForAddress2Config, RpcLargestAccountsConfig,
RpcSendTransactionConfig, RpcTokenAccountsFilter,
@@ -14,26 +15,21 @@ use bincode::serialize;
use indicatif::{ProgressBar, ProgressStyle};
use log::*;
use serde_json::{json, Value};
use solana_account_decoder::{
parse_token::{
get_token_account_mint, parse_token, TokenAccountType, UiMint, UiMultisig, UiTokenAccount,
UiTokenAmount,
},
UiAccount,
};
use solana_account_decoder::{parse_token::UiTokenAmount, UiAccount, UiAccountEncoding};
use solana_sdk::{
account::Account,
clock::{
Slot, UnixTimestamp, DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT,
MAX_HASH_AGE_IN_SECONDS,
},
commitment_config::{CommitmentConfig, CommitmentLevel},
commitment_config::CommitmentConfig,
epoch_info::EpochInfo,
epoch_schedule::EpochSchedule,
fee_calculator::{FeeCalculator, FeeRateGovernor},
hash::Hash,
pubkey::Pubkey,
signature::Signature,
signers::Signers,
transaction::{self, Transaction},
};
use solana_transaction_status::{
@@ -41,7 +37,6 @@ use solana_transaction_status::{
};
use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY;
use std::{
collections::HashMap,
net::SocketAddr,
thread::sleep,
time::{Duration, Instant},
@@ -62,10 +57,6 @@ impl RpcClient {
Self::new_sender(HttpSender::new(url))
}
pub fn new_with_timeout(url: String, timeout: Duration) -> Self {
Self::new_sender(HttpSender::new_with_timeout(url, timeout))
}
pub fn new_mock(url: String) -> Self {
Self::new_sender(MockSender::new(url))
}
@@ -80,7 +71,7 @@ impl RpcClient {
pub fn new_socket_with_timeout(addr: SocketAddr, timeout: Duration) -> Self {
let url = get_rpc_request_str(addr, false);
Self::new_with_timeout(url, timeout)
Self::new_sender(HttpSender::new_with_timeout(url, timeout))
}
pub fn confirm_transaction(&self, signature: &Signature) -> ClientResult<bool> {
@@ -300,18 +291,21 @@ impl RpcClient {
&self,
address: &Pubkey,
) -> ClientResult<Vec<RpcConfirmedTransactionStatusWithSignature>> {
self.get_confirmed_signatures_for_address2_with_config(address, None, None)
self.get_confirmed_signatures_for_address2_with_config(
address,
GetConfirmedSignaturesForAddress2Config::default(),
)
}
pub fn get_confirmed_signatures_for_address2_with_config(
&self,
address: &Pubkey,
before: Option<Signature>,
limit: Option<usize>,
config: GetConfirmedSignaturesForAddress2Config,
) -> ClientResult<Vec<RpcConfirmedTransactionStatusWithSignature>> {
let config = RpcGetConfirmedSignaturesForAddress2Config {
before: before.map(|signature| signature.to_string()),
limit,
before: config.before.map(|signature| signature.to_string()),
until: config.until.map(|signature| signature.to_string()),
limit: config.limit,
};
let result: Vec<RpcConfirmedTransactionStatusWithSignature> = self.send(
@@ -414,47 +408,56 @@ impl RpcClient {
&self,
transaction: &Transaction,
) -> ClientResult<Signature> {
let mut send_retries = 20;
loop {
let mut status_retries = 15;
let signature = self.send_transaction(transaction)?;
let status = loop {
let status = self.get_signature_status(&signature)?;
if status.is_none() {
status_retries -= 1;
if status_retries == 0 {
break status;
}
} else {
let signature = self.send_transaction(transaction)?;
let recent_blockhash = transaction.message.recent_blockhash;
let status = loop {
let status = self.get_signature_status(&signature)?;
if status.is_none() {
if self
.get_fee_calculator_for_blockhash_with_commitment(
&recent_blockhash,
CommitmentConfig::recent(),
)?
.value
.is_none()
{
break status;
}
if cfg!(not(test)) {
// Retry twice a second
sleep(Duration::from_millis(500));
}
};
send_retries = if let Some(result) = status.clone() {
match result {
Ok(_) => return Ok(signature),
Err(_) => 0,
}
} else {
send_retries - 1
};
if send_retries == 0 {
if let Some(err) = status {
return Err(err.unwrap_err().into());
} else {
return Err(
RpcError::ForUser("unable to confirm transaction. \
This can happen in situations such as transaction expiration \
and insufficient fee-payer funds".to_string()).into(),
);
}
break status;
}
if cfg!(not(test)) {
// Retry twice a second
sleep(Duration::from_millis(500));
}
};
if let Some(result) = status {
match result {
Ok(_) => Ok(signature),
Err(err) => Err(err.into()),
}
} else {
Err(RpcError::ForUser(
"unable to confirm transaction. \
This can happen in situations such as transaction expiration \
and insufficient fee-payer funds"
.to_string(),
)
.into())
}
}
pub fn resign_transaction<T: Signers>(
&self,
tx: &mut Transaction,
signer_keys: &T,
) -> ClientResult<()> {
let (blockhash, _fee_calculator) =
self.get_new_blockhash(&tx.message().recent_blockhash)?;
tx.try_sign(signer_keys, blockhash)?;
Ok(())
}
pub fn get_account(&self, pubkey: &Pubkey) -> ClientResult<Account> {
self.get_account_with_commitment(pubkey, CommitmentConfig::default())?
.value
@@ -466,9 +469,14 @@ impl RpcClient {
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> RpcResult<Option<Account>> {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
commitment: Some(commitment_config),
data_slice: None,
};
let response = self.sender.send(
RpcRequest::GetAccountInfo,
json!([pubkey.to_string(), commitment_config]),
json!([pubkey.to_string(), config]),
);
response
@@ -497,6 +505,38 @@ impl RpcClient {
})?
}
pub fn get_multiple_accounts(&self, pubkeys: &[Pubkey]) -> ClientResult<Vec<Option<Account>>> {
Ok(self
.get_multiple_accounts_with_commitment(pubkeys, CommitmentConfig::default())?
.value)
}
pub fn get_multiple_accounts_with_commitment(
&self,
pubkeys: &[Pubkey],
commitment_config: CommitmentConfig,
) -> RpcResult<Vec<Option<Account>>> {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
commitment: Some(commitment_config),
data_slice: None,
};
let pubkeys: Vec<_> = pubkeys.iter().map(|pubkey| pubkey.to_string()).collect();
let response = self.send(RpcRequest::GetMultipleAccounts, json!([pubkeys, config]))?;
let Response {
context,
value: accounts,
} = serde_json::from_value::<Response<Vec<Option<UiAccount>>>>(response)?;
let accounts: Vec<Option<Account>> = accounts
.into_iter()
.map(|rpc_account| rpc_account.map(|a| a.decode()).flatten())
.collect();
Ok(Response {
context,
value: accounts,
})
}
pub fn get_account_data(&self, pubkey: &Pubkey) -> ClientResult<Vec<u8>> {
Ok(self.get_account(pubkey)?.data)
}
@@ -537,8 +577,16 @@ impl RpcClient {
}
pub fn get_program_accounts(&self, pubkey: &Pubkey) -> ClientResult<Vec<(Pubkey, Account)>> {
let accounts: Vec<RpcKeyedAccount> =
self.send(RpcRequest::GetProgramAccounts, json!([pubkey.to_string()]))?;
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
commitment: None,
data_slice: None,
};
let accounts: Vec<RpcKeyedAccount> = self.send(
RpcRequest::GetProgramAccounts,
json!([pubkey.to_string(), config]),
)?;
parse_keyed_accounts(accounts, RpcRequest::GetProgramAccounts)
}
@@ -686,103 +734,6 @@ impl RpcClient {
Ok(hash)
}
pub fn get_token_account(&self, pubkey: &Pubkey) -> ClientResult<Option<UiTokenAccount>> {
Ok(self
.get_token_account_with_commitment(pubkey, CommitmentConfig::default())?
.value)
}
pub fn get_token_account_with_commitment(
&self,
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> RpcResult<Option<UiTokenAccount>> {
let Response {
context,
value: account,
} = self.get_account_with_commitment(pubkey, commitment_config)?;
if account.is_none() {
return Err(RpcError::ForUser(format!("AccountNotFound: pubkey={}", pubkey)).into());
}
let account = account.unwrap();
let mint = get_token_account_mint(&account.data)
.and_then(|mint_pubkey| {
self.get_token_mint_with_commitment(&mint_pubkey, commitment_config)
.ok()
.map(|response| response.value)
.flatten()
})
.ok_or_else(|| {
Into::<ClientError>::into(RpcError::ForUser(format!(
"AccountNotFound: mint for token acccount pubkey={}",
pubkey
)))
})?;
Ok(Response {
context,
value: match parse_token(&account.data, Some(mint.decimals)) {
Ok(TokenAccountType::Account(ui_token_account)) => Some(ui_token_account),
_ => None,
},
})
}
pub fn get_token_mint(&self, pubkey: &Pubkey) -> ClientResult<Option<UiMint>> {
Ok(self
.get_token_mint_with_commitment(pubkey, CommitmentConfig::default())?
.value)
}
pub fn get_token_mint_with_commitment(
&self,
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> RpcResult<Option<UiMint>> {
let Response {
context,
value: account,
} = self.get_account_with_commitment(pubkey, commitment_config)?;
Ok(Response {
context,
value: account
.map(|account| match parse_token(&account.data, None) {
Ok(TokenAccountType::Mint(ui_token_mint)) => Some(ui_token_mint),
_ => None,
})
.flatten(),
})
}
pub fn get_token_multisig(&self, pubkey: &Pubkey) -> ClientResult<Option<UiMultisig>> {
Ok(self
.get_token_multisig_with_commitment(pubkey, CommitmentConfig::default())?
.value)
}
pub fn get_token_multisig_with_commitment(
&self,
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> RpcResult<Option<UiMultisig>> {
let Response {
context,
value: account,
} = self.get_account_with_commitment(pubkey, commitment_config)?;
Ok(Response {
context,
value: account
.map(|account| match parse_token(&account.data, None) {
Ok(TokenAccountType::Multisig(ui_token_multisig)) => Some(ui_token_multisig),
_ => None,
})
.flatten(),
})
}
pub fn get_token_account_balance(&self, pubkey: &Pubkey) -> ClientResult<UiTokenAmount> {
Ok(self
.get_token_account_balance_with_commitment(pubkey, CommitmentConfig::default())?
@@ -804,7 +755,7 @@ impl RpcClient {
&self,
delegate: &Pubkey,
token_account_filter: TokenAccountsFilter,
) -> ClientResult<Vec<(Pubkey, UiTokenAccount)>> {
) -> ClientResult<Vec<RpcKeyedAccount>> {
Ok(self
.get_token_accounts_by_delegate_with_commitment(
delegate,
@@ -819,39 +770,31 @@ impl RpcClient {
delegate: &Pubkey,
token_account_filter: TokenAccountsFilter,
commitment_config: CommitmentConfig,
) -> RpcResult<Vec<(Pubkey, UiTokenAccount)>> {
) -> RpcResult<Vec<RpcKeyedAccount>> {
let token_account_filter = match token_account_filter {
TokenAccountsFilter::Mint(mint) => RpcTokenAccountsFilter::Mint(mint.to_string()),
TokenAccountsFilter::ProgramId(program_id) => {
RpcTokenAccountsFilter::ProgramId(program_id.to_string())
}
};
let Response {
context,
value: accounts,
} = self.send(
RpcRequest::GetTokenAccountsByDelegate,
json!([
delegate.to_string(),
token_account_filter,
commitment_config
]),
)?;
let pubkey_accounts = self.accounts_to_token_accounts(
commitment_config,
parse_keyed_accounts(accounts, RpcRequest::GetTokenAccountsByDelegate)?,
);
Ok(Response {
context,
value: pubkey_accounts,
})
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::JsonParsed),
commitment: Some(commitment_config),
data_slice: None,
};
self.send(
RpcRequest::GetTokenAccountsByOwner,
json!([delegate.to_string(), token_account_filter, config]),
)
}
pub fn get_token_accounts_by_owner(
&self,
owner: &Pubkey,
token_account_filter: TokenAccountsFilter,
) -> ClientResult<Vec<(Pubkey, UiTokenAccount)>> {
) -> ClientResult<Vec<RpcKeyedAccount>> {
Ok(self
.get_token_accounts_by_owner_with_commitment(
owner,
@@ -866,28 +809,24 @@ impl RpcClient {
owner: &Pubkey,
token_account_filter: TokenAccountsFilter,
commitment_config: CommitmentConfig,
) -> RpcResult<Vec<(Pubkey, UiTokenAccount)>> {
) -> RpcResult<Vec<RpcKeyedAccount>> {
let token_account_filter = match token_account_filter {
TokenAccountsFilter::Mint(mint) => RpcTokenAccountsFilter::Mint(mint.to_string()),
TokenAccountsFilter::ProgramId(program_id) => {
RpcTokenAccountsFilter::ProgramId(program_id.to_string())
}
};
let Response {
context,
value: accounts,
} = self.send(
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::JsonParsed),
commitment: Some(commitment_config),
data_slice: None,
};
self.send(
RpcRequest::GetTokenAccountsByOwner,
json!([owner.to_string(), token_account_filter, commitment_config]),
)?;
let pubkey_accounts = self.accounts_to_token_accounts(
commitment_config,
parse_keyed_accounts(accounts, RpcRequest::GetTokenAccountsByDelegate)?,
);
Ok(Response {
context,
value: pubkey_accounts,
})
json!([owner.to_string(), token_account_filter, config]),
)
}
pub fn get_token_supply(&self, mint: &Pubkey) -> ClientResult<UiTokenAmount> {
@@ -907,36 +846,7 @@ impl RpcClient {
)
}
fn accounts_to_token_accounts(
&self,
commitment_config: CommitmentConfig,
pubkey_accounts: Vec<(Pubkey, Account)>,
) -> Vec<(Pubkey, UiTokenAccount)> {
let mut mint_decimals: HashMap<Pubkey, u8> = HashMap::new();
pubkey_accounts
.into_iter()
.filter_map(|(pubkey, account)| {
let mint_pubkey = get_token_account_mint(&account.data)?;
let decimals = mint_decimals.get(&mint_pubkey).cloned().or_else(|| {
let mint = self
.get_token_mint_with_commitment(&mint_pubkey, commitment_config)
.ok()
.map(|response| response.value)
.flatten()?;
mint_decimals.insert(mint_pubkey, mint.decimals);
Some(mint.decimals)
})?;
match parse_token(&account.data, Some(decimals)) {
Ok(TokenAccountType::Account(ui_token_account)) => {
Some((pubkey, ui_token_account))
}
_ => None,
}
})
.collect()
}
fn poll_balance_with_timeout_and_commitment(
pub fn poll_balance_with_timeout_and_commitment(
&self,
pubkey: &Pubkey,
polling_frequency: &Duration,
@@ -945,7 +855,7 @@ impl RpcClient {
) -> ClientResult<u64> {
let now = Instant::now();
loop {
match self.get_balance_with_commitment(&pubkey, commitment_config) {
match self.get_balance_with_commitment(&pubkey, commitment_config.clone()) {
Ok(bal) => {
return Ok(bal.value);
}
@@ -980,7 +890,8 @@ impl RpcClient {
) -> Option<u64> {
const LAST: usize = 30;
for run in 0..LAST {
let balance_result = self.poll_get_balance_with_commitment(pubkey, commitment_config);
let balance_result =
self.poll_get_balance_with_commitment(pubkey, commitment_config.clone());
if expected_balance.is_none() {
return balance_result.ok();
}
@@ -1014,7 +925,7 @@ impl RpcClient {
let now = Instant::now();
loop {
if let Ok(Some(_)) =
self.get_signature_status_with_commitment(&signature, commitment_config)
self.get_signature_status_with_commitment(&signature, commitment_config.clone())
{
break;
}
@@ -1030,6 +941,36 @@ impl RpcClient {
Ok(())
}
/// Check a signature in the bank.
pub fn check_signature(&self, signature: &Signature) -> bool {
trace!("check_signature: {:?}", signature);
for _ in 0..30 {
let response =
self.confirm_transaction_with_commitment(signature, CommitmentConfig::recent());
match response {
Ok(Response {
value: signature_status,
..
}) => {
if signature_status {
trace!("Response found signature");
} else {
trace!("Response signature not found");
}
return signature_status;
}
Err(err) => {
debug!("check_signature request failed: {:?}", err);
}
};
sleep(Duration::from_millis(250));
}
panic!("Couldn't check signature of {}", signature);
}
/// Poll the server to confirm a transaction.
pub fn poll_for_signature_confirmation(
&self,
@@ -1112,19 +1053,6 @@ impl RpcClient {
) -> ClientResult<Signature> {
self.send_and_confirm_transaction_with_spinner_and_config(
transaction,
CommitmentConfig::default(),
RpcSendTransactionConfig::default(),
)
}
pub fn send_and_confirm_transaction_with_spinner_and_commitment(
&self,
transaction: &Transaction,
commitment: CommitmentConfig,
) -> ClientResult<Signature> {
self.send_and_confirm_transaction_with_spinner_and_config(
transaction,
commitment,
RpcSendTransactionConfig::default(),
)
}
@@ -1132,99 +1060,69 @@ impl RpcClient {
pub fn send_and_confirm_transaction_with_spinner_and_config(
&self,
transaction: &Transaction,
commitment: CommitmentConfig,
config: RpcSendTransactionConfig,
) -> ClientResult<Signature> {
let desired_confirmations = match commitment.commitment {
CommitmentLevel::Max | CommitmentLevel::Root => MAX_LOCKOUT_HISTORY + 1,
_ => 1,
};
let mut confirmations = 0;
let progress_bar = new_spinner_progress_bar();
let mut send_retries = 20;
let signature = loop {
progress_bar.set_message(&format!(
"[{}/{}] Finalizing transaction {}",
confirmations, desired_confirmations, transaction.signatures[0],
));
let mut status_retries = 15;
let (signature, status) = loop {
let signature = self.send_transaction_with_config(transaction, config)?;
// Get recent commitment in order to count confirmations for successful transactions
let status = self
.get_signature_status_with_commitment(&signature, CommitmentConfig::recent())?;
if status.is_none() {
status_retries -= 1;
if status_retries == 0 {
break (signature, status);
}
} else {
progress_bar.set_message(&format!(
"[{}/{}] Finalizing transaction {}",
confirmations,
MAX_LOCKOUT_HISTORY + 1,
transaction.signatures[0],
));
let recent_blockhash = transaction.message.recent_blockhash;
let signature = self.send_transaction_with_config(transaction, config)?;
let (signature, status) = loop {
// Get recent commitment in order to count confirmations for successful transactions
let status =
self.get_signature_status_with_commitment(&signature, CommitmentConfig::recent())?;
if status.is_none() {
if self
.get_fee_calculator_for_blockhash_with_commitment(
&recent_blockhash,
CommitmentConfig::recent(),
)?
.value
.is_none()
{
break (signature, status);
}
if cfg!(not(test)) {
sleep(Duration::from_millis(500));
}
};
send_retries = if let Some(result) = status.clone() {
match result {
Ok(_) => 0,
// If transaction errors, return right away; no point in counting confirmations
Err(_) => 0,
}
} else {
send_retries - 1
};
if send_retries == 0 {
if let Some(result) = status {
match result {
Ok(_) => {
break signature;
}
Err(err) => {
return Err(err.into());
}
}
} else {
return Err(RpcError::ForUser(
"unable to confirm transaction. \
This can happen in situations such as transaction \
expiration and insufficient fee-payer funds"
.to_string(),
)
.into());
}
break (signature, status);
}
if cfg!(not(test)) {
sleep(Duration::from_millis(500));
}
};
if let Some(result) = status {
if let Err(err) = result {
return Err(err.into());
}
} else {
return Err(RpcError::ForUser(
"unable to confirm transaction. \
This can happen in situations such as transaction expiration \
and insufficient fee-payer funds"
.to_string(),
)
.into());
}
let now = Instant::now();
loop {
match commitment.commitment {
CommitmentLevel::Max | CommitmentLevel::Root =>
// Return when default (max) commitment is reached
// Failed transactions have already been eliminated, `is_some` check is sufficient
{
if self.get_signature_status(&signature)?.is_some() {
progress_bar.set_message("Transaction confirmed");
progress_bar.finish_and_clear();
return Ok(signature);
}
}
_ => {
// Return when one confirmation has been reached
if confirmations >= desired_confirmations {
progress_bar.set_message("Transaction reached commitment");
progress_bar.finish_and_clear();
return Ok(signature);
}
}
// Return when default (max) commitment is reached
// Failed transactions have already been eliminated, `is_some` check is sufficient
if self.get_signature_status(&signature)?.is_some() {
progress_bar.set_message("Transaction confirmed");
progress_bar.finish_and_clear();
return Ok(signature);
}
progress_bar.set_message(&format!(
"[{}/{}] Finalizing transaction {}",
confirmations + 1,
desired_confirmations,
MAX_LOCKOUT_HISTORY + 1,
signature,
));
sleep(Duration::from_millis(500));
@@ -1259,6 +1157,13 @@ impl RpcClient {
}
}
#[derive(Debug, Default)]
pub struct GetConfirmedSignaturesForAddress2Config {
pub before: Option<Signature>,
pub until: Option<Signature>,
pub limit: Option<usize>,
}
fn new_spinner_progress_bar() -> ProgressBar {
let progress_bar = ProgressBar::new(42);
progress_bar
@@ -1453,6 +1358,28 @@ mod tests {
}
}
#[test]
fn test_resign_transaction() {
let rpc_client = RpcClient::new_mock("succeeds".to_string());
let key = Keypair::new();
let to = Pubkey::new_rand();
let blockhash: Hash = "HUu3LwEzGRsUkuJS121jzkPJW39Kq62pXCTmTa1F9jDL"
.parse()
.unwrap();
let prev_tx = system_transaction::transfer(&key, &to, 50, blockhash);
let mut tx = system_transaction::transfer(&key, &to, 50, blockhash);
rpc_client.resign_transaction(&mut tx, &[&key]).unwrap();
assert_ne!(prev_tx, tx);
assert_ne!(prev_tx.signatures, tx.signatures);
assert_ne!(
prev_tx.message().recent_blockhash,
tx.message().recent_blockhash
);
}
#[test]
fn test_rpc_client_thread() {
let rpc_client = RpcClient::new_mock("succeeds".to_string());

View File

@@ -1,6 +1,9 @@
use crate::rpc_filter::RpcFilterType;
use solana_account_decoder::UiAccountEncoding;
use solana_sdk::{clock::Epoch, commitment_config::CommitmentConfig};
use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig};
use solana_sdk::{
clock::Epoch,
commitment_config::{CommitmentConfig, CommitmentLevel},
};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
@@ -8,16 +11,21 @@ pub struct RpcSignatureStatusConfig {
pub search_transaction_history: bool,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcSendTransactionConfig {
#[serde(default)]
pub skip_preflight: bool,
pub preflight_commitment: Option<CommitmentLevel>,
}
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcSimulateTransactionConfig {
#[serde(default)]
pub sig_verify: bool,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@@ -47,6 +55,7 @@ pub struct RpcStakeConfig {
#[serde(rename_all = "camelCase")]
pub struct RpcAccountInfoConfig {
pub encoding: Option<UiAccountEncoding>,
pub data_slice: Option<UiDataSliceConfig>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
}
@@ -70,5 +79,6 @@ pub enum RpcTokenAccountsFilter {
#[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>,
}

View File

@@ -28,6 +28,7 @@ pub enum RpcRequest {
GetLargestAccounts,
GetLeaderSchedule,
GetMinimumBalanceForRentExemption,
GetMultipleAccounts,
GetProgramAccounts,
GetRecentBlockhash,
GetSignatureStatuses,
@@ -80,6 +81,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetLargestAccounts => "getLargestAccounts",
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
RpcRequest::GetMinimumBalanceForRentExemption => "getMinimumBalanceForRentExemption",
RpcRequest::GetMultipleAccounts => "getMultipleAccounts",
RpcRequest::GetProgramAccounts => "getProgramAccounts",
RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
RpcRequest::GetSignatureStatuses => "getSignatureStatuses",
@@ -110,11 +112,12 @@ impl fmt::Display for RpcRequest {
}
}
pub const NUM_LARGEST_ACCOUNTS: usize = 20;
pub const MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS: usize = 256;
pub const MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE: u64 = 10_000;
pub const MAX_GET_CONFIRMED_BLOCKS_RANGE: u64 = 500_000;
pub const MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT: usize = 1_000;
pub const MAX_MULTIPLE_ACCOUNTS: usize = 100;
pub const NUM_LARGEST_ACCOUNTS: usize = 20;
// Validators that are this number of slots behind are considered delinquent
pub const DELINQUENT_VALIDATOR_SLOT_DISTANCE: u64 = 128;
@@ -159,12 +162,12 @@ mod tests {
fn test_build_request_json() {
let test_request = RpcRequest::GetAccountInfo;
let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
let request = test_request.build_request_json(1, json!([addr]));
let request = test_request.build_request_json(1, json!([addr.clone()]));
assert_eq!(request["method"], "getAccountInfo");
assert_eq!(request["params"], json!([addr]));
let test_request = RpcRequest::GetBalance;
let request = test_request.build_request_json(1, json!([addr]));
let request = test_request.build_request_json(1, json!([addr.clone()]));
assert_eq!(request["method"], "getBalance");
let test_request = RpcRequest::GetEpochInfo;
@@ -209,12 +212,13 @@ mod tests {
// Test request with CommitmentConfig and no params
let test_request = RpcRequest::GetRecentBlockhash;
let request = test_request.build_request_json(1, json!([commitment_config]));
let request = test_request.build_request_json(1, json!([commitment_config.clone()]));
assert_eq!(request["params"], json!([commitment_config.clone()]));
// Test request with CommitmentConfig and params
let test_request = RpcRequest::GetBalance;
let request = test_request.build_request_json(1, json!([addr, commitment_config]));
let request =
test_request.build_request_json(1, json!([addr.clone(), commitment_config.clone()]));
assert_eq!(request["params"], json!([addr, commitment_config]));
// Test request with CommitmentConfig and params

View File

@@ -254,6 +254,37 @@ impl ThinClient {
.into())
}
pub fn poll_balance_with_timeout_and_commitment(
&self,
pubkey: &Pubkey,
polling_frequency: &Duration,
timeout: &Duration,
commitment_config: CommitmentConfig,
) -> TransportResult<u64> {
self.rpc_client()
.poll_balance_with_timeout_and_commitment(
pubkey,
polling_frequency,
timeout,
commitment_config,
)
.map_err(|e| e.into())
}
pub fn poll_balance_with_timeout(
&self,
pubkey: &Pubkey,
polling_frequency: &Duration,
timeout: &Duration,
) -> TransportResult<u64> {
self.poll_balance_with_timeout_and_commitment(
pubkey,
polling_frequency,
timeout,
CommitmentConfig::default(),
)
}
pub fn poll_get_balance(&self, pubkey: &Pubkey) -> TransportResult<u64> {
self.poll_get_balance_with_commitment(pubkey, CommitmentConfig::default())
}
@@ -299,6 +330,12 @@ impl ThinClient {
.map_err(|e| e.into())
}
/// Check a signature in the bank. This method blocks
/// until the server sends a response.
pub fn check_signature(&self, signature: &Signature) -> bool {
self.rpc_client().check_signature(signature)
}
pub fn validator_exit(&self) -> TransportResult<bool> {
self.rpc_client().validator_exit().map_err(|e| e.into())
}

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