Compare commits

..

241 Commits

Author SHA1 Message Date
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
1431 changed files with 23270 additions and 117683 deletions

BIN
.DS_Store vendored

Binary file not shown.

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

6
.gitignore vendored
View File

@@ -23,9 +23,3 @@ log-*/
/.idea/
/solana.iml
/.vscode/
# 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

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"

3019
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,6 @@ members = [
"bench-tps",
"accounts-bench",
"banking-bench",
"clap-utils",
"cli-config",
"client",
"core",
@@ -26,15 +25,15 @@ members = [
"log-analyzer",
"merkle-tree",
"stake-o-matic",
"storage-bigtable",
"streamer",
"measure",
"metrics",
"net-shaper",
"notifier",
"poh-bench",
"programs/bpf_loader",
"programs/budget",
"programs/btc_spv",
"programs/btc_spv_bin",
"programs/config",
"programs/exchange",
"programs/failure",
@@ -65,4 +64,6 @@ members = [
exclude = [
"programs/bpf",
"programs/move_loader",
"programs/librapay",
]

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.2"
version = "1.2.13"
description = "Solana account decoder"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
@@ -9,20 +9,16 @@ license = "Apache-2.0"
edition = "2018"
[dependencies]
base64 = "0.12.3"
bincode = "1.3.1"
bincode = "1.2.1"
bs58 = "0.3.1"
bv = "0.11.1"
Inflector = "0.11.4"
lazy_static = "1.4.0"
solana-config-program = { path = "../programs/config", version = "1.3.2" }
solana-sdk = { path = "../sdk", version = "1.3.2" }
solana-stake-program = { path = "../programs/stake", version = "1.3.2" }
solana-vote-program = { path = "../programs/vote", version = "1.3.2" }
spl-token-v1-0 = { package = "spl-token", version = "1.0.6", features = ["skip-no-mangle"] }
solana-sdk = { path = "../sdk", version = "1.2.13" }
solana-vote-program = { path = "../programs/vote", version = "1.2.13" }
spl-memo = "1.0.1"
serde = "1.0.112"
serde_derive = "1.0.103"
serde_json = "1.0.56"
serde_json = "1.0.54"
thiserror = "1.0"
[package.metadata.docs.rs]

View File

@@ -4,20 +4,14 @@ 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, fee_calculator::FeeCalculator, pubkey::Pubkey};
use crate::parse_account_data::parse_account_data;
use serde_json::Value;
use solana_sdk::{account::Account, clock::Epoch, pubkey::Pubkey};
use std::str::FromStr;
pub type StringAmount = String;
/// A duplicate representation of an Account for pretty JSON serialization
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
@@ -33,8 +27,13 @@ pub struct UiAccount {
#[serde(rename_all = "camelCase", untagged)]
pub enum UiAccountData {
Binary(String),
Json(ParsedAccount),
Binary64(String),
Json(Value),
}
impl From<Vec<u8>> for UiAccountData {
fn from(data: Vec<u8>) -> Self {
Self::Binary(bs58::encode(data).into_string())
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
@@ -42,32 +41,17 @@ pub enum UiAccountData {
pub enum UiAccountEncoding {
Binary,
JsonParsed,
Binary64,
}
impl UiAccount {
pub fn encode(
pubkey: &Pubkey,
account: Account,
encoding: UiAccountEncoding,
additional_data: Option<AccountAdditionalData>,
data_slice_config: Option<UiDataSliceConfig>,
) -> Self {
pub fn encode(account: Account, encoding: UiAccountEncoding) -> Self {
let data = match encoding {
UiAccountEncoding::Binary => UiAccountData::Binary(
bs58::encode(slice_data(&account.data, data_slice_config)).into_string(),
),
UiAccountEncoding::Binary64 => UiAccountData::Binary64(base64::encode(slice_data(
&account.data,
data_slice_config,
))),
UiAccountEncoding::Binary => account.data.into(),
UiAccountEncoding::JsonParsed => {
if let Ok(parsed_data) =
parse_account_data(pubkey, &account.owner, &account.data, additional_data)
{
if let Ok(parsed_data) = parse_account_data(&account.owner, &account.data) {
UiAccountData::Json(parsed_data)
} else {
UiAccountData::Binary64(base64::encode(&account.data))
account.data.into()
}
}
};
@@ -84,7 +68,6 @@ impl UiAccount {
let data = match &self.data {
UiAccountData::Json(_) => None,
UiAccountData::Binary(blob) => bs58::decode(blob).into_vec().ok(),
UiAccountData::Binary64(blob) => base64::decode(blob).ok(),
}?;
Some(Account {
lamports: self.lamports,
@@ -95,79 +78,3 @@ 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,31 +1,18 @@
use crate::{
parse_config::parse_config,
parse_nonce::parse_nonce,
parse_stake::parse_stake,
parse_sysvar::parse_sysvar,
parse_token::{parse_token, spl_token_id_v1_0},
parse_vote::parse_vote,
};
use crate::{parse_nonce::parse_nonce, parse_vote::parse_vote};
use inflector::Inflector;
use serde_json::Value;
use solana_sdk::{instruction::InstructionError, pubkey::Pubkey, system_program, sysvar};
use std::collections::HashMap;
use serde_json::{json, Value};
use solana_sdk::{instruction::InstructionError, pubkey::Pubkey, system_program};
use std::{collections::HashMap, str::FromStr};
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 SYSVAR_PROGRAM_ID: Pubkey = sysvar::id();
static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v1_0();
static ref VOTE_PROGRAM_ID: Pubkey = solana_vote_program::id();
static ref SYSTEM_PROGRAM_ID: Pubkey =
Pubkey::from_str(&system_program::id().to_string()).unwrap();
static ref VOTE_PROGRAM_ID: Pubkey =
Pubkey::from_str(&solana_vote_program::id().to_string()).unwrap();
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
};
@@ -33,15 +20,9 @@ lazy_static! {
#[derive(Error, Debug)]
pub enum ParseAccountError {
#[error("{0:?} account not parsable")]
AccountNotParsable(ParsableAccount),
#[error("Program not parsable")]
ProgramNotParsable,
#[error("Additional data required to parse: {0}")]
AdditionalDataMissing(String),
#[error("Instruction error")]
InstructionError(#[from] InstructionError),
@@ -49,55 +30,24 @@ pub enum ParseAccountError {
SerdeJsonError(#[from] serde_json::error::Error),
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
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,
}
#[derive(Default)]
pub struct AccountAdditionalData {
pub spl_token_decimals: Option<u8>,
}
pub fn parse_account_data(
pubkey: &Pubkey,
program_id: &Pubkey,
data: &[u8],
additional_data: Option<AccountAdditionalData>,
) -> Result<ParsedAccount, ParseAccountError> {
pub fn parse_account_data(program_id: &Pubkey, data: &[u8]) -> Result<Value, ParseAccountError> {
let program_name = PARSABLE_PROGRAM_IDS
.get(program_id)
.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,
})
Ok(json!({
format!("{:?}", program_name).to_kebab_case(): parsed_json
}))
}
#[cfg(test)]
@@ -111,35 +61,20 @@ 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(&account_pubkey, &other_program, &data, None).is_err());
assert!(parse_account_data(&other_program, &data).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(
&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 parsed = parse_account_data(&solana_vote_program::id(), &vote_account_data).unwrap();
assert!(parsed.as_object().unwrap().contains_key("vote"));
let nonce_data = Versions::new_current(State::Initialized(Data::default()));
let nonce_account_data = bincode::serialize(&nonce_data).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);
let parsed = parse_account_data(&system_program::id(), &nonce_account_data).unwrap();
assert!(parsed.as_object().unwrap().contains_key("nonce"));
}
}

View File

@@ -1,146 +0,0 @@
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,5 +1,6 @@
use crate::{parse_account_data::ParseAccountError, UiFeeCalculator};
use crate::parse_account_data::ParseAccountError;
use solana_sdk::{
fee_calculator::FeeCalculator,
instruction::InstructionError,
nonce::{state::Versions, State},
};
@@ -13,14 +14,14 @@ 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.into(),
fee_calculator: data.fee_calculator,
})),
}
}
/// A duplicate representation of NonceState for pretty JSON serialization
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase", tag = "type", content = "info")]
#[serde(rename_all = "camelCase")]
pub enum UiNonceState {
Uninitialized,
Initialized(UiNonceData),
@@ -31,7 +32,7 @@ pub enum UiNonceState {
pub struct UiNonceData {
pub authority: String,
pub blockhash: String,
pub fee_calculator: UiFeeCalculator,
pub fee_calculator: FeeCalculator,
}
#[cfg(test)]
@@ -55,9 +56,7 @@ mod test {
UiNonceState::Initialized(UiNonceData {
authority: Pubkey::default().to_string(),
blockhash: Hash::default().to_string(),
fee_calculator: UiFeeCalculator {
lamports_per_signature: 0.to_string(),
},
fee_calculator: FeeCalculator::default(),
}),
);

View File

@@ -1,235 +0,0 @@
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")]
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

@@ -1,328 +0,0 @@
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

@@ -1,250 +0,0 @@
use crate::{
parse_account_data::{ParsableAccount, ParseAccountError},
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 std::{mem::size_of, str::FromStr};
// A helper function to convert spl_token_v1_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()
}
// A helper function to convert spl_token_v1_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 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)
.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(),
)
})?;
Ok(TokenAccountType::Account(UiTokenAccount {
mint: account.mint.to_string(),
owner: account.owner.to_string(),
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: if account.delegate.is_none() {
None
} else {
Some(token_amount_to_ui_amount(
account.delegated_amount,
decimals,
))
},
}))
} 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 {
COption::Some(pubkey) => Some(pubkey.to_string()),
COption::None => None,
},
decimals: mint.decimals,
is_initialized: mint.is_initialized,
}))
} else if data.len() == size_of::<Multisig>() {
let multisig: Multisig = *unpack(&mut data)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
Ok(TokenAccountType::Multisig(UiMultisig {
num_required_signers: multisig.m,
num_valid_signers: multisig.n,
is_initialized: multisig.is_initialized,
signers: multisig
.signers
.iter()
.filter_map(|pubkey| {
if pubkey != &SplTokenPubkey::default() {
Some(pubkey.to_string())
} else {
None
}
})
.collect(),
}))
} else {
Err(ParseAccountError::AccountNotParsable(
ParsableAccount::SplToken,
))
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase", tag = "type", content = "info")]
pub enum TokenAccountType {
Account(UiTokenAccount),
Mint(UiMint),
Multisig(UiMultisig),
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
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 is_native: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub delegated_amount: Option<UiTokenAmount>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiTokenAmount {
pub ui_amount: f64,
pub decimals: u8,
pub amount: StringAmount,
}
pub fn token_amount_to_ui_amount(amount: u64, decimals: u8) -> UiTokenAmount {
// Use `amount_to_ui_amount()` once spl_token is bumped to a version that supports it: https://github.com/solana-labs/solana-program-library/pull/211
let amount_decimals = amount as f64 / 10_usize.pow(decimals as u32) as f64;
UiTokenAmount {
ui_amount: amount_decimals,
decimals,
amount: amount.to_string(),
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiMint {
pub owner: Option<String>,
pub decimals: u8,
pub is_initialized: bool,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UiMultisig {
pub num_required_signers: u8,
pub num_valid_signers: u8,
pub is_initialized: bool,
pub signers: Vec<String>,
}
pub fn get_token_account_mint(data: &[u8]) -> Option<Pubkey> {
if data.len() == size_of::<Account>() {
Some(Pubkey::new(&data[0..32]))
} else {
None
}
}
#[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();
account.mint = mint_pubkey;
account.owner = owner_pubkey;
account.amount = 42;
account.is_initialized = true;
assert!(parse_token(&account_data, None).is_err());
assert_eq!(
parse_token(&account_data, Some(2)).unwrap(),
TokenAccountType::Account(UiTokenAccount {
mint: mint_pubkey.to_string(),
owner: owner_pubkey.to_string(),
token_amount: UiTokenAmount {
ui_amount: 0.42,
decimals: 2,
amount: "42".to_string()
},
delegate: None,
is_initialized: true,
is_native: false,
delegated_amount: None,
}),
);
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);
mint.decimals = 3;
mint.is_initialized = true;
assert_eq!(
parse_token(&mint_data, None).unwrap(),
TokenAccountType::Mint(UiMint {
owner: Some(owner_pubkey.to_string()),
decimals: 3,
is_initialized: true,
}),
);
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 signers = [SplTokenPubkey::default(); 11];
signers[0] = signer1;
signers[1] = signer2;
signers[2] = signer3;
multisig.m = 2;
multisig.n = 3;
multisig.is_initialized = true;
multisig.signers = signers;
assert_eq!(
parse_token(&multisig_data, None).unwrap(),
TokenAccountType::Multisig(UiMultisig {
num_required_signers: 2,
num_valid_signers: 3,
is_initialized: true,
signers: vec![
signer1.to_string(),
signer2.to_string(),
signer3.to_string()
],
}),
);
let bad_data = vec![0; 4];
assert!(parse_token(&bad_data, None).is_err());
}
#[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();
account.mint = mint_pubkey;
let expected_mint_pubkey = Pubkey::new(&[2; 32]);
assert_eq!(
get_token_account_mint(&account_data),
Some(expected_mint_pubkey)
);
}
}

View File

@@ -1,19 +1,19 @@
use crate::{parse_account_data::ParseAccountError, StringAmount};
use crate::parse_account_data::ParseAccountError;
use solana_sdk::{
clock::{Epoch, Slot},
pubkey::Pubkey,
};
use solana_vote_program::vote_state::{BlockTimestamp, Lockout, VoteState};
pub fn parse_vote(data: &[u8]) -> Result<VoteAccountType, ParseAccountError> {
pub fn parse_vote(data: &[u8]) -> Result<UiVoteState, ParseAccountError> {
let mut vote_state = VoteState::deserialize(data).map_err(ParseAccountError::from)?;
let epoch_credits = vote_state
.epoch_credits()
.iter()
.map(|(epoch, credits, previous_credits)| UiEpochCredits {
epoch: *epoch,
credits: credits.to_string(),
previous_credits: previous_credits.to_string(),
credits: *credits,
previous_credits: *previous_credits,
})
.collect();
let votes = vote_state
@@ -45,7 +45,7 @@ pub fn parse_vote(data: &[u8]) -> Result<VoteAccountType, ParseAccountError> {
},
)
.collect();
Ok(VoteAccountType::Vote(UiVoteState {
Ok(UiVoteState {
node_pubkey: vote_state.node_pubkey.to_string(),
authorized_withdrawer: vote_state.authorized_withdrawer.to_string(),
commission: vote_state.commission,
@@ -55,14 +55,7 @@ pub fn parse_vote(data: &[u8]) -> Result<VoteAccountType, ParseAccountError> {
prior_voters,
epoch_credits,
last_timestamp: vote_state.last_timestamp,
}))
}
/// A wrapper enum for consistency across programs
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase", tag = "type", content = "info")]
pub enum VoteAccountType {
Vote(UiVoteState),
})
}
/// A duplicate representation of VoteState for pretty JSON serialization
@@ -115,8 +108,8 @@ struct UiPriorVoters {
#[serde(rename_all = "camelCase")]
struct UiEpochCredits {
epoch: Epoch,
credits: StringAmount,
previous_credits: StringAmount,
credits: u64,
previous_credits: u64,
}
#[cfg(test)]
@@ -133,10 +126,7 @@ mod test {
let mut expected_vote_state = UiVoteState::default();
expected_vote_state.node_pubkey = Pubkey::default().to_string();
expected_vote_state.authorized_withdrawer = Pubkey::default().to_string();
assert_eq!(
parse_vote(&vote_account_data).unwrap(),
VoteAccountType::Vote(expected_vote_state)
);
assert_eq!(parse_vote(&vote_account_data).unwrap(), expected_vote_state,);
let bad_data = vec![0; 4];
assert!(parse_vote(&bad_data).is_err());

View File

@@ -1,18 +0,0 @@
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.2"
version = "1.2.13"
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.2" }
solana-runtime = { path = "../runtime", version = "1.3.2" }
solana-measure = { path = "../measure", version = "1.3.2" }
solana-sdk = { path = "../sdk", version = "1.3.2" }
rayon = "1.3.0"
solana-logger = { path = "../logger", version = "1.2.13" }
solana-runtime = { path = "../runtime", version = "1.2.13" }
solana-measure = { path = "../measure", version = "1.2.13" }
solana-sdk = { path = "../sdk", version = "1.2.13" }
rand = "0.7.0"
clap = "2.33.1"
crossbeam-channel = "0.4"

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.2"
version = "1.2.13"
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.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.3.2" }
solana-streamer = { path = "../streamer", version = "1.3.2" }
solana-perf = { path = "../perf", version = "1.3.2" }
solana-ledger = { path = "../ledger", version = "1.3.2" }
solana-logger = { path = "../logger", version = "1.3.2" }
solana-runtime = { path = "../runtime", version = "1.3.2" }
solana-measure = { path = "../measure", version = "1.3.2" }
solana-sdk = { path = "../sdk", version = "1.3.2" }
solana-version = { path = "../version", version = "1.3.2" }
rayon = "1.3.0"
solana-core = { path = "../core", version = "1.2.13" }
solana-clap-utils = { path = "../clap-utils", version = "1.2.13" }
solana-streamer = { path = "../streamer", version = "1.2.13" }
solana-perf = { path = "../perf", version = "1.2.13" }
solana-ledger = { path = "../ledger", version = "1.2.13" }
solana-logger = { path = "../logger", version = "1.2.13" }
solana-runtime = { path = "../runtime", version = "1.2.13" }
solana-measure = { path = "../measure", version = "1.2.13" }
solana-sdk = { path = "../sdk", version = "1.2.13" }
solana-version = { path = "../version", version = "1.2.13" }
[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.2"
version = "1.2.13"
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.2" }
solana-core = { path = "../core", version = "1.3.2" }
solana-genesis = { path = "../genesis", version = "1.3.2" }
solana-client = { path = "../client", version = "1.3.2" }
solana-faucet = { path = "../faucet", version = "1.3.2" }
solana-exchange-program = { path = "../programs/exchange", version = "1.3.2" }
solana-logger = { path = "../logger", version = "1.3.2" }
solana-metrics = { path = "../metrics", version = "1.3.2" }
solana-net-utils = { path = "../net-utils", version = "1.3.2" }
solana-runtime = { path = "../runtime", version = "1.3.2" }
solana-sdk = { path = "../sdk", version = "1.3.2" }
solana-version = { path = "../version", version = "1.3.2" }
rayon = "1.3.0"
serde_json = "1.0.53"
serde_yaml = "0.8.12"
solana-clap-utils = { path = "../clap-utils", version = "1.2.13" }
solana-core = { path = "../core", version = "1.2.13" }
solana-genesis = { path = "../genesis", version = "1.2.13" }
solana-client = { path = "../client", version = "1.2.13" }
solana-faucet = { path = "../faucet", version = "1.2.13" }
solana-exchange-program = { path = "../programs/exchange", version = "1.2.13" }
solana-logger = { path = "../logger", version = "1.2.13" }
solana-metrics = { path = "../metrics", version = "1.2.13" }
solana-net-utils = { path = "../net-utils", version = "1.2.13" }
solana-runtime = { path = "../runtime", version = "1.2.13" }
solana-sdk = { path = "../sdk", version = "1.2.13" }
solana-version = { path = "../version", version = "1.2.13" }
[dev-dependencies]
solana-local-cluster = { path = "../local-cluster", version = "1.3.2" }
solana-local-cluster = { path = "../local-cluster", version = "1.2.13" }
[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.2"
version = "1.2.13"
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.2" }
solana-streamer = { path = "../streamer", version = "1.3.2" }
solana-logger = { path = "../logger", version = "1.3.2" }
solana-net-utils = { path = "../net-utils", version = "1.3.2" }
solana-version = { path = "../version", version = "1.3.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.2.13" }
solana-streamer = { path = "../streamer", version = "1.2.13" }
solana-logger = { path = "../logger", version = "1.2.13" }
solana-net-utils = { path = "../net-utils", version = "1.2.13" }
solana-version = { path = "../version", version = "1.2.13" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -1,36 +1,41 @@
[package]
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
authors = ["Solana Maintainers <maintainers@solana.com>"]
edition = "2018"
name = "solana-bench-tps"
version = "1.3.2"
version = "1.2.13"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
[dependencies]
bincode = "1.3.1"
bincode = "1.2.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.2" }
solana-core = { path = "../core", version = "1.3.2" }
solana-genesis = { path = "../genesis", version = "1.3.2" }
solana-client = { path = "../client", version = "1.3.2" }
solana-faucet = { path = "../faucet", version = "1.3.2" }
solana-logger = { path = "../logger", version = "1.3.2" }
solana-metrics = { path = "../metrics", version = "1.3.2" }
solana-measure = { path = "../measure", version = "1.3.2" }
solana-net-utils = { path = "../net-utils", version = "1.3.2" }
solana-runtime = { path = "../runtime", version = "1.3.2" }
solana-sdk = { path = "../sdk", version = "1.3.2" }
solana-version = { path = "../version", version = "1.3.2" }
rayon = "1.3.0"
serde_json = "1.0.53"
serde_yaml = "0.8.12"
solana-clap-utils = { path = "../clap-utils", version = "1.2.13" }
solana-core = { path = "../core", version = "1.2.13" }
solana-genesis = { path = "../genesis", version = "1.2.13" }
solana-client = { path = "../client", version = "1.2.13" }
solana-faucet = { path = "../faucet", version = "1.2.13" }
solana-librapay = { path = "../programs/librapay", version = "1.2.13", optional = true }
solana-logger = { path = "../logger", version = "1.2.13" }
solana-metrics = { path = "../metrics", version = "1.2.13" }
solana-measure = { path = "../measure", version = "1.2.13" }
solana-net-utils = { path = "../net-utils", version = "1.2.13" }
solana-runtime = { path = "../runtime", version = "1.2.13" }
solana-sdk = { path = "../sdk", version = "1.2.13" }
solana-move-loader-program = { path = "../programs/move_loader", version = "1.2.13", optional = true }
solana-version = { path = "../version", version = "1.2.13" }
[dev-dependencies]
serial_test = "0.4.0"
serial_test_derive = "0.4.0"
solana-local-cluster = { path = "../local-cluster", version = "1.3.2" }
solana-local-cluster = { path = "../local-cluster", version = "1.2.13" }
[features]
move = ["solana-librapay", "solana-move-loader-program"]
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -4,6 +4,8 @@ use rayon::prelude::*;
use solana_client::perf_utils::{sample_txs, SampleStats};
use solana_core::gen_keys::GenKeys;
use solana_faucet::faucet::request_airdrop_transaction;
#[cfg(feature = "move")]
use solana_librapay::{create_genesis, upload_mint_script, upload_payment_script};
use solana_measure::measure::Measure;
use solana_metrics::{self, datapoint_info};
use solana_sdk::{
@@ -35,6 +37,9 @@ use std::{
const MAX_TX_QUEUE_AGE: u64 =
MAX_PROCESSING_AGE as u64 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND;
#[cfg(feature = "move")]
use solana_librapay::librapay_transaction;
pub const MAX_SPENDS_PER_TX: u64 = 4;
#[derive(Debug)]
@@ -46,6 +51,8 @@ pub type Result<T> = std::result::Result<T, BenchTpsError>;
pub type SharedTransactions = Arc<RwLock<VecDeque<Vec<(Transaction, u64)>>>>;
type LibraKeys = (Keypair, Pubkey, Pubkey, Vec<Keypair>);
fn get_recent_blockhash<T: Client>(client: &T) -> (Hash, FeeCalculator) {
loop {
match client.get_recent_blockhash_with_commitment(CommitmentConfig::recent()) {
@@ -115,6 +122,7 @@ fn generate_chunked_transfers(
threads: usize,
duration: Duration,
sustained: bool,
libra_args: Option<LibraKeys>,
) {
// generate and send transactions for the specified duration
let start = Instant::now();
@@ -129,6 +137,7 @@ fn generate_chunked_transfers(
&dest_keypair_chunks[chunk_index],
threads,
reclaim_lamports_back_to_source_account,
&libra_args,
);
// In sustained mode, overlap the transfers with generation. This has higher average
@@ -196,7 +205,12 @@ where
.collect()
}
pub fn do_bench_tps<T>(client: Arc<T>, config: Config, gen_keypairs: Vec<Keypair>) -> u64
pub fn do_bench_tps<T>(
client: Arc<T>,
config: Config,
gen_keypairs: Vec<Keypair>,
libra_args: Option<LibraKeys>,
) -> u64
where
T: 'static + Client + Send + Sync,
{
@@ -280,6 +294,7 @@ where
threads,
duration,
sustained,
libra_args,
);
// Stop the sampling threads so it will collect the stats
@@ -325,6 +340,52 @@ fn metrics_submit_lamport_balance(lamport_balance: u64) {
);
}
#[cfg(feature = "move")]
fn generate_move_txs(
source: &[&Keypair],
dest: &VecDeque<&Keypair>,
reclaim: bool,
move_keypairs: &[Keypair],
libra_pay_program_id: &Pubkey,
libra_mint_id: &Pubkey,
blockhash: &Hash,
) -> Vec<(Transaction, u64)> {
let count = move_keypairs.len() / 2;
let source_move = &move_keypairs[..count];
let dest_move = &move_keypairs[count..];
let pairs: Vec<_> = if !reclaim {
source_move
.iter()
.zip(dest_move.iter())
.zip(source.iter())
.collect()
} else {
dest_move
.iter()
.zip(source_move.iter())
.zip(dest.iter())
.collect()
};
pairs
.par_iter()
.map(|((from, to), payer)| {
(
librapay_transaction::transfer(
libra_pay_program_id,
libra_mint_id,
&payer,
&from,
&to.pubkey(),
1,
*blockhash,
),
timestamp(),
)
})
.collect()
}
fn generate_system_txs(
source: &[&Keypair],
dest: &VecDeque<&Keypair>,
@@ -355,6 +416,7 @@ fn generate_txs(
dest: &VecDeque<&Keypair>,
threads: usize,
reclaim: bool,
libra_args: &Option<LibraKeys>,
) {
let blockhash = *blockhash.read().unwrap();
let tx_count = source.len();
@@ -364,7 +426,33 @@ fn generate_txs(
);
let signing_start = Instant::now();
let transactions = generate_system_txs(source, dest, reclaim, &blockhash);
let transactions = if let Some((
_libra_genesis_keypair,
_libra_pay_program_id,
_libra_mint_program_id,
_libra_keys,
)) = libra_args
{
#[cfg(not(feature = "move"))]
{
return;
}
#[cfg(feature = "move")]
{
generate_move_txs(
source,
dest,
reclaim,
&_libra_keys,
_libra_pay_program_id,
&_libra_genesis_keypair.pubkey(),
&blockhash,
)
}
} else {
generate_system_txs(source, dest, reclaim, &blockhash)
};
let duration = signing_start.elapsed();
let ns = duration.as_secs() * 1_000_000_000 + u64::from(duration.subsec_nanos());
@@ -866,13 +954,181 @@ pub fn generate_keypairs(seed_keypair: &Keypair, count: u64) -> (Vec<Keypair>, u
(rnd.gen_n_keypairs(total_keys), extra)
}
#[cfg(feature = "move")]
fn fund_move_keys<T: Client>(
client: &T,
funding_key: &Keypair,
keypairs: &[Keypair],
total: u64,
libra_pay_program_id: &Pubkey,
libra_mint_program_id: &Pubkey,
libra_genesis_key: &Keypair,
) {
let (mut blockhash, _fee_calculator) = get_recent_blockhash(client);
info!("creating the libra funding account..");
let libra_funding_key = Keypair::new();
let tx = librapay_transaction::create_account(funding_key, &libra_funding_key, 1, blockhash);
client
.send_and_confirm_message(&[funding_key, &libra_funding_key], tx.message)
.unwrap();
info!("minting to funding keypair");
let tx = librapay_transaction::mint_tokens(
&libra_mint_program_id,
funding_key,
libra_genesis_key,
&libra_funding_key.pubkey(),
total,
blockhash,
);
client
.send_and_confirm_message(&[funding_key, libra_genesis_key], tx.message)
.unwrap();
info!("creating {} move accounts...", keypairs.len());
let total_len = keypairs.len();
let create_len = 5;
let mut funding_time = Measure::start("funding_time");
for (i, keys) in keypairs.chunks(create_len).enumerate() {
if client
.get_balance_with_commitment(&keys[0].pubkey(), CommitmentConfig::recent())
.unwrap_or(0)
> 0
{
// already created these accounts.
break;
}
let keypairs: Vec<_> = keys.iter().map(|k| k).collect();
let tx = librapay_transaction::create_accounts(funding_key, &keypairs, 1, blockhash);
let ser_size = bincode::serialized_size(&tx).unwrap();
let mut keys = vec![funding_key];
keys.extend(&keypairs);
client.send_and_confirm_message(&keys, tx.message).unwrap();
if i % 10 == 0 {
info!(
"created {} accounts of {} (size {})",
i,
total_len / create_len,
ser_size,
);
}
}
const NUM_FUNDING_KEYS: usize = 10;
let funding_keys: Vec<_> = (0..NUM_FUNDING_KEYS).map(|_| Keypair::new()).collect();
let pubkey_amounts: Vec<_> = funding_keys
.iter()
.map(|key| (key.pubkey(), total / NUM_FUNDING_KEYS as u64))
.collect();
let instructions = system_instruction::transfer_many(&funding_key.pubkey(), &pubkey_amounts);
let message = Message::new(&instructions, Some(&funding_key.pubkey()));
let tx = Transaction::new(&[funding_key], message, blockhash);
client
.send_and_confirm_message(&[funding_key], tx.message)
.unwrap();
let mut balance = 0;
for _ in 0..20 {
if let Ok(balance_) = client
.get_balance_with_commitment(&funding_keys[0].pubkey(), CommitmentConfig::recent())
{
if balance_ > 0 {
balance = balance_;
break;
}
}
sleep(Duration::from_millis(100));
}
assert!(balance > 0);
info!(
"funded multiple funding accounts with {:?} lanports",
balance
);
let libra_funding_keys: Vec<_> = (0..NUM_FUNDING_KEYS).map(|_| Keypair::new()).collect();
for (i, key) in libra_funding_keys.iter().enumerate() {
let tx = librapay_transaction::create_account(&funding_keys[i], &key, 1, blockhash);
client
.send_and_confirm_message(&[&funding_keys[i], &key], tx.message)
.unwrap();
let tx = librapay_transaction::transfer(
libra_pay_program_id,
&libra_genesis_key.pubkey(),
&funding_keys[i],
&libra_funding_key,
&key.pubkey(),
total / NUM_FUNDING_KEYS as u64,
blockhash,
);
client
.send_and_confirm_message(&[&funding_keys[i], &libra_funding_key], tx.message)
.unwrap();
info!("funded libra funding key {}", i);
}
let keypair_count = keypairs.len();
let amount = total / (keypair_count as u64);
for (i, keys) in keypairs[..keypair_count]
.chunks(NUM_FUNDING_KEYS)
.enumerate()
{
for (j, key) in keys.iter().enumerate() {
let tx = librapay_transaction::transfer(
libra_pay_program_id,
&libra_genesis_key.pubkey(),
&funding_keys[j],
&libra_funding_keys[j],
&key.pubkey(),
amount,
blockhash,
);
let _sig = client
.async_send_transaction(tx.clone())
.expect("create_account in generate_and_fund_keypairs");
}
for (j, key) in keys.iter().enumerate() {
let mut times = 0;
loop {
let balance =
librapay_transaction::get_libra_balance(client, &key.pubkey()).unwrap();
if balance >= amount {
break;
} else if times > 20 {
info!("timed out.. {} key: {} balance: {}", i, j, balance);
break;
} else {
times += 1;
sleep(Duration::from_millis(100));
}
}
}
info!(
"funded group {} of {}",
i + 1,
keypairs.len() / NUM_FUNDING_KEYS
);
blockhash = get_recent_blockhash(client).0;
}
funding_time.stop();
info!("done funding keys, took {} ms", funding_time.as_ms());
}
pub fn generate_and_fund_keypairs<T: 'static + Client + Send + Sync>(
client: Arc<T>,
faucet_addr: Option<SocketAddr>,
funding_key: &Keypair,
keypair_count: usize,
lamports_per_account: u64,
) -> Result<Vec<Keypair>> {
use_move: bool,
) -> Result<(Vec<Keypair>, Option<LibraKeys>)> {
info!("Creating {} keypairs...", keypair_count);
let (mut keypairs, extra) = generate_keypairs(funding_key, keypair_count as u64);
info!("Get lamports...");
@@ -885,6 +1141,12 @@ pub fn generate_and_fund_keypairs<T: 'static + Client + Send + Sync>(
let last_key = keypairs[keypair_count - 1].pubkey();
let last_keypair_balance = client.get_balance(&last_key).unwrap_or(0);
#[cfg(feature = "move")]
let mut move_keypairs_ret = None;
#[cfg(not(feature = "move"))]
let move_keypairs_ret = None;
// Repeated runs will eat up keypair balances from transaction fees. In order to quickly
// start another bench-tps run without re-funding all of the keypairs, check if the
// keypairs still have at least 80% of the expected funds. That should be enough to
@@ -895,7 +1157,10 @@ pub fn generate_and_fund_keypairs<T: 'static + Client + Send + Sync>(
let max_fee = fee_rate_governor.max_lamports_per_signature;
let extra_fees = extra * max_fee;
let total_keypairs = keypairs.len() as u64 + 1; // Add one for funding keypair
let total = lamports_per_account * total_keypairs + extra_fees;
let mut total = lamports_per_account * total_keypairs + extra_fees;
if use_move {
total *= 3;
}
let funding_key_balance = client.get_balance(&funding_key.pubkey()).unwrap_or(0);
info!(
@@ -907,6 +1172,40 @@ pub fn generate_and_fund_keypairs<T: 'static + Client + Send + Sync>(
airdrop_lamports(client.as_ref(), &faucet_addr.unwrap(), funding_key, total)?;
}
#[cfg(feature = "move")]
{
if use_move {
let libra_genesis_keypair =
create_genesis(&funding_key, client.as_ref(), 10_000_000);
let libra_mint_program_id = upload_mint_script(&funding_key, client.as_ref());
let libra_pay_program_id = upload_payment_script(&funding_key, client.as_ref());
// Generate another set of keypairs for move accounts.
// Still fund the solana ones which will be used for fees.
let seed = [0u8; 32];
let mut rnd = GenKeys::new(seed);
let move_keypairs = rnd.gen_n_keypairs(keypair_count as u64);
fund_move_keys(
client.as_ref(),
funding_key,
&move_keypairs,
total / 3,
&libra_pay_program_id,
&libra_mint_program_id,
&libra_genesis_keypair,
);
move_keypairs_ret = Some((
libra_genesis_keypair,
libra_pay_program_id,
libra_mint_program_id,
move_keypairs,
));
// Give solana keys 1/3 and move keys 1/3 the lamports. Keep 1/3 for fees.
total /= 3;
}
}
fund_keys(
client,
funding_key,
@@ -920,7 +1219,7 @@ pub fn generate_and_fund_keypairs<T: 'static + Client + Send + Sync>(
// 'generate_keypairs' generates extra keys to be able to have size-aligned funding batches for fund_keys.
keypairs.truncate(keypair_count);
Ok(keypairs)
Ok((keypairs, move_keypairs_ret))
}
#[cfg(test)]
@@ -944,11 +1243,11 @@ mod tests {
config.duration = Duration::from_secs(5);
let keypair_count = config.tx_count * config.keypair_multiplier;
let keypairs =
generate_and_fund_keypairs(client.clone(), None, &config.id, keypair_count, 20)
let (keypairs, _move_keypairs) =
generate_and_fund_keypairs(client.clone(), None, &config.id, keypair_count, 20, false)
.unwrap();
do_bench_tps(client, config, keypairs);
do_bench_tps(client, config, keypairs, None);
}
#[test]
@@ -959,8 +1258,9 @@ mod tests {
let keypair_count = 20;
let lamports = 20;
let keypairs =
generate_and_fund_keypairs(client.clone(), None, &id, keypair_count, lamports).unwrap();
let (keypairs, _move_keypairs) =
generate_and_fund_keypairs(client.clone(), None, &id, keypair_count, lamports, false)
.unwrap();
for kp in &keypairs {
assert_eq!(
@@ -982,8 +1282,9 @@ mod tests {
let keypair_count = 20;
let lamports = 20;
let keypairs =
generate_and_fund_keypairs(client.clone(), None, &id, keypair_count, lamports).unwrap();
let (keypairs, _move_keypairs) =
generate_and_fund_keypairs(client.clone(), None, &id, keypair_count, lamports, false)
.unwrap();
for kp in &keypairs {
assert_eq!(client.get_balance(&kp.pubkey()).unwrap(), lamports);

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;
@@ -26,9 +23,9 @@ pub struct Config {
pub read_from_client_file: bool,
pub target_lamports_per_signature: u64,
pub multi_client: bool,
pub use_move: bool,
pub num_lamports_per_account: u64,
pub target_slots_per_epoch: u64,
pub target_node: Option<Pubkey>,
}
impl Default for Config {
@@ -49,9 +46,9 @@ impl Default for Config {
read_from_client_file: false,
target_lamports_per_signature: FeeRateGovernor::default().target_lamports_per_signature,
multi_client: true,
use_move: false,
num_lamports_per_account: NUM_LAMPORTS_PER_ACCOUNT_DEFAULT,
target_slots_per_epoch: 0,
target_node: None,
}
}
}
@@ -112,19 +109,16 @@ pub fn build_args<'a, 'b>(version: &'b str) -> App<'a, 'b> {
.long("sustained")
.help("Use sustained performance mode vs. peak mode. This overlaps the tx generation with transfers."),
)
.arg(
Arg::with_name("use-move")
.long("use-move")
.help("Use Move language transactions to perform transfers."),
)
.arg(
Arg::with_name("no-multi-client")
.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")
@@ -269,10 +263,8 @@ pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
args.target_lamports_per_signature = v.to_string().parse().expect("can't parse lamports");
}
args.use_move = matches.is_present("use-move");
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

@@ -29,9 +29,9 @@ fn main() {
write_to_client_file,
read_from_client_file,
target_lamports_per_signature,
use_move,
multi_client,
num_lamports_per_account,
target_node,
..
} = &cli_config;
@@ -82,24 +82,11 @@ 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))
};
let keypairs = if *read_from_client_file {
let (keypairs, move_keypairs) = if *read_from_client_file && !use_move {
let path = Path::new(&client_ids_and_stake_file);
let file = File::open(path).unwrap();
@@ -128,8 +115,8 @@ fn main() {
// Sort keypairs so that do_bench_tps() uses the same subset of accounts for each run.
// This prevents the amount of storage needed for bench-tps accounts from creeping up
// across multiple runs.
keypairs.sort_by_key(|x| x.pubkey().to_string());
keypairs
keypairs.sort_by(|x, y| x.pubkey().to_string().cmp(&y.pubkey().to_string()));
(keypairs, None)
} else {
generate_and_fund_keypairs(
client.clone(),
@@ -137,6 +124,7 @@ fn main() {
&id,
keypair_count,
*num_lamports_per_account,
*use_move,
)
.unwrap_or_else(|e| {
eprintln!("Error could not fund keys: {:?}", e);
@@ -144,5 +132,5 @@ fn main() {
})
};
do_bench_tps(client, cli_config, keypairs);
do_bench_tps(client, cli_config, keypairs, move_keypairs);
}

View File

@@ -6,11 +6,17 @@ use solana_core::cluster_info::VALIDATOR_PORT_RANGE;
use solana_core::validator::ValidatorConfig;
use solana_faucet::faucet::run_local_faucet;
use solana_local_cluster::local_cluster::{ClusterConfig, LocalCluster};
#[cfg(feature = "move")]
use solana_sdk::move_loader::solana_move_loader_program;
use solana_sdk::signature::{Keypair, Signer};
use std::sync::{mpsc::channel, Arc};
use std::time::Duration;
fn test_bench_tps_local_cluster(config: Config) {
#[cfg(feature = "move")]
let native_instruction_processors = vec![solana_move_loader_program()];
#[cfg(not(feature = "move"))]
let native_instruction_processors = vec![];
solana_logger::setup();
@@ -42,16 +48,17 @@ fn test_bench_tps_local_cluster(config: Config) {
let lamports_per_account = 100;
let keypair_count = config.tx_count * config.keypair_multiplier;
let keypairs = generate_and_fund_keypairs(
let (keypairs, move_keypairs) = generate_and_fund_keypairs(
client.clone(),
Some(faucet_addr),
&config.id,
keypair_count,
lamports_per_account,
config.use_move,
)
.unwrap();
let _total = do_bench_tps(client, config, keypairs);
let _total = do_bench_tps(client, config, keypairs, move_keypairs);
#[cfg(not(debug_assertions))]
assert!(_total > 100);
@@ -66,3 +73,14 @@ fn test_bench_tps_local_cluster_solana() {
test_bench_tps_local_cluster(config);
}
#[test]
#[serial]
fn test_bench_tps_local_cluster_move() {
let mut config = Config::default();
config.tx_count = 100;
config.duration = Duration::from_secs(10);
config.use_move = true;
test_bench_tps_local_cluster(config);
}

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}"

View File

@@ -16,3 +16,6 @@ steps:
timeout_in_minutes: 240
name: "publish crate"
branches: "!master"
# - command: ". ci/rust-version.sh; ci/docker-run.sh $$rust_stable_docker_image ci/test-move.sh"
# name: "move"
# timeout_in_minutes: 20

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"

41
ci/buildkite.yml Normal file
View File

@@ -0,0 +1,41 @@
# 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_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

@@ -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

@@ -45,16 +45,7 @@ linux)
TARGET=x86_64-unknown-linux-gnu
;;
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
)
TARGET=x86_64-pc-windows-gnu
;;
*)
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

@@ -7,7 +7,7 @@ source multinode-demo/common.sh
rm -rf config/run/init-completed config/ledger config/snapshot-ledger
timeout 120 ./run.sh &
timeout 15 ./run.sh &
pid=$!
attempts=20

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
@@ -38,8 +38,7 @@ export rust_nightly_docker_image=solanalabs/rust-nightly:"$nightly_version"
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
@@ -59,7 +58,7 @@ export rust_nightly_docker_image=solanalabs/rust-nightly:"$nightly_version"
rustup_install "$rust_nightly"
;;
*)
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.13" MAJOR MINOR PATCH SPECIAL
semverParseInto "3.2.1" MAJOR MINOR PATCH SPECIAL

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,53 +8,32 @@ 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
_ cargo +"$rust_stable" audit --version
_ 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
@@ -66,6 +44,7 @@ _ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit --ignore RUSTSEC-202
cd "$project"
_ cargo +"$rust_stable" fmt -- --check
_ cargo +"$rust_nightly" test
_ cargo +"$rust_nightly" clippy --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"

1
ci/test-move.sh Symbolic link
View File

@@ -0,0 +1 @@
test-stable.sh

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
@@ -38,8 +47,27 @@ echo "Executing $testName"
case $testName in
test-stable)
_ cargo +"$rust_stable" test --jobs "$NPROC" --all --exclude solana-local-cluster ${V:+--verbose} -- --nocapture
_ cargo +"$rust_stable" test --manifest-path bench-tps/Cargo.toml --features=move ${V:+--verbose} test_bench_tps_local_cluster_move -- --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 +92,27 @@ 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-move)
ci/affects-files.sh \
Cargo.lock$ \
Cargo.toml$ \
^ci/rust-version.sh \
^ci/test-stable.sh \
^ci/test-move.sh \
^programs/move_loader \
^programs/librapay \
^logger/ \
^runtime/ \
^sdk/ \
|| {
annotate --style info \
"Skipped $testName as no relevant files were modified"
exit 0
}
_ cargo +"$rust_stable" test --manifest-path programs/move_loader/Cargo.toml ${V:+--verbose} -- --nocapture
_ cargo +"$rust_stable" test --manifest-path programs/librapay/Cargo.toml ${V:+--verbose} -- --nocapture
exit 0
;;
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.2"
version = "1.2.13"
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.2" }
solana-sdk = { path = "../sdk", version = "1.3.2" }
thiserror = "1.0.20"
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.13" }
solana-sdk = { path = "../sdk", version = "1.2.13" }
thiserror = "1.0.11"
tiny-bip39 = "0.7.0"
url = "2.1.0"
chrono = "0.4"

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.2"
version = "1.2.13"
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)]

View File

@@ -1,55 +1,55 @@
[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.2"
version = "1.2.13"
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
[dependencies]
bincode = "1.3.1"
bincode = "1.2.1"
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.2" }
solana-budget-program = { path = "../programs/budget", version = "1.3.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.3.2" }
solana-cli-config = { path = "../cli-config", version = "1.3.2" }
solana-client = { path = "../client", version = "1.3.2" }
solana-config-program = { path = "../programs/config", version = "1.3.2" }
solana-faucet = { path = "../faucet", version = "1.3.2" }
solana-logger = { path = "../logger", version = "1.3.2" }
solana-net-utils = { path = "../net-utils", version = "1.3.2" }
solana-remote-wallet = { path = "../remote-wallet", version = "1.3.2" }
solana-runtime = { path = "../runtime", version = "1.3.2" }
solana-sdk = { path = "../sdk", version = "1.3.2" }
solana-stake-program = { path = "../programs/stake", version = "1.3.2" }
solana-transaction-status = { path = "../transaction-status", version = "1.3.2" }
solana-version = { path = "../version", version = "1.3.2" }
solana-vote-program = { path = "../programs/vote", version = "1.3.2" }
solana-vote-signer = { path = "../vote-signer", version = "1.3.2" }
thiserror = "1.0.20"
serde_json = "1.0.53"
solana-account-decoder = { path = "../account-decoder", version = "1.2.13" }
solana-budget-program = { path = "../programs/budget", version = "1.2.13" }
solana-clap-utils = { path = "../clap-utils", version = "1.2.13" }
solana-cli-config = { path = "../cli-config", version = "1.2.13" }
solana-client = { path = "../client", version = "1.2.13" }
solana-config-program = { path = "../programs/config", version = "1.2.13" }
solana-faucet = { path = "../faucet", version = "1.2.13" }
solana-logger = { path = "../logger", version = "1.2.13" }
solana-net-utils = { path = "../net-utils", version = "1.2.13" }
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.13" }
solana-runtime = { path = "../runtime", version = "1.2.13" }
solana-sdk = { path = "../sdk", version = "1.2.13" }
solana-stake-program = { path = "../programs/stake", version = "1.2.13" }
solana-transaction-status = { path = "../transaction-status", version = "1.2.13" }
solana-version = { path = "../version", version = "1.2.13" }
solana-vote-program = { path = "../programs/vote", version = "1.2.13" }
solana-vote-signer = { path = "../vote-signer", version = "1.2.13" }
thiserror = "1.0.19"
url = "2.1.1"
[dev-dependencies]
solana-core = { path = "../core", version = "1.3.2" }
solana-budget-program = { path = "../programs/budget", version = "1.3.2" }
solana-core = { path = "../core", version = "1.2.13" }
solana-budget-program = { path = "../programs/budget", version = "1.2.13" }
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);
}

View File

@@ -18,14 +18,18 @@ use serde_json::{self, json, Value};
use solana_account_decoder::{UiAccount, UiAccountEncoding};
use solana_budget_program::budget_instruction::{self, BudgetError};
use solana_clap_utils::{
commitment::commitment_arg_with_default, input_parsers::*, input_validators::*,
keypair::signer_from_path, offline::SIGN_ONLY_ARG, ArgConstant,
commitment::{commitment_arg_with_default, COMMITMENT_ARG},
input_parsers::*,
input_validators::*,
keypair::signer_from_path,
offline::SIGN_ONLY_ARG,
ArgConstant,
};
use solana_client::{
client_error::{ClientError, ClientErrorKind, Result as ClientResult},
rpc_client::RpcClient,
rpc_config::{RpcLargestAccountsFilter, RpcSendTransactionConfig},
rpc_response::{Response, RpcKeyedAccount},
rpc_response::RpcKeyedAccount,
};
#[cfg(not(test))]
use solana_faucet::faucet::request_airdrop_transaction;
@@ -57,13 +61,11 @@ use solana_stake_program::{
use solana_transaction_status::{EncodedTransaction, UiTransactionEncoding};
use solana_vote_program::vote_state::VoteAuthorize;
use std::{
collections::HashMap,
error,
fmt::Write as FmtWrite,
fs::File,
io::{Read, Write},
net::{IpAddr, SocketAddr},
str::FromStr,
sync::Arc,
thread::sleep,
time::Duration,
@@ -117,7 +119,6 @@ pub(crate) fn generate_unique_signers(
}
const DATA_CHUNK_SIZE: usize = 229; // Keep program chunks under PACKET_DATA_SIZE
pub const DEFAULT_RPC_TIMEOUT_SECONDS: &str = "30";
pub const FEE_PAYER_ARG: ArgConstant<'static> = ArgConstant {
name: "fee_payer",
@@ -183,6 +184,7 @@ pub enum CliCommand {
Catchup {
node_pubkey: Pubkey,
node_json_rpc_url: Option<String>,
commitment_config: CommitmentConfig,
follow: bool,
},
ClusterDate,
@@ -196,15 +198,30 @@ pub enum CliCommand {
GetBlockTime {
slot: Option<Slot>,
},
GetEpoch,
GetEpochInfo,
GetEpochInfo {
commitment_config: CommitmentConfig,
},
GetGenesisHash,
GetSlot,
GetBlockHeight,
GetTransactionCount,
GetEpoch {
commitment_config: CommitmentConfig,
},
GetSlot {
commitment_config: CommitmentConfig,
},
LargestAccounts {
commitment_config: CommitmentConfig,
filter: Option<RpcLargestAccountsFilter>,
},
Supply {
commitment_config: CommitmentConfig,
print_accounts: bool,
},
TotalSupply {
commitment_config: CommitmentConfig,
},
GetTransactionCount {
commitment_config: CommitmentConfig,
},
LeaderSchedule,
LiveSlots,
Ping {
@@ -212,6 +229,7 @@ pub enum CliCommand {
interval: Duration,
count: Option<u64>,
timeout: Duration,
commitment_config: CommitmentConfig,
},
ShowBlockProduction {
epoch: Option<Epoch>,
@@ -224,15 +242,12 @@ pub enum CliCommand {
},
ShowValidators {
use_lamports_unit: bool,
commitment_config: CommitmentConfig,
},
Supply {
print_accounts: bool,
},
TotalSupply,
TransactionHistory {
address: Pubkey,
before: Option<Signature>,
limit: usize,
end_slot: Option<Slot>, // None == latest slot
slot_limit: Option<u64>, // None == search full history
},
// Nonce commands
AuthorizeNonceAccount {
@@ -262,10 +277,7 @@ pub enum CliCommand {
lamports: u64,
},
// Program Deployment
Deploy {
program_location: String,
address: Option<SignerIndex>,
},
Deploy(String),
// Stake Commands
CreateStakeAccount {
stake_account: SignerIndex,
@@ -380,6 +392,7 @@ pub enum CliCommand {
ShowVoteAccount {
pubkey: Pubkey,
use_lamports_unit: bool,
commitment_config: CommitmentConfig,
},
WithdrawFromVoteAccount {
vote_account_pubkey: Pubkey,
@@ -413,6 +426,7 @@ pub enum CliCommand {
Balance {
pubkey: Option<Pubkey>,
use_lamports_unit: bool,
commitment_config: CommitmentConfig,
},
Cancel(Pubkey),
Confirm(Signature),
@@ -497,12 +511,8 @@ pub struct CliConfig<'a> {
pub signers: Vec<&'a dyn Signer>,
pub keypair_path: String,
pub rpc_client: Option<RpcClient>,
pub rpc_timeout: Duration,
pub verbose: bool,
pub output_format: OutputFormat,
pub commitment: CommitmentConfig,
pub send_transaction_config: RpcSendTransactionConfig,
pub address_labels: HashMap<String, String>,
}
impl CliConfig<'_> {
@@ -579,15 +589,6 @@ impl CliConfig<'_> {
))
}
}
pub fn recent_for_tests() -> Self {
let mut config = Self::default();
config.commitment = CommitmentConfig::recent();
config.send_transaction_config = RpcSendTransactionConfig {
skip_preflight: true,
};
config
}
}
impl Default for CliConfig<'_> {
@@ -596,18 +597,15 @@ impl Default for CliConfig<'_> {
command: CliCommand::Balance {
pubkey: Some(Pubkey::default()),
use_lamports_unit: false,
commitment_config: CommitmentConfig::default(),
},
json_rpc_url: Self::default_json_rpc_url(),
websocket_url: Self::default_websocket_url(),
signers: Vec::new(),
keypair_path: Self::default_keypair_path(),
rpc_client: None,
rpc_timeout: Duration::from_secs(u64::from_str(DEFAULT_RPC_TIMEOUT_SECONDS).unwrap()),
verbose: false,
output_format: OutputFormat::Display,
commitment: CommitmentConfig::default(),
send_transaction_config: RpcSendTransactionConfig::default(),
address_labels: HashMap::new(),
}
}
}
@@ -643,7 +641,6 @@ pub fn parse_command(
}),
("epoch", Some(matches)) => parse_get_epoch(matches),
("slot", Some(matches)) => parse_get_slot(matches),
("block-height", Some(matches)) => parse_get_block_height(matches),
("largest-accounts", Some(matches)) => parse_largest_accounts(matches),
("supply", Some(matches)) => parse_supply(matches),
("total-supply", Some(matches)) => parse_total_supply(matches),
@@ -683,27 +680,15 @@ pub fn parse_command(
parse_withdraw_from_nonce_account(matches, default_signer_path, wallet_manager)
}
// Program Deployment
("deploy", Some(matches)) => {
let (address_signer, _address) = signer_of(matches, "address_signer", wallet_manager)?;
let mut signers = vec![signer_from_path(
("deploy", Some(matches)) => Ok(CliCommandInfo {
command: CliCommand::Deploy(matches.value_of("program_location").unwrap().to_string()),
signers: vec![signer_from_path(
matches,
default_signer_path,
"keypair",
wallet_manager,
)?];
let address = address_signer.map(|signer| {
signers.push(signer);
1
});
Ok(CliCommandInfo {
command: CliCommand::Deploy {
program_location: matches.value_of("program_location").unwrap().to_string(),
address,
},
signers,
})
}
)?],
}),
// Stake Commands
("create-stake-account", Some(matches)) => {
parse_stake_create_account(matches, default_signer_path, wallet_manager)
@@ -778,18 +763,25 @@ pub fn parse_command(
("airdrop", Some(matches)) => {
let faucet_port = matches
.value_of("faucet_port")
.ok_or_else(|| CliError::BadParameter("Missing faucet port".to_string()))?
.unwrap()
.parse()
.map_err(|err| CliError::BadParameter(format!("Invalid faucet port: {}", err)))?;
.or_else(|err| {
Err(CliError::BadParameter(format!(
"Invalid faucet port: {}",
err
)))
})?;
let faucet_host = matches
.value_of("faucet_host")
.map(|faucet_host| {
solana_net_utils::parse_host(faucet_host).map_err(|err| {
CliError::BadParameter(format!("Invalid faucet host: {}", err))
})
})
.transpose()?;
let faucet_host = if let Some(faucet_host) = matches.value_of("faucet_host") {
Some(solana_net_utils::parse_host(faucet_host).or_else(|err| {
Err(CliError::BadParameter(format!(
"Invalid faucet host: {}",
err
)))
})?)
} else {
None
};
let pubkey = pubkey_of_signer(matches, "to", wallet_manager)?;
let signers = if pubkey.is_some() {
vec![]
@@ -814,6 +806,7 @@ pub fn parse_command(
}
("balance", Some(matches)) => {
let pubkey = pubkey_of_signer(matches, "pubkey", wallet_manager)?;
let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap();
let signers = if pubkey.is_some() {
vec![]
} else {
@@ -828,6 +821,7 @@ pub fn parse_command(
command: CliCommand::Balance {
pubkey,
use_lamports_unit: matches.is_present("lamports"),
commitment_config,
},
signers,
})
@@ -1156,6 +1150,7 @@ fn process_balance(
config: &CliConfig,
pubkey: &Option<Pubkey>,
use_lamports_unit: bool,
commitment_config: CommitmentConfig,
) -> ProcessResult {
let pubkey = if let Some(pubkey) = pubkey {
*pubkey
@@ -1163,7 +1158,7 @@ fn process_balance(
config.pubkey()?
};
let balance = rpc_client
.get_balance_with_commitment(&pubkey, config.commitment)?
.get_balance_with_commitment(&pubkey, commitment_config)?
.value;
Ok(build_balance_message(balance, use_lamports_unit, true))
}
@@ -1235,13 +1230,7 @@ fn process_show_account(
let cli_account = CliAccount {
keyed_account: RpcKeyedAccount {
pubkey: account_pubkey.to_string(),
account: UiAccount::encode(
account_pubkey,
account,
UiAccountEncoding::Binary64,
None,
None,
),
account: UiAccount::encode(account, UiAccountEncoding::Binary),
},
use_lamports_unit,
};
@@ -1319,16 +1308,23 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
transactions_signatures = transactions_signatures
.into_iter()
.filter(|(_transaction, signature)| {
signature
.and_then(|signature| rpc_client.get_signature_statuses(&[signature]).ok())
.map(|Response { context: _, value }| match &value[0] {
None => true,
Some(transaction_status) => {
!(transaction_status.confirmations.is_none()
|| transaction_status.confirmations.unwrap() > 1)
if let Some(signature) = signature {
if let Ok(status) = rpc_client.get_signature_status(&signature) {
if rpc_client
.get_num_blocks_since_signature_confirmation(&signature)
.unwrap_or(0)
> 1
{
return false;
} else {
return match status {
None => true,
Some(result) => result.is_err(),
};
}
})
.unwrap_or(true)
}
}
true
})
.collect();
@@ -1357,14 +1353,8 @@ fn process_deploy(
rpc_client: &RpcClient,
config: &CliConfig,
program_location: &str,
address: Option<SignerIndex>,
) -> ProcessResult {
let new_keypair = Keypair::new(); // Create ephemeral keypair to use for program address, if not provided
let program_id = if let Some(i) = address {
config.signers[i]
} else {
&new_keypair
};
let program_id = Keypair::new();
let mut file = File::open(program_location).map_err(|err| {
CliError::DynamicProgramError(format!("Unable to open program file: {}", err))
})?;
@@ -1375,9 +1365,7 @@ fn process_deploy(
// Build transactions to calculate fees
let mut messages: Vec<&Message> = Vec::new();
let (blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let minimum_balance = rpc_client.get_minimum_balance_for_rent_exemption(program_data.len())?;
let ix = system_instruction::create_account(
&config.signers[0].pubkey(),
@@ -1388,10 +1376,10 @@ fn process_deploy(
);
let message = Message::new(&[ix], Some(&config.signers[0].pubkey()));
let mut create_account_tx = Transaction::new_unsigned(message);
let signers = [config.signers[0], program_id];
create_account_tx.try_sign(&signers, blockhash)?;
create_account_tx.try_sign(&[config.signers[0], &program_id], blockhash)?;
messages.push(&create_account_tx.message);
let mut write_messages = vec![];
let signers = [config.signers[0], &program_id];
let mut write_transactions = vec![];
for (chunk, i) in program_data.chunks(DATA_CHUNK_SIZE).zip(0..) {
let instruction = loader_instruction::write(
&program_id.pubkey(),
@@ -1400,63 +1388,42 @@ fn process_deploy(
chunk.to_vec(),
);
let message = Message::new(&[instruction], Some(&signers[0].pubkey()));
write_messages.push(message);
}
let mut write_message_refs = vec![];
for message in write_messages.iter() {
write_message_refs.push(message);
}
messages.append(&mut write_message_refs);
let instruction = loader_instruction::finalize(&program_id.pubkey(), &bpf_loader::id());
let finalize_message = Message::new(&[instruction], Some(&signers[0].pubkey()));
messages.push(&finalize_message);
check_account_for_multiple_fees_with_commitment(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&messages,
config.commitment,
)?;
trace!("Creating program account");
let result = rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&create_account_tx,
config.commitment,
config.send_transaction_config,
);
log_instruction_custom_error::<SystemError>(result, &config).map_err(|_| {
CliError::DynamicProgramError("Program account allocation failed".to_string())
})?;
let (blockhash, _, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let mut write_transactions = vec![];
for message in write_messages.into_iter() {
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&signers, blockhash)?;
write_transactions.push(tx);
}
for transaction in write_transactions.iter() {
messages.push(&transaction.message);
}
let instruction = loader_instruction::finalize(&program_id.pubkey(), &bpf_loader::id());
let message = Message::new(&[instruction], Some(&signers[0].pubkey()));
let mut finalize_tx = Transaction::new_unsigned(message);
finalize_tx.try_sign(&signers, blockhash)?;
messages.push(&finalize_tx.message);
check_account_for_multiple_fees(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&messages,
)?;
trace!("Creating program account");
let result = rpc_client.send_and_confirm_transaction_with_spinner(&create_account_tx);
log_instruction_custom_error::<SystemError>(result, &config).map_err(|_| {
CliError::DynamicProgramError("Program account allocation failed".to_string())
})?;
trace!("Writing program data");
send_and_confirm_transactions_with_spinner(&rpc_client, write_transactions, &signers).map_err(
|_| CliError::DynamicProgramError("Data writes to program account failed".to_string()),
)?;
let (blockhash, _, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let mut finalize_tx = Transaction::new_unsigned(finalize_message);
finalize_tx.try_sign(&signers, blockhash)?;
trace!("Finalizing program account");
rpc_client
.send_and_confirm_transaction_with_spinner_and_config(
&finalize_tx,
config.commitment,
RpcSendTransactionConfig {
skip_preflight: true,
},
@@ -1492,7 +1459,7 @@ fn process_pay(
)?;
let (blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let cancelable = if cancelable {
Some(config.signers[0].pubkey())
@@ -1518,7 +1485,6 @@ fn process_pay(
&fee_calculator,
&config.signers[0].pubkey(),
build_message,
config.commitment,
)?;
let mut tx = Transaction::new_unsigned(message);
@@ -1527,20 +1493,12 @@ fn process_pay(
return_signers(&tx, &config)
} else {
if let Some(nonce_account) = &nonce_account {
let nonce_account = nonce::get_account_with_commitment(
rpc_client,
nonce_account,
config.commitment,
)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &blockhash)?;
}
tx.try_sign(&config.signers, 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)
}
} else if *witnesses == None {
@@ -1572,7 +1530,6 @@ fn process_pay(
&fee_calculator,
&config.signers[0].pubkey(),
build_message,
config.commitment,
)?;
let mut tx = Transaction::new_unsigned(message);
if sign_only {
@@ -1580,11 +1537,7 @@ fn process_pay(
return_signers(&tx, &config)
} else {
tx.try_sign(&[config.signers[0], &contract_state], 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);
let signature = log_instruction_custom_error::<BudgetError>(result, &config)?;
Ok(json!({
"signature": signature,
@@ -1623,7 +1576,6 @@ fn process_pay(
&fee_calculator,
&config.signers[0].pubkey(),
build_message,
config.commitment,
)?;
let mut tx = Transaction::new_unsigned(message);
if sign_only {
@@ -1631,11 +1583,7 @@ fn process_pay(
return_signers(&tx, &config)
} else {
tx.try_sign(&[config.signers[0], &contract_state], 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);
let signature = log_instruction_custom_error::<BudgetError>(result, &config)?;
Ok(json!({
"signature": signature,
@@ -1649,9 +1597,7 @@ fn process_pay(
}
fn process_cancel(rpc_client: &RpcClient, config: &CliConfig, pubkey: &Pubkey) -> ProcessResult {
let (blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let ix = budget_instruction::apply_signature(
&config.signers[0].pubkey(),
pubkey,
@@ -1660,18 +1606,13 @@ fn process_cancel(rpc_client: &RpcClient, config: &CliConfig, pubkey: &Pubkey) -
let message = Message::new(&[ix], Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, 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::<BudgetError>(result, &config)
}
@@ -1682,26 +1623,19 @@ fn process_time_elapsed(
pubkey: &Pubkey,
dt: DateTime<Utc>,
) -> ProcessResult {
let (blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(config.commitment)?
.value;
let (blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let ix = budget_instruction::apply_timestamp(&config.signers[0].pubkey(), pubkey, to, dt);
let message = Message::new(&[ix], Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, 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::<BudgetError>(result, &config)
}
@@ -1722,7 +1656,7 @@ fn process_transfer(
let from = config.signers[from];
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let nonce_authority = config.signers[nonce_authority];
let fee_payer = config.signers[fee_payer];
@@ -1750,7 +1684,6 @@ fn process_transfer(
&from.pubkey(),
&fee_payer.pubkey(),
build_message,
config.commitment,
)?;
let mut tx = Transaction::new_unsigned(message);
@@ -1759,20 +1692,19 @@ fn process_transfer(
return_signers(&tx, &config)
} else {
if let Some(nonce_account) = &nonce_account {
let nonce_account =
nonce::get_account_with_commitment(rpc_client, nonce_account, config.commitment)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
tx.try_sign(&config.signers, recent_blockhash)?;
if let Some(nonce_account) = &nonce_account {
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
let result = if no_wait {
rpc_client.send_transaction(&tx)
} else {
rpc_client.send_and_confirm_transaction_with_spinner_and_config(
&tx,
config.commitment,
config.send_transaction_config,
)
rpc_client.send_and_confirm_transaction_with_spinner(&tx)
};
log_instruction_custom_error::<SystemError>(result, &config)
}
@@ -1784,26 +1716,19 @@ fn process_witness(
to: &Pubkey,
pubkey: &Pubkey,
) -> ProcessResult {
let (blockhash, fee_calculator, _) = rpc_client
.get_recent_blockhash_with_commitment(CommitmentConfig::recent())?
.value;
let (blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let ix = budget_instruction::apply_signature(&config.signers[0].pubkey(), pubkey, to);
let message = Message::new(&[ix], Some(&config.signers[0].pubkey()));
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&config.signers, 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::<BudgetError>(result, &config)
}
@@ -1818,8 +1743,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
let mut _rpc_client;
let rpc_client = if config.rpc_client.is_none() {
_rpc_client =
RpcClient::new_with_timeout(config.json_rpc_url.to_string(), config.rpc_timeout);
_rpc_client = RpcClient::new(config.json_rpc_url.to_string());
&_rpc_client
} else {
// Primarily for testing
@@ -1835,8 +1759,15 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
CliCommand::Catchup {
node_pubkey,
node_json_rpc_url,
commitment_config,
follow,
} => process_catchup(&rpc_client, config, node_pubkey, node_json_rpc_url, *follow),
} => process_catchup(
&rpc_client,
node_pubkey,
node_json_rpc_url,
*commitment_config,
*follow,
),
CliCommand::ClusterDate => process_cluster_date(&rpc_client, config),
CliCommand::ClusterVersion => process_cluster_version(&rpc_client),
CliCommand::CreateAddressWithSeed {
@@ -1846,15 +1777,30 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
} => process_create_address_with_seed(config, from_pubkey.as_ref(), &seed, &program_id),
CliCommand::Fees => process_fees(&rpc_client, config),
CliCommand::GetBlockTime { slot } => process_get_block_time(&rpc_client, config, *slot),
CliCommand::GetEpoch => process_get_epoch(&rpc_client, config),
CliCommand::GetEpochInfo => process_get_epoch_info(&rpc_client, config),
CliCommand::GetGenesisHash => process_get_genesis_hash(&rpc_client),
CliCommand::GetSlot => process_get_slot(&rpc_client, config),
CliCommand::GetBlockHeight => process_get_block_height(&rpc_client, config),
CliCommand::LargestAccounts { filter } => {
process_largest_accounts(&rpc_client, config, filter.clone())
CliCommand::GetEpochInfo { commitment_config } => {
process_get_epoch_info(&rpc_client, config, *commitment_config)
}
CliCommand::GetEpoch { commitment_config } => {
process_get_epoch(&rpc_client, *commitment_config)
}
CliCommand::GetSlot { commitment_config } => {
process_get_slot(&rpc_client, *commitment_config)
}
CliCommand::LargestAccounts {
commitment_config,
filter,
} => process_largest_accounts(&rpc_client, config, *commitment_config, filter.clone()),
CliCommand::Supply {
commitment_config,
print_accounts,
} => process_supply(&rpc_client, config, *commitment_config, *print_accounts),
CliCommand::TotalSupply { commitment_config } => {
process_total_supply(&rpc_client, *commitment_config)
}
CliCommand::GetTransactionCount { commitment_config } => {
process_get_transaction_count(&rpc_client, *commitment_config)
}
CliCommand::GetTransactionCount => process_get_transaction_count(&rpc_client, config),
CliCommand::LeaderSchedule => process_leader_schedule(&rpc_client),
CliCommand::LiveSlots => process_live_slots(&config.websocket_url),
CliCommand::Ping {
@@ -1862,11 +1808,20 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
interval,
count,
timeout,
} => process_ping(&rpc_client, config, *lamports, interval, count, timeout),
commitment_config,
} => process_ping(
&rpc_client,
config,
*lamports,
interval,
count,
timeout,
*commitment_config,
),
CliCommand::ShowBlockProduction { epoch, slot_limit } => {
process_show_block_production(&rpc_client, config, *epoch, *slot_limit)
}
CliCommand::ShowGossip => process_show_gossip(&rpc_client, config),
CliCommand::ShowGossip => process_show_gossip(&rpc_client),
CliCommand::ShowStakes {
use_lamports_unit,
vote_account_pubkeys,
@@ -1876,18 +1831,15 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
*use_lamports_unit,
vote_account_pubkeys.as_deref(),
),
CliCommand::ShowValidators { use_lamports_unit } => {
process_show_validators(&rpc_client, config, *use_lamports_unit)
}
CliCommand::Supply { print_accounts } => {
process_supply(&rpc_client, config, *print_accounts)
}
CliCommand::TotalSupply => process_total_supply(&rpc_client, config),
CliCommand::ShowValidators {
use_lamports_unit,
commitment_config,
} => process_show_validators(&rpc_client, config, *use_lamports_unit, *commitment_config),
CliCommand::TransactionHistory {
address,
before,
limit,
} => process_transaction_history(&rpc_client, config, address, *before, *limit),
end_slot,
slot_limit,
} => process_transaction_history(&rpc_client, address, *end_slot, *slot_limit),
// Nonce Commands
@@ -1919,7 +1871,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
),
// Get the current nonce
CliCommand::GetNonce(nonce_account_pubkey) => {
process_get_nonce(&rpc_client, config, &nonce_account_pubkey)
process_get_nonce(&rpc_client, &nonce_account_pubkey)
}
// Get a new nonce
CliCommand::NewNonce {
@@ -1954,10 +1906,9 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
// Program Deployment
// Deploy a custom program to the chain
CliCommand::Deploy {
program_location,
address,
} => process_deploy(&rpc_client, config, program_location, *address),
CliCommand::Deploy(ref program_location) => {
process_deploy(&rpc_client, config, program_location)
}
// Stake Commands
@@ -2199,11 +2150,13 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
CliCommand::ShowVoteAccount {
pubkey: vote_account_pubkey,
use_lamports_unit,
commitment_config,
} => process_show_vote_account(
&rpc_client,
config,
&vote_account_pubkey,
*use_lamports_unit,
*commitment_config,
),
CliCommand::WithdrawFromVoteAccount {
vote_account_pubkey,
@@ -2281,7 +2234,14 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
CliCommand::Balance {
pubkey,
use_lamports_unit,
} => process_balance(&rpc_client, config, &pubkey, *use_lamports_unit),
commitment_config,
} => process_balance(
&rpc_client,
config,
&pubkey,
*use_lamports_unit,
*commitment_config,
),
// Cancel a contract by contract Pubkey
CliCommand::Cancel(pubkey) => process_cancel(&rpc_client, config, &pubkey),
// Confirm the last client transaction by signature
@@ -2424,8 +2384,7 @@ pub fn request_and_confirm_airdrop(
}
}?;
let tx = keypair.airdrop_transaction();
let result =
rpc_client.send_and_confirm_transaction_with_spinner_and_commitment(&tx, config.commitment);
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
log_instruction_custom_error::<SystemError>(result, &config)
}
@@ -2626,14 +2585,6 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
.takes_value(true)
.required(true)
.help("/path/to/program.o"),
)
.arg(
Arg::with_name("address_signer")
.index(2)
.value_name("SIGNER_KEYPAIR")
.takes_value(true)
.validator(is_valid_signer)
.help("The signer for the desired address of the program [default: new random address]")
),
)
.subcommand(
@@ -2954,6 +2905,7 @@ mod tests {
command: CliCommand::Balance {
pubkey: Some(keypair.pubkey()),
use_lamports_unit: false,
commitment_config: CommitmentConfig::default(),
},
signers: vec![],
}
@@ -2970,6 +2922,7 @@ mod tests {
command: CliCommand::Balance {
pubkey: Some(keypair.pubkey()),
use_lamports_unit: true,
commitment_config: CommitmentConfig::default(),
},
signers: vec![],
}
@@ -2984,6 +2937,7 @@ mod tests {
command: CliCommand::Balance {
pubkey: None,
use_lamports_unit: true,
commitment_config: CommitmentConfig::default(),
},
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
@@ -3075,37 +3029,11 @@ mod tests {
assert_eq!(
parse_command(&test_deploy, &keypair_file, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::Deploy {
program_location: "/Users/test/program.o".to_string(),
address: None,
},
command: CliCommand::Deploy("/Users/test/program.o".to_string()),
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
);
let custom_address = Keypair::new();
let custom_address_file = make_tmp_path("custom_address_file");
write_keypair_file(&custom_address, &custom_address_file).unwrap();
let test_deploy = test_commands.clone().get_matches_from(vec![
"test",
"deploy",
"/Users/test/program.o",
&custom_address_file,
]);
assert_eq!(
parse_command(&test_deploy, &keypair_file, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::Deploy {
program_location: "/Users/test/program.o".to_string(),
address: Some(1),
},
signers: vec![
read_keypair_file(&keypair_file).unwrap().into(),
read_keypair_file(&custom_address_file).unwrap().into(),
],
}
);
// Test ResolveSigner Subcommand, KeypairUrl::Filepath
let test_resolve_signer =
test_commands
@@ -3480,12 +3408,14 @@ mod tests {
config.command = CliCommand::Balance {
pubkey: None,
use_lamports_unit: true,
commitment_config: CommitmentConfig::default(),
};
assert_eq!(process_command(&config).unwrap(), "50 lamports");
config.command = CliCommand::Balance {
pubkey: None,
use_lamports_unit: false,
commitment_config: CommitmentConfig::default(),
};
assert_eq!(process_command(&config).unwrap(), "0.00000005 SOL");
@@ -3623,10 +3553,14 @@ mod tests {
let result = process_command(&config);
assert!(dbg!(result).is_ok());
config.command = CliCommand::GetSlot;
config.command = CliCommand::GetSlot {
commitment_config: CommitmentConfig::default(),
};
assert_eq!(process_command(&config).unwrap(), "0");
config.command = CliCommand::GetTransactionCount;
config.command = CliCommand::GetTransactionCount {
commitment_config: CommitmentConfig::default(),
};
assert_eq!(process_command(&config).unwrap(), "1234");
config.signers = vec![&keypair];
@@ -3734,6 +3668,7 @@ mod tests {
config.command = CliCommand::Balance {
pubkey: None,
use_lamports_unit: false,
commitment_config: CommitmentConfig::default(),
};
assert!(process_command(&config).is_err());
@@ -3764,10 +3699,14 @@ mod tests {
};
assert!(process_command(&config).is_err());
config.command = CliCommand::GetSlot;
config.command = CliCommand::GetSlot {
commitment_config: CommitmentConfig::default(),
};
assert!(process_command(&config).is_err());
config.command = CliCommand::GetTransactionCount;
config.command = CliCommand::GetTransactionCount {
commitment_config: CommitmentConfig::default(),
};
assert!(process_command(&config).is_err());
config.command = CliCommand::Pay(PayCommand {
@@ -3814,10 +3753,7 @@ mod tests {
let default_keypair = Keypair::new();
config.signers = vec![&default_keypair];
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 result = process_command(&config);
let json: Value = serde_json::from_str(&result.unwrap()).unwrap();
let program_id = json
@@ -3831,10 +3767,7 @@ mod tests {
assert!(program_id.parse::<Pubkey>().is_ok());
// Failure case
config.command = CliCommand::Deploy {
program_location: "bad/file/location.so".to_string(),
address: None,
};
config.command = CliCommand::Deploy("bad/file/location.so".to_string());
assert!(process_command(&config).is_err());
}

View File

@@ -1,7 +1,4 @@
use crate::{
cli::build_balance_message,
display::{format_labeled_address, writeln_name_value},
};
use crate::{cli::build_balance_message, display::writeln_name_value};
use chrono::{DateTime, NaiveDateTime, SecondsFormat, Utc};
use console::{style, Emoji};
use inflector::cases::titlecase::to_title_case;
@@ -21,11 +18,7 @@ use solana_vote_program::{
authorized_voters::AuthorizedVoters,
vote_state::{BlockTimestamp, Lockout},
};
use std::{
collections::{BTreeMap, HashMap},
fmt,
time::Duration,
};
use std::{collections::BTreeMap, fmt, time::Duration};
static WARNING: Emoji = Emoji("⚠️", "!");
@@ -206,11 +199,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 +247,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 +255,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 +278,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 +290,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 +330,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 +378,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 +400,6 @@ impl CliValidator {
})
.unwrap_or(0),
activated_stake: vote_account.activated_stake,
version,
}
}
}
@@ -569,25 +516,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 +552,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 +650,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(())

View File

@@ -1,18 +1,22 @@
use crate::{
cli::{CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult},
cli_output::*,
display::{format_labeled_address, new_spinner_progress_bar, println_name_value},
display::{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::signer_from_path,
};
use solana_client::{
pubsub_client::{PubsubClient, SlotInfoMessage},
rpc_client::RpcClient,
rpc_config::{RpcLargestAccountsConfig, RpcLargestAccountsFilter},
rpc_request::MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE,
};
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
@@ -23,7 +27,6 @@ use solana_sdk::{
message::Message,
native_token::lamports_to_sol,
pubkey::{self, Pubkey},
signature::Signature,
system_instruction, system_program,
sysvar::{
self,
@@ -33,7 +36,7 @@ use solana_sdk::{
transaction::Transaction,
};
use std::{
collections::{BTreeMap, HashMap, VecDeque},
collections::{HashMap, VecDeque},
net::SocketAddr,
sync::{
atomic::{AtomicBool, Ordering},
@@ -115,10 +118,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()),
@@ -257,8 +256,9 @@ impl ClusterQuerySubCommands for App<'_, '_> {
)
.subcommand(
SubCommand::with_name("transaction-history")
.about("Show historical transactions affecting the given address \
from newest to oldest")
.about("Show historical transactions affecting the given address, \
ordered based on the slot in which they were confirmed in \
from lowest to highest slot")
.arg(
pubkey!(Arg::with_name("address")
.index(1)
@@ -266,22 +266,26 @@ impl ClusterQuerySubCommands for App<'_, '_> {
.required(true),
"Account address"),
)
.arg(
Arg::with_name("end_slot")
.takes_value(false)
.value_name("SLOT")
.index(2)
.validator(is_slot)
.help(
"Slot to start from [default: latest slot at maximum commitment]"
),
)
.arg(
Arg::with_name("limit")
.long("limit")
.takes_value(true)
.value_name("LIMIT")
.value_name("NUMBER OF SLOTS")
.validator(is_slot)
.default_value("1000")
.help("Maximum number of transaction signatures to return"),
)
.arg(
Arg::with_name("before")
.long("before")
.value_name("TRANSACTION_SIGNATURE")
.takes_value(true)
.help("Start with the first signature older than this one"),
)
.help(
"Limit the search to this many slots"
),
),
)
}
}
@@ -292,11 +296,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![],
@@ -316,12 +322,14 @@ 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,
@@ -340,35 +348,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 +382,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 +437,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![],
})
}
@@ -435,22 +453,14 @@ pub fn parse_transaction_history(
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> {
let address = pubkey_of_signer(matches, "address", wallet_manager)?.unwrap();
let before = match matches.value_of("before") {
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);
let end_slot = value_t!(matches, "end_slot", Slot).ok();
let slot_limit = value_t!(matches, "limit", u64).ok();
Ok(CliCommandInfo {
command: CliCommand::TransactionHistory {
address,
before,
limit,
end_slot,
slot_limit,
},
signers: vec![],
})
@@ -458,9 +468,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 +519,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 +653,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 +669,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 +768,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 +849,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 +865,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 +898,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 +944,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 +952,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 +1130,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 +1139,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 +1180,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 +1198,6 @@ pub fn process_show_stakes(
&stake_state,
use_lamports_unit,
&stake_history,
&clock,
),
});
}
@@ -1198,7 +1215,6 @@ pub fn process_show_stakes(
&stake_state,
use_lamports_unit,
&stake_history,
&clock,
),
});
}
@@ -1216,21 +1232,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 +1254,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))
@@ -1308,36 +1276,41 @@ pub fn process_show_validators(
pub fn process_transaction_history(
rpc_client: &RpcClient,
config: &CliConfig,
address: &Pubkey,
before: Option<Signature>,
limit: usize,
end_slot: Option<Slot>, // None == use latest slot
slot_limit: Option<u64>,
) -> ProcessResult {
let results = rpc_client.get_confirmed_signatures_for_address2_with_config(
address,
before,
Some(limit),
)?;
let transactions_found = format!("{} transactions found", results.len());
for result in results {
if config.verbose {
println!(
"{} [slot={} status={}] {}",
result.signature,
result.slot,
match result.err {
None => "Confirmed".to_string(),
Some(err) => format!("Failed: {:?}", err),
},
result.memo.unwrap_or_else(|| "".to_string()),
);
let end_slot = {
if let Some(end_slot) = end_slot {
end_slot
} else {
println!("{}", result.signature);
rpc_client.get_slot_with_commitment(CommitmentConfig::max())?
}
};
let mut start_slot = match slot_limit {
Some(slot_limit) => end_slot.saturating_sub(slot_limit),
None => rpc_client.minimum_ledger_slot()?,
};
println!(
"Transactions affecting {} within slots [{},{}]",
address, start_slot, end_slot
);
let mut transaction_count = 0;
while start_slot < end_slot {
let signatures = rpc_client.get_confirmed_signatures_for_address(
address,
start_slot,
(start_slot + MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE).min(end_slot),
)?;
for signature in &signatures {
println!("{}", signature);
}
transaction_count += signatures.len();
start_slot += MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE;
}
Ok(transactions_found)
Ok(format!("{} transactions found", transaction_count))
}
#[cfg(test)]
@@ -1403,24 +1376,15 @@ mod tests {
}
);
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(),
CliCommandInfo {
command: CliCommand::GetEpochInfo,
command: CliCommand::GetEpochInfo {
commitment_config: CommitmentConfig::recent(),
},
signers: vec![],
}
);
@@ -1440,7 +1404,22 @@ mod tests {
assert_eq!(
parse_command(&test_get_slot, &default_keypair_file, &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_keypair_file, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetEpoch {
commitment_config: CommitmentConfig::recent(),
},
signers: vec![],
}
);
@@ -1451,7 +1430,9 @@ mod tests {
assert_eq!(
parse_command(&test_total_supply, &default_keypair_file, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::TotalSupply,
command: CliCommand::TotalSupply {
commitment_config: CommitmentConfig::recent(),
},
signers: vec![],
}
);
@@ -1462,7 +1443,9 @@ mod tests {
assert_eq!(
parse_command(&test_transaction_count, &default_keypair_file, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::GetTransactionCount,
command: CliCommand::GetTransactionCount {
commitment_config: CommitmentConfig::recent(),
},
signers: vec![],
}
);
@@ -1487,6 +1470,7 @@ mod tests {
interval: Duration::from_secs(1),
count: Some(2),
timeout: Duration::from_secs(3),
commitment_config: CommitmentConfig::max(),
},
signers: vec![default_keypair.into()],
}

View File

@@ -6,7 +6,7 @@ use solana_sdk::{
transaction::Transaction,
};
use solana_transaction_status::UiTransactionStatusMeta;
use std::{collections::HashMap, fmt, io};
use std::{fmt, io};
// Pretty print a "name value"
pub fn println_name_value(name: &str, value: &str) {
@@ -27,19 +27,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 => "",
@@ -223,32 +210,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)"
);
}
}

View File

@@ -1,43 +1,25 @@
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::SKIP_SEED_PHRASE_VALIDATION_ARG, DisplayError,
};
use solana_cli::{
cli::{
app, parse_command, process_command, CliCommandInfo, CliConfig, CliSigners,
DEFAULT_RPC_TIMEOUT_SECONDS,
},
cli::{app, parse_command, process_command, CliCommandInfo, CliConfig, CliSigners},
cli_output::OutputFormat,
display::{println_name_value, println_name_value_or},
};
use solana_cli_config::{Config, CONFIG_FILE};
use solana_client::rpc_config::RpcSendTransactionConfig;
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use std::{collections::HashMap, error, path::PathBuf, sync::Arc, time::Duration};
use std::{error, sync::Arc};
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 +45,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 +68,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 +85,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,10 +113,6 @@ 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,
@@ -156,18 +136,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 +144,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 +207,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 +222,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 +248,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,5 +1,5 @@
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,
@@ -16,7 +16,6 @@ use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
account::Account,
account_utils::StateMut,
commitment_config::CommitmentConfig,
hash::Hash,
message::Message,
nonce::{
@@ -223,23 +222,10 @@ 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)
.get_account(nonce_pubkey)
.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),
@@ -447,9 +433,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 +441,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 +494,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 +503,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 +528,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 +550,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 +559,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 +579,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 +610,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 +622,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)
}

View File

@@ -1,5 +1,4 @@
use super::*;
use solana_sdk::commitment_config::CommitmentConfig;
#[derive(Debug, PartialEq)]
pub enum Source {
@@ -11,17 +10,14 @@ 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)
let data = nonce::get_account(rpc_client, pubkey)
.and_then(|ref a| nonce::data_from_account(a))?;
Ok((data.blockhash, data.fee_calculator))
}
@@ -32,21 +28,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::get_account(rpc_client, pubkey)
.and_then(|ref a| nonce::data_from_account(a))
.and_then(|d| {
if d.blockhash == *blockhash {
Ok(Some(d.fee_calculator))
} else {
Ok(None)
}
})?;
Ok(res)
}
}
}
@@ -82,19 +80,16 @@ impl BlockhashQuery {
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),
}
}
}
@@ -298,7 +293,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 +309,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 +321,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,13 +345,7 @@ mod tests {
)
.unwrap();
let nonce_pubkey = Pubkey::new(&[4u8; 32]);
let rpc_nonce_account = UiAccount::encode(
&nonce_pubkey,
nonce_account,
UiAccountEncoding::Binary64,
None,
None,
);
let rpc_nonce_account = UiAccount::encode(nonce_account, UiAccountEncoding::Binary);
let get_account_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!(Some(rpc_nonce_account)),
@@ -367,7 +356,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()),
);
@@ -376,7 +365,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),
);
@@ -385,7 +374,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();
@@ -393,14 +382,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,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)));
}
}

View File

@@ -1,12 +1,12 @@
use crate::{
checks::{check_account_for_fee_with_commitment, check_unique_pubkeys},
checks::{check_account_for_fee, check_unique_pubkeys},
cli::{
fee_payer_arg, generate_unique_signers, log_instruction_custom_error, nonce_authority_arg,
return_signers, CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult,
SignerIndex, FEE_PAYER_ARG,
},
cli_output::{CliStakeHistory, CliStakeHistoryEntry, CliStakeState, CliStakeType},
nonce::{self, check_nonce_account, nonce_arg, NONCE_ARG, NONCE_AUTHORITY_ARG},
nonce::{check_nonce_account, nonce_arg, NONCE_ARG, NONCE_AUTHORITY_ARG},
offline::{blockhash_query::BlockhashQuery, *},
spend_utils::{resolve_spend_tx_and_check_account_balances, SpendAmount},
};
@@ -16,12 +16,10 @@ use solana_client::{rpc_client::RpcClient, rpc_request::DELINQUENT_VALIDATOR_SLO
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
account_utils::StateMut,
clock::Clock,
message::Message,
pubkey::Pubkey,
system_instruction::SystemError,
sysvar::{
clock,
stake_history::{self, StakeHistory},
Sysvar,
},
@@ -896,7 +894,7 @@ pub fn process_create_stake_account(
};
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let (message, lamports) = resolve_spend_tx_and_check_account_balances(
rpc_client,
@@ -906,7 +904,6 @@ pub fn process_create_stake_account(
&from.pubkey(),
&fee_payer.pubkey(),
build_message,
config.commitment,
)?;
if !sign_only {
@@ -934,8 +931,7 @@ pub fn process_create_stake_account(
}
if let Some(nonce_account) = &nonce_account {
let nonce_account =
nonce::get_account_with_commitment(rpc_client, nonce_account, config.commitment)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
}
@@ -946,11 +942,7 @@ pub fn process_create_stake_account(
return_signers(&tx, &config)
} else {
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)
}
}
@@ -983,7 +975,7 @@ pub fn process_stake_authorize(
}
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let nonce_authority = config.signers[nonce_authority];
let fee_payer = config.signers[fee_payer];
@@ -1006,22 +998,16 @@ pub fn process_stake_authorize(
} else {
tx.try_sign(&config.signers, recent_blockhash)?;
if let Some(nonce_account) = &nonce_account {
let nonce_account =
nonce::get_account_with_commitment(rpc_client, nonce_account, config.commitment)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&tx.message.account_keys[0],
&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::<StakeError>(result, &config)
}
}
@@ -1039,7 +1025,7 @@ pub fn process_deactivate_stake_account(
fee_payer: SignerIndex,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let stake_authority = config.signers[stake_authority];
let ixs = vec![stake_instruction::deactivate_stake(
stake_account_pubkey,
@@ -1066,22 +1052,16 @@ pub fn process_deactivate_stake_account(
} else {
tx.try_sign(&config.signers, recent_blockhash)?;
if let Some(nonce_account) = &nonce_account {
let nonce_account =
nonce::get_account_with_commitment(rpc_client, nonce_account, config.commitment)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&tx.message.account_keys[0],
&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::<StakeError>(result, &config)
}
}
@@ -1102,7 +1082,7 @@ pub fn process_withdraw_stake(
fee_payer: SignerIndex,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let withdraw_authority = config.signers[withdraw_authority];
let custodian = custodian.map(|index| config.signers[index]);
@@ -1135,22 +1115,16 @@ pub fn process_withdraw_stake(
} else {
tx.try_sign(&config.signers, recent_blockhash)?;
if let Some(nonce_account) = &nonce_account {
let nonce_account =
nonce::get_account_with_commitment(rpc_client, nonce_account, config.commitment)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&tx.message.account_keys[0],
&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)
}
}
@@ -1235,7 +1209,7 @@ pub fn process_split_stake(
}
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let ixs = if let Some(seed) = split_stake_account_seed {
stake_instruction::split_with_seed(
@@ -1275,22 +1249,16 @@ pub fn process_split_stake(
} else {
tx.try_sign(&config.signers, recent_blockhash)?;
if let Some(nonce_account) = &nonce_account {
let nonce_account =
nonce::get_account_with_commitment(rpc_client, nonce_account, config.commitment)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&tx.message.account_keys[0],
&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::<StakeError>(result, &config)
}
}
@@ -1346,7 +1314,7 @@ pub fn process_merge_stake(
}
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let ixs = stake_instruction::merge(
&stake_account_pubkey,
@@ -1374,22 +1342,16 @@ pub fn process_merge_stake(
} else {
tx.try_sign(&config.signers, recent_blockhash)?;
if let Some(nonce_account) = &nonce_account {
let nonce_account =
nonce::get_account_with_commitment(rpc_client, nonce_account, config.commitment)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&tx.message.account_keys[0],
&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::<StakeError>(result, &config)
}
}
@@ -1408,7 +1370,7 @@ pub fn process_stake_set_lockup(
fee_payer: SignerIndex,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let custodian = config.signers[custodian];
let ixs = vec![stake_instruction::set_lockup(
@@ -1437,22 +1399,16 @@ pub fn process_stake_set_lockup(
} else {
tx.try_sign(&config.signers, recent_blockhash)?;
if let Some(nonce_account) = &nonce_account {
let nonce_account =
nonce::get_account_with_commitment(rpc_client, nonce_account, config.commitment)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&tx.message.account_keys[0],
&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::<StakeError>(result, &config)
}
}
@@ -1470,7 +1426,6 @@ pub fn build_stake_state(
stake_state: &StakeState,
use_lamports_unit: bool,
stake_history: &StakeHistory,
clock: &Clock,
) -> CliStakeState {
match stake_state {
StakeState::Stake(
@@ -1481,15 +1436,11 @@ pub fn build_stake_state(
},
stake,
) => {
let current_epoch = clock.epoch;
// The first entry in stake history is the previous epoch, so +1 for current
let current_epoch = stake_history.iter().next().unwrap().0 + 1;
let (active_stake, activating_stake, deactivating_stake) = stake
.delegation
.stake_activating_and_deactivating(current_epoch, Some(stake_history));
let lockup = if lockup.is_in_force(clock, None) {
Some(lockup.into())
} else {
None
};
CliStakeState {
stake_type: CliStakeType::Stake,
account_balance,
@@ -1512,7 +1463,7 @@ pub fn build_stake_state(
None
},
authorized: Some(authorized.into()),
lockup,
lockup: Some(lockup.into()),
use_lamports_unit,
current_epoch,
rent_exempt_reserve: Some(*rent_exempt_reserve),
@@ -1534,22 +1485,15 @@ pub fn build_stake_state(
rent_exempt_reserve,
authorized,
lockup,
}) => {
let lockup = if lockup.is_in_force(clock, None) {
Some(lockup.into())
} else {
None
};
CliStakeState {
stake_type: CliStakeType::Initialized,
account_balance,
authorized: Some(authorized.into()),
lockup,
use_lamports_unit,
rent_exempt_reserve: Some(*rent_exempt_reserve),
..CliStakeState::default()
}
}
}) => CliStakeState {
stake_type: CliStakeType::Initialized,
account_balance,
authorized: Some(authorized.into()),
lockup: Some(lockup.into()),
use_lamports_unit,
rent_exempt_reserve: Some(*rent_exempt_reserve),
..CliStakeState::default()
},
}
}
@@ -1574,17 +1518,12 @@ pub fn process_show_stake_account(
StakeHistory::from_account(&stake_history_account).ok_or_else(|| {
CliError::RpcRequestError("Failed to deserialize stake history".to_string())
})?;
let clock_account = rpc_client.get_account(&clock::id())?;
let clock: Clock = Sysvar::from_account(&clock_account).ok_or_else(|| {
CliError::RpcRequestError("Failed to deserialize clock sysvar".to_string())
})?;
let state = build_stake_state(
stake_account.lamports,
&stake_state,
use_lamports_unit,
&stake_history,
&clock,
);
Ok(config.output_format.formatted_string(&state))
}
@@ -1640,23 +1579,14 @@ pub fn process_delegate_stake(
if !sign_only {
// Sanity check the vote account to ensure it is attached to a validator that has recently
// voted at the tip of the ledger
let vote_account = rpc_client
.get_account_with_commitment(vote_account_pubkey, config.commitment)
let vote_account_data = rpc_client
.get_account_data(vote_account_pubkey)
.map_err(|_| {
CliError::RpcRequestError(format!(
"Vote account not found: {}",
vote_account_pubkey
))
})?;
let vote_account_data = if let Some(account) = vote_account.value {
account.data
} else {
return Err(CliError::RpcRequestError(format!(
"Vote account not found: {}",
vote_account_pubkey
))
.into());
};
let vote_state = VoteState::deserialize(&vote_account_data).map_err(|_| {
CliError::RpcRequestError(
@@ -1694,7 +1624,7 @@ pub fn process_delegate_stake(
}
let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
blockhash_query.get_blockhash_and_fee_calculator(rpc_client)?;
let ixs = vec![stake_instruction::delegate_stake(
stake_account_pubkey,
@@ -1722,22 +1652,16 @@ pub fn process_delegate_stake(
} else {
tx.try_sign(&config.signers, recent_blockhash)?;
if let Some(nonce_account) = &nonce_account {
let nonce_account =
nonce::get_account_with_commitment(rpc_client, nonce_account, config.commitment)?;
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
}
check_account_for_fee_with_commitment(
check_account_for_fee(
rpc_client,
&tx.message.account_keys[0],
&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::<StakeError>(result, &config)
}
}

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

@@ -6,10 +6,9 @@ use crate::{
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},
@@ -28,6 +27,23 @@ 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 {
@@ -273,7 +289,7 @@ pub fn process_set_validator_info(
.iter()
.filter(|(_, account)| {
let key_list: ConfigKeys = deserialize(&account.data).map_err(|_| false).unwrap();
key_list.keys.contains(&(validator_info::id(), false))
key_list.keys.contains(&(id(), false))
})
.find(|(pubkey, account)| {
let (validator_pubkey, _) = parse_validator_info(&pubkey, &account).unwrap();
@@ -312,10 +328,7 @@ pub fn process_set_validator_info(
};
let build_message = |lamports| {
let keys = vec![
(validator_info::id(), false),
(config.signers[0].pubkey(), true),
];
let keys = vec![(id(), false), (config.signers[0].pubkey(), true)];
if balance == 0 {
println!(
"Publishing info for Validator {:?}",
@@ -359,7 +372,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)?;
@@ -388,7 +400,7 @@ pub fn process_get_validator_info(
let key_list: ConfigKeys = deserialize(&validator_info_account.data)
.map_err(|_| false)
.unwrap();
key_list.keys.contains(&(validator_info::id(), false))
key_list.keys.contains(&(id(), false))
})
.collect()
};
@@ -490,7 +502,7 @@ mod tests {
#[test]
fn test_parse_validator_info() {
let pubkey = Pubkey::new_rand();
let keys = vec![(validator_info::id(), false), (pubkey, true)];
let keys = vec![(id(), false), (pubkey, true)];
let config = ConfigKeys { keys };
let mut info = Map::new();

View File

@@ -1,5 +1,5 @@
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,
@@ -8,7 +8,11 @@ use crate::{
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::*,
};
use solana_client::rpc_client::RpcClient;
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{
@@ -374,10 +378,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![],
})
@@ -478,25 +484,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 +505,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 +531,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 +542,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 +566,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 +576,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 +594,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 +604,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 +647,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 +696,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 +725,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)
}

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,3 +1,4 @@
use solana_cli::test_utils::check_balance;
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
cli_output::OutputFormat,
@@ -7,14 +8,12 @@ use solana_cli::{
parse_sign_only_reply_string,
},
spend_utils::SpendAmount,
test_utils::{check_ready, check_recent_balance},
};
use solana_client::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 +83,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 +96,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 +131,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 +181,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 +224,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 +250,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 +270,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 +280,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 +293,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::get_account(&rpc_client, &nonce_address)
.and_then(|ref a| nonce::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 +329,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 +348,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,5 +1,6 @@
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,
@@ -9,13 +10,11 @@ use solana_cli::{
parse_sign_only_reply_string,
},
spend_utils::SpendAmount,
test_utils::check_recent_balance,
};
use solana_client::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 +40,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 +62,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 +92,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 +127,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 +174,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 +209,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 +249,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 +284,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 +314,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 +328,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 +347,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 +373,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 +389,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 +406,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
let bob_pubkey = Pubkey::new_rand();
config.signers = vec![&default_signer];
@@ -434,18 +429,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::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,3 +1,4 @@
use solana_cli::test_utils::check_balance;
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
cli_output::OutputFormat,
@@ -7,14 +8,12 @@ use solana_cli::{
parse_sign_only_reply_string,
},
spend_utils::SpendAmount,
test_utils::{check_ready, check_recent_balance},
};
use solana_client::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 +40,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 +137,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 +150,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 +182,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 +226,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 +241,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 +267,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 +310,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 +338,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 +348,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 +374,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 +393,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 +454,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 +502,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
// Delegate stake
config.signers = vec![&config_keypair];
@@ -518,7 +513,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 +526,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
// Deactivate stake
config.command = CliCommand::DeactivateStake {
@@ -577,7 +568,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 +582,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 +633,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 +660,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 +682,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 +693,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 +719,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 +742,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
// Nonced assignment of new online stake authority
let online_authority = Keypair::new();
@@ -812,11 +780,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 +788,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
assert_ne!(nonce_hash, new_nonce_hash);
server.close().unwrap();
@@ -862,18 +822,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 +844,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 +874,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 +889,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 +922,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 +954,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 +974,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 +1002,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 +1021,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::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 +1067,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 +1105,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 +1125,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 +1158,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 +1182,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 +1233,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 +1278,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
// Nonced offline set lockup
let lockup = LockupArgs {
@@ -1383,11 +1322,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 +1356,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 +1378,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 +1400,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
// Create stake account offline
let stake_keypair = keypair_from_seed(&[4u8; 32]).unwrap();
@@ -1517,17 +1448,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
// Offline, nonced stake-withdraw
let recipient = keypair_from_seed(&[5u8; 32]).unwrap();
@@ -1565,17 +1492,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
// Create another stake account. This time with seed
let seed = "seedy";
@@ -1619,7 +1542,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,3 +1,4 @@
use solana_cli::test_utils::check_balance;
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
cli_output::OutputFormat,
@@ -7,13 +8,11 @@ use solana_cli::{
parse_sign_only_reply_string,
},
spend_utils::SpendAmount,
test_utils::{check_ready, check_recent_balance},
};
use solana_client::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 +42,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 +51,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 +67,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 +83,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 +95,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 +128,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 +144,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
// Nonced transfer
config.signers = vec![&default_signer];
@@ -179,16 +169,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
assert_ne!(nonce_hash, new_nonce_hash);
// Assign nonce authority to offline
@@ -199,17 +185,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::get_account(&rpc_client, &nonce_account.pubkey())
.and_then(|ref a| nonce::data_from_account(a))
.unwrap()
.blockhash;
// Offline, nonced transfer
offline.signers = vec![&default_offline_signer];
@@ -244,8 +226,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 +255,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 +275,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 +308,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 +334,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 +350,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 +380,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 +389,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 +405,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

@@ -2,14 +2,13 @@ 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::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 +31,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 +58,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 +67,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 +84,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 +96,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 +112,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,38 +1,38 @@
[package]
name = "solana-client"
version = "1.3.2"
version = "1.2.13"
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"
edition = "2018"
[dependencies]
bincode = "1.3.1"
bincode = "1.2.1"
bs58 = "0.3.1"
indicatif = "0.15.0"
jsonrpc-core = "14.2.0"
indicatif = "0.14.0"
jsonrpc-core = "14.1.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.3.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.2" }
solana-net-utils = { path = "../net-utils", version = "1.3.2" }
solana-sdk = { path = "../sdk", version = "1.3.2" }
solana-transaction-status = { path = "../transaction-status", version = "1.3.2" }
solana-vote-program = { path = "../programs/vote", version = "1.3.2" }
serde_json = "1.0.53"
solana-account-decoder = { path = "../account-decoder", version = "1.2.13" }
solana-net-utils = { path = "../net-utils", version = "1.2.13" }
solana-sdk = { path = "../sdk", version = "1.2.13" }
solana-transaction-status = { path = "../transaction-status", version = "1.2.13" }
solana-vote-program = { path = "../programs/vote", version = "1.2.13" }
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.2" }
jsonrpc-core = "14.1.0"
jsonrpc-http-server = "14.1.0"
solana-logger = { path = "../logger", version = "1.2.13" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@@ -2,12 +2,8 @@ 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,
},
rpc_request::{RpcError, RpcRequest, TokenAccountsFilter},
rpc_config::{RpcLargestAccountsConfig, RpcSendTransactionConfig},
rpc_request::{RpcError, RpcRequest},
rpc_response::*,
rpc_sender::RpcSender,
};
@@ -15,25 +11,21 @@ use bincode::serialize;
use indicatif::{ProgressBar, ProgressStyle};
use log::*;
use serde_json::{json, Value};
use solana_account_decoder::{
parse_token::UiTokenAmount,
UiAccount,
UiAccountData::{Binary, Binary64},
UiAccountEncoding,
};
use solana_account_decoder::UiAccount;
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::{
@@ -61,10 +53,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))
}
@@ -79,7 +67,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> {
@@ -295,32 +283,6 @@ impl RpcClient {
Ok(signatures)
}
pub fn get_confirmed_signatures_for_address2(
&self,
address: &Pubkey,
) -> ClientResult<Vec<RpcConfirmedTransactionStatusWithSignature>> {
self.get_confirmed_signatures_for_address2_with_config(address, None, None)
}
pub fn get_confirmed_signatures_for_address2_with_config(
&self,
address: &Pubkey,
before: Option<Signature>,
limit: Option<usize>,
) -> ClientResult<Vec<RpcConfirmedTransactionStatusWithSignature>> {
let config = RpcGetConfirmedSignaturesForAddress2Config {
before: before.map(|signature| signature.to_string()),
limit,
};
let result: Vec<RpcConfirmedTransactionStatusWithSignature> = self.send(
RpcRequest::GetConfirmedSignaturesForAddress2,
json!([address.to_string(), config]),
)?;
Ok(result)
}
pub fn get_confirmed_transaction(
&self,
signature: &Signature,
@@ -454,6 +416,17 @@ impl RpcClient {
}
}
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
@@ -465,14 +438,9 @@ impl RpcClient {
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> RpcResult<Option<Account>> {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Binary64),
commitment: Some(commitment_config),
data_slice: None,
};
let response = self.sender.send(
RpcRequest::GetAccountInfo,
json!([pubkey.to_string(), config]),
json!([pubkey.to_string(), commitment_config]),
);
response
@@ -484,17 +452,8 @@ impl RpcClient {
}
let Response {
context,
value: mut rpc_account,
value: rpc_account,
} = serde_json::from_value::<Response<Option<UiAccount>>>(result_json)?;
if let Some(ref mut account) = rpc_account {
if let Binary(_) = &account.data {
let tmp = Binary64(String::new());
match std::mem::replace(&mut account.data, tmp) {
Binary(new_data) => account.data = Binary64(new_data),
_ => panic!("should have gotten binary here."),
}
}
}
trace!("Response account {:?} {:?}", pubkey, rpc_account);
let account = rpc_account.and_then(|rpc_account| rpc_account.decode());
Ok(Response {
@@ -552,7 +511,17 @@ 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()]))?;
parse_keyed_accounts(accounts, RpcRequest::GetProgramAccounts)
let mut pubkey_accounts: Vec<(Pubkey, Account)> = Vec::new();
for RpcKeyedAccount { pubkey, account } in accounts.into_iter() {
let pubkey = pubkey.parse().map_err(|_| {
ClientError::new_with_request(
RpcError::ParseError("Pubkey".to_string()).into(),
RpcRequest::GetProgramAccounts,
)
})?;
pubkey_accounts.push((pubkey, account.decode().unwrap()));
}
Ok(pubkey_accounts)
}
/// Request the transaction count.
@@ -699,119 +668,7 @@ impl RpcClient {
Ok(hash)
}
pub fn get_token_account_balance(&self, pubkey: &Pubkey) -> ClientResult<UiTokenAmount> {
Ok(self
.get_token_account_balance_with_commitment(pubkey, CommitmentConfig::default())?
.value)
}
pub fn get_token_account_balance_with_commitment(
&self,
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> RpcResult<UiTokenAmount> {
self.send(
RpcRequest::GetTokenAccountBalance,
json!([pubkey.to_string(), commitment_config]),
)
}
pub fn get_token_accounts_by_delegate(
&self,
delegate: &Pubkey,
token_account_filter: TokenAccountsFilter,
) -> ClientResult<Vec<RpcKeyedAccount>> {
Ok(self
.get_token_accounts_by_delegate_with_commitment(
delegate,
token_account_filter,
CommitmentConfig::default(),
)?
.value)
}
pub fn get_token_accounts_by_delegate_with_commitment(
&self,
delegate: &Pubkey,
token_account_filter: TokenAccountsFilter,
commitment_config: CommitmentConfig,
) -> 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 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<RpcKeyedAccount>> {
Ok(self
.get_token_accounts_by_owner_with_commitment(
owner,
token_account_filter,
CommitmentConfig::default(),
)?
.value)
}
pub fn get_token_accounts_by_owner_with_commitment(
&self,
owner: &Pubkey,
token_account_filter: TokenAccountsFilter,
commitment_config: CommitmentConfig,
) -> 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 config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::JsonParsed),
commitment: Some(commitment_config),
data_slice: None,
};
self.send(
RpcRequest::GetTokenAccountsByOwner,
json!([owner.to_string(), token_account_filter, config]),
)
}
pub fn get_token_supply(&self, mint: &Pubkey) -> ClientResult<UiTokenAmount> {
Ok(self
.get_token_supply_with_commitment(mint, CommitmentConfig::default())?
.value)
}
pub fn get_token_supply_with_commitment(
&self,
mint: &Pubkey,
commitment_config: CommitmentConfig,
) -> RpcResult<UiTokenAmount> {
self.send(
RpcRequest::GetTokenSupply,
json!([mint.to_string(), commitment_config]),
)
}
fn poll_balance_with_timeout_and_commitment(
pub fn poll_balance_with_timeout_and_commitment(
&self,
pubkey: &Pubkey,
polling_frequency: &Duration,
@@ -820,7 +677,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);
}
@@ -855,7 +712,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();
}
@@ -889,7 +747,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;
}
@@ -905,6 +763,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,
@@ -987,19 +875,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(),
)
}
@@ -1007,13 +882,8 @@ 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();
@@ -1022,11 +892,13 @@ impl RpcClient {
let signature = loop {
progress_bar.set_message(&format!(
"[{}/{}] Finalizing transaction {}",
confirmations, desired_confirmations, transaction.signatures[0],
confirmations,
MAX_LOCKOUT_HISTORY + 1,
transaction.signatures[0],
));
let mut status_retries = 15;
let (signature, status) = loop {
let signature = self.send_transaction_with_config(transaction, config)?;
let signature = self.send_transaction_with_config(transaction, config.clone())?;
// Get recent commitment in order to count confirmations for successful transactions
let status = self
@@ -1076,30 +948,17 @@ impl RpcClient {
};
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));
@@ -1150,31 +1009,6 @@ pub fn get_rpc_request_str(rpc_addr: SocketAddr, tls: bool) -> String {
}
}
fn parse_keyed_accounts(
accounts: Vec<RpcKeyedAccount>,
request: RpcRequest,
) -> ClientResult<Vec<(Pubkey, Account)>> {
let mut pubkey_accounts: Vec<(Pubkey, Account)> = Vec::new();
for RpcKeyedAccount { pubkey, account } in accounts.into_iter() {
let pubkey = pubkey.parse().map_err(|_| {
ClientError::new_with_request(
RpcError::ParseError("Pubkey".to_string()).into(),
request,
)
})?;
pubkey_accounts.push((
pubkey,
account.decode().ok_or_else(|| {
ClientError::new_with_request(
RpcError::ParseError("Account from rpc".to_string()).into(),
request,
)
})?,
));
}
Ok(pubkey_accounts)
}
#[cfg(test)]
mod tests {
use super::*;
@@ -1328,6 +1162,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,5 +1,5 @@
use crate::rpc_filter::RpcFilterType;
use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig};
use solana_account_decoder::UiAccountEncoding;
use solana_sdk::{clock::Epoch, commitment_config::CommitmentConfig};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@@ -8,7 +8,7 @@ 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 {
pub skip_preflight: bool,
@@ -47,7 +47,6 @@ 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>,
}
@@ -59,17 +58,3 @@ pub struct RpcProgramAccountsConfig {
#[serde(flatten)]
pub account_config: RpcAccountInfoConfig,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum RpcTokenAccountsFilter {
Mint(String),
ProgramId(String),
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcGetConfirmedSignaturesForAddress2Config {
pub before: Option<String>, // Signature as base-58 string
pub limit: Option<usize>,
}

View File

@@ -1,5 +1,4 @@
use serde_json::{json, Value};
use solana_sdk::pubkey::Pubkey;
use std::fmt;
use thiserror::Error;
@@ -14,7 +13,6 @@ pub enum RpcRequest {
GetConfirmedBlock,
GetConfirmedBlocks,
GetConfirmedSignaturesForAddress,
GetConfirmedSignaturesForAddress2,
GetConfirmedTransaction,
GetEpochInfo,
GetEpochSchedule,
@@ -38,10 +36,6 @@ pub enum RpcRequest {
GetSlotsPerSegment,
GetStoragePubkeysForSlot,
GetSupply,
GetTokenAccountBalance,
GetTokenAccountsByDelegate,
GetTokenAccountsByOwner,
GetTokenSupply,
GetTotalSupply,
GetTransactionCount,
GetVersion,
@@ -66,7 +60,6 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetConfirmedBlock => "getConfirmedBlock",
RpcRequest::GetConfirmedBlocks => "getConfirmedBlocks",
RpcRequest::GetConfirmedSignaturesForAddress => "getConfirmedSignaturesForAddress",
RpcRequest::GetConfirmedSignaturesForAddress2 => "getConfirmedSignaturesForAddress2",
RpcRequest::GetConfirmedTransaction => "getConfirmedTransaction",
RpcRequest::GetEpochInfo => "getEpochInfo",
RpcRequest::GetEpochSchedule => "getEpochSchedule",
@@ -90,10 +83,6 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetSlotsPerSegment => "getSlotsPerSegment",
RpcRequest::GetStoragePubkeysForSlot => "getStoragePubkeysForSlot",
RpcRequest::GetSupply => "getSupply",
RpcRequest::GetTokenAccountBalance => "getTokenAccountBalance",
RpcRequest::GetTokenAccountsByDelegate => "getTokenAccountsByDelegate",
RpcRequest::GetTokenAccountsByOwner => "getTokenAccountsByOwner",
RpcRequest::GetTokenSupply => "getTokenSupply",
RpcRequest::GetTotalSupply => "getTotalSupply",
RpcRequest::GetTransactionCount => "getTransactionCount",
RpcRequest::GetVersion => "getVersion",
@@ -114,7 +103,6 @@ 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;
// Validators that are this number of slots behind are considered delinquent
pub const DELINQUENT_VALIDATOR_SLOT_DISTANCE: u64 = 128;
@@ -143,28 +131,21 @@ pub enum RpcError {
ForUser(String), /* "direct-to-user message" */
}
#[derive(Serialize, Deserialize)]
pub enum TokenAccountsFilter {
Mint(Pubkey),
ProgramId(Pubkey),
}
#[cfg(test)]
mod tests {
use super::*;
use crate::rpc_config::RpcTokenAccountsFilter;
use solana_sdk::commitment_config::{CommitmentConfig, CommitmentLevel};
#[test]
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,23 +190,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
let test_request = RpcRequest::GetTokenAccountsByOwner;
let mint = Pubkey::new_rand();
let token_account_filter = RpcTokenAccountsFilter::Mint(mint.to_string());
let request = test_request
.build_request_json(1, json!([addr, token_account_filter, commitment_config]));
assert_eq!(
request["params"],
json!([addr, token_account_filter, commitment_config])
);
}
}

View File

@@ -1,12 +1,11 @@
use crate::client_error;
use solana_account_decoder::{parse_token::UiTokenAmount, UiAccount};
use solana_account_decoder::UiAccount;
use solana_sdk::{
clock::{Epoch, Slot},
fee_calculator::{FeeCalculator, FeeRateGovernor},
inflation::Inflation,
transaction::{Result, TransactionError},
};
use solana_transaction_status::ConfirmedTransactionStatusWithSignature;
use std::{collections::HashMap, net::SocketAddr};
pub type RpcResult<T> = client_error::Result<Response<T>>;
@@ -220,37 +219,3 @@ pub struct RpcStakeActivation {
pub active: u64,
pub inactive: u64,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct RpcTokenAccountBalance {
pub address: String,
#[serde(flatten)]
pub amount: UiTokenAmount,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcConfirmedTransactionStatusWithSignature {
pub signature: String,
pub slot: Slot,
pub err: Option<TransactionError>,
pub memo: Option<String>,
}
impl From<ConfirmedTransactionStatusWithSignature> for RpcConfirmedTransactionStatusWithSignature {
fn from(value: ConfirmedTransactionStatusWithSignature) -> Self {
let ConfirmedTransactionStatusWithSignature {
signature,
slot,
err,
memo,
} = value;
Self {
signature: signature.to_string(),
slot,
err,
memo,
}
}
}

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())
}

View File

@@ -1,12 +1,12 @@
[package]
name = "solana-core"
description = "Blockchain, Rebuilt for Scale"
version = "1.3.2"
version = "1.2.13"
documentation = "https://docs.rs/solana"
homepage = "https://solana.com/"
readme = "../README.md"
repository = "https://github.com/solana-labs/solana"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
authors = ["Solana Maintainers <maintainers@solana.com>"]
license = "Apache-2.0"
edition = "2018"
@@ -14,81 +14,73 @@ edition = "2018"
codecov = { repository = "solana-labs/solana", branch = "master", service = "github" }
[dependencies]
bincode = "1.3.1"
bincode = "1.2.1"
bv = { version = "0.11.1", features = ["serde"] }
bs58 = "0.3.1"
byteorder = "1.3.4"
chrono = { version = "0.4.11", features = ["serde"] }
core_affinity = "0.5.10"
crossbeam-channel = "0.4"
ed25519-dalek = "=1.0.0-pre.4"
ed25519-dalek = "=1.0.0-pre.3"
fs_extra = "1.1.0"
flate2 = "1.0"
indexmap = "1.4"
indexmap = "1.3"
itertools = "0.9.0"
jsonrpc-core = "14.2.0"
jsonrpc-core-client = { version = "14.2.0", features = ["ws"] }
jsonrpc-derive = "14.2.1"
jsonrpc-http-server = "14.2.0"
jsonrpc-pubsub = "14.2.0"
jsonrpc-ws-server = "14.2.0"
jsonrpc-core = "14.1.0"
jsonrpc-core-client = { version = "14.1.0", features = ["ws"] }
jsonrpc-derive = "14.1.0"
jsonrpc-http-server = "14.1.0"
jsonrpc-pubsub = "14.1.0"
jsonrpc-ws-server = "14.1.0"
log = "0.4.8"
num_cpus = "1.13.0"
num-traits = "0.2"
rand = "0.7.0"
rand_chacha = "0.2.2"
raptorq = "1.4.2"
rayon = "1.3.1"
regex = "1.3.9"
serde = "1.0.112"
rayon = "1.3.0"
regex = "1.3.7"
serde = "1.0.110"
serde_derive = "1.0.103"
serde_json = "1.0.56"
solana-account-decoder = { path = "../account-decoder", version = "1.3.2" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.3.2" }
solana-budget-program = { path = "../programs/budget", version = "1.3.2" }
solana-clap-utils = { path = "../clap-utils", version = "1.3.2" }
solana-client = { path = "../client", version = "1.3.2" }
solana-faucet = { path = "../faucet", version = "1.3.2" }
solana-genesis-programs = { path = "../genesis-programs", version = "1.3.2" }
solana-ledger = { path = "../ledger", version = "1.3.2" }
solana-logger = { path = "../logger", version = "1.3.2" }
solana-merkle-tree = { path = "../merkle-tree", version = "1.3.2" }
solana-metrics = { path = "../metrics", version = "1.3.2" }
solana-measure = { path = "../measure", version = "1.3.2" }
solana-net-utils = { path = "../net-utils", version = "1.3.2" }
solana-perf = { path = "../perf", version = "1.3.2" }
solana-runtime = { path = "../runtime", version = "1.3.2" }
solana-sdk = { path = "../sdk", version = "1.3.2" }
solana-sdk-macro-frozen-abi = { path = "../sdk/macro-frozen-abi", version = "1.3.2" }
solana-stake-program = { path = "../programs/stake", version = "1.3.2" }
solana-storage-bigtable = { path = "../storage-bigtable", version = "1.3.2" }
solana-streamer = { path = "../streamer", version = "1.3.2" }
solana-sys-tuner = { path = "../sys-tuner", version = "1.3.2" }
solana-transaction-status = { path = "../transaction-status", version = "1.3.2" }
solana-version = { path = "../version", version = "1.3.2" }
solana-vote-program = { path = "../programs/vote", version = "1.3.2" }
solana-vote-signer = { path = "../vote-signer", version = "1.3.2" }
spl-token-v1-0 = { package = "spl-token", version = "1.0.6", features = ["skip-no-mangle"] }
serde_json = "1.0.53"
solana-account-decoder = { path = "../account-decoder", version = "1.2.13" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.2.13" }
solana-budget-program = { path = "../programs/budget", version = "1.2.13" }
solana-clap-utils = { path = "../clap-utils", version = "1.2.13" }
solana-client = { path = "../client", version = "1.2.13" }
solana-faucet = { path = "../faucet", version = "1.2.13" }
solana-genesis-programs = { path = "../genesis-programs", version = "1.2.13" }
solana-ledger = { path = "../ledger", version = "1.2.13" }
solana-logger = { path = "../logger", version = "1.2.13" }
solana-merkle-tree = { path = "../merkle-tree", version = "1.2.13" }
solana-metrics = { path = "../metrics", version = "1.2.13" }
solana-measure = { path = "../measure", version = "1.2.13" }
solana-net-utils = { path = "../net-utils", version = "1.2.13" }
solana-perf = { path = "../perf", version = "1.2.13" }
solana-runtime = { path = "../runtime", version = "1.2.13" }
solana-sdk = { path = "../sdk", version = "1.2.13" }
solana-stake-program = { path = "../programs/stake", version = "1.2.13" }
solana-streamer = { path = "../streamer", version = "1.2.13" }
solana-sys-tuner = { path = "../sys-tuner", version = "1.2.13" }
solana-transaction-status = { path = "../transaction-status", version = "1.2.13" }
solana-version = { path = "../version", version = "1.2.13" }
solana-vote-program = { path = "../programs/vote", version = "1.2.13" }
solana-vote-signer = { path = "../vote-signer", version = "1.2.13" }
tempfile = "3.1.0"
thiserror = "1.0"
tokio_01 = { version = "0.1", package = "tokio" }
tokio_fs_01 = { version = "0.1", package = "tokio-fs" }
tokio_io_01 = { version = "0.1", package = "tokio-io" }
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.3.2" }
tokio = { version = "0.2.22", features = ["full"] }
tokio = "0.1"
tokio-codec = "0.1"
tokio-fs = "0.1"
tokio-io = "0.1"
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.13" }
trees = "0.2.1"
[dev-dependencies]
base64 = "0.12.3"
matches = "0.1.6"
reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] }
reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serial_test = "0.4.0"
serial_test_derive = "0.4.0"
systemstat = "0.1.5"
[build-dependencies]
rustc_version = "0.2"
[[bench]]
name = "banking_stage"

View File

@@ -73,7 +73,6 @@ fn bench_consume_buffered(bencher: &mut Bencher) {
let batch_len = batch.packets.len();
packets.push((batch, vec![0usize; batch_len]));
}
let (s, _r) = unbounded();
// This tests the performance of buffering packets.
// If the packet buffers are copied, performance will be poor.
bencher.iter(move || {
@@ -83,7 +82,6 @@ fn bench_consume_buffered(bencher: &mut Bencher) {
&mut packets,
10_000,
None,
&s,
);
});
@@ -112,6 +110,7 @@ fn make_accounts_txs(txes: usize, mint_keypair: &Keypair, hash: Hash) -> Vec<Tra
fn make_programs_txs(txes: usize, hash: Hash) -> Vec<Transaction> {
let progs = 4;
(0..txes)
.into_iter()
.map(|_| {
let mut instructions = vec![];
let from_key = Keypair::new();
@@ -182,7 +181,7 @@ fn bench_banking(bencher: &mut Bencher, tx_type: TransactionType) {
assert!(r.is_ok(), "sanity parallel execution");
}
bank.clear_signatures();
let verified: Vec<_> = to_packets_chunked(&transactions, PACKETS_PER_BATCH);
let verified: Vec<_> = to_packets_chunked(&transactions.clone(), PACKETS_PER_BATCH);
let ledger_path = get_tmp_ledger_path!();
{
let blockstore = Arc::new(
@@ -192,14 +191,12 @@ fn bench_banking(bencher: &mut Bencher, tx_type: TransactionType) {
create_test_recorder(&bank, &blockstore, None);
let cluster_info = ClusterInfo::new_with_invalid_keypair(Node::new_localhost().info);
let cluster_info = Arc::new(cluster_info);
let (s, _r) = unbounded();
let _banking_stage = BankingStage::new(
&cluster_info,
&poh_recorder,
verified_receiver,
vote_receiver,
None,
s,
);
poh_recorder.lock().unwrap().set_bank(&bank);
@@ -210,7 +207,7 @@ fn bench_banking(bencher: &mut Bencher, tx_type: TransactionType) {
// If it is dropped before poh_service, then poh_service will error when
// calling send() on the channel.
let signal_receiver = Arc::new(signal_receiver);
let signal_receiver2 = signal_receiver;
let signal_receiver2 = signal_receiver.clone();
bencher.iter(move || {
let now = Instant::now();
let mut sent = 0;
@@ -265,7 +262,7 @@ fn simulate_process_entries(
mint_keypair: &Keypair,
mut tx_vector: Vec<Transaction>,
genesis_config: &GenesisConfig,
keypairs: &[Keypair],
keypairs: &Vec<Keypair>,
initial_lamports: u64,
num_accounts: usize,
) {
@@ -291,7 +288,7 @@ fn simulate_process_entries(
hash: next_hash(&bank.last_blockhash(), 1, &tx_vector),
transactions: tx_vector,
};
process_entries(&bank, &[entry], randomize_txs, None, None).unwrap();
process_entries(&bank, &vec![entry], randomize_txs, None).unwrap();
}
fn bench_process_entries(randomize_txs: bool, bencher: &mut Bencher) {

View File

@@ -1,4 +1,6 @@
#![feature(test)]
use rand;
extern crate solana_ledger;
extern crate test;

View File

@@ -22,7 +22,7 @@ fn broadcast_shreds_bench(bencher: &mut Bencher) {
solana_logger::setup();
let leader_pubkey = Pubkey::new_rand();
let leader_info = Node::new_localhost_with_pubkey(&leader_pubkey);
let cluster_info = ClusterInfo::new_with_invalid_keypair(leader_info.info);
let cluster_info = ClusterInfo::new_with_invalid_keypair(leader_info.info.clone());
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
const NUM_SHREDS: usize = 32;
@@ -37,7 +37,7 @@ fn broadcast_shreds_bench(bencher: &mut Bencher) {
}
let stakes = Arc::new(stakes);
let cluster_info = Arc::new(cluster_info);
let (peers, peers_and_stakes) = get_broadcast_peers(&cluster_info, Some(stakes));
let (peers, peers_and_stakes) = get_broadcast_peers(&cluster_info, Some(stakes.clone()));
let shreds = Arc::new(shreds);
let last_datapoint = Arc::new(AtomicU64::new(0));
bencher.iter(move || {

View File

@@ -7,13 +7,13 @@ use log::*;
use solana_core::cluster_info::{ClusterInfo, Node};
use solana_core::contact_info::ContactInfo;
use solana_core::retransmit_stage::retransmitter;
use solana_ledger::bank_forks::BankForks;
use solana_ledger::genesis_utils::{create_genesis_config, GenesisConfigInfo};
use solana_ledger::leader_schedule_cache::LeaderScheduleCache;
use solana_measure::measure::Measure;
use solana_perf::packet::to_packets_chunked;
use solana_perf::test_tx::test_tx;
use solana_runtime::bank::Bank;
use solana_runtime::bank_forks::BankForks;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::timing::timestamp;
use std::net::UdpSocket;
@@ -65,10 +65,7 @@ fn bench_retransmitter(bencher: &mut Bencher) {
let tx = test_tx();
const NUM_PACKETS: usize = 50;
let chunk_size = NUM_PACKETS / (4 * NUM_THREADS);
let batches = to_packets_chunked(
&std::iter::repeat(tx).take(NUM_PACKETS).collect::<Vec<_>>(),
chunk_size,
);
let batches = to_packets_chunked(&vec![tx; NUM_PACKETS], chunk_size);
info!("batches: {}", batches.len());
let retransmitter_handles = retransmitter(
@@ -83,6 +80,7 @@ fn bench_retransmitter(bencher: &mut Bencher) {
bencher.iter(move || {
let peer_sockets1 = peer_sockets.clone();
let handles: Vec<_> = (0..NUM_PEERS)
.into_iter()
.map(|p| {
let peer_sockets2 = peer_sockets1.clone();
let total2 = total.clone();

View File

@@ -2,13 +2,10 @@
extern crate test;
use rand::seq::SliceRandom;
use raptorq::{Decoder, Encoder};
use solana_ledger::entry::{create_ticks, Entry};
use solana_ledger::shred::{
max_entries_per_n_shred, max_ticks_per_n_shreds, Shred, Shredder,
MAX_DATA_SHREDS_PER_FEC_BLOCK, RECOMMENDED_FEC_RATE, SHRED_PAYLOAD_SIZE,
SIZE_OF_DATA_SHRED_IGNORED_TAIL, SIZE_OF_DATA_SHRED_PAYLOAD,
max_entries_per_n_shred, max_ticks_per_n_shreds, Shred, Shredder, RECOMMENDED_FEC_RATE,
SIZE_OF_DATA_SHRED_PAYLOAD,
};
use solana_perf::test_tx;
use solana_sdk::hash::Hash;
@@ -29,34 +26,6 @@ fn make_large_unchained_entries(txs_per_entry: u64, num_entries: u64) -> Vec<Ent
.collect()
}
fn make_shreds(num_shreds: usize) -> Vec<Shred> {
let shred_size = SIZE_OF_DATA_SHRED_PAYLOAD;
let txs_per_entry = 128;
let num_entries = max_entries_per_n_shred(
&make_test_entry(txs_per_entry),
2 * num_shreds as u64,
Some(shred_size),
);
let entries = make_large_unchained_entries(txs_per_entry, num_entries);
let shredder =
Shredder::new(1, 0, RECOMMENDED_FEC_RATE, Arc::new(Keypair::new()), 0, 0).unwrap();
let data_shreds = shredder.entries_to_data_shreds(&entries, true, 0).0;
assert!(data_shreds.len() >= num_shreds);
data_shreds
}
fn make_concatenated_shreds(num_shreds: usize) -> Vec<u8> {
let data_shreds = make_shreds(num_shreds);
let valid_shred_data_len = (SHRED_PAYLOAD_SIZE - SIZE_OF_DATA_SHRED_IGNORED_TAIL) as usize;
let mut data: Vec<u8> = vec![0; num_shreds * valid_shred_data_len];
for (i, shred) in (data_shreds[0..num_shreds]).iter().enumerate() {
data[i * valid_shred_data_len..(i + 1) * valid_shred_data_len]
.copy_from_slice(&shred.payload[..valid_shred_data_len]);
}
data
}
#[bench]
fn bench_shredder_ticks(bencher: &mut Bencher) {
let kp = Arc::new(Keypair::new());
@@ -117,68 +86,3 @@ fn bench_deserialize_hdr(bencher: &mut Bencher) {
let _ = Shred::new_from_serialized_shred(payload).unwrap();
})
}
#[bench]
fn bench_shredder_coding(bencher: &mut Bencher) {
let symbol_count = MAX_DATA_SHREDS_PER_FEC_BLOCK as usize;
let data_shreds = make_shreds(symbol_count);
bencher.iter(|| {
Shredder::generate_coding_shreds(0, RECOMMENDED_FEC_RATE, &data_shreds[..symbol_count], 0)
.len();
})
}
#[bench]
fn bench_shredder_decoding(bencher: &mut Bencher) {
let symbol_count = MAX_DATA_SHREDS_PER_FEC_BLOCK as usize;
let data_shreds = make_shreds(symbol_count);
let coding_shreds =
Shredder::generate_coding_shreds(0, RECOMMENDED_FEC_RATE, &data_shreds[..symbol_count], 0);
bencher.iter(|| {
Shredder::try_recovery(
coding_shreds[..].to_vec(),
symbol_count,
symbol_count,
0,
0,
1,
)
.unwrap();
})
}
#[bench]
fn bench_shredder_coding_raptorq(bencher: &mut Bencher) {
let symbol_count = MAX_DATA_SHREDS_PER_FEC_BLOCK;
let data = make_concatenated_shreds(symbol_count as usize);
let valid_shred_data_len = (SHRED_PAYLOAD_SIZE - SIZE_OF_DATA_SHRED_IGNORED_TAIL) as usize;
bencher.iter(|| {
let encoder = Encoder::with_defaults(&data, valid_shred_data_len as u16);
encoder.get_encoded_packets(symbol_count);
})
}
#[bench]
fn bench_shredder_decoding_raptorq(bencher: &mut Bencher) {
let symbol_count = MAX_DATA_SHREDS_PER_FEC_BLOCK;
let data = make_concatenated_shreds(symbol_count as usize);
let valid_shred_data_len = (SHRED_PAYLOAD_SIZE - SIZE_OF_DATA_SHRED_IGNORED_TAIL) as usize;
let encoder = Encoder::with_defaults(&data, valid_shred_data_len as u16);
let mut packets = encoder.get_encoded_packets(symbol_count as u32);
packets.shuffle(&mut rand::thread_rng());
// Here we simulate losing 1 less than 50% of the packets randomly
packets.truncate(packets.len() - packets.len() / 2 + 1);
bencher.iter(|| {
let mut decoder = Decoder::new(encoder.get_config());
let mut result = None;
for packet in &packets {
result = decoder.decode(packet.clone());
if result != None {
break;
}
}
assert_eq!(result.unwrap(), data);
})
}

View File

@@ -37,14 +37,16 @@ fn bench_sigverify_stage(bencher: &mut Bencher) {
let from_keypair = Keypair::new();
let to_keypair = Keypair::new();
let txs: Vec<_> = (0..len)
.into_iter()
.map(|_| {
let amount = thread_rng().gen();
system_transaction::transfer(
let tx = system_transaction::transfer(
&from_keypair,
&to_keypair.pubkey(),
amount,
Hash::default(),
)
);
tx
})
.collect();
to_packets_chunked(&txs, chunk_size)

View File

@@ -1 +0,0 @@
../sdk/build.rs

View File

@@ -2,8 +2,7 @@
//
// This can be expensive since we have to walk the append vecs being cleaned up.
use rand::{thread_rng, Rng};
use solana_runtime::bank_forks::BankForks;
use solana_ledger::bank_forks::BankForks;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc, RwLock,
@@ -40,9 +39,7 @@ impl AccountsBackgroundService {
consumed_budget = bank
.process_stale_slot_with_budget(consumed_budget, SHRUNKEN_ACCOUNT_PER_INTERVAL);
if bank.block_height() - last_cleaned_slot
> (CLEAN_INTERVAL_SLOTS + thread_rng().gen_range(0, 10))
{
if bank.block_height() - last_cleaned_slot > CLEAN_INTERVAL_SLOTS {
bank.clean_accounts();
last_cleaned_slot = bank.block_height();
}

View File

@@ -5,8 +5,9 @@
// set and halt the node if a mismatch is detected.
use crate::cluster_info::{ClusterInfo, MAX_SNAPSHOT_HASHES};
use solana_runtime::snapshot_package::{
AccountsPackage, AccountsPackageReceiver, AccountsPackageSender,
use solana_ledger::{
snapshot_package::AccountsPackage, snapshot_package::AccountsPackageReceiver,
snapshot_package::AccountsPackageSender,
};
use solana_sdk::{clock::Slot, hash::Hash, pubkey::Pubkey};
use std::collections::{HashMap, HashSet};
@@ -175,8 +176,8 @@ mod tests {
use super::*;
use crate::cluster_info::make_accounts_hashes_message;
use crate::contact_info::ContactInfo;
use solana_runtime::bank_forks::CompressionType;
use solana_runtime::snapshot_utils::SnapshotVersion;
use solana_ledger::bank_forks::CompressionType;
use solana_ledger::snapshot_utils::SnapshotVersion;
use solana_sdk::{
hash::hash,
signature::{Keypair, Signer},

View File

@@ -3,7 +3,8 @@ use crate::{
fork_choice::ForkChoice,
progress_map::{ForkStats, ProgressMap},
};
use solana_runtime::{bank::Bank, bank_forks::BankForks};
use solana_ledger::bank_forks::BankForks;
use solana_runtime::bank::Bank;
use solana_sdk::timing;
use std::time::Instant;
use std::{
@@ -63,7 +64,7 @@ impl ForkChoice for BankWeightForkChoice {
.filter(|b| b.slot() < tower.root().unwrap_or(0))
.count();
let last_voted_slot = tower.last_voted_slot();
let last_vote = tower.last_vote().slots.last().cloned();
let mut heaviest_bank_on_same_fork = None;
let mut heaviest_same_fork_weight = 0;
let stats: Vec<&ForkStats> = frozen_banks
@@ -76,18 +77,18 @@ impl ForkChoice for BankWeightForkChoice {
.get_fork_stats(bank.slot())
.expect("All frozen banks must exist in the Progress map");
if let Some(last_voted_slot) = last_voted_slot {
if let Some(last_vote) = last_vote {
if ancestors
.get(&bank.slot())
.expect("Entry in frozen banks must exist in ancestors")
.contains(&last_voted_slot)
.contains(&last_vote)
{
// Descendant of last vote cannot be locked out
assert!(!stats.is_locked_out);
// ancestors(slot) should not contain the slot itself,
// so we should never get the same bank as the last vote
assert_ne!(bank.slot(), last_voted_slot);
assert_ne!(bank.slot(), last_vote);
// highest weight, lowest slot first. frozen_banks is sorted
// from least slot to greatest slot, so if two banks have
// the same fork weight, the lower slot will be picked

View File

@@ -24,9 +24,7 @@ use solana_perf::{
use solana_runtime::{
accounts_db::ErrorCounters,
bank::{Bank, TransactionBalancesSet, TransactionProcessResult},
bank_utils,
transaction_batch::TransactionBatch,
vote_sender_types::ReplayVoteSender,
};
use solana_sdk::{
clock::{
@@ -83,7 +81,6 @@ impl BankingStage {
verified_receiver: CrossbeamReceiver<Vec<Packets>>,
verified_vote_receiver: CrossbeamReceiver<Vec<Packets>>,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: ReplayVoteSender,
) -> Self {
Self::new_num_threads(
cluster_info,
@@ -92,7 +89,6 @@ impl BankingStage {
verified_vote_receiver,
Self::num_threads(),
transaction_status_sender,
gossip_vote_sender,
)
}
@@ -103,7 +99,6 @@ impl BankingStage {
verified_vote_receiver: CrossbeamReceiver<Vec<Packets>>,
num_threads: u32,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: ReplayVoteSender,
) -> Self {
let batch_limit = TOTAL_BUFFERED_PACKETS / ((num_threads - 1) as usize * PACKETS_PER_BATCH);
// Single thread to generate entries from many banks.
@@ -124,7 +119,6 @@ impl BankingStage {
let cluster_info = cluster_info.clone();
let mut recv_start = Instant::now();
let transaction_status_sender = transaction_status_sender.clone();
let gossip_vote_sender = gossip_vote_sender.clone();
Builder::new()
.name("solana-banking-stage-tx".to_string())
.spawn(move || {
@@ -138,8 +132,7 @@ impl BankingStage {
enable_forwarding,
i,
batch_limit,
transaction_status_sender,
gossip_vote_sender,
transaction_status_sender.clone(),
);
})
.unwrap()
@@ -175,7 +168,6 @@ impl BankingStage {
buffered_packets: &mut Vec<PacketsAndOffsets>,
batch_limit: usize,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: &ReplayVoteSender,
) -> UnprocessedPackets {
let mut unprocessed_packets = vec![];
let mut rebuffered_packets = 0;
@@ -207,7 +199,6 @@ impl BankingStage {
&msgs,
unprocessed_indexes.to_owned(),
transaction_status_sender.clone(),
gossip_vote_sender,
);
new_tx_count += processed;
@@ -292,7 +283,6 @@ impl BankingStage {
)
}
#[allow(clippy::too_many_arguments)]
fn process_buffered_packets(
my_pubkey: &Pubkey,
socket: &std::net::UdpSocket,
@@ -302,7 +292,6 @@ impl BankingStage {
enable_forwarding: bool,
batch_limit: usize,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: &ReplayVoteSender,
) -> BufferedPacketsDecision {
let (leader_at_slot_offset, poh_has_bank, would_be_leader) = {
let poh = poh_recorder.lock().unwrap();
@@ -330,7 +319,6 @@ impl BankingStage {
buffered_packets,
batch_limit,
transaction_status_sender,
gossip_vote_sender,
);
buffered_packets.append(&mut unprocessed);
}
@@ -364,7 +352,6 @@ impl BankingStage {
decision
}
#[allow(clippy::too_many_arguments)]
pub fn process_loop(
my_pubkey: Pubkey,
verified_receiver: &CrossbeamReceiver<Vec<Packets>>,
@@ -375,7 +362,6 @@ impl BankingStage {
id: u32,
batch_limit: usize,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: ReplayVoteSender,
) {
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let mut buffered_packets = vec![];
@@ -390,7 +376,6 @@ impl BankingStage {
enable_forwarding,
batch_limit,
transaction_status_sender.clone(),
&gossip_vote_sender,
);
if decision == BufferedPacketsDecision::Hold {
// If we are waiting on a new bank,
@@ -418,7 +403,6 @@ impl BankingStage {
id,
batch_limit,
transaction_status_sender.clone(),
&gossip_vote_sender,
) {
Err(RecvTimeoutError::Timeout) => (),
Err(RecvTimeoutError::Disconnected) => break,
@@ -517,7 +501,6 @@ impl BankingStage {
poh: &Arc<Mutex<PohRecorder>>,
batch: &TransactionBatch,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: &ReplayVoteSender,
) -> (Result<usize, PohRecorderError>, Vec<usize>) {
let mut load_execute_time = Measure::start("load_execute_time");
// Use a shorter maximum age when adding transactions into the pipeline. This will reduce
@@ -550,23 +533,24 @@ impl BankingStage {
let num_to_commit = num_to_commit.unwrap();
if num_to_commit != 0 {
let tx_results = bank.commit_transactions(
txs,
None,
&mut loaded_accounts,
&results,
tx_count,
signature_count,
);
let transaction_statuses = bank
.commit_transactions(
txs,
None,
&mut loaded_accounts,
&results,
tx_count,
signature_count,
)
.processing_results;
bank_utils::find_and_send_votes(txs, &tx_results, Some(gossip_vote_sender));
if let Some(sender) = transaction_status_sender {
let post_balances = bank.collect_balances(batch);
send_transaction_status_batch(
bank.clone(),
batch.transactions(),
batch.iteration_order_vec(),
tx_results.processing_results,
transaction_statuses,
TransactionBalancesSet::new(pre_balances, post_balances),
sender,
);
@@ -594,7 +578,6 @@ impl BankingStage {
poh: &Arc<Mutex<PohRecorder>>,
chunk_offset: usize,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: &ReplayVoteSender,
) -> (Result<usize, PohRecorderError>, Vec<usize>) {
let mut lock_time = Measure::start("lock_time");
// Once accounts are locked, other threads cannot encode transactions that will modify the
@@ -607,7 +590,6 @@ impl BankingStage {
poh,
&batch,
transaction_status_sender,
gossip_vote_sender,
);
retryable_txs.iter_mut().for_each(|x| *x += chunk_offset);
@@ -636,7 +618,6 @@ impl BankingStage {
transactions: &[Transaction],
poh: &Arc<Mutex<PohRecorder>>,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: &ReplayVoteSender,
) -> (usize, Vec<usize>) {
let mut chunk_start = 0;
let mut unprocessed_txs = vec![];
@@ -652,7 +633,6 @@ impl BankingStage {
poh,
chunk_start,
transaction_status_sender.clone(),
gossip_vote_sender,
);
trace!("process_transactions result: {:?}", result);
@@ -784,7 +764,6 @@ impl BankingStage {
msgs: &Packets,
packet_indexes: Vec<usize>,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: &ReplayVoteSender,
) -> (usize, usize, Vec<usize>) {
let (transactions, transaction_to_packet_indexes) =
Self::transactions_from_packets(msgs, &packet_indexes);
@@ -796,13 +775,8 @@ impl BankingStage {
let tx_len = transactions.len();
let (processed, unprocessed_tx_indexes) = Self::process_transactions(
bank,
&transactions,
poh,
transaction_status_sender,
gossip_vote_sender,
);
let (processed, unprocessed_tx_indexes) =
Self::process_transactions(bank, &transactions, poh, transaction_status_sender);
let unprocessed_tx_count = unprocessed_tx_indexes.len();
@@ -872,7 +846,6 @@ impl BankingStage {
.collect()
}
#[allow(clippy::too_many_arguments)]
/// Process the incoming packets
pub fn process_packets(
my_pubkey: &Pubkey,
@@ -883,7 +856,6 @@ impl BankingStage {
id: u32,
batch_limit: usize,
transaction_status_sender: Option<TransactionStatusSender>,
gossip_vote_sender: &ReplayVoteSender,
) -> Result<UnprocessedPackets, RecvTimeoutError> {
let mut recv_time = Measure::start("process_packets_recv");
let mms = verified_receiver.recv_timeout(recv_timeout)?;
@@ -926,7 +898,6 @@ impl BankingStage {
&msgs,
packet_indexes,
transaction_status_sender.clone(),
gossip_vote_sender,
);
new_tx_count += processed;
@@ -1073,7 +1044,6 @@ mod tests {
let bank = Arc::new(Bank::new(&genesis_config));
let (verified_sender, verified_receiver) = unbounded();
let (vote_sender, vote_receiver) = unbounded();
let (gossip_vote_sender, _gossip_vote_receiver) = unbounded();
let ledger_path = get_tmp_ledger_path!();
{
let blockstore = Arc::new(
@@ -1090,7 +1060,6 @@ mod tests {
verified_receiver,
vote_receiver,
None,
gossip_vote_sender,
);
drop(verified_sender);
drop(vote_sender);
@@ -1125,15 +1094,12 @@ mod tests {
create_test_recorder(&bank, &blockstore, Some(poh_config));
let cluster_info = ClusterInfo::new_with_invalid_keypair(Node::new_localhost().info);
let cluster_info = Arc::new(cluster_info);
let (gossip_vote_sender, _gossip_vote_receiver) = unbounded();
let banking_stage = BankingStage::new(
&cluster_info,
&poh_recorder,
verified_receiver,
vote_receiver,
None,
gossip_vote_sender,
);
trace!("sending bank");
drop(verified_sender);
@@ -1191,15 +1157,12 @@ mod tests {
create_test_recorder(&bank, &blockstore, Some(poh_config));
let cluster_info = ClusterInfo::new_with_invalid_keypair(Node::new_localhost().info);
let cluster_info = Arc::new(cluster_info);
let (gossip_vote_sender, _gossip_vote_receiver) = unbounded();
let banking_stage = BankingStage::new(
&cluster_info,
&poh_recorder,
verified_receiver,
vote_receiver,
None,
gossip_vote_sender,
);
// fund another account so we can send 2 good transactions in a single batch.
@@ -1320,8 +1283,6 @@ mod tests {
let (vote_sender, vote_receiver) = unbounded();
let ledger_path = get_tmp_ledger_path!();
{
let (gossip_vote_sender, _gossip_vote_receiver) = unbounded();
let entry_receiver = {
// start a banking_stage to eat verified receiver
let bank = Arc::new(Bank::new(&genesis_config));
@@ -1344,7 +1305,6 @@ mod tests {
vote_receiver,
2,
None,
gossip_vote_sender,
);
// wait for banking_stage to eat the packets
@@ -1722,7 +1682,6 @@ mod tests {
let poh_recorder = Arc::new(Mutex::new(poh_recorder));
poh_recorder.lock().unwrap().set_working_bank(working_bank);
let (gossip_vote_sender, _gossip_vote_receiver) = unbounded();
BankingStage::process_and_record_transactions(
&bank,
@@ -1730,7 +1689,6 @@ mod tests {
&poh_recorder,
0,
None,
&gossip_vote_sender,
)
.0
.unwrap();
@@ -1767,7 +1725,6 @@ mod tests {
&poh_recorder,
0,
None,
&gossip_vote_sender,
)
.0,
Err(PohRecorderError::MaxHeightReached)
@@ -1819,15 +1776,12 @@ mod tests {
poh_recorder.lock().unwrap().set_working_bank(working_bank);
let (gossip_vote_sender, _gossip_vote_receiver) = unbounded();
let (result, unprocessed) = BankingStage::process_and_record_transactions(
&bank,
&transactions,
&poh_recorder,
0,
None,
&gossip_vote_sender,
);
assert!(result.is_ok());
@@ -1911,16 +1865,8 @@ mod tests {
// record
let poh_recorder = Arc::new(Mutex::new(poh_recorder));
let (gossip_vote_sender, _gossip_vote_receiver) = unbounded();
let (processed_transactions_count, mut retryable_txs) =
BankingStage::process_transactions(
&bank,
&transactions,
&poh_recorder,
None,
&gossip_vote_sender,
);
BankingStage::process_transactions(&bank, &transactions, &poh_recorder, None);
assert_eq!(processed_transactions_count, 0,);
@@ -1997,15 +1943,12 @@ mod tests {
&Arc::new(AtomicBool::new(false)),
);
let (gossip_vote_sender, _gossip_vote_receiver) = unbounded();
let _ = BankingStage::process_and_record_transactions(
&bank,
&transactions,
&poh_recorder,
0,
Some(transaction_status_sender),
&gossip_vote_sender,
);
transaction_status_service.join().unwrap();

View File

@@ -96,7 +96,7 @@ impl BroadcastStats for InsertShredsStats {
}
}
// Tracks metrics of type `T` across multiple threads
// Tracks metrics of type `T` acrosss multiple threads
#[derive(Default)]
pub(crate) struct BatchCounter<T: BroadcastStats + Default> {
// The number of batches processed across all threads so far

View File

@@ -37,7 +37,7 @@ use itertools::Itertools;
use rayon::iter::IntoParallelIterator;
use rayon::iter::ParallelIterator;
use rayon::ThreadPool;
use solana_ledger::staking_utils;
use solana_ledger::{bank_forks::BankForks, staking_utils};
use solana_measure::measure::Measure;
use solana_measure::thread_mem_usage;
use solana_metrics::{datapoint_debug, inc_new_counter_debug, inc_new_counter_error};
@@ -50,7 +50,6 @@ use solana_perf::packet::{
PACKET_DATA_SIZE,
};
use solana_rayon_threadlimit::get_thread_count;
use solana_runtime::bank_forks::BankForks;
use solana_sdk::hash::Hash;
use solana_sdk::{
clock::{Slot, DEFAULT_MS_PER_SLOT, DEFAULT_SLOTS_PER_EPOCH},
@@ -288,7 +287,7 @@ impl fmt::Debug for Locality {
}
}
#[derive(Debug, Default, Deserialize, Serialize, AbiExample)]
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct PruneData {
/// Pubkey of the node that sent this prune data
pub pubkey: Pubkey,
@@ -357,8 +356,7 @@ pub fn make_accounts_hashes_message(
}
// TODO These messages should go through the gpu pipeline for spam filtering
#[frozen_abi(digest = "6qRS1ZwydpdSqzeyRdDvn5uwfDdFYkuUz4K4jSkd1oFW")]
#[derive(Serialize, Deserialize, Debug, AbiEnumVisitor, AbiExample)]
#[derive(Serialize, Deserialize, Debug)]
#[allow(clippy::large_enum_variant)]
enum Protocol {
/// Gossip protocol messages
@@ -444,7 +442,7 @@ impl ClusterInfo {
pub fn update_contact_info<F>(&self, modify: F)
where
F: FnOnce(&mut ContactInfo),
F: FnOnce(&mut ContactInfo) -> (),
{
let my_id = self.id();
modify(&mut self.my_contact_info.write().unwrap());
@@ -780,7 +778,7 @@ impl ClusterInfo {
.crds
.table
.values()
.filter_map(|x| x.value.snapshot_hash())
.filter_map(|x| x.value.snapshot_hash().map(|v| v))
.filter_map(|x| {
for (table_slot, hash) in &x.hashes {
if *table_slot == slot {
@@ -1492,6 +1490,12 @@ impl ClusterInfo {
.time_gossip_write_lock("purge", &self.stats.purge)
.purge(timestamp(), &timeouts);
inc_new_counter_info!("cluster_info-purge-count", num_purged);
let table_size = self.gossip.read().unwrap().crds.table.len();
datapoint_debug!(
"cluster_info-purge",
("table_size", table_size as i64, i64),
("purge_stake_timeout", timeout as i64, i64)
);
}
/// randomly pick a node and ask them for updates asynchronously
@@ -1739,7 +1743,7 @@ impl ClusterInfo {
"generate_pull_responses",
&self.stats.generate_pull_responses,
)
.generate_pull_responses(&caller_and_filters, now);
.generate_pull_responses(&caller_and_filters);
self.time_gossip_write_lock("process_pull_reqs", &self.stats.process_pull_requests)
.process_pull_requests(caller_and_filters, now);
@@ -1957,18 +1961,19 @@ impl ClusterInfo {
.into_iter()
.filter_map(|(from, prune_set)| {
inc_new_counter_debug!("cluster_info-push_message-prunes", prune_set.len());
self.lookup_contact_info(&from, |ci| ci.clone()).map(|ci| {
let mut prune_msg = PruneData {
pubkey: self_id,
prunes: prune_set.into_iter().collect(),
signature: Signature::default(),
destination: from,
wallclock: timestamp(),
};
prune_msg.sign(&self.keypair);
let rsp = Protocol::PruneMessage(self_id, prune_msg);
(ci.gossip, rsp)
})
self.lookup_contact_info(&from, |ci| ci.clone())
.and_then(|ci| {
let mut prune_msg = PruneData {
pubkey: self_id,
prunes: prune_set.into_iter().collect(),
signature: Signature::default(),
destination: from,
wallclock: timestamp(),
};
prune_msg.sign(&self.keypair);
let rsp = Protocol::PruneMessage(self_id, prune_msg);
Some((ci.gossip, rsp))
})
})
.collect();
if rsp.is_empty() {
@@ -2080,10 +2085,6 @@ impl ClusterInfo {
fn print_reset_stats(&self, last_print: &mut Instant) {
if last_print.elapsed().as_millis() > 2000 {
let (table_size, purged_values_size) = {
let r_gossip = self.gossip.read().unwrap();
(r_gossip.crds.table.len(), r_gossip.pull.purged_values.len())
};
datapoint_info!(
"cluster_info_stats",
("entrypoint", self.stats.entrypoint.clear(), i64),
@@ -2107,8 +2108,6 @@ impl ClusterInfo {
self.stats.new_push_requests_num.clear(),
i64
),
("table_size", table_size as i64, i64),
("purged_values_size", purged_values_size as i64, i64),
);
datapoint_info!(
"cluster_info_stats2",
@@ -2598,7 +2597,8 @@ mod tests {
fn test_crds_values(pubkey: Pubkey) -> Vec<CrdsValue> {
let entrypoint = ContactInfo::new_localhost(&pubkey, timestamp());
let entrypoint_crdsvalue = CrdsValue::new_unsigned(CrdsData::ContactInfo(entrypoint));
let entrypoint_crdsvalue =
CrdsValue::new_unsigned(CrdsData::ContactInfo(entrypoint.clone()));
vec![entrypoint_crdsvalue]
}
@@ -3026,7 +3026,7 @@ mod tests {
assert_eq!(slots.len(), 1);
assert!(since.is_some());
let (slots, since2) = cluster_info.get_epoch_slots_since(since);
let (slots, since2) = cluster_info.get_epoch_slots_since(since.clone());
assert!(slots.is_empty());
assert_eq!(since2, since);
}

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