From 4911c4c052c3fd5be6b885a0ba1fe466db4d7b73 Mon Sep 17 00:00:00 2001 From: Lucas B Date: Thu, 25 Aug 2022 17:18:46 -0500 Subject: [PATCH] jito patch only reroute if relayer connected (#123) feat: add client tls config (#121) remove extra val (#129) fix clippy (#130) copy all binaries to docker-output (#131) Ledger tool halts at slot passed to create-snapshot (#118) update program submodule (#133) quick fix for tips and clearing old bundles (#135) update submodule to new program (#136) Improve stake-meta-generator usability (#134) pinning submodule head (#140) Use BundleAccountLocker when handling tip txs (#147) Add metrics for relayer + block engine proxy (#149) Build claim-mev in docker (#141) Rework bundle receiving and add metrics (#152) (#154) update submodule + dev files (#158) Deterministically find tip amounts, add meta to stake info, and cleanup pubkey/strings in MEV tips (#159) update jito-programs submodule (#160) Separate MEV tip related workflow (#161) Add block builder fee protos (#162) fix jito programs (#163) update submodule so autosnapshot exits out of ledger tool early (#164) Pipe through block builder fee (#167) use current config block builder backport 177 and update programs (#178) add accountsdb conn submod (#170) (#179) new submodules (#180) (#182) --- .dockerignore | 1 + .github/dependabot.yml | 41 - .github/workflows/client-targets.yml | 6 +- .gitignore | 5 +- .gitmodules | 12 + Cargo.lock | 3010 ++++++++++------- Cargo.toml | 7 + README.md | 12 +- anchor | 1 + banking-bench/Cargo.toml | 2 +- banking-bench/src/main.rs | 15 +- banks-server/Cargo.toml | 4 + banks-server/src/banks_server.rs | 5 +- banks-server/src/rpc_banks_service.rs | 33 +- bench-batch-simulate-bundle/Cargo.toml | 16 + bench-batch-simulate-bundle/src/main.rs | 396 +++ bench-batch-simulate-bundle/src/simulator.rs | 149 + .../Cargo.toml | 12 + .../src/main.rs | 120 + bootstrap | 21 + ci/buildkite-pipeline-in-disk.sh | 34 +- ci/buildkite-pipeline.sh | 34 +- ci/buildkite-solana-private.sh | 32 +- ci/docker-rust/Dockerfile | 1 + cli-output/Cargo.toml | 2 +- client/src/http_sender.rs | 203 +- client/src/mock_sender.rs | 7 + client/src/nonblocking/rpc_client.rs | 124 +- client/src/rpc_client.rs | 30 + client/src/rpc_config.rs | 45 + client/src/rpc_request.rs | 3 + client/src/rpc_response.rs | 50 +- client/src/rpc_sender.rs | 4 + core/Cargo.toml | 19 +- core/benches/banking_stage.rs | 17 +- core/benches/cluster_info.rs | 1 + core/benches/proto_to_packet.rs | 56 + core/benches/retransmit_stage.rs | 1 + core/src/backoff.rs | 45 + core/src/banking_stage.rs | 156 +- core/src/broadcast_stage.rs | 62 +- .../broadcast_duplicates_run.rs | 3 +- .../broadcast_fake_shreds_run.rs | 2 + core/src/broadcast_stage/broadcast_utils.rs | 37 +- .../fail_entry_verification_broadcast_run.rs | 4 +- .../broadcast_stage/standard_broadcast_run.rs | 18 +- core/src/bundle_account_locker.rs | 334 ++ core/src/bundle_sanitizer.rs | 612 ++++ core/src/bundle_stage.rs | 1943 +++++++++++ core/src/bundle_stage_leader_stats.rs | 326 ++ core/src/consensus_cache_updater.rs | 52 + core/src/lib.rs | 48 + core/src/packet_bundle.rs | 7 + core/src/proxy/auth.rs | 247 ++ core/src/proxy/block_engine_stage.rs | 383 +++ core/src/proxy/fetch_stage_manager.rs | 161 + core/src/proxy/mod.rs | 55 + core/src/proxy/relayer_stage.rs | 362 ++ core/src/qos_service.rs | 2 +- core/src/retransmit_stage.rs | 12 +- core/src/tip_manager.rs | 473 +++ core/src/tpu.rs | 121 +- core/src/tvu.rs | 7 +- core/src/validator.rs | 23 +- core/tests/snapshots.rs | 2 + deploy_programs | 17 + dev/Dockerfile | 44 + dos/Cargo.toml | 2 +- entry/src/entry.rs | 2 +- entry/src/poh.rs | 29 +- f | 25 + frozen-abi/Cargo.toml | 2 +- gossip/src/cluster_info.rs | 4 + jito-programs | 1 + jito-protos/Cargo.toml | 16 + jito-protos/build.rs | 17 + jito-protos/protos | 1 + jito-protos/src/lib.rs | 25 + ledger-tool/src/main.rs | 6 + ledger/src/bank_forks_utils.rs | 11 +- ledger/src/blockstore_processor.rs | 5 +- ledger/src/token_balances.rs | 58 +- .../src/local_cluster_snapshot_utils.rs | 3 +- local-cluster/src/validator_configs.rs | 4 + local-cluster/tests/local_cluster.rs | 8 +- logger/Cargo.toml | 2 +- measure/src/lib.rs | 1 + measure/src/macros.rs | 143 + merkle-tree/src/merkle_tree.rs | 46 +- multinode-demo/bootstrap-validator.sh | 36 + multinode-demo/validator.sh | 32 + perf/src/sigverify.rs | 2 +- poh/src/poh_recorder.rs | 117 +- poh/src/poh_service.rs | 34 +- programs/bpf/Cargo.lock | 2635 +++++++++------ programs/bpf/tests/programs.rs | 4 +- replica-node/src/replica_node.rs | 1 + replica-node/src/replica_util.rs | 7 +- replica-node/tests/local_replica.rs | 2 +- rpc/src/rpc.rs | 435 ++- rpc/src/rpc_service.rs | 6 +- runtime/Cargo.toml | 6 +- runtime/src/account_overrides.rs | 22 +- runtime/src/accounts.rs | 96 +- runtime/src/bank.rs | 1150 ++++++- runtime/src/builtins.rs | 2 +- runtime/src/snapshot_utils.rs | 50 +- runtime/src/stakes.rs | 4 +- rustfmt.toml | 5 + s | 15 + scripts/increment-cargo-version.sh | 3 + scripts/run.sh | 5 + sdk/Cargo.toml | 3 + sdk/src/bundle/error.rs | 51 + sdk/src/bundle/mod.rs | 12 + sdk/src/bundle/sanitized.rs | 8 + sdk/src/bundle/utils.rs | 20 + sdk/src/lib.rs | 1 + sdk/src/transaction/error.rs | 8 + send-transaction-service/Cargo.toml | 3 +- .../src/send_transaction_service.rs | 39 +- solana-accountsdb-connector | 1 + start | 9 + start_multi | 29 + storage-bigtable/src/bigtable.rs | 2 +- storage-proto/proto/transaction_by_addr.proto | 2 + storage-proto/src/convert.rs | 8 + tip-distributor/Cargo.toml | 48 + tip-distributor/README.md | 43 + tip-distributor/src/bin/claim-mev-tips.rs | 52 + .../src/bin/merkle-root-generator.rs | 29 + .../src/bin/merkle-root-uploader.rs | 50 + .../src/bin/stake-meta-generator.rs | 67 + tip-distributor/src/claim_mev_workflow.rs | 143 + tip-distributor/src/lib.rs | 779 +++++ .../src/merkle_root_generator_workflow.rs | 49 + .../src/merkle_root_upload_workflow.rs | 126 + .../src/stake_meta_generator_workflow.rs | 836 +++++ validator/Cargo.toml | 1 + validator/src/bootstrap.rs | 3 +- validator/src/dashboard.rs | 1 + validator/src/main.rs | 240 ++ 142 files changed, 15057 insertions(+), 2775 deletions(-) create mode 100644 .dockerignore delete mode 100644 .github/dependabot.yml create mode 100644 .gitmodules create mode 160000 anchor create mode 100644 bench-batch-simulate-bundle/Cargo.toml create mode 100644 bench-batch-simulate-bundle/src/main.rs create mode 100644 bench-batch-simulate-bundle/src/simulator.rs create mode 100644 bench-get-confirmed-blocks-with-data/Cargo.toml create mode 100644 bench-get-confirmed-blocks-with-data/src/main.rs create mode 100755 bootstrap create mode 100644 core/benches/proto_to_packet.rs create mode 100644 core/src/backoff.rs create mode 100644 core/src/bundle_account_locker.rs create mode 100644 core/src/bundle_sanitizer.rs create mode 100644 core/src/bundle_stage.rs create mode 100644 core/src/bundle_stage_leader_stats.rs create mode 100644 core/src/consensus_cache_updater.rs create mode 100644 core/src/packet_bundle.rs create mode 100644 core/src/proxy/auth.rs create mode 100644 core/src/proxy/block_engine_stage.rs create mode 100644 core/src/proxy/fetch_stage_manager.rs create mode 100644 core/src/proxy/mod.rs create mode 100644 core/src/proxy/relayer_stage.rs create mode 100644 core/src/tip_manager.rs create mode 100755 deploy_programs create mode 100644 dev/Dockerfile create mode 100755 f create mode 160000 jito-programs create mode 100644 jito-protos/Cargo.toml create mode 100644 jito-protos/build.rs create mode 160000 jito-protos/protos create mode 100644 jito-protos/src/lib.rs create mode 100644 measure/src/macros.rs create mode 100755 s create mode 100644 sdk/src/bundle/error.rs create mode 100644 sdk/src/bundle/mod.rs create mode 100644 sdk/src/bundle/sanitized.rs create mode 100644 sdk/src/bundle/utils.rs create mode 160000 solana-accountsdb-connector create mode 100755 start create mode 100755 start_multi create mode 100644 tip-distributor/Cargo.toml create mode 100644 tip-distributor/README.md create mode 100644 tip-distributor/src/bin/claim-mev-tips.rs create mode 100644 tip-distributor/src/bin/merkle-root-generator.rs create mode 100644 tip-distributor/src/bin/merkle-root-uploader.rs create mode 100644 tip-distributor/src/bin/stake-meta-generator.rs create mode 100644 tip-distributor/src/claim_mev_workflow.rs create mode 100644 tip-distributor/src/lib.rs create mode 100644 tip-distributor/src/merkle_root_generator_workflow.rs create mode 100644 tip-distributor/src/merkle_root_upload_workflow.rs create mode 100644 tip-distributor/src/stake_meta_generator_workflow.rs diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..2f7896d1d1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +target/ diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index c2fc36a3e6..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -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 diff --git a/.github/workflows/client-targets.yml b/.github/workflows/client-targets.yml index 88b160b448..dd0b67d17a 100644 --- a/.github/workflows/client-targets.yml +++ b/.github/workflows/client-targets.yml @@ -45,8 +45,10 @@ jobs: platform: android os: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + with: + submodules: recursive + ssh-key: ${{ secrets.DEPLOYER_SSH_KEY }} - uses: actions-rs/toolchain@v1 with: toolchain: stable diff --git a/.gitignore b/.gitignore index 124358b46f..92281a9a08 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ /solana-release.tar.bz2 /solana-metrics/ /solana-metrics.tar.bz2 -/target/ +**/target/ /test-ledger/ **/*.rs.bk @@ -30,3 +30,6 @@ log-*/ .DS_Store # scripts that may be generated by cargo *-bpf commands **/cargo-*-bpf-child-script-*.sh + +.env +docker-output/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..c6bb20e21c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,12 @@ +[submodule "anchor"] + path = anchor + url = org-87542516@github.com:jito-foundation/anchor.git +[submodule "jito-programs"] + path = jito-programs + url = org-87542516@github.com:jito-foundation/jito-programs.git +[submodule "jito-protos/protos"] + path = jito-protos/protos + url = org-87542516@github.com:jito-labs/mev-protos-priv.git +[submodule "solana-accountsdb-connector"] + path = solana-accountsdb-connector + url = org-87542516@github.com:jito-foundation/solana-accountsdb-connector.git diff --git a/Cargo.lock b/Cargo.lock index 5bd6310871..070249353d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,7 +24,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -36,7 +36,7 @@ dependencies = [ "cfg-if 1.0.0", "cipher 0.3.0", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -60,16 +60,16 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.8", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -82,39 +82,187 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" [[package]] name = "alloc-no-stdlib" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "anchor-attribute-access-control" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "regex", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-account" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "bs58 0.4.0", + "proc-macro2 1.0.47", + "quote 1.0.21", + "rustversion", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-constant" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "proc-macro2 1.0.47", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-error" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-event" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-interface" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "heck 0.3.3", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-program" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-state" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-derive-accounts" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-lang" +version = "0.24.2" +dependencies = [ + "anchor-attribute-access-control", + "anchor-attribute-account", + "anchor-attribute-constant", + "anchor-attribute-error", + "anchor-attribute-event", + "anchor-attribute-interface", + "anchor-attribute-program", + "anchor-attribute-state", + "anchor-derive-accounts", + "arrayref", + "base64 0.13.1", + "bincode", + "borsh", + "bytemuck", + "solana-program 1.13.6", + "thiserror", +] + +[[package]] +name = "anchor-syn" +version = "0.24.2" +dependencies = [ + "anyhow", + "bs58 0.3.1", + "heck 0.3.3", + "proc-macro2 1.0.47", + "proc-macro2-diagnostics", + "quote 1.0.21", + "serde", + "serde_json", + "sha2 0.9.9", + "syn 1.0.103", + "thiserror", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ "winapi 0.3.9", ] [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "arc-swap" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f" +checksum = "983cd8b9d4b02a6dc6ffa557262eb5858a27a0038ffffe21a0f133eaa819a164" [[package]] name = "arrayref" @@ -143,11 +291,11 @@ dependencies = [ "asn1-rs-derive", "asn1-rs-impl", "displaydoc", - "nom 7.0.0", + "nom", "num-traits", "rusticata-macros", "thiserror", - "time 0.3.7", + "time 0.3.17", ] [[package]] @@ -156,9 +304,9 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "synstructure", ] @@ -168,18 +316,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "assert_cmd" -version = "2.0.4" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e" +checksum = "ba45b8163c49ab5f972e59a8a5a03b6d2972619d486e19ec9fe744f7c2753d3c" dependencies = [ - "bstr", + "bstr 1.0.1", "doc-comment", "predicates", "predicates-core", @@ -195,9 +343,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-compression" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345fd392ab01f746c717b1357165b76f0b67a60192007b234058c9045fdcf695" +checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" dependencies = [ "brotli", "flate2", @@ -218,9 +366,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" dependencies = [ "async-stream-impl", "futures-core", @@ -228,24 +376,24 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "async-trait" -version = "0.1.52" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -261,15 +409,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.5.1" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47594e438a243791dba58124b6669561f5baa14cb12046641d8008bf035e5a25" +checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43" dependencies = [ "async-trait", "axum-core", @@ -279,11 +427,11 @@ dependencies = [ "http", "http-body", "hyper", - "itoa 1.0.1", + "itoa 1.0.4", "matchit", "memchr", "mime", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project-lite", "serde", "sync_wrapper", @@ -296,9 +444,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c0a60006f2a293d82d571f635042a72edf927539b7685bd62d361963839b" +checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc" dependencies = [ "async-trait", "bytes", @@ -317,18 +465,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ "futures-core", - "getrandom 0.2.3", + "getrandom 0.2.8", "instant", "pin-project-lite", - "rand 0.8.4", + "rand 0.8.5", "tokio", ] [[package]] name = "base-x" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] name = "base64" @@ -338,15 +486,38 @@ checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64ct" -version = "1.3.3" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" + +[[package]] +name = "bench-get-confirmed-blocks-with-data" +version = "1.13.6" +dependencies = [ + "env_logger", + "log", + "solana-sdk 1.13.6", + "solana-storage-bigtable", + "solana-transaction-status", + "tokio", +] + +[[package]] +name = "bigdecimal" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874f8444adcb4952a8bc51305c8be95c8ec8237bb0d2e78d2e039f771f8828a0" +checksum = "6aaf33151a6429fe9211d1b276eafdf70cdff28b071e76c0b0e1503221ea3744" +dependencies = [ + "num-bigint 0.4.3", + "num-integer", + "num-traits", +] [[package]] name = "bincode" @@ -359,9 +530,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.59.1" +version = "0.59.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" dependencies = [ "bitflags", "cexpr", @@ -369,8 +540,8 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.47", + "quote 1.0.21", "regex", "rustc-hash", "shlex", @@ -378,9 +549,9 @@ dependencies = [ [[package]] name = "bit-set" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] @@ -406,18 +577,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "bitvec" -version = "0.19.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "blake3" version = "1.3.1" @@ -429,19 +588,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "constant_time_eq", - "digest 0.10.3", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding 0.1.5", - "byte-tools", - "byteorder", - "generic-array 0.12.4", + "digest 0.10.6", ] [[package]] @@ -450,26 +597,17 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1", - "generic-array 0.14.5", + "block-padding", + "generic-array", ] [[package]] name = "block-buffer" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" -dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "block-padding" -version = "0.1.5" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -485,7 +623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ "borsh-derive", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -497,8 +635,8 @@ dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.32", - "syn 1.0.91", + "proc-macro2 1.0.47", + "syn 1.0.103", ] [[package]] @@ -507,9 +645,9 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -518,9 +656,9 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -544,6 +682,12 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bs58" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" + [[package]] name = "bs58" version = "0.4.0" @@ -562,11 +706,23 @@ dependencies = [ "serde", ] +[[package]] +name = "bstr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd" +dependencies = [ + "memchr", + "once_cell", + "regex-automata", + "serde", +] + [[package]] name = "bumpalo" -version = "3.8.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bv" @@ -578,45 +734,40 @@ dependencies = [ "serde", ] -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - [[package]] name = "byte-unit" -version = "4.0.14" +version = "4.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ebf10dda65f19ff0f42ea15572a359ed60d7fc74fdc984d90310937be0014b" +checksum = "581ad4b3d627b0c09a0ccb2912148f839acaca0b93cf54cbe42b6c674e86079c" dependencies = [ + "serde", "utf8-width", ] [[package]] name = "bytecount" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" +checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" [[package]] name = "bytemuck" -version = "1.8.0" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e851ca7c24871e7336801608a4797d7376545b6928a10d32d75685687141ead" +checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.0.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" +checksum = "5fe233b960f12f8007e3db2d136e3cb1c291bfd7396e384ee76025fc1a3932b4" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -627,9 +778,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "bytesize" @@ -660,20 +811,19 @@ dependencies = [ [[package]] name = "camino" -version = "1.0.5" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b" +checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e" dependencies = [ "serde", ] [[package]] name = "caps" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61bf7211aad104ce2769ec05efcdfabf85ee84ac92461d142f22cf8badd0e54c" +checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" dependencies = [ - "errno", "libc", "thiserror", ] @@ -695,7 +845,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.6", + "semver 1.0.14", "serde", "serde_json", ] @@ -711,20 +861,20 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.71" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" +checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f" dependencies = [ "jobserver", ] [[package]] name = "cexpr" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom 6.1.2", + "nom", ] [[package]] @@ -741,23 +891,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.43", + "time 0.1.44", + "wasm-bindgen", "winapi 0.3.9", ] [[package]] name = "chrono-humanize" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eddc119501d583fd930cb92144e605f44e0252c38dd89d9247fffa1993375cb" +checksum = "32dce1ea1988dbdf9f9815ff11425828523bd2a134ec0805d2ac8af26ee6096e" dependencies = [ "chrono", ] @@ -768,7 +920,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -783,9 +935,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.2.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10612c0ec0e0a1ff0e97980647cb058a6e7aedb913d01d009c406b8b7d0b26ee" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", @@ -794,9 +946,9 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", @@ -809,43 +961,62 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.6" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", "bitflags", "clap_derive", + "clap_lex", "indexmap", - "lazy_static", - "os_str_bytes", + "once_cell", "strsim 0.10.0", "termcolor", - "textwrap 0.15.0", + "textwrap 0.16.0", ] [[package]] name = "clap_derive" -version = "3.1.4" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da95d038ede1a964ce99f49cbe27a7fb538d1da595e4b4f70b8c8f338d17bf16" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck 0.4.0", "proc-macro-error", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", ] [[package]] name = "cmake" -version = "0.1.46" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b858541263efe664aead4a5209a4ae5c5d2811167d4ed4ee0944503f8d2089" +checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" dependencies = [ "cc", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "combine" version = "3.8.1" @@ -861,14 +1032,13 @@ dependencies = [ [[package]] name = "console" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", - "regex", "terminal_size", "unicode-width", "winapi 0.3.9", @@ -902,28 +1072,28 @@ checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "const_fn" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92cfa0fd5690b3cf8c1ef2cabbd9b7ef22fa53cf5e1f92b05103f6d5d1cf6e7" +checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" [[package]] name = "const_format" -version = "0.2.22" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22bc6cd49b0ec407b680c3e380182b6ac63b73991cb7602de350352fc309b614" +checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.22" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef196d5d972878a48da7decb7686eded338b4858fbabeed513d63a7c98b2b82d" +checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "unicode-xid 0.2.2", + "proc-macro2 1.0.47", + "quote 1.0.21", + "unicode-xid 0.2.4", ] [[package]] @@ -940,9 +1110,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -968,18 +1138,18 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if 1.0.0", ] @@ -999,9 +1169,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.3" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdbfe11fe19ff083c48923cf179540e8cd0535903dc35e178a1fdeeb59aef51f" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1009,9 +1179,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", @@ -1033,12 +1203,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if 1.0.0", - "lazy_static", ] [[package]] @@ -1049,11 +1218,11 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.5", + "generic-array", "typenum", ] @@ -1063,7 +1232,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.5", + "generic-array", "subtle", ] @@ -1073,7 +1242,7 @@ version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ - "bstr", + "bstr 0.2.17", "csv-core", "itoa 0.4.8", "ryu", @@ -1100,11 +1269,11 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.2.1" +version = "3.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19c6cedffdc8c03a3346d723eb20bd85a13362bb96dc2ac000842c6381ec7bf" +checksum = "1d91974fbbe88ec1df0c24a4f00f99583667a7e2e6272b2b92d294d81e462173" dependencies = [ - "nix", + "nix 0.25.0", "winapi 0.3.9", ] @@ -1122,6 +1291,50 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cxx" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2 1.0.47", + "quote 1.0.21", + "scratch", + "syn 1.0.103", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" +dependencies = [ + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + [[package]] name = "dashmap" version = "4.0.2" @@ -1133,6 +1346,17 @@ dependencies = [ "rayon", ] +[[package]] +name = "dashmap" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c" +dependencies = [ + "cfg-if 1.0.0", + "num_cpus", + "parking_lot 0.12.1", +] + [[package]] name = "data-encoding" version = "2.3.2" @@ -1156,8 +1380,8 @@ checksum = "42d4bc9b0db0a0df9ae64634ac5bdefb7afcb534e182275ca0beadbe486701c1" dependencies = [ "asn1-rs", "displaydoc", - "nom 7.0.0", - "num-bigint 0.4.2", + "nom", + "num-bigint 0.4.3", "num-traits", "rusticata-macros", ] @@ -1168,35 +1392,24 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", -] - [[package]] name = "derive_more" -version = "0.99.16" +version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", - "proc-macro2 1.0.32", - "quote 1.0.10", - "rustc_version 0.3.3", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "rustc_version 0.4.0", + "syn 1.0.103", ] [[package]] name = "dialoguer" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d6b4fabcd9e97e1df1ae15395ac7e49fb144946a0d453959dc2696273b9da" +checksum = "a92e7e37ecef6857fdc0c0c5d42fd5b0938e46590c2183cc92dd310a6d078eb1" dependencies = [ "console", "tempfile", @@ -1209,31 +1422,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] name = "digest" -version = "0.10.3" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "block-buffer 0.10.0", + "block-buffer 0.10.3", "crypto-common", "subtle", ] @@ -1280,9 +1484,9 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -1316,9 +1520,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "ed25519" -version = "1.2.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" dependencies = [ "signature", ] @@ -1346,26 +1550,26 @@ dependencies = [ "derivation-path", "ed25519-dalek", "hmac 0.12.1", - "sha2 0.10.2", + "sha2 0.10.6", ] [[package]] name = "educe" -version = "0.4.18" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86b50932a01e7ec5c06160492ab660fb19b6bb2a7878030dd6cd68d21df9d4d" +checksum = "cb0188e3c3ba8df5753894d54461f0e39bc91741dc5b22e1c46999ec2c71f4e4" dependencies = [ "enum-ordinalize", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "encode_unicode" @@ -1375,9 +1579,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.29" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ "cfg-if 1.0.0", ] @@ -1397,22 +1601,23 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "enum-ordinalize" -version = "3.1.10" +version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b166c9e378360dd5a6666a9604bb4f54ae0cac39023ffbac425e917a2a04fef" +checksum = "a62bb1df8b45ecb7ffa78dca1c17a438fb193eb083db0b1b494d2a61bcb5096a" dependencies = [ - "num-bigint 0.4.2", + "num-bigint 0.4.3", "num-traits", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "rustc_version 0.4.0", + "syn 1.0.103", ] [[package]] @@ -1422,9 +1627,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eb359f1476bf611266ac1f5355bc14aeca37b299d0ebccc038ee7058891c9cb" dependencies = [ "once_cell", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -1478,15 +1683,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fast-math" @@ -1499,22 +1698,22 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] [[package]] name = "fd-lock" -version = "3.0.4" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02ecad9808e0596f8956d14f7fa868f996290bd01c8d7329d6e5bc2bb76adf8f" +checksum = "bb21c69b9fea5e15dbc1049e4b77145dd0ba1c84019c488102de0dc4ea4b0a27" dependencies = [ "cfg-if 1.0.0", "rustix", - "windows-sys 0.30.0", + "windows-sys 0.42.0", ] [[package]] @@ -1525,9 +1724,9 @@ checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" [[package]] name = "filedescriptor" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed3d8a5e20435ff00469e51a0d82049bae66504b5c429920dadf9bb54d47b3f" +checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e" dependencies = [ "libc", "thiserror", @@ -1536,31 +1735,35 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] name = "fixedbitset" -version = "0.4.0" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" + +[[package]] +name = "fixedbitset" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "398ea4fabe40b9b0d885340a2a991a44c8a645624075ad966d21f88688e2b69e" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ - "cfg-if 1.0.0", "crc32fast", - "libc", "miniz_oxide", ] @@ -1587,12 +1790,11 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", ] [[package]] @@ -1607,12 +1809,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -[[package]] -name = "funty" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - [[package]] name = "futures" version = "0.1.31" @@ -1621,9 +1817,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", @@ -1636,9 +1832,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", "futures-sink", @@ -1646,15 +1842,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" dependencies = [ "futures-core", "futures-task", @@ -1664,38 +1860,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures 0.1.31", "futures-channel", @@ -1738,18 +1934,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "serde", "typenum", @@ -1781,13 +1968,15 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1798,12 +1987,12 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "globset" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" dependencies = [ "aho-corasick", - "bstr", + "bstr 0.2.17", "fnv", "log", "regex", @@ -1816,7 +2005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38f3d68c8343245dc047982651b5afb8bd659c9959ed72efe5a73bf22684e5fd" dependencies = [ "arc-swap", - "futures 0.3.21", + "futures 0.3.25", "log", "reqwest", "serde", @@ -1824,7 +2013,7 @@ dependencies = [ "serde_json", "simpl", "smpl_jwt", - "time 0.3.7", + "time 0.3.17", "tokio", ] @@ -1841,9 +2030,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.11" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -1854,7 +2043,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.6.9", + "tokio-util 0.7.2", "tracing", ] @@ -1882,20 +2071,29 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + [[package]] name = "headers" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bitflags", "bytes", "headers-core", "http", "httpdate", "mime", - "sha-1 0.10.0", + "sha1 0.10.5", ] [[package]] @@ -1939,13 +2137,14 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hidapi" -version = "1.3.4" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ec6bf425a5c3af047bb2a029de540a7d74cefa4761f14be67d7884dcd497b0" +checksum = "798154e4b6570af74899d71155fb0072d5b17e6aa12f39c8ef22c60fb8ec99e7" dependencies = [ "cc", "libc", "pkg-config", + "winapi 0.3.9", ] [[package]] @@ -1970,7 +2169,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.3", + "digest 0.10.6", ] [[package]] @@ -1980,7 +2179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array 0.14.5", + "generic-array", "hmac 0.8.1", ] @@ -1992,7 +2191,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa 1.0.4", ] [[package]] @@ -2014,15 +2213,15 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" [[package]] name = "httparse" -version = "1.5.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "humantime" @@ -2032,9 +2231,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.14" +version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b91bb1f221b6ea1f1e4371216b70f40748774c2fb5971b450c07773fb92d26b" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ "bytes", "futures-channel", @@ -2045,7 +2244,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa 1.0.4", "pin-project-lite", "socket2", "tokio", @@ -2061,7 +2260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" dependencies = [ "bytes", - "futures 0.3.21", + "futures 0.3.25", "headers", "http", "hyper", @@ -2074,15 +2273,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d" dependencies = [ "http", "hyper", - "rustls 0.20.4", + "rustls 0.20.7", "tokio", - "tokio-rustls 0.23.2", + "tokio-rustls 0.23.4", ] [[package]] @@ -2110,6 +2309,30 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi 0.3.9", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "idna" version = "0.1.5" @@ -2123,11 +2346,10 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -2145,7 +2367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" dependencies = [ "bitmaps", - "rand_core 0.6.3", + "rand_core 0.6.4", "rand_xoshiro", "rayon", "serde", @@ -2162,12 +2384,12 @@ checksum = "5a9d968042a4902e08810946fc7cd5851eb75e80301342305af755ca06cb82ce" [[package]] name = "indexmap" -version = "1.8.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", "rayon", ] @@ -2185,11 +2407,11 @@ dependencies = [ [[package]] name = "inout" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1f03d4ab4d5dc9ec2d219f86c15d2a15fc08239d1cd3b2d6a19717c0a2f443" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -2203,21 +2425,25 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "0.5.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec58677acfea8a15352d42fc87d11d63596ade9239e0a7c9352914417515dbe6" +checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87" +dependencies = [ + "libc", + "windows-sys 0.42.0", +] [[package]] name = "ipnet" -version = "2.3.1" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] @@ -2230,24 +2456,37 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" + +[[package]] +name = "jito-protos" +version = "1.13.6" +dependencies = [ + "bytes", + "crossbeam-epoch", + "lock_api", + "prost 0.8.0", + "prost-types 0.8.0", + "tonic 0.5.2", + "tonic-build 0.5.2", +] [[package]] name = "jobserver" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -2270,7 +2509,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.21", + "futures 0.3.25", "jsonrpc-core", "jsonrpc-pubsub", "jsonrpc-server-utils", @@ -2288,7 +2527,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "futures-executor", "futures-util", "log", @@ -2303,7 +2542,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "jsonrpc-client-transports", ] @@ -2314,9 +2553,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2" dependencies = [ "proc-macro-crate 0.1.5", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -2325,7 +2564,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "hyper", "jsonrpc-core", "jsonrpc-server-utils", @@ -2341,7 +2580,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "jsonrpc-core", "jsonrpc-server-utils", "log", @@ -2356,7 +2595,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "jsonrpc-core", "lazy_static", "log", @@ -2372,22 +2611,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes", - "futures 0.3.21", + "futures 0.3.25", "globset", "jsonrpc-core", "lazy_static", "log", "tokio", "tokio-stream", - "tokio-util 0.6.9", + "tokio-util 0.6.10", "unicase", ] [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] [[package]] name = "kernel32-sys" @@ -2413,15 +2655,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.120" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad5c14e80759d0939d013e6ca49930e59fc53dd8e5009132f76240c179380c09" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if 1.0.0", "winapi 0.3.9", @@ -2429,9 +2671,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "librocksdb-sys" @@ -2497,26 +2739,35 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.3" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "pkg-config", "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.0.42" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5284f00d480e1c39af34e72f8ad60b94f47007e3481cd3b731c1d67190ddc7b7" +checksum = "bb68f22743a3fb35785f1e7f844ca5a3de2dde5bd0c0ef5b372065814699b121" [[package]] name = "lock_api" @@ -2529,20 +2780,20 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "lru" -version = "0.7.5" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32613e41de4c47ab04970c348ca7ae7382cf116625755af070b008a15516a889" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" dependencies = [ - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -2565,12 +2816,6 @@ dependencies = [ "libc", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matches" version = "0.1.9" @@ -2585,24 +2830,24 @@ checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.3" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] @@ -2615,7 +2860,7 @@ checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder", "keccak", - "rand_core 0.6.3", + "rand_core 0.6.4", "zeroize", ] @@ -2633,18 +2878,17 @@ checksum = "2687e6cf9c00f48e9284cf9fd15f2ef341d03cc7743abf9df4c5f07fdee50b18" [[package]] name = "minimal-lexical" -version = "0.1.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", - "autocfg", ] [[package]] @@ -2685,9 +2929,9 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -2698,9 +2942,9 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "native-tls" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -2716,9 +2960,9 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" dependencies = [ "cfg-if 0.1.10", "libc", @@ -2739,33 +2983,32 @@ dependencies = [ ] [[package]] -name = "nom" -version = "6.1.2" +name = "nix" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" +checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" dependencies = [ - "bitvec", - "funty", - "memchr", - "version_check", + "autocfg", + "bitflags", + "cfg-if 1.0.0", + "libc", ] [[package]] name = "nom" -version = "7.0.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", "minimal-lexical", - "version_check", ] [[package]] name = "ntapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ "winapi 0.3.9", ] @@ -2797,9 +3040,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", @@ -2822,16 +3065,16 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -2862,18 +3105,18 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi", "libc", @@ -2881,33 +3124,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9bd055fb730c4f8f4f57d45d35cd6b3f0980535b056dc7ff119cee6a66ed6f" +checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" dependencies = [ - "derivative", "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9" -dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", -] - -[[package]] -name = "num_threads" -version = "0.1.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15" +checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ - "libc", + "proc-macro-crate 1.2.1", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -2927,15 +3160,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" - -[[package]] -name = "opaque-debug" -version = "0.2.3" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "opaque-debug" @@ -2945,9 +3172,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -2964,31 +3191,31 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "openssl-probe" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.22.0+1.1.1q" +version = "111.24.0+1.1.1s" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f31f0d509d1c1ae9cada2f9539ff8f37933831fd5098879e482aa687d659853" +checksum = "3498f259dab01178c6228c6b00dcef0ed2a2d5e20d648c017861227773ea4abd" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.73" +version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" +checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ "autocfg", "cc", @@ -3006,23 +3233,20 @@ checksum = "e1cf9b1c4e9a6c4de793c632496fa490bdc0e1eea73f0c91394f7b6990935d22" dependencies = [ "async-trait", "crossbeam-channel", - "futures 0.3.21", + "futures 0.3.25", "js-sys", "lazy_static", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project", - "rand 0.8.4", + "rand 0.8.5", "thiserror", ] [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] +checksum = "7b5bf27447411e9ee3ff51186bf7a08e16c341efdde93f4d823e8844429bed7e" [[package]] name = "ouroboros" @@ -3043,9 +3267,9 @@ checksum = "ed9a247206016d424fe8497bc611e510887af5c261fbbf977877c4bb55ca4d82" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -3054,7 +3278,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "libc", "log", "rand 0.7.3", @@ -3075,12 +3299,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.1", + "parking_lot_core 0.9.4", ] [[package]] @@ -3099,15 +3323,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys 0.32.0", + "windows-sys 0.42.0", ] [[package]] @@ -3125,7 +3349,16 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" dependencies = [ - "digest 0.10.3", + "digest 0.10.6", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.6", ] [[package]] @@ -3136,11 +3369,11 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pem" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" +checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] @@ -3151,9 +3384,9 @@ checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "percentage" @@ -3166,18 +3399,19 @@ dependencies = [ [[package]] name = "pest" -version = "2.1.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "a528564cc62c19a7acac4d81e01f39e53e25e17b934878f4c6d25cc2836e62f8" dependencies = [ + "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "d5fd9bc6500181952d34bd0b2b0163a54d794227b498be0b7afa7698d0a7b18f" dependencies = [ "pest", "pest_generator", @@ -3185,35 +3419,45 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "d2610d5ac5156217b4ff8e46ddcef7cdf44b273da2ac5bca2ecbfa86a330e7c4" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "824749bf7e21dd66b36fbe26b3f45c713879cccd4a009a917ab8e045ca8246fe" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1 0.8.2", + "sha1 0.10.5", ] [[package]] name = "petgraph" -version = "0.6.0" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +dependencies = [ + "fixedbitset 0.2.0", + "indexmap", +] + +[[package]] +name = "petgraph" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ - "fixedbitset", + "fixedbitset 0.4.2", "indexmap", ] @@ -3232,29 +3476,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -3275,9 +3519,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plain" @@ -3293,21 +3537,21 @@ checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug", "universal-hash", ] [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "predicates" -version = "2.0.3" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6ce811d0b2e103743eec01db1c50612221f173084ce2f7941053e94b6bb474" +checksum = "ed6bd09a7f7e68f3f0bf710fb7ab9c4615a488b58b5f653382a687701e458c92" dependencies = [ "difflib", "itertools", @@ -3316,15 +3560,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" +checksum = "72f883590242d3c6fc5bf50299011695fa6590c2c70eac95ee1bdb9a733ad1a2" [[package]] name = "predicates-tree" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338c7be2905b732ae3984a2f40032b5e94fd8f52505b186c7d4d68d193445df7" +checksum = "54ff541861505aabf6ea722d2131ee980b8276e10a1297b94e896dd8b621850d" dependencies = [ "predicates-core", "termtree", @@ -3338,12 +3582,12 @@ checksum = "bc5c99d529f0d30937f6f4b8a86d988047327bb88d04d2c4afc356de74722131" [[package]] name = "prettyplease" -version = "0.1.9" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b83ec2d0af5c5c556257ff52c9f98934e243b9fd39604bfb2a9b75ec2e97f18" +checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" dependencies = [ - "proc-macro2 1.0.32", - "syn 1.0.91", + "proc-macro2 1.0.47", + "syn 1.0.103", ] [[package]] @@ -3357,10 +3601,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ + "once_cell", "thiserror", "toml", ] @@ -3372,9 +3617,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "version_check", ] @@ -3384,8 +3629,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.47", + "quote 1.0.21", "version_check", ] @@ -3406,11 +3651,24 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" dependencies = [ - "unicode-xid 0.2.2", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", + "version_check", + "yansi", ] [[package]] @@ -3425,7 +3683,7 @@ dependencies = [ "lazy_static", "num-traits", "quick-error 2.0.1", - "rand 0.8.4", + "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", "regex-syntax", @@ -3433,6 +3691,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "prost" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" +dependencies = [ + "bytes", + "prost-derive 0.8.0", +] + [[package]] name = "prost" version = "0.9.0" @@ -3445,12 +3713,30 @@ dependencies = [ [[package]] name = "prost" -version = "0.10.0" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" +dependencies = [ + "bytes", + "prost-derive 0.10.1", +] + +[[package]] +name = "prost-build" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bd5316aa8f5c82add416dfbc25116b84b748a21153f512917e8143640a71bbd" +checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603" dependencies = [ "bytes", - "prost-derive 0.10.0", + "heck 0.3.3", + "itertools", + "log", + "multimap", + "petgraph 0.5.1", + "prost 0.8.0", + "prost-types 0.8.0", + "tempfile", + "which", ] [[package]] @@ -3465,7 +3751,7 @@ dependencies = [ "lazy_static", "log", "multimap", - "petgraph", + "petgraph 0.6.2", "prost 0.9.0", "prost-types 0.9.0", "regex", @@ -3475,9 +3761,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.10.0" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328f9f29b82409216decb172d81e936415d21245befa79cd34c3f29d87d1c50b" +checksum = "8ae5a4388762d5815a9fc0dea33c56b021cdc8dde0c55e0c9ca57197254b0cab" dependencies = [ "bytes", "cfg-if 1.0.0", @@ -3487,14 +3773,27 @@ dependencies = [ "lazy_static", "log", "multimap", - "petgraph", - "prost 0.10.0", - "prost-types 0.10.0", + "petgraph 0.6.2", + "prost 0.10.4", + "prost-types 0.10.1", "regex", "tempfile", "which", ] +[[package]] +name = "prost-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + [[package]] name = "prost-derive" version = "0.9.0" @@ -3503,22 +3802,32 @@ checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "prost-derive" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df35198f0777b75e9ff669737c6da5136b59dba33cf5a010a6d1cc4d56defc6f" +checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "prost-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b" +dependencies = [ + "bytes", + "prost 0.8.0", ] [[package]] @@ -3533,12 +3842,12 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "926681c118ae6e512a3ccefd4abbe5521a14f4cc1e207356d4d00c0b7f2006fd" +checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ "bytes", - "prost 0.10.0", + "prost 0.10.4", ] [[package]] @@ -3547,7 +3856,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" dependencies = [ - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", ] [[package]] @@ -3564,9 +3873,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quinn" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7542006acd6e057ff632307d219954c44048f818898da03113d6c0086bfddd9" +checksum = "5b435e71d9bfa0d8889927231970c51fb89c58fa63bffcab117c9c7a41e5ef8f" dependencies = [ "bytes", "futures-channel", @@ -3574,7 +3883,7 @@ dependencies = [ "fxhash", "quinn-proto", "quinn-udp", - "rustls 0.20.4", + "rustls 0.20.7", "thiserror", "tokio", "tracing", @@ -3583,16 +3892,16 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a13a5c0a674c1ce7150c9df7bc4a1e46c2fbbe7c710f56c0dc78b1a810e779e" +checksum = "3fce546b9688f767a57530652488420d419a8b1f44a478b451c3d1ab6d992a55" dependencies = [ "bytes", "fxhash", - "rand 0.8.4", + "rand 0.8.5", "ring", - "rustls 0.20.4", - "rustls-native-certs", + "rustls 0.20.7", + "rustls-native-certs 0.6.2", "rustls-pemfile 0.2.1", "slab", "thiserror", @@ -3603,13 +3912,12 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7996776e9ee3fc0e5c14476c1a640a17e993c847ae9c81191c2c102fbef903" +checksum = "9f832d8958db3e84d2ec93b5eb2272b45aa23cf7f8fe6e79f578896f4e6c231b" dependencies = [ "futures-util", "libc", - "mio", "quinn-proto", "socket2", "tokio", @@ -3627,19 +3935,13 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.10" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ - "proc-macro2 1.0.32", + "proc-macro2 1.0.47", ] -[[package]] -name = "radium" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" - [[package]] name = "rand" version = "0.4.6" @@ -3663,20 +3965,19 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", "rand_pcg", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", - "rand_core 0.6.3", - "rand_hc 0.3.1", + "rand_core 0.6.4", ] [[package]] @@ -3696,7 +3997,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -3725,11 +4026,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.8", ] [[package]] @@ -3741,15 +4042,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "rand_pcg" version = "0.2.1" @@ -3765,7 +4057,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -3774,7 +4066,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -3785,9 +4077,9 @@ checksum = "5cb37e7b5c272e9d7d75d3ab9d4f3a028edfbb4e99a2f35ec887057ea51656ad" [[package]] name = "rayon" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ "autocfg", "crossbeam-deque", @@ -3797,14 +4089,13 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", "num_cpus", ] @@ -3812,7 +4103,7 @@ dependencies = [ name = "rbpf-cli" version = "1.13.6" dependencies = [ - "clap 3.1.6", + "clap 3.2.23", "serde", "serde_json", "solana-bpf-loader-program", @@ -3824,13 +4115,13 @@ dependencies = [ [[package]] name = "rcgen" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fa2d386df8533b02184941c76ae2e0d0c1d053f5d43339169d80f21275fc5e" +checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" dependencies = [ "pem", "ring", - "time 0.3.7", + "time 0.3.17", "yasna", ] @@ -3845,42 +4136,43 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.8", "redox_syscall", + "thiserror", ] [[package]] name = "reed-solomon-erasure" -version = "5.0.1" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170bac0d8306941e101df0caaa6518b10bc4232dd36c34f1cb78b8a063024db" +checksum = "c2fe31452b684b8b33f65f8730c8b8812c3f5a0bb8a096934717edb1ac488641" dependencies = [ "cc", "libc", "libm", "parking_lot 0.11.2", "smallvec", - "spin 0.9.2", + "spin 0.9.4", ] [[package]] name = "regex" -version = "1.5.5" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -3895,9 +4187,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -3910,12 +4202,12 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.10" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" +checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" dependencies = [ "async-compression", - "base64 0.13.0", + "base64 0.13.1", "bytes", "encoding_rs", "futures-core", @@ -3928,34 +4220,35 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", - "percent-encoding 2.1.0", + "once_cell", + "percent-encoding 2.2.0", "pin-project-lite", - "rustls 0.20.4", - "rustls-pemfile 0.3.0", + "rustls 0.20.7", + "rustls-pemfile 1.0.1", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", - "tokio-rustls 0.23.2", - "tokio-util 0.6.9", - "url 2.2.2", + "tokio-rustls 0.23.4", + "tokio-util 0.7.2", + "tower-service", + "url 2.3.1", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.22.5", "winreg", ] [[package]] name = "retain_mut" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c31b5c4033f8fdde8700e4657be2c497e7288f01515be52168c631e2e4d4086" +checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" [[package]] name = "ring" @@ -4015,22 +4308,13 @@ dependencies = [ "semver 0.9.0", ] -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.6", + "semver 1.0.14", ] [[package]] @@ -4039,21 +4323,21 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" dependencies = [ - "nom 7.0.0", + "nom", ] [[package]] name = "rustix" -version = "0.33.3" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9466f25b92a648960ac1042fd3baa6b0bf285e60f754d7e5070770c813a177a" +checksum = "203974af07ea769452490ee8de3e5947971efc3a090dca8a779dd432d3fa46a7" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -4062,7 +4346,7 @@ version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "log", "ring", "sct 0.6.1", @@ -4071,9 +4355,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.4" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" dependencies = [ "log", "ring", @@ -4083,12 +4367,24 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" +checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" dependencies = [ "openssl-probe", - "rustls-pemfile 0.2.1", + "rustls 0.19.1", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.1", "schannel", "security-framework", ] @@ -4099,23 +4395,23 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] name = "rustls-pemfile" -version = "0.3.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] name = "rustversion" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "rusty-fork" @@ -4131,9 +4427,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -4146,12 +4442,12 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "winapi 0.3.9", + "windows-sys 0.36.1", ] [[package]] @@ -4160,6 +4456,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "scroll" version = "0.10.2" @@ -4175,9 +4477,9 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -4202,9 +4504,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.4.2" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -4215,9 +4517,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", @@ -4229,23 +4531,14 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser 0.10.2", + "semver-parser", ] [[package]] name = "semver" -version = "1.0.6" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ "serde", ] @@ -4256,29 +4549,20 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - [[package]] name = "serde" -version = "1.0.136" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.5" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" +checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" dependencies = [ "serde", ] @@ -4295,22 +4579,22 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "8e8b3801309262e8184d9687fb697586833e939767aea0dda89f5a8e650e8bd7" dependencies = [ - "itoa 1.0.1", + "itoa 1.0.4", "ryu", "serde", ] @@ -4322,16 +4606,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.1", + "itoa 1.0.4", "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.8.23" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap", "ryu", @@ -4347,7 +4631,21 @@ checksum = "e5bcc41d18f7a1d50525d080fd3e953be87c4f9f1a974f3c21798ca00d54ec15" dependencies = [ "lazy_static", "parking_lot 0.11.2", - "serial_test_derive", + "serial_test_derive 0.6.0", +] + +[[package]] +name = "serial_test" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92761393ee4dc3ff8f4af487bd58f4307c9329bbedea02cac0089ad9c411e153" +dependencies = [ + "dashmap 5.2.0", + "futures 0.3.25", + "lazy_static", + "log", + "parking_lot 0.12.1", + "serial_test_derive 0.9.0", ] [[package]] @@ -4357,22 +4655,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2881bccd7d60fb32dfa3d7b3136385312f8ad75e2674aab2852867a09790cae8" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustversion", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] -name = "sha-1" -version = "0.8.2" +name = "serial_test_derive" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +checksum = "4b6f5d1c3087fb119617cff2966fe3808a80e5eb59a8c1601d5994d66f4346a5" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", + "proc-macro-error", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -4385,7 +4683,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -4396,14 +4694,34 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.10.6", ] [[package]] name = "sha1" -version = "0.6.0" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.6", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" [[package]] name = "sha2" @@ -4415,18 +4733,18 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.10.6", ] [[package]] @@ -4438,16 +4756,16 @@ dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", "keccak", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] name = "sha3" -version = "0.10.1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881bf8156c87b6301fc5ca6b27f11eeb2761224c7081e69b409d5a1951a70c86" +checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" dependencies = [ - "digest 0.10.3", + "digest 0.10.6", "keccak", ] @@ -4468,9 +4786,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "signal-hook" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" dependencies = [ "libc", "signal-hook-registry", @@ -4487,9 +4805,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.4.0" +version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" [[package]] name = "simpl" @@ -4509,15 +4827,18 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smpl_jwt" @@ -4525,7 +4846,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4370044f8b20f944e05c35d77edd3518e6f21fc4de77e593919f287c6a3f428a" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "log", "openssl", "serde", @@ -4537,9 +4858,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi 0.3.9", @@ -4551,12 +4872,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bytes", - "futures 0.3.21", + "futures 0.3.25", "httparse", "log", - "rand 0.8.4", + "rand 0.8.5", "sha-1 0.9.8", ] @@ -4565,9 +4886,9 @@ name = "solana-account-decoder" version = "1.13.6" dependencies = [ "Inflector", - "base64 0.13.0", + "base64 0.13.1", "bincode", - "bs58", + "bs58 0.4.0", "bv", "lazy_static", "serde", @@ -4586,7 +4907,7 @@ dependencies = [ name = "solana-accounts-bench" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "log", "rayon", "solana-logger 1.13.6", @@ -4600,7 +4921,7 @@ dependencies = [ name = "solana-accounts-cluster-bench" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "log", "rand 0.7.3", "rayon", @@ -4657,7 +4978,7 @@ dependencies = [ name = "solana-banking-bench" version = "1.13.6" dependencies = [ - "clap 3.1.6", + "clap 3.2.23", "crossbeam-channel", "log", "rand 0.7.3", @@ -4681,7 +5002,7 @@ name = "solana-banks-client" version = "1.13.6" dependencies = [ "borsh", - "futures 0.3.21", + "futures 0.3.25", "solana-banks-interface", "solana-banks-server", "solana-program 1.13.6", @@ -4708,23 +5029,40 @@ version = "1.13.6" dependencies = [ "bincode", "crossbeam-channel", - "futures 0.3.21", + "futures 0.3.25", "solana-banks-interface", "solana-client", + "solana-gossip", "solana-runtime", "solana-sdk 1.13.6", "solana-send-transaction-service", + "solana-streamer", "tarpc", "tokio", "tokio-serde", "tokio-stream", ] +[[package]] +name = "solana-bench-batch-simulate-bundle" +version = "1.13.6" +dependencies = [ + "clap 3.2.23", + "env_logger", + "log", + "num-traits", + "rayon", + "solana-client", + "solana-runtime", + "solana-sdk 1.13.6", + "solana-transaction-status", +] + [[package]] name = "solana-bench-streamer" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "solana-net-utils", "solana-streamer", @@ -4735,13 +5073,13 @@ dependencies = [ name = "solana-bench-tps" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "log", "rayon", "serde_json", "serde_yaml", - "serial_test", + "serial_test 0.6.0", "solana-clap-utils", "solana-cli-config", "solana-client", @@ -4821,9 +5159,9 @@ version = "1.13.6" dependencies = [ "bzip2", "cargo_metadata", - "clap 3.1.6", + "clap 3.2.23", "regex", - "serial_test", + "serial_test 0.9.0", "solana-download-utils", "solana-sdk 1.13.6", "tar", @@ -4834,7 +5172,7 @@ name = "solana-cargo-test-bpf" version = "1.13.6" dependencies = [ "cargo_metadata", - "clap 3.1.6", + "clap 3.2.23", ] [[package]] @@ -4842,7 +5180,7 @@ name = "solana-clap-utils" version = "1.13.6" dependencies = [ "chrono", - "clap 2.33.3", + "clap 2.34.0", "rpassword", "solana-perf", "solana-remote-wallet", @@ -4851,7 +5189,7 @@ dependencies = [ "thiserror", "tiny-bip39", "uriparse", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -4859,8 +5197,8 @@ name = "solana-cli" version = "1.13.6" dependencies = [ "bincode", - "bs58", - "clap 2.33.3", + "bs58 0.4.0", + "clap 2.34.0", "console", "const_format", "criterion-stats", @@ -4871,7 +5209,7 @@ dependencies = [ "num-traits", "pretty-hex", "reqwest", - "semver 1.0.6", + "semver 1.0.14", "serde", "serde_derive", "serde_json", @@ -4911,7 +5249,7 @@ dependencies = [ "serde_yaml", "solana-clap-utils", "solana-sdk 1.13.6", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -4919,14 +5257,14 @@ name = "solana-cli-output" version = "1.13.6" dependencies = [ "Inflector", - "base64 0.13.0", + "base64 0.13.1", "chrono", - "clap 2.33.3", + "clap 2.34.0", "console", "ed25519-dalek", "humantime", "indicatif", - "semver 1.0.6", + "semver 1.0.14", "serde", "serde_json", "solana-account-decoder", @@ -4946,14 +5284,14 @@ dependencies = [ "assert_matches", "async-mutex", "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bincode", - "bs58", + "bs58 0.4.0", "bytes", - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "enum_dispatch", - "futures 0.3.21", + "futures 0.3.25", "futures-util", "indexmap", "indicatif", @@ -4969,8 +5307,8 @@ dependencies = [ "rand_chacha 0.2.2", "rayon", "reqwest", - "rustls 0.20.4", - "semver 1.0.6", + "rustls 0.20.7", + "semver 1.0.14", "serde", "serde_derive", "serde_json", @@ -4993,7 +5331,7 @@ dependencies = [ "tokio-stream", "tokio-tungstenite", "tungstenite", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -5002,7 +5340,7 @@ version = "1.13.6" dependencies = [ "futures-util", "serde_json", - "serial_test", + "serial_test 0.6.0", "solana-client", "solana-ledger", "solana-logger 1.13.6", @@ -5048,20 +5386,31 @@ name = "solana-core" version = "1.13.6" dependencies = [ "ahash", - "base64 0.13.0", + "anchor-lang", + "base64 0.13.1", "bincode", - "bs58", + "bs58 0.4.0", + "bytes", "chrono", + "clap 3.2.23", "crossbeam-channel", - "dashmap", + "dashmap 4.0.2", "etcd-client", "fs_extra", + "futures 0.3.25", + "futures-util", "histogram", + "indexmap", "itertools", + "jito-protos", + "lazy_static", "log", "lru", "matches", "min-max-heap", + "num_enum", + "prost 0.8.0", + "prost-types 0.8.0", "rand 0.7.3", "rand_chacha 0.2.2", "raptorq", @@ -5072,7 +5421,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serial_test", + "serial_test 0.6.0", "solana-address-lookup-table-program", "solana-bloom", "solana-client", @@ -5106,8 +5455,14 @@ dependencies = [ "systemstat", "tempfile", "thiserror", + "tip-distribution", + "tip-payment", "tokio", + "tokio-stream", + "tonic 0.5.2", + "tonic-build 0.5.2", "trees", + "uuid", ] [[package]] @@ -5115,7 +5470,7 @@ name = "solana-dos" version = "1.13.6" dependencies = [ "bincode", - "clap 3.1.6", + "clap 3.2.23", "log", "rand 0.7.3", "serde", @@ -5182,7 +5537,7 @@ version = "1.13.6" dependencies = [ "bincode", "byteorder", - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "log", "serde", @@ -5200,13 +5555,11 @@ dependencies = [ [[package]] name = "solana-frozen-abi" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a5d3280421bb53fc12bdba1eaa505153fb4f99a06b5609dae22192652ead3b" +version = "1.13.6" dependencies = [ - "bs58", + "bs58 0.4.0", "bv", - "generic-array 0.14.5", + "generic-array", "im", "lazy_static", "log", @@ -5215,60 +5568,74 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "sha2 0.10.2", - "solana-frozen-abi-macro 1.10.33", + "sha2 0.10.6", + "solana-frozen-abi-macro 1.13.6", + "solana-logger 1.13.6", "thiserror", ] [[package]] name = "solana-frozen-abi" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9d5107e663df4a87c658ee764e9f0e4d15adf8bc1d1c9088b45ed8eaaf4958" dependencies = [ - "bs58", + "ahash", + "blake3", + "block-buffer 0.9.0", + "bs58 0.4.0", "bv", - "generic-array 0.14.5", + "byteorder", + "cc", + "either", + "generic-array", + "getrandom 0.1.16", + "hashbrown 0.12.3", "im", "lazy_static", "log", "memmap2", + "once_cell", + "rand_core 0.6.4", "rustc_version 0.4.0", "serde", "serde_bytes", "serde_derive", - "sha2 0.10.2", - "solana-frozen-abi-macro 1.13.6", - "solana-logger 1.13.6", + "serde_json", + "sha2 0.10.6", + "solana-frozen-abi-macro 1.14.7", + "subtle", "thiserror", ] [[package]] name = "solana-frozen-abi-macro" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "635c60ac96b1347af272c625465068b908aff919d19f29b5795a44310310494d" +version = "1.13.6" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustc_version 0.4.0", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] name = "solana-frozen-abi-macro" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4600fe5ae28cec848debc4ea3b41f34d9d8fd088aca209fbb1e8205489d08d" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustc_version 0.4.0", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] name = "solana-genesis" version = "1.13.6" dependencies = [ - "base64 0.13.0", - "clap 2.33.3", + "base64 0.13.1", + "clap 2.34.0", "serde", "serde_json", "serde_yaml", @@ -5308,7 +5675,7 @@ dependencies = [ name = "solana-geyser-plugin-manager" version = "1.13.6" dependencies = [ - "bs58", + "bs58 0.4.0", "crossbeam-channel", "json5", "libloading", @@ -5330,7 +5697,7 @@ version = "1.13.6" dependencies = [ "bincode", "bv", - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "flate2", "indexmap", @@ -5347,7 +5714,7 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "serial_test", + "serial_test 0.6.0", "solana-bloom", "solana-clap-utils", "solana-client", @@ -5377,16 +5744,16 @@ dependencies = [ "bincode", "bzip2", "chrono", - "clap 2.33.3", + "clap 2.34.0", "console", "crossbeam-channel", "ctrlc", "dirs-next", "indicatif", "lazy_static", - "nix", + "nix 0.23.1", "reqwest", - "semver 1.0.6", + "semver 1.0.14", "serde", "serde_yaml", "solana-clap-utils", @@ -5397,7 +5764,7 @@ dependencies = [ "solana-version", "tar", "tempfile", - "url 2.2.2", + "url 2.3.1", "winapi 0.3.9", "winreg", ] @@ -5406,8 +5773,8 @@ dependencies = [ name = "solana-keygen" version = "1.13.6" dependencies = [ - "bs58", - "clap 2.33.3", + "bs58 0.4.0", + "clap 2.34.0", "dirs-next", "num_cpus", "solana-clap-utils", @@ -5430,7 +5797,7 @@ dependencies = [ "chrono-humanize", "crossbeam-channel", "fs_extra", - "futures 0.3.21", + "futures 0.3.25", "itertools", "lazy_static", "libc", @@ -5439,7 +5806,7 @@ dependencies = [ "matches", "num_cpus", "num_enum", - "prost 0.10.0", + "prost 0.10.4", "rand 0.7.3", "rand_chacha 0.2.2", "rayon", @@ -5448,7 +5815,7 @@ dependencies = [ "rustc_version 0.4.0", "serde", "serde_bytes", - "sha2 0.10.2", + "sha2 0.10.6", "solana-account-decoder", "solana-bpf-loader-program", "solana-entry", @@ -5480,12 +5847,12 @@ name = "solana-ledger-tool" version = "1.13.6" dependencies = [ "assert_cmd", - "base64 0.13.0", + "base64 0.13.1", "bytecount", - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "csv", - "dashmap", + "dashmap 4.0.2", "histogram", "itertools", "log", @@ -5523,7 +5890,7 @@ dependencies = [ "log", "rand 0.7.3", "rayon", - "serial_test", + "serial_test 0.6.0", "solana-client", "solana-config-program", "solana-core", @@ -5545,7 +5912,7 @@ name = "solana-log-analyzer" version = "1.13.6" dependencies = [ "byte-unit", - "clap 2.33.3", + "clap 2.34.0", "serde", "serde_json", "solana-logger 1.13.6", @@ -5554,9 +5921,7 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b12cb6e6f1f9c9876d356c928b8c2ac532f6715e7cd2a1b4343d747bee3eca73" +version = "1.13.6" dependencies = [ "env_logger", "lazy_static", @@ -5565,7 +5930,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f78a1849908659ed28696b92f030b1048b8ddafadfad0e95e79dcd21fe31072" dependencies = [ "env_logger", "lazy_static", @@ -5584,7 +5951,7 @@ dependencies = [ name = "solana-merkle-root-bench" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "log", "solana-logger 1.13.6", "solana-measure", @@ -5614,7 +5981,7 @@ dependencies = [ "log", "rand 0.7.3", "reqwest", - "serial_test", + "serial_test 0.6.0", "solana-sdk 1.13.6", ] @@ -5622,7 +5989,7 @@ dependencies = [ name = "solana-net-shaper" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "rand 0.7.3", "serde", "serde_json", @@ -5634,10 +6001,10 @@ name = "solana-net-utils" version = "1.13.6" dependencies = [ "bincode", - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "log", - "nix", + "nix 0.23.1", "rand 0.7.3", "serde", "serde_derive", @@ -5646,7 +6013,7 @@ dependencies = [ "solana-sdk 1.13.6", "solana-version", "tokio", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -5674,7 +6041,7 @@ dependencies = [ "libc", "log", "matches", - "nix", + "nix 0.23.1", "rand 0.7.3", "rayon", "serde", @@ -5711,7 +6078,7 @@ dependencies = [ name = "solana-poh-bench" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "log", "rand 0.7.3", "rayon", @@ -5725,17 +6092,17 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeecf504cee2821b006871f70e7a1f54db15f914cedf259eaf5976fe606470f0" +version = "1.13.6" dependencies = [ - "base64 0.13.0", + "anyhow", + "assert_matches", + "base64 0.13.1", "bincode", "bitflags", "blake3", "borsh", "borsh-derive", - "bs58", + "bs58 0.4.0", "bv", "bytemuck", "console_error_panic_hook", @@ -5749,72 +6116,79 @@ dependencies = [ "log", "num-derive", "num-traits", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", "rustc_version 0.4.0", "rustversion", "serde", "serde_bytes", "serde_derive", - "sha2 0.10.2", - "sha3 0.10.1", - "solana-frozen-abi 1.10.33", - "solana-frozen-abi-macro 1.10.33", - "solana-sdk-macro 1.10.33", + "serde_json", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.13.6", + "solana-frozen-abi-macro 1.13.6", + "solana-logger 1.13.6", + "solana-sdk-macro 1.13.6", + "static_assertions", "thiserror", "wasm-bindgen", ] [[package]] name = "solana-program" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512475cccb7e13f96ba76ed091b2d79a8431a485c73be728cd2235f9adba5a4e" dependencies = [ - "anyhow", - "assert_matches", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "blake3", "borsh", "borsh-derive", - "bs58", + "bs58 0.4.0", "bv", "bytemuck", + "cc", "console_error_panic_hook", "console_log", "curve25519-dalek", - "getrandom 0.1.16", + "getrandom 0.2.8", "itertools", "js-sys", "lazy_static", + "libc", "libsecp256k1", "log", + "memoffset", "num-derive", "num-traits", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", + "rand_chacha 0.2.2", "rustc_version 0.4.0", "rustversion", "serde", "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.2", - "sha3 0.10.1", - "solana-frozen-abi 1.13.6", - "solana-frozen-abi-macro 1.13.6", - "solana-logger 1.13.6", - "solana-sdk-macro 1.13.6", - "static_assertions", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.14.7", + "solana-frozen-abi-macro 1.14.7", + "solana-sdk-macro 1.14.7", "thiserror", + "tiny-bip39", "wasm-bindgen", + "zeroize", ] [[package]] name = "solana-program-runtime" version = "1.13.6" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bincode", "enum-iterator", "itertools", @@ -5838,7 +6212,7 @@ name = "solana-program-test" version = "1.13.6" dependencies = [ "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bincode", "chrono-humanize", "log", @@ -5873,9 +6247,9 @@ dependencies = [ "log", "num-derive", "num-traits", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "qstring", - "semver 1.0.6", + "semver 1.0.14", "solana-sdk 1.13.6", "thiserror", "uriparse", @@ -5888,24 +6262,24 @@ dependencies = [ "crossbeam-channel", "futures-util", "log", - "prost 0.10.0", + "prost 0.10.4", "solana-rpc", "solana-runtime", "solana-sdk 1.13.6", "tokio", - "tonic 0.7.1", - "tonic-build 0.7.0", + "tonic 0.7.2", + "tonic-build 0.7.2", ] [[package]] name = "solana-replica-node" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "log", "rand 0.7.3", - "serial_test", + "serial_test 0.6.0", "solana-clap-utils", "solana-client", "solana-core", @@ -5925,18 +6299,18 @@ dependencies = [ "solana-validator", "solana-version", "tempfile", - "tonic-build 0.7.0", + "tonic-build 0.7.2", ] [[package]] name = "solana-rpc" version = "1.13.6" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bincode", - "bs58", + "bs58 0.4.0", "crossbeam-channel", - "dashmap", + "dashmap 4.0.2", "itertools", "jsonrpc-core", "jsonrpc-core-client", @@ -5950,7 +6324,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serial_test", + "serial_test 0.6.0", "soketto", "solana-account-decoder", "solana-address-lookup-table-program", @@ -5980,7 +6354,7 @@ dependencies = [ "symlink", "thiserror", "tokio", - "tokio-util 0.6.9", + "tokio-util 0.6.10", ] [[package]] @@ -5988,7 +6362,7 @@ name = "solana-rpc-test" version = "1.13.6" dependencies = [ "bincode", - "bs58", + "bs58 0.4.0", "crossbeam-channel", "futures-util", "log", @@ -6019,7 +6393,7 @@ dependencies = [ "byteorder", "bzip2", "crossbeam-channel", - "dashmap", + "dashmap 4.0.2", "dir-diff", "ed25519-dalek", "flate2", @@ -6070,24 +6444,25 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "636f6c615aca6f75e22b6baceaf0ffed9d74367f9320b07ed57cd9b5ce2e4ff9" +version = "1.13.6" dependencies = [ + "anchor-lang", + "anyhow", "assert_matches", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "borsh", - "bs58", + "bs58 0.4.0", "bytemuck", "byteorder", "chrono", + "curve25519-dalek", "derivation-path", - "digest 0.10.3", + "digest 0.10.6", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array 0.14.5", + "generic-array", "hmac 0.12.1", "itertools", "js-sys", @@ -6107,38 +6482,40 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.2", - "sha3 0.10.1", - "solana-frozen-abi 1.10.33", - "solana-frozen-abi-macro 1.10.33", - "solana-logger 1.10.33", - "solana-program 1.10.33", - "solana-sdk-macro 1.10.33", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.13.6", + "solana-frozen-abi-macro 1.13.6", + "solana-logger 1.13.6", + "solana-program 1.13.6", + "solana-sdk-macro 1.13.6", "thiserror", + "tiny-bip39", "uriparse", + "uuid", "wasm-bindgen", ] [[package]] name = "solana-sdk" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cb45fd782d3793c3821dd961b9c7a28b675e187f7f22cff06e694c7743904ce" dependencies = [ - "anyhow", "assert_matches", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "borsh", - "bs58", + "bs58 0.4.0", "bytemuck", "byteorder", "chrono", - "curve25519-dalek", "derivation-path", - "digest 0.10.3", + "digest 0.10.6", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array 0.14.5", + "generic-array", "hmac 0.12.1", "itertools", "js-sys", @@ -6148,7 +6525,7 @@ dependencies = [ "memmap2", "num-derive", "num-traits", - "pbkdf2 0.10.1", + "pbkdf2 0.11.0", "qstring", "rand 0.7.3", "rand_chacha 0.2.2", @@ -6158,41 +6535,40 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.2", - "sha3 0.10.1", - "solana-frozen-abi 1.13.6", - "solana-frozen-abi-macro 1.13.6", - "solana-logger 1.13.6", - "solana-program 1.13.6", - "solana-sdk-macro 1.13.6", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.14.7", + "solana-frozen-abi-macro 1.14.7", + "solana-logger 1.14.7", + "solana-program 1.14.7", + "solana-sdk-macro 1.14.7", "thiserror", - "tiny-bip39", "uriparse", "wasm-bindgen", ] [[package]] name = "solana-sdk-macro" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8bcac4394644f21dc013e932a7df9f536fcecef3e5df43fe362b4ec532ce30" +version = "1.13.6" dependencies = [ - "bs58", - "proc-macro2 1.0.32", - "quote 1.0.10", + "bs58 0.4.0", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustversion", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] name = "solana-sdk-macro" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08cc4804804ecb9eb07a16c7ff2d4a770fe0533298f36f867a5efc2e3284745" dependencies = [ - "bs58", - "proc-macro2 1.0.32", - "quote 1.0.10", + "bs58 0.4.0", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustversion", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] @@ -6202,18 +6578,20 @@ dependencies = [ "crossbeam-channel", "log", "solana-client", + "solana-gossip", "solana-logger 1.13.6", "solana-measure", "solana-metrics", "solana-runtime", "solana-sdk 1.13.6", + "solana-streamer", ] [[package]] name = "solana-stake-accounts" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "solana-clap-utils", "solana-cli-config", "solana-client", @@ -6256,15 +6634,15 @@ dependencies = [ "bzip2", "enum-iterator", "flate2", - "futures 0.3.21", + "futures 0.3.25", "goauth", "http", "hyper", "hyper-proxy", "log", "openssl", - "prost 0.10.0", - "prost-types 0.10.0", + "prost 0.10.4", + "prost-types 0.10.1", "serde", "serde_derive", "smpl_jwt", @@ -6274,7 +6652,7 @@ dependencies = [ "solana-transaction-status", "thiserror", "tokio", - "tonic 0.7.1", + "tonic 0.7.2", "zstd", ] @@ -6283,21 +6661,21 @@ name = "solana-storage-proto" version = "1.13.6" dependencies = [ "bincode", - "bs58", + "bs58 0.4.0", "enum-iterator", - "prost 0.10.0", + "prost 0.10.4", "serde", "solana-account-decoder", "solana-sdk 1.13.6", "solana-transaction-status", - "tonic-build 0.7.0", + "tonic-build 0.7.2", ] [[package]] name = "solana-store-tool" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "log", "solana-logger 1.13.6", "solana-runtime", @@ -6315,14 +6693,14 @@ dependencies = [ "itertools", "libc", "log", - "nix", + "nix 0.23.1", "pem", "percentage", "pkcs8", "quinn", "rand 0.7.3", "rcgen", - "rustls 0.20.4", + "rustls 0.20.7", "solana-logger 1.13.6", "solana-metrics", "solana-perf", @@ -6336,10 +6714,10 @@ dependencies = [ name = "solana-sys-tuner" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "libc", "log", - "nix", + "nix 0.23.1", "solana-logger 1.13.6", "solana-version", "sysctl", @@ -6351,7 +6729,7 @@ dependencies = [ name = "solana-test-validator" version = "1.13.6" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "log", "serde_derive", "serde_json", @@ -6370,13 +6748,43 @@ dependencies = [ "tokio", ] +[[package]] +name = "solana-tip-distributor" +version = "1.13.6" +dependencies = [ + "anchor-lang", + "bigdecimal", + "clap 3.2.23", + "env_logger", + "futures 0.3.25", + "im", + "itertools", + "log", + "num-traits", + "serde", + "serde_json", + "solana-client", + "solana-genesis-utils", + "solana-ledger", + "solana-merkle-tree", + "solana-program 1.13.6", + "solana-rpc", + "solana-runtime", + "solana-sdk 1.13.6", + "solana-stake-program", + "thiserror", + "tip-distribution", + "tip-payment", + "tokio", +] + [[package]] name = "solana-tokens" version = "1.13.6" dependencies = [ "bincode", "chrono", - "clap 2.33.3", + "clap 2.34.0", "console", "csv", "ctrlc", @@ -6406,7 +6814,7 @@ name = "solana-transaction-dos" version = "1.13.6" dependencies = [ "bincode", - "clap 2.33.3", + "clap 2.34.0", "log", "rand 0.7.3", "rayon", @@ -6432,10 +6840,10 @@ name = "solana-transaction-status" version = "1.13.6" dependencies = [ "Inflector", - "base64 0.13.0", + "base64 0.13.1", "bincode", "borsh", - "bs58", + "bs58 0.4.0", "lazy_static", "log", "serde", @@ -6466,7 +6874,7 @@ name = "solana-validator" version = "1.13.6" dependencies = [ "chrono", - "clap 2.33.3", + "clap 2.34.0", "console", "core_affinity", "crossbeam-channel", @@ -6511,6 +6919,7 @@ dependencies = [ "solana-vote-program", "symlink", "tikv-jemallocator", + "tonic 0.5.2", ] [[package]] @@ -6519,7 +6928,7 @@ version = "1.13.6" dependencies = [ "log", "rustc_version 0.4.0", - "semver 1.0.6", + "semver 1.0.14", "serde", "serde_derive", "solana-frozen-abi 1.13.6", @@ -6551,7 +6960,7 @@ dependencies = [ name = "solana-watchtower" version = "1.13.6" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "humantime", "log", "solana-clap-utils", @@ -6580,13 +6989,11 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410ee53a26ac91098c289c983863535d4fbb6604b229ae1159503f48fa4fc90f" +version = "1.13.6" dependencies = [ "aes-gcm-siv", "arrayref", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bytemuck", "byteorder", @@ -6601,8 +7008,8 @@ dependencies = [ "serde", "serde_json", "sha3 0.9.1", - "solana-program 1.10.33", - "solana-sdk 1.10.33", + "solana-program 1.13.6", + "solana-sdk 1.13.6", "subtle", "thiserror", "zeroize", @@ -6610,17 +7017,20 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4f9818b158e7a49266b83e0c06e551ba429d2395a55de5803eb6e2daa1260c" dependencies = [ "aes-gcm-siv", "arrayref", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bytemuck", "byteorder", "cipher 0.4.3", "curve25519-dalek", "getrandom 0.1.16", + "itertools", "lazy_static", "merlin", "num-derive", @@ -6629,8 +7039,8 @@ dependencies = [ "serde", "serde_json", "sha3 0.9.1", - "solana-program 1.13.6", - "solana-sdk 1.13.6", + "solana-program 1.14.7", + "solana-sdk 1.14.7", "subtle", "thiserror", "zeroize", @@ -6652,7 +7062,7 @@ dependencies = [ "rustc-demangle", "scroll", "thiserror", - "time 0.1.43", + "time 0.1.44", ] [[package]] @@ -6663,9 +7073,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" [[package]] name = "spki" @@ -6687,7 +7097,7 @@ dependencies = [ "borsh", "num-derive", "num-traits", - "solana-program 1.10.33", + "solana-program 1.14.7", "spl-token", "spl-token-2022", "thiserror", @@ -6699,7 +7109,7 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" dependencies = [ - "solana-program 1.10.33", + "solana-program 1.14.7", ] [[package]] @@ -6713,7 +7123,7 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-program 1.10.33", + "solana-program 1.14.7", "thiserror", ] @@ -6728,8 +7138,8 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-program 1.10.33", - "solana-zk-token-sdk 1.10.33", + "solana-program 1.14.7", + "solana-zk-token-sdk 1.14.7", "spl-memo", "spl-token", "thiserror", @@ -6776,11 +7186,11 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.47", + "quote 1.0.21", "serde", "serde_derive", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] @@ -6790,13 +7200,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ "base-x", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.47", + "quote 1.0.21", "serde", "serde_derive", "serde_json", - "sha1", - "syn 1.0.91", + "sha1 0.6.1", + "syn 1.0.103", ] [[package]] @@ -6830,24 +7240,24 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.24.0" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.0", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustversion", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] @@ -6875,13 +7285,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.91" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "unicode-xid 0.2.2", + "proc-macro2 1.0.47", + "quote 1.0.21", + "unicode-ident", ] [[package]] @@ -6896,10 +7306,10 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", - "unicode-xid 0.2.2", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", + "unicode-xid 0.2.4", ] [[package]] @@ -6914,9 +7324,9 @@ dependencies = [ [[package]] name = "sysctl" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1123645dfaf2b5eac6b6c88addafc359c789b8ef2a770ecaef758c1ddf363ea4" +checksum = "225e483f02d0ad107168dc57381a8a40c3aeea6abe47f37506931f861643cfa8" dependencies = [ "bitflags", "byteorder", @@ -6927,24 +7337,18 @@ dependencies = [ [[package]] name = "systemstat" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8862adb0fd5f4c5707b0eeb6c2ec7610bd7a8bf5e069150bd6dde04a7f40ebf7" +checksum = "91a3cae256f8af5246c2daad51ff29c32de4b4b0b0222063920af445fa3e12ab" dependencies = [ "bytesize", "chrono", "lazy_static", "libc", - "nom 7.0.0", + "nom", "winapi 0.3.9", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "tar" version = "0.4.38" @@ -6964,18 +7368,18 @@ checksum = "b85d0a9369a919ba0db919b142a2b704cd207dfc676f7a43c2d105d0bc225487" dependencies = [ "anyhow", "fnv", - "futures 0.3.21", + "futures 0.3.25", "humantime", "opentelemetry", "pin-project", - "rand 0.8.4", + "rand 0.8.5", "serde", "static_assertions", "tarpc-plugins", "thiserror", "tokio", "tokio-serde", - "tokio-util 0.6.9", + "tokio-util 0.6.10", "tracing", "tracing-opentelemetry", ] @@ -6986,9 +7390,9 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee42b4e559f17bce0385ebf511a7beb67d5cc33c12c96b7f4e9789919d9c10f" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -7007,9 +7411,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -7026,9 +7430,9 @@ dependencies = [ [[package]] name = "termtree" -version = "0.2.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13a4ec180a2de59b57434704ccfad967f789b12737738798fa08798cd5824c16" +checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8" [[package]] name = "textwrap" @@ -7041,28 +7445,28 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -7082,9 +7486,9 @@ dependencies = [ [[package]] name = "tikv-jemalloc-sys" -version = "0.4.2+5.2.1-patched.2" +version = "0.4.3+5.2.1-patched.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5844e429d797c62945a566f8da4e24c7fe3fbd5d6617fd8bf7a0b7dc1ee0f22e" +checksum = "a1792ccb507d955b46af42c123ea8863668fae24d03721e40cad6a41773dbb49" dependencies = [ "cc", "fs_extra", @@ -7093,9 +7497,9 @@ dependencies = [ [[package]] name = "tikv-jemallocator" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c14a5a604eb8715bc5785018a37d00739b180bcf609916ddf4393d33d49ccdf" +checksum = "a5b7bcecfafe4998587d636f9ae9d55eb9d0499877b88757767c346875067098" dependencies = [ "libc", "tikv-jemalloc-sys", @@ -7103,11 +7507,12 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi 0.3.9", ] @@ -7128,16 +7533,22 @@ dependencies = [ [[package]] name = "time" -version = "0.3.7" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ - "itoa 1.0.1", - "libc", - "num_threads", - "time-macros 0.2.3", + "itoa 1.0.4", + "serde", + "time-core", + "time-macros 0.2.6", ] +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + [[package]] name = "time-macros" version = "0.1.1" @@ -7150,9 +7561,12 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] [[package]] name = "time-macros-impl" @@ -7161,10 +7575,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.47", + "quote 1.0.21", "standback", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] @@ -7188,9 +7602,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -7201,6 +7615,21 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[package]] +name = "tip-distribution" +version = "0.1.0" +dependencies = [ + "anchor-lang", + "solana-program 1.13.6", +] + +[[package]] +name = "tip-payment" +version = "0.1.0" +dependencies = [ + "anchor-lang", +] + [[package]] name = "tokio" version = "1.14.1" @@ -7223,9 +7652,9 @@ dependencies = [ [[package]] name = "tokio-io-timeout" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90c49f106be240de154571dd31fbe48acb10ba6c6dd6f6517ad603abffa42de9" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" dependencies = [ "pin-project-lite", "tokio", @@ -7233,13 +7662,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -7265,11 +7694,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.2" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "rustls 0.20.4", + "rustls 0.20.7", "tokio", "webpki 0.22.0", ] @@ -7292,9 +7721,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite", @@ -7303,25 +7732,25 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.17.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06cda1232a49558c46f8a504d5b93101d42c0bf7f911f12a105ba48168f821ae" +checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" dependencies = [ "futures-util", "log", - "rustls 0.20.4", + "rustls 0.20.7", "tokio", - "tokio-rustls 0.23.2", + "tokio-rustls 0.23.4", "tungstenite", "webpki 0.22.0", - "webpki-roots", + "webpki-roots 0.22.5", ] [[package]] name = "tokio-util" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ "bytes", "futures-core", @@ -7335,9 +7764,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" dependencies = [ "bytes", "futures-core", @@ -7349,13 +7778,47 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] +[[package]] +name = "tonic" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "796c5e1cd49905e65dd8e700d4cb1dffcbfdb4fc9d017de08c1a537afd83627c" +dependencies = [ + "async-stream", + "async-trait", + "base64 0.13.1", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding 2.2.0", + "pin-project", + "prost 0.8.0", + "prost-derive 0.8.0", + "rustls-native-certs 0.5.0", + "tokio", + "tokio-rustls 0.22.0", + "tokio-stream", + "tokio-util 0.6.10", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", + "webpki-roots 0.21.1", +] + [[package]] name = "tonic" version = "0.6.2" @@ -7364,7 +7827,7 @@ checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a" dependencies = [ "async-stream", "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bytes", "futures-core", "futures-util", @@ -7373,14 +7836,14 @@ dependencies = [ "http-body", "hyper", "hyper-timeout", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project", "prost 0.9.0", "prost-derive 0.9.0", "tokio", "tokio-rustls 0.22.0", "tokio-stream", - "tokio-util 0.6.9", + "tokio-util 0.6.10", "tower", "tower-layer", "tower-service", @@ -7390,14 +7853,14 @@ dependencies = [ [[package]] name = "tonic" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30fb54bf1e446f44d870d260d99957e7d11fb9d0a0f5bd1a662ad1411cc103f9" +checksum = "5be9d60db39854b30b835107500cf0aca0b0d14d6e1c3de124217c23a29c2ddb" dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.13.0", + "base64 0.13.1", "bytes", "futures-core", "futures-util", @@ -7406,15 +7869,15 @@ dependencies = [ "http-body", "hyper", "hyper-timeout", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project", - "prost 0.10.0", - "prost-derive 0.10.0", - "rustls-pemfile 0.3.0", + "prost 0.10.4", + "prost-derive 0.10.1", + "rustls-pemfile 1.0.1", "tokio", - "tokio-rustls 0.23.2", + "tokio-rustls 0.23.4", "tokio-stream", - "tokio-util 0.7.1", + "tokio-util 0.7.2", "tower", "tower-layer", "tower-service", @@ -7422,46 +7885,58 @@ dependencies = [ "tracing-futures", ] +[[package]] +name = "tonic-build" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b52d07035516c2b74337d2ac7746075e7dcae7643816c1b12c5ff8a7484c08" +dependencies = [ + "proc-macro2 1.0.47", + "prost-build 0.8.0", + "quote 1.0.21", + "syn 1.0.103", +] + [[package]] name = "tonic-build" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757" dependencies = [ - "proc-macro2 1.0.32", + "proc-macro2 1.0.47", "prost-build 0.9.0", - "quote 1.0.10", - "syn 1.0.91", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "tonic-build" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d17087af5c80e5d5fc8ba9878e60258065a0a757e35efe7a05b7904bece1943" +checksum = "d9263bf4c9bfaae7317c1c2faf7f18491d2fe476f70c414b73bf5d445b00ffa1" dependencies = [ "prettyplease", - "proc-macro2 1.0.32", - "prost-build 0.10.0", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "prost-build 0.10.4", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "tower" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", "indexmap", "pin-project", "pin-project-lite", - "rand 0.8.4", + "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.1", + "tokio-util 0.7.2", "tower-layer", "tower-service", "tracing", @@ -7469,9 +7944,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.2.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8" +checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba" dependencies = [ "bitflags", "bytes", @@ -7488,21 +7963,21 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "log", @@ -7513,22 +7988,23 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.18" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "lazy_static", + "once_cell", + "valuable", ] [[package]] @@ -7578,37 +8054,37 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "tungstenite" -version = "0.17.2" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5" +checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "byteorder", "bytes", "http", "httparse", "log", - "rand 0.8.4", - "rustls 0.20.4", + "rand 0.8.5", + "rustls 0.20.7", "sha-1 0.10.0", "thiserror", - "url 2.2.2", + "url 2.3.1", "utf-8", "webpki 0.22.0", - "webpki-roots", + "webpki-roots 0.22.5", ] [[package]] name = "typenum" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "unicase" @@ -7621,30 +8097,36 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" @@ -7654,9 +8136,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "universal-hash" @@ -7664,7 +8146,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" dependencies = [ - "generic-array 0.14.5", + "generic-array", "subtle", ] @@ -7694,9 +8176,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "uriparse" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e515b1ada404168e145ac55afba3c42f04cf972201a8552d42e2abb17c1b7221" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" dependencies = [ "fnv", "lazy_static", @@ -7715,14 +8197,13 @@ dependencies = [ [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", - "idna 0.2.3", - "matches", - "percent-encoding 2.1.0", + "idna 0.3.0", + "percent-encoding 2.2.0", ] [[package]] @@ -7743,9 +8224,25 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf8-width" -version = "0.1.5" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" + +[[package]] +name = "uuid" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf7d77f457ef8dfa11e4cd5933c5ddb5dc52a94664071951219a97710f0a32b" +checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" +dependencies = [ + "getrandom 0.2.8", + "rand 0.8.5", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vcpkg" @@ -7761,9 +8258,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "void" @@ -7809,15 +8306,21 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -7825,24 +8328,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", "log", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "once_cell", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.28" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -7852,38 +8355,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote 1.0.10", + "quote 1.0.21", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -7911,22 +8414,31 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.1" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki 0.21.4", +] + +[[package]] +name = "webpki-roots" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c475786c6f47219345717a043a37ec04cb4bc185e28853adcc4fa0a947eba630" +checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" dependencies = [ "webpki 0.22.0", ] [[package]] name = "which" -version = "4.2.2" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" dependencies = [ "either", - "lazy_static", "libc", + "once_cell", ] [[package]] @@ -7974,89 +8486,103 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030b7ff91626e57a05ca64a07c481973cbb2db774e4852c9c7ca342408c6a99a" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc 0.30.0", - "windows_i686_gnu 0.30.0", - "windows_i686_msvc 0.30.0", - "windows_x86_64_gnu 0.30.0", - "windows_x86_64_msvc 0.30.0", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] [[package]] name = "windows-sys" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc 0.32.0", - "windows_i686_gnu 0.32.0", - "windows_i686_msvc 0.32.0", - "windows_x86_64_gnu 0.32.0", - "windows_x86_64_msvc 0.32.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_aarch64_msvc" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_gnu" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_i686_msvc" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_gnu" -version = "0.32.0" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] name = "windows_x86_64_msvc" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "winreg" @@ -8067,12 +8593,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "wyz" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" - [[package]] name = "x509-parser" version = "0.14.0" @@ -8080,22 +8600,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" dependencies = [ "asn1-rs", - "base64 0.13.0", + "base64 0.13.1", "data-encoding", "der-parser", "lazy_static", - "nom 7.0.0", + "nom", "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.7", + "time 0.3.17", ] [[package]] name = "xattr" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" dependencies = [ "libc", ] @@ -8109,13 +8629,19 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "yasna" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346d34a236c9d3e5f3b9b74563f238f955bbd05fa0b8b4efa53c130c43982f4c" dependencies = [ - "time 0.3.7", + "time 0.3.17", ] [[package]] @@ -8129,30 +8655,30 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "synstructure", ] [[package]] name = "zstd" -version = "0.11.1+zstd.1.5.2" +version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a16b8414fde0414e90c612eba70985577451c4c504b99885ebed24762cb81a" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "5.0.1+zstd.1.5.2" +version = "5.0.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c12659121420dd6365c5c3de4901f97145b79651fb1d25814020ed2ed0585ae" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" dependencies = [ "libc", "zstd-sys", diff --git a/Cargo.toml b/Cargo.toml index 2f6e9f66f5..c4c0b96976 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,8 @@ members = [ "banks-client", "banks-interface", "banks-server", + "bench-batch-simulate-bundle", + "bench-get-confirmed-blocks-with-data", "bench-streamer", "bench-tps", "bloom", @@ -29,6 +31,7 @@ members = [ "geyser-plugin-manager", "gossip", "install", + "jito-protos", "keygen", "ledger", "ledger-tool", @@ -75,6 +78,7 @@ members = [ "streamer", "sys-tuner", "test-validator", + "tip-distributor", "tokens", "transaction-dos", "transaction-status", @@ -86,7 +90,10 @@ members = [ ] exclude = [ + "anchor", + "jito-programs", "programs/bpf", + "programs/sbf", ] # This prevents a Travis CI error when building for Windows. diff --git a/README.md b/README.md index 496f7dedb2..a01c4c8c88 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,14 @@

-[![Solana crate](https://img.shields.io/crates/v/solana-core.svg)](https://crates.io/crates/solana-core) -[![Solana documentation](https://docs.rs/solana-core/badge.svg)](https://docs.rs/solana-core) -[![Build status](https://badge.buildkite.com/8cc350de251d61483db98bdfc895b9ea0ac8ffa4a32ee850ed.svg?branch=master)](https://buildkite.com/solana-labs/solana/builds?branch=master) -[![codecov](https://codecov.io/gh/solana-labs/solana/branch/master/graph/badge.svg)](https://codecov.io/gh/solana-labs/solana) +[![Build status](https://badge.buildkite.com/a6981eb34c6e0c7c09e3a3cb4bda09579f0ff2dcb1bd74b2ad.svg?branch=master)](https://buildkite.com/jito-labs/jito-solana) + +[//]: # ([![Solana crate](https://img.shields.io/crates/v/solana-core.svg)](https://crates.io/crates/solana-core)) +[//]: # ([![Solana documentation](https://docs.rs/solana-core/badge.svg)](https://docs.rs/solana-core)) +[//]: # ([![codecov](https://codecov.io/gh/solana-labs/solana/branch/master/graph/badge.svg)](https://codecov.io/gh/solana-labs/solana)) + +# About +This repository contains Jito Foundations's fork of the Solana validator. # Building diff --git a/anchor b/anchor new file mode 160000 index 0000000000..7532647bb8 --- /dev/null +++ b/anchor @@ -0,0 +1 @@ +Subproject commit 7532647bb86d26fd7497d9cbc7ac99e2b3941e86 diff --git a/banking-bench/Cargo.toml b/banking-bench/Cargo.toml index 820473b025..b7f216b57f 100644 --- a/banking-bench/Cargo.toml +++ b/banking-bench/Cargo.toml @@ -9,7 +9,7 @@ homepage = "https://solana.com/" publish = false [dependencies] -clap = {version = "3.1.5", features = ["derive", "cargo"]} +clap = { version = "3.1.5", features = ["derive", "cargo"] } crossbeam-channel = "0.5" log = "0.4.14" rand = "0.7.0" diff --git a/banking-bench/src/main.rs b/banking-bench/src/main.rs index e23e881827..20de455b02 100644 --- a/banking-bench/src/main.rs +++ b/banking-bench/src/main.rs @@ -6,7 +6,7 @@ use { rand::{thread_rng, Rng}, rayon::prelude::*, solana_client::connection_cache::{ConnectionCache, DEFAULT_TPU_CONNECTION_POOL_SIZE}, - solana_core::banking_stage::BankingStage, + solana_core::{banking_stage::BankingStage, bundle_account_locker::BundleAccountLocker}, solana_gossip::cluster_info::{ClusterInfo, Node}, solana_ledger::{ blockstore::Blockstore, @@ -30,6 +30,7 @@ use { }, solana_streamer::socket::SocketAddrSpace, std::{ + collections::HashSet, sync::{atomic::Ordering, Arc, Mutex, RwLock}, thread::sleep, time::{Duration, Instant}, @@ -45,9 +46,15 @@ fn check_txs( let now = Instant::now(); let mut no_bank = false; loop { - if let Ok((_bank, (entry, _tick_height))) = receiver.recv_timeout(Duration::from_millis(10)) + if let Ok(WorkingBankEntry { + bank: _, + entries_ticks, + }) = receiver.recv_timeout(Duration::from_millis(10)) { - total += entry.transactions.len(); + total += entries_ticks + .iter() + .map(|e| e.0.transactions.len()) + .sum::(); } if total >= ref_tx_count { break; @@ -358,6 +365,8 @@ fn main() { Arc::new(RwLock::new(CostModel::default())), Arc::new(connection_cache), bank_forks.clone(), + HashSet::default(), + BundleAccountLocker::default(), ); poh_recorder.lock().unwrap().set_bank(&bank); diff --git a/banks-server/Cargo.toml b/banks-server/Cargo.toml index 3353cecd5d..8648d5f1a7 100644 --- a/banks-server/Cargo.toml +++ b/banks-server/Cargo.toml @@ -15,6 +15,7 @@ crossbeam-channel = "0.5" futures = "0.3" solana-banks-interface = { path = "../banks-interface", version = "=1.13.6" } solana-client = { path = "../client", version = "=1.13.6" } +solana-gossip = { path = "../gossip", version = "=1.13.6" } solana-runtime = { path = "../runtime", version = "=1.13.6" } solana-sdk = { path = "../sdk", version = "=1.13.6" } solana-send-transaction-service = { path = "../send-transaction-service", version = "=1.13.6" } @@ -23,6 +24,9 @@ tokio = { version = "1", features = ["full"] } tokio-serde = { version = "0.8", features = ["bincode"] } tokio-stream = "0.1" +[dev-dependencies] +solana-streamer = { path = "../streamer", version = "=1.13.6" } + [lib] crate-type = ["lib"] name = "solana_banks_server" diff --git a/banks-server/src/banks_server.rs b/banks-server/src/banks_server.rs index 606cb50352..124f6f38f3 100644 --- a/banks-server/src/banks_server.rs +++ b/banks-server/src/banks_server.rs @@ -7,6 +7,7 @@ use { TransactionConfirmationStatus, TransactionSimulationDetails, TransactionStatus, }, solana_client::connection_cache::ConnectionCache, + solana_gossip::cluster_info::ClusterInfo, solana_runtime::{ bank::{Bank, TransactionSimulationResult}, bank_forks::BankForks, @@ -373,7 +374,7 @@ pub async fn start_local_server( pub async fn start_tcp_server( listen_addr: SocketAddr, - tpu_addr: SocketAddr, + cluster_info: Arc, bank_forks: Arc>, block_commitment_cache: Arc>, connection_cache: Arc, @@ -397,7 +398,7 @@ pub async fn start_tcp_server( let (sender, receiver) = unbounded(); SendTransactionService::new::( - tpu_addr, + cluster_info.clone(), &bank_forks, None, receiver, diff --git a/banks-server/src/rpc_banks_service.rs b/banks-server/src/rpc_banks_service.rs index 822798dd1f..8e0bfbeaaf 100644 --- a/banks-server/src/rpc_banks_service.rs +++ b/banks-server/src/rpc_banks_service.rs @@ -4,6 +4,7 @@ use { crate::banks_server::start_tcp_server, futures::{future::FutureExt, pin_mut, prelude::stream::StreamExt, select}, solana_client::connection_cache::ConnectionCache, + solana_gossip::cluster_info::ClusterInfo, solana_runtime::{bank_forks::BankForks, commitment::BlockCommitmentCache}, std::{ net::SocketAddr, @@ -27,7 +28,7 @@ pub struct RpcBanksService { /// Run the TCP service until `exit` is set to true async fn start_abortable_tcp_server( listen_addr: SocketAddr, - tpu_addr: SocketAddr, + cluster_info: Arc, bank_forks: Arc>, block_commitment_cache: Arc>, connection_cache: Arc, @@ -35,7 +36,7 @@ async fn start_abortable_tcp_server( ) { let server = start_tcp_server( listen_addr, - tpu_addr, + cluster_info, bank_forks.clone(), block_commitment_cache.clone(), connection_cache, @@ -58,7 +59,7 @@ async fn start_abortable_tcp_server( impl RpcBanksService { fn run( listen_addr: SocketAddr, - tpu_addr: SocketAddr, + cluster_info: Arc, bank_forks: Arc>, block_commitment_cache: Arc>, connection_cache: Arc, @@ -66,7 +67,7 @@ impl RpcBanksService { ) { let server = start_abortable_tcp_server( listen_addr, - tpu_addr, + cluster_info, bank_forks, block_commitment_cache, connection_cache, @@ -77,7 +78,7 @@ impl RpcBanksService { pub fn new( listen_addr: SocketAddr, - tpu_addr: SocketAddr, + cluster_info: Arc, bank_forks: &Arc>, block_commitment_cache: &Arc>, connection_cache: &Arc, @@ -92,7 +93,7 @@ impl RpcBanksService { .spawn(move || { Self::run( listen_addr, - tpu_addr, + cluster_info, bank_forks, block_commitment_cache, connection_cache, @@ -111,7 +112,14 @@ impl RpcBanksService { #[cfg(test)] mod tests { - use {super::*, solana_runtime::bank::Bank}; + use { + super::*, + solana_gossip::contact_info::ContactInfo, + solana_runtime::bank::Bank, + solana_sdk::signature::Keypair, + solana_streamer::socket::SocketAddrSpace, + std::net::{IpAddr, Ipv4Addr}, + }; #[test] fn test_rpc_banks_server_exit() { @@ -120,9 +128,18 @@ mod tests { let connection_cache = Arc::new(ConnectionCache::default()); let exit = Arc::new(AtomicBool::new(false)); let addr = "127.0.0.1:0".parse().unwrap(); + let contact_info = ContactInfo { + tpu: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080), + ..ContactInfo::default() + }; + let cluster_info: Arc = Arc::new(ClusterInfo::new( + contact_info, + Arc::new(Keypair::new()), + SocketAddrSpace::new(false), + )); let service = RpcBanksService::new( addr, - addr, + cluster_info, &bank_forks, &block_commitment_cache, &connection_cache, diff --git a/bench-batch-simulate-bundle/Cargo.toml b/bench-batch-simulate-bundle/Cargo.toml new file mode 100644 index 0000000000..6e06249524 --- /dev/null +++ b/bench-batch-simulate-bundle/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "solana-bench-batch-simulate-bundle" +version = "1.13.6" +edition = "2021" +publish = false + +[dependencies] +clap = { version = "3.1.12", features = ["derive", "env"] } +env_logger = "0.9.0" +log = "0.4.17" +num-traits = "0.2.15" +rayon = "1.5.2" +solana-client = { path = "../client" } +solana-runtime = { path = "../runtime" } +solana-sdk = { path = "../sdk" } +solana-transaction-status = { path = "../transaction-status" } diff --git a/bench-batch-simulate-bundle/src/main.rs b/bench-batch-simulate-bundle/src/main.rs new file mode 100644 index 0000000000..56e8762ddb --- /dev/null +++ b/bench-batch-simulate-bundle/src/main.rs @@ -0,0 +1,396 @@ +mod simulator; + +use { + crate::simulator::{Simulator, Stats}, + clap::Parser, + log::*, + num_traits::abs_sub, + solana_client::{ + pubsub_client::PubsubClient, rpc_client::RpcClient, rpc_config::RpcBlockConfig, + }, + solana_runtime::cost_model::CostModel, + solana_sdk::{ + bundle::VersionedBundle, + clock::Slot, + commitment_config::{CommitmentConfig, CommitmentLevel}, + message::{ + v0::{LoadedAddresses, MessageAddressTableLookup}, + AddressLoaderError, + }, + transaction::{AddressLoader, SanitizedTransaction, VersionedTransaction}, + }, + solana_transaction_status::{TransactionDetails, UiConfirmedBlock, UiTransactionEncoding}, + std::{ + cmp::Reverse, + collections::BinaryHeap, + sync::{ + atomic::{AtomicBool, AtomicU64, Ordering}, + Arc, RwLock, + }, + thread::{self, sleep, Builder, JoinHandle}, + time::Duration, + }, +}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// URL of the RPC server with no simulations running + #[clap(long, env, default_value = "https://api.testnet.solana.com")] + baseline_rpc_url: String, + + /// websocket URL of the RPC server with no simulations running + #[clap(long, env, default_value = "ws://api.testnet.solana.com")] + baseline_ws_url: String, + + /// URL of the RPC server running simulations against + #[clap(long, env)] + simulation_rpc_url: String, + + /// websocket URL of the RPC server running simulations against + #[clap(long, env)] + simulation_ws_url: String, + + /// duration to run the test for, must be >= [SIMULATION_REFRESH_SECS] + #[clap(long, env, default_value_t = 60)] + test_duration_secs: u64, + + /// size of the bundle batch being sent for simulation + #[clap(long, env, default_value_t = 5)] + bundle_batch_size: usize, + + /// number of threads sharing a single RPC connection + #[clap(long, env, default_value_t = 16)] + n_threads: usize, + + /// number of unique RPC connections + #[clap(long, env, default_value_t = 32)] + n_rpc_connections: u64, +} + +const SIMULATION_REFRESH_SECS: u64 = 5; +const BUNDLE_SIZE: usize = 3; + +pub struct BundleBatch { + pub bundles: Vec, + pub simulation_slot: Slot, +} + +fn main() { + env_logger::init(); + + println!("starting load test..."); + + let args = Args::parse(); + assert!(args.test_duration_secs >= SIMULATION_REFRESH_SECS); + + let stats = Arc::new(Stats { + total_rpc_errs: Arc::new(AtomicU64::new(0)), + total_sim_errs: Arc::new(AtomicU64::new(0)), + total_sim_success: Arc::new(AtomicU64::new(0)), + }); + let simulation_refresh_interval = Duration::from_secs(SIMULATION_REFRESH_SECS); + let exit = Arc::new(AtomicBool::new(false)); + + // get the current finalized slots of each node and make sure they're not too far off + const TOLERABLE_SLOT_DIFF: i64 = 3; + let baseline_rpc_client = RpcClient::new(args.baseline_rpc_url.clone()); + let simulation_rpc_client = RpcClient::new(args.simulation_rpc_url.clone()); + let (baseline_node_slot, simulation_node_slot) = fetch_and_assert_slot_diff( + &baseline_rpc_client, + &simulation_rpc_client, + Some(TOLERABLE_SLOT_DIFF), + ); + println!( + "[baseline_node_slot: {}, simulation_node_slot: {}, diff: {}]", + baseline_node_slot, + simulation_node_slot, + abs_sub(baseline_node_slot, simulation_node_slot) + ); + + let t_hdls = vec![ + spawn_slots_subscribe_thread( + args.simulation_ws_url, + "simulation-node".into(), + exit.clone(), + ), + spawn_slots_subscribe_thread(args.baseline_ws_url, "baseline-node".into(), exit.clone()), + ]; + + let rpc_client = RpcClient::new(args.baseline_rpc_url.clone()); + let (transactions, simulation_slot) = + fetch_n_highest_cost_transactions(&rpc_client, BUNDLE_SIZE); + + let bundle = VersionedBundle { transactions }; + let bundles = (0..args.bundle_batch_size) + .map(|_| bundle.clone()) + .collect::>(); + drop(bundle); + + // This object is read-locked by all Simulator threads and write-locked by `spawn_highest_cost_bundle_scraper` + // periodically to update. + let bundle_batch = BundleBatch { + bundles, + simulation_slot, + }; + let bundle_batch = Arc::new(RwLock::new(bundle_batch)); + + spawn_highest_cost_bundle_scraper( + bundle_batch.clone(), + rpc_client, + simulation_refresh_interval, + args.bundle_batch_size, + BUNDLE_SIZE, + ); + + let simulators: Vec> = (0..args.n_rpc_connections) + .map(|_| { + let stats = stats.clone(); + let rpc_client = RpcClient::new(args.simulation_rpc_url.clone()); + Arc::new(Simulator::new( + rpc_client, + stats, + args.n_threads, + exit.clone(), + )) + }) + .collect(); + for s in &simulators { + let s = s.clone(); + let bundle_batch = bundle_batch.clone(); + thread::spawn(move || { + s.start(bundle_batch); + }); + } + + sleep(Duration::from_secs(args.test_duration_secs)); + exit.store(true, Ordering::Relaxed); + + for t in t_hdls { + info!("joining..."); + t.join().unwrap(); + } + + { + let t0 = stats.total_sim_success.load(Ordering::Acquire) as f64; + let t1 = stats.total_sim_errs.load(Ordering::Acquire) as f64; + let actual_rps = (t0 + t1) / args.test_duration_secs as f64; + println!( + "[successful simulations: {}, total_sim_errs: {}, total_rpc_errs: {}, actual_rps: {}]", + stats.total_sim_success.load(Ordering::Acquire), + stats.total_sim_errs.load(Ordering::Acquire), + stats.total_rpc_errs.load(Ordering::Acquire), + actual_rps, + ); + + let (baseline_node_slot, simulation_node_slot) = + fetch_and_assert_slot_diff(&baseline_rpc_client, &simulation_rpc_client, None); + println!( + "[baseline_node_slot: {}, simulation_node_slot: {}, diff: {}]", + baseline_node_slot, + simulation_node_slot, + abs_sub(baseline_node_slot, simulation_node_slot) + ); + } + + println!("finished load test..."); +} + +fn spawn_highest_cost_bundle_scraper( + bundle_batch: Arc>, + rpc_client: RpcClient, + refresh: Duration, + batch_size: usize, + bundle_size: usize, +) -> JoinHandle<()> { + Builder::new() + .name("highest-cost-tx-scraper".into()) + .spawn(move || loop { + let (transactions, simulation_slot) = + fetch_n_highest_cost_transactions(&rpc_client, bundle_size); + + let bundle = VersionedBundle { transactions }; + let bundles = (0..batch_size) + .map(|_| bundle.clone()) + .collect::>(); + drop(bundle); + + let mut w_bundle_batch = bundle_batch.write().unwrap(); + *w_bundle_batch = BundleBatch { + bundles, + simulation_slot, + }; + drop(w_bundle_batch); + + sleep(refresh); + }) + .unwrap() +} + +fn spawn_slots_subscribe_thread( + pubsub_addr: String, + node_name: String, + exit: Arc, +) -> JoinHandle<()> { + let mut slots_sub = PubsubClient::slot_subscribe(&*pubsub_addr).unwrap(); + thread::spawn(move || loop { + if exit.load(Ordering::Acquire) { + let _ = slots_sub.0.shutdown(); + break; + } + + match slots_sub.1.recv() { + Ok(slot_info) => info!("[RPC={} slot={:?}]", node_name, slot_info.slot), + Err(e) => { + error!("error receiving on slots_sub channel: {}", e); + slots_sub = PubsubClient::slot_subscribe(&*pubsub_addr).unwrap(); + } + } + }) +} + +/// Fetches the N highest cost transactions from the last confirmed block and returns said block's parent slot +fn fetch_n_highest_cost_transactions( + rpc_client: &RpcClient, + n: usize, +) -> (Vec, Slot) { + let slot = rpc_client + .get_slot_with_commitment(CommitmentConfig::confirmed()) + .unwrap(); + info!("fetched slot {}", slot); + + let config = RpcBlockConfig { + encoding: Some(UiTransactionEncoding::Base64), + transaction_details: Some(TransactionDetails::Full), + rewards: None, + commitment: Some(CommitmentConfig { + commitment: CommitmentLevel::Confirmed, + }), + max_supported_transaction_version: None, + }; + let block = rpc_client + .get_block_with_config(slot, config) + .expect(&*format!("failed to fetch block at slot: {}", slot)); + + let parent_slot = block.parent_slot; + ( + n_highest_cost_transactions_from_block(block, &CostModel::default(), n), + parent_slot, + ) +} + +#[derive(Eq)] +struct TransactionCost { + transaction: VersionedTransaction, + cost: u64, +} + +impl PartialEq for TransactionCost { + fn eq(&self, other: &Self) -> bool { + self.cost == other.cost + } +} + +impl PartialOrd for TransactionCost { + fn partial_cmp(&self, other: &Self) -> Option { + self.cost.partial_cmp(&other.cost) + } +} + +impl Ord for TransactionCost { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.cost.cmp(&other.cost) + } +} + +/// Returns the N highest cost transactions from a given block +fn n_highest_cost_transactions_from_block( + block: UiConfirmedBlock, + cost_model: &CostModel, + n: usize, +) -> Vec { + let txs: Vec = block + .transactions + .unwrap() + .into_iter() + .filter(|encoded_tx| encoded_tx.meta.as_ref().unwrap().err.is_none()) + .filter_map(|encoded_tx| encoded_tx.transaction.decode()) + .collect(); + let mut max_costs: BinaryHeap> = BinaryHeap::with_capacity(n); + + for tx in txs { + if let Ok(sanitized_tx) = SanitizedTransaction::try_create( + tx.clone(), + tx.message.hash(), + None, + MockAddressLoader {}, + false, + ) { + let cost = cost_model.calculate_cost(&sanitized_tx).sum(); + if let Some(min_cost) = max_costs.peek() { + if cost > min_cost.0.cost { + if max_costs.len() == n { + let _ = max_costs.pop(); + } + max_costs.push(Reverse(TransactionCost { + cost, + transaction: tx.clone(), + })); + } + } else { + max_costs.push(Reverse(TransactionCost { + cost, + transaction: tx.clone(), + })); + } + } + } + + max_costs + .into_iter() + .map(|tx_cost| tx_cost.0.transaction) + .collect::>() +} + +fn fetch_and_assert_slot_diff( + rpc_client_0: &RpcClient, + rpc_client_1: &RpcClient, + tolerable_diff: Option, +) -> (i64, i64) { + let slot_0 = rpc_client_0 + .get_slot_with_commitment(CommitmentConfig { + commitment: CommitmentLevel::Finalized, + }) + .unwrap() as i64; + let slot_1 = rpc_client_1 + .get_slot_with_commitment(CommitmentConfig { + commitment: CommitmentLevel::Finalized, + }) + .unwrap() as i64; + + if let Some(tolerable_diff) = tolerable_diff { + let actual_diff = abs_sub(slot_0, slot_1); + assert!( + actual_diff < tolerable_diff, + "{}", + format!( + "actual_diff: {}, tolerable_diff: {}", + actual_diff, tolerable_diff + ) + ); + } + + (slot_0, slot_1) +} + +#[derive(Clone)] +struct MockAddressLoader; + +impl AddressLoader for MockAddressLoader { + fn load_addresses( + self, + _lookups: &[MessageAddressTableLookup], + ) -> Result { + Ok(LoadedAddresses::default()) + } +} diff --git a/bench-batch-simulate-bundle/src/simulator.rs b/bench-batch-simulate-bundle/src/simulator.rs new file mode 100644 index 0000000000..e8d844ba58 --- /dev/null +++ b/bench-batch-simulate-bundle/src/simulator.rs @@ -0,0 +1,149 @@ +use { + crate::{BundleBatch, Slot}, + log::*, + rayon::{ThreadPool, ThreadPoolBuilder}, + solana_client::{ + rpc_client::RpcClient, + rpc_config::{RpcSimulateBundleConfig, SimulationSlotConfig}, + rpc_response::RpcBundleSimulationSummary, + }, + solana_sdk::bundle::VersionedBundle, + std::{ + sync::{ + atomic::{AtomicBool, AtomicU64, Ordering}, + Arc, RwLock, + }, + thread::sleep, + time::Duration, + }, +}; + +pub struct Simulator { + t_pool: ThreadPool, + /// shared tcp socket amongst the thread pool + rpc_client: Arc, + stats: Arc, + exit: Arc, +} + +pub struct Stats { + pub total_rpc_errs: Arc, + pub total_sim_errs: Arc, + pub total_sim_success: Arc, +} + +impl Simulator { + pub fn new( + rpc_client: RpcClient, + stats: Arc, + n_threads: usize, + exit: Arc, + ) -> Self { + let t_pool = ThreadPoolBuilder::new() + .num_threads(n_threads) + .build() + .unwrap(); + let rpc_client = Arc::new(rpc_client); + + Self { + t_pool, + rpc_client, + stats, + exit, + } + } + + pub fn start(&self, bundle_batch: Arc>) { + info!("starting bundle batch simulator..."); + + loop { + if self.exit.load(Ordering::Relaxed) { + info!("simulator exiting..."); + break; + } + + let (bundles, simulation_slot) = { + let r_bundle_batch = bundle_batch.read().unwrap(); + ( + r_bundle_batch.bundles.clone(), + r_bundle_batch.simulation_slot, + ) + }; + let rpc_client = self.rpc_client.clone(); + let stats = self.stats.clone(); + + self.t_pool.spawn(move || { + // TODO: is this slow? + if let Some((n_succeeded, n_failed)) = + Self::do_simulate(bundles, simulation_slot, &rpc_client) + { + stats + .total_sim_success + .fetch_add(n_succeeded, Ordering::Relaxed); + stats.total_sim_errs.fetch_add(n_failed, Ordering::Relaxed); + info!( + "succeeded={}, failed={}, simulation_slot={}", + n_succeeded, n_failed, simulation_slot + ); + } else { + stats.total_rpc_errs.fetch_add(1, Ordering::Relaxed); + } + }); + + sleep(Duration::from_millis(10)); + } + } + + /// returns (num_succeeded, num_failed) simulations + fn do_simulate( + bundles: Vec, + simulation_slot: Slot, + rpc_client: &Arc, + ) -> Option<(u64, u64)> { + let configs = bundles + .iter() + .map(|b| RpcSimulateBundleConfig { + // TODO: Let's set some accounts data for more realistic performance metrics. + pre_execution_accounts_configs: vec![None; b.transactions.len()], + post_execution_accounts_configs: vec![None; b.transactions.len()], + replace_recent_blockhash: true, + simulation_bank: Some(SimulationSlotConfig::Slot(simulation_slot)), + skip_sig_verify: true, + transaction_encoding: None, + }) + .collect::>(); + + match rpc_client + .batch_simulate_bundle_with_config(bundles.into_iter().zip(configs).collect()) + { + Ok(response) => { + let mut n_succeeded: u64 = 0; + let mut n_failed: u64 = 0; + + for result in response { + match result.result.value.summary { + RpcBundleSimulationSummary::Failed { + error, + tx_signature, + } => { + error!( + "bundle simulation failed [error={:?}, tx_signature={}]", + error, tx_signature + ); + n_failed = n_failed.checked_add(1).unwrap(); + } + RpcBundleSimulationSummary::Succeeded => { + n_succeeded = n_succeeded.checked_add(1).unwrap() + } + } + } + + Some((n_succeeded, n_failed)) + } + Err(e) => { + error!("error from rpc {}", e); + None + } + } + } +} diff --git a/bench-get-confirmed-blocks-with-data/Cargo.toml b/bench-get-confirmed-blocks-with-data/Cargo.toml new file mode 100644 index 0000000000..375863f7e8 --- /dev/null +++ b/bench-get-confirmed-blocks-with-data/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "bench-get-confirmed-blocks-with-data" +version = "1.13.6" +edition = "2021" + +[dependencies] +env_logger = "0.9.0" +log = "0.4.17" +solana-sdk = { path = "../sdk", version = "=1.13.6" } +solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.13.6" } +solana-transaction-status = { path = "../transaction-status", version = "=1.13.6" } +tokio = { version = "1", features = ["full"] } diff --git a/bench-get-confirmed-blocks-with-data/src/main.rs b/bench-get-confirmed-blocks-with-data/src/main.rs new file mode 100644 index 0000000000..5361ab667c --- /dev/null +++ b/bench-get-confirmed-blocks-with-data/src/main.rs @@ -0,0 +1,120 @@ +use { + log::info, + solana_sdk::clock::Slot, + solana_transaction_status::ConfirmedBlock, + std::{ + sync::{Arc, Mutex}, + thread::{self, sleep}, + time::{Duration, Instant}, + }, + tokio::task::JoinHandle, +}; + +fn main() { + env_logger::init(); + + let num_blocks_to_fetch: Vec = vec![10]; + let num_tasks = 128; + let lowest_slot: Slot = 1_000_000; + let highest_slot: Slot = 135_000_000; + let task_unit = (highest_slot.checked_sub(lowest_slot).unwrap()) + .checked_div(num_tasks) + .unwrap(); + let test_duration_s = 4_u64.checked_mul(60).unwrap().checked_mul(60).unwrap(); + + let log_duration = Duration::from_secs(1); + + let test_duration = Duration::from_secs(test_duration_s); + + for chunk_size in num_blocks_to_fetch { + info!( + "Benchmarking performance of get_confirmed_blocks_with_data for {:?} blocks", + chunk_size + ); + + let total_blocks_read = Arc::new(Mutex::new(0_usize)); + + let thread = { + let total_blocks_read = total_blocks_read.clone(); + thread::spawn(move || { + let test_start = Instant::now(); + + let mut last_update_time = Instant::now(); + let mut last_update_count = 0; + + while test_start.elapsed() < test_duration { + let elapsed = last_update_time.elapsed(); + if elapsed > log_duration { + let total_blocks_read = *total_blocks_read.lock().unwrap(); + let blocks_received = + total_blocks_read.checked_sub(last_update_count).unwrap(); + let recent_block_rate = blocks_received as f64 / elapsed.as_secs_f64(); + let total_block_rate = + total_blocks_read as f64 / test_start.elapsed().as_secs_f64(); + info!( + "tasks: {}, chunk_size: {}, recent_block_rate: {:.2}, total_blocks_read: {}, total_elapsed: {:.2}, total blocks/s: {:.2}", + num_tasks, + chunk_size, + recent_block_rate, + total_blocks_read, + test_start.elapsed().as_secs_f64(), + total_block_rate + ); + + last_update_time = Instant::now(); + last_update_count = total_blocks_read; + } + + sleep(Duration::from_millis(100)); + } + }) + }; + + let runtime = tokio::runtime::Runtime::new().unwrap(); + runtime.block_on(async { + let tasks: Vec> = (0..num_tasks) + .map(|i| { + let total_blocks_read = total_blocks_read.clone(); + runtime.spawn(async move { + let bigtable = + solana_storage_bigtable::LedgerStorage::new(true, None, None) + .await + .expect("connected to bigtable"); + + let start = Instant::now(); + let mut starting_slot = (task_unit.checked_mul(i).unwrap()) + .checked_add(lowest_slot) + .unwrap(); + let stopping_slot = starting_slot.checked_add(task_unit).unwrap(); + + while start.elapsed() < test_duration { + let slot_requests: Vec<_> = (starting_slot + ..starting_slot.checked_add(chunk_size).unwrap_or(u64::MAX)) + .collect(); + let slots_blocks: Vec<(Slot, ConfirmedBlock)> = bigtable + .get_confirmed_blocks_with_data(slot_requests.as_slice()) + .await + .expect("got blocks") + .collect(); + starting_slot = slots_blocks.last().unwrap().0; + { + let mut total_blocks_read = total_blocks_read.lock().unwrap(); + *total_blocks_read = + total_blocks_read.checked_add(slots_blocks.len()).unwrap(); + } + if starting_slot >= stopping_slot { + info!("work here is done!!"); + break; + } + } + }) + }) + .collect(); + for t in tasks { + t.await.expect("results fetched"); + } + }); + + thread.join().unwrap(); + } +} diff --git a/bootstrap b/bootstrap new file mode 100755 index 0000000000..b01bc6734f --- /dev/null +++ b/bootstrap @@ -0,0 +1,21 @@ +#!/usr/bin/env sh +bank_hash=$(./target/release/solana-ledger-tool -l config/bootstrap-validator bank-hash) + +# NOTE: make sure tip-payment and tip-distribution program are deployed using the correct pubkeys +RUST_LOG=INFO,solana_core::bundle_stage=DEBUG \ + NDEBUG=1 ./multinode-demo/bootstrap-validator.sh \ + --wait-for-supermajority 0 \ + --expected-bank-hash $bank_hash \ + --block-engine-address http://127.0.0.1:1003 \ + --block-engine-auth-service-address http://127.0.0.1:1005 \ + --relayer-auth-service-address http://127.0.0.1:11226 \ + --relayer-address http://127.0.0.1:11226 \ + --rpc-pubsub-enable-block-subscription \ + --enable-rpc-transaction-history \ + --tip-payment-program-pubkey 6veFRUKJBNGMR58LEcKn5Bc6MR17WZF4rsgD4Lqq7fsU \ + --tip-distribution-program-pubkey 3PX9z1qPj37eNZqH7e5fyaVDyG7ARqkjkYEe1a4xsBkA \ + --commission-bps 0 \ + --shred-receiver-address 127.0.0.1:1002 \ + --allow-private-addr \ + --trust-relayer-packets \ + --trust-block-engine-packets diff --git a/ci/buildkite-pipeline-in-disk.sh b/ci/buildkite-pipeline-in-disk.sh index 4d0832ef24..a4a3d99dad 100644 --- a/ci/buildkite-pipeline-in-disk.sh +++ b/ci/buildkite-pipeline-in-disk.sh @@ -185,7 +185,7 @@ all_test_steps() { - "queue=default" EOF else - annotate --style info \ + annotate --style info --context test-stable-bpf \ "Stable-BPF skipped as no relevant files were modified" fi @@ -203,16 +203,18 @@ EOF ^programs/ \ ^sdk/ \ ; then - cat >> "$output_file" <<"EOF" - - command: "ci/test-stable-perf.sh" - name: "stable-perf" - timeout_in_minutes: 20 - artifact_paths: "log-*.txt" - agents: - - "queue=cuda" -EOF + annotate --style warning --context test-stable-perf \ + "test-stable-perf is currently disabled because it requires GPUs (LB)" +#cat >> "$output_file" <<"EOF" +# - command: "ci/test-stable-perf.sh" +# name: "stable-perf" +# timeout_in_minutes: 20 +# artifact_paths: "log-*.txt" +# agents: +# queue: "cuda" +#EOF else - annotate --style info \ + annotate --style info --context test-stable-perf \ "Stable-perf skipped as no relevant files were modified" fi @@ -237,7 +239,7 @@ EOF timeout_in_minutes: 30 EOF else - annotate --style info \ + annotate --style info --context test-downstream-projects \ "downstream-projects skipped as no relevant files were modified" fi @@ -247,9 +249,11 @@ EOF ^ci/test-stable.sh \ ^sdk/ \ ; then - command_step wasm ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-wasm.sh" 20 + annotate --style warning --context test-wasm \ + "test-wasm is currently disabled because it times out (LB)" +# command_step wasm ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-wasm.sh" 20 else - annotate --style info \ + annotate --style info --context test-wasm \ "wasm skipped as no relevant files were modified" fi @@ -308,7 +312,7 @@ if [[ -n $BUILDKITE_TAG ]]; then "https://github.com/solana-labs/solana/releases/$BUILDKITE_TAG" # Jump directly to the secondary build to publish release artifacts quickly - trigger_secondary_step +# trigger_secondary_step exit 0 fi @@ -336,5 +340,5 @@ fi start_pipeline "Push pipeline for ${BUILDKITE_BRANCH:-?unknown branch?}" pull_or_push_steps wait_step -trigger_secondary_step +#trigger_secondary_step exit 0 diff --git a/ci/buildkite-pipeline.sh b/ci/buildkite-pipeline.sh index cfc24d2528..7f59a691a6 100755 --- a/ci/buildkite-pipeline.sh +++ b/ci/buildkite-pipeline.sh @@ -190,7 +190,7 @@ all_test_steps() { - "queue=solana" EOF else - annotate --style info \ + annotate --style info --context test-stable-bpf \ "Stable-BPF skipped as no relevant files were modified" fi @@ -208,17 +208,19 @@ EOF ^programs/ \ ^sdk/ \ ; then - cat >> "$output_file" <<"EOF" - - command: "ci/test-stable-perf.sh" - name: "stable-perf" - timeout_in_minutes: 20 - artifact_paths: "log-*.txt" - agents: - - "queue=cuda" -EOF + annotate --style warning --context test-stable-perf \ + "Stable perf skipped because CI doesn't have GPUs (LB)" +# cat >> "$output_file" <<"EOF" +# - command: "ci/test-stable-perf.sh" +# name: "stable-perf" +# timeout_in_minutes: 20 +# artifact_paths: "log-*.txt" +# agents: +# - "queue=cuda" +#EOF else - annotate --style info \ - "Stable-perf skipped as no relevant files were modified" + annotate --style info --context test-stable-perf \ + "Stable perf skipped as no relevant files were modified" fi # Wasm support @@ -227,9 +229,11 @@ EOF ^ci/test-stable.sh \ ^sdk/ \ ; then - command_step wasm ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-wasm.sh" 20 + annotate --style warning --context test-wasm \ + "test-wasm is currently disabled because it times out (LB)" +# command_step wasm ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-wasm.sh" 20 else - annotate --style info \ + annotate --style info --context test-wasm \ "wasm skipped as no relevant files were modified" fi @@ -292,7 +296,7 @@ if [[ -n $BUILDKITE_TAG ]]; then "https://github.com/solana-labs/solana/releases/$BUILDKITE_TAG" # Jump directly to the secondary build to publish release artifacts quickly - trigger_secondary_step +# trigger_secondary_step exit 0 fi @@ -320,5 +324,5 @@ fi start_pipeline "Push pipeline for ${BUILDKITE_BRANCH:-?unknown branch?}" pull_or_push_steps wait_step -trigger_secondary_step +#trigger_secondary_step exit 0 diff --git a/ci/buildkite-solana-private.sh b/ci/buildkite-solana-private.sh index 797f40ac0b..7d4110ed6a 100644 --- a/ci/buildkite-solana-private.sh +++ b/ci/buildkite-solana-private.sh @@ -185,8 +185,8 @@ all_test_steps() { - "queue=sol-private" EOF else - annotate --style info \ - "Stable-BPF skipped as no relevant files were modified" + annotate --style info --context test-stable-bpf \ + "Stable-SBF skipped as no relevant files were modified" fi # Perf test suite @@ -203,16 +203,18 @@ EOF ^programs/ \ ^sdk/ \ ; then - cat >> "$output_file" <<"EOF" - - command: "ci/test-stable-perf.sh" - name: "stable-perf" - timeout_in_minutes: 35 - artifact_paths: "log-*.txt" - agents: - - "queue=sol-private" -EOF + annotate --style warning --context test-stable-perf \ + "test-stable-perf is currently disabled because it requires GPUs (LB)" +# cat >> "$output_file" <<"EOF" +# - command: "ci/test-stable-perf.sh" +# name: "stable-perf" +# timeout_in_minutes: 35 +# artifact_paths: "log-*.txt" +# agents: +# - "queue=sol-private" +#EOF else - annotate --style info \ + annotate --style info --context test-stable-perf \ "Stable-perf skipped as no relevant files were modified" fi @@ -239,7 +241,7 @@ EOF - "queue=sol-private" EOF else - annotate --style info \ + annotate --style info --context test-downstream-projects \ "downstream-projects skipped as no relevant files were modified" fi @@ -249,9 +251,11 @@ EOF ^ci/test-stable.sh \ ^sdk/ \ ; then - command_step wasm ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-wasm.sh" 20 + annotate --style warning --context test-wasm \ + "test-wasm is currently disabled because it times out (LB)" +# command_step wasm ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-wasm.sh" 20 else - annotate --style info \ + annotate --style info --context test-wasm \ "wasm skipped as no relevant files were modified" fi diff --git a/ci/docker-rust/Dockerfile b/ci/docker-rust/Dockerfile index 7238a1615a..6ab67b8d79 100644 --- a/ci/docker-rust/Dockerfile +++ b/ci/docker-rust/Dockerfile @@ -39,6 +39,7 @@ RUN set -x \ && cargo install mdbook-linkcheck \ && cargo install svgbob_cli \ && cargo install wasm-pack \ + && cargo install sccache \ && rustc --version \ && cargo --version \ && curl -OL https://github.com/google/protobuf/releases/download/v$PROTOC_VERSION/$PROTOC_ZIP \ diff --git a/cli-output/Cargo.toml b/cli-output/Cargo.toml index a14931ef36..d50a1c37b3 100644 --- a/cli-output/Cargo.toml +++ b/cli-output/Cargo.toml @@ -22,8 +22,8 @@ serde = "1.0.136" serde_json = "1.0.79" solana-account-decoder = { path = "../account-decoder", version = "=1.13.6" } solana-clap-utils = { path = "../clap-utils", version = "=1.13.6" } -solana-client = { path = "../client", version = "=1.13.6" } solana-cli-config = { path = "../cli-config", version = "=1.13.6" } +solana-client = { path = "../client", version = "=1.13.6" } solana-sdk = { path = "../sdk", version = "=1.13.6" } solana-transaction-status = { path = "../transaction-status", version = "=1.13.6" } solana-vote-program = { path = "../programs/vote", version = "=1.13.6" } diff --git a/client/src/http_sender.rs b/client/src/http_sender.rs index 84e1418d7a..c05e2673e1 100644 --- a/client/src/http_sender.rs +++ b/client/src/http_sender.rs @@ -70,6 +70,102 @@ impl HttpSender { stats: RwLock::new(RpcTransportStats::default()), } } + + fn check_response(response: &serde_json::Value) -> Result<()> { + if response["error"].is_object() { + return match serde_json::from_value::(response["error"].clone()) { + Ok(rpc_error_object) => { + let data = match rpc_error_object.code { + rpc_custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE => { + match serde_json::from_value::(response["error"]["data"].clone()) { + Ok(data) => RpcResponseErrorData::SendTransactionPreflightFailure(data), + Err(err) => { + debug!("Failed to deserialize RpcSimulateTransactionResult: {:?}", err); + RpcResponseErrorData::Empty + } + } + }, + rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY => { + match serde_json::from_value::(response["error"]["data"].clone()) { + Ok(rpc_custom_error::NodeUnhealthyErrorData {num_slots_behind}) => RpcResponseErrorData::NodeUnhealthy {num_slots_behind}, + Err(_err) => { + RpcResponseErrorData::Empty + } + } + }, + _ => RpcResponseErrorData::Empty + }; + Err(RpcError::RpcResponseError { + request_id: response["id"].as_u64().unwrap(), + code: rpc_error_object.code, + message: rpc_error_object.message, + data, + } + .into()) + } + Err(err) => Err(RpcError::RpcRequestError(format!( + "Failed to deserialize RPC error response: {} [{}]", + serde_json::to_string(&response["error"]).unwrap(), + err + )) + .into()), + }; + } + + Ok(()) + } + + async fn do_send_with_retry( + &self, + request: serde_json::Value, + ) -> reqwest::Result { + let mut stats_updater = StatsUpdater::new(&self.stats); + let mut too_many_requests_retries = 5; + loop { + let response = { + let client = self.client.clone(); + let request = request.to_string(); + client + .post(&self.url) + .header(CONTENT_TYPE, "application/json") + .body(request) + .send() + .await + }?; + + if !response.status().is_success() { + if response.status() == StatusCode::TOO_MANY_REQUESTS + && too_many_requests_retries > 0 + { + let mut duration = Duration::from_millis(500); + if let Some(retry_after) = response.headers().get(RETRY_AFTER) { + if let Ok(retry_after) = retry_after.to_str() { + if let Ok(retry_after) = retry_after.parse::() { + if retry_after < 120 { + duration = Duration::from_secs(retry_after); + } + } + } + } + + too_many_requests_retries -= 1; + debug!( + "Too many requests: server responded with {:?}, {} retries left, pausing for {:?}", + response, too_many_requests_retries, duration + ); + + sleep(duration).await; + stats_updater.add_rate_limited_time(duration); + + continue; + } + + return Err(response.error_for_status().unwrap_err()); + } + + return response.json::().await; + } + } } #[derive(Deserialize, Debug)] @@ -109,103 +205,38 @@ impl<'a> Drop for StatsUpdater<'a> { #[async_trait] impl RpcSender for HttpSender { - fn get_transport_stats(&self) -> RpcTransportStats { - self.stats.read().unwrap().clone() - } - async fn send( &self, request: RpcRequest, params: serde_json::Value, ) -> Result { - let mut stats_updater = StatsUpdater::new(&self.stats); - let request_id = self.request_id.fetch_add(1, Ordering::Relaxed); - let request_json = request.build_request_json(request_id, params).to_string(); + let request = request.build_request_json(request_id, params); + let mut resp = self.do_send_with_retry(request).await?; + Self::check_response(&resp)?; - let mut too_many_requests_retries = 5; - loop { - let response = { - let client = self.client.clone(); - let request_json = request_json.clone(); - client - .post(&self.url) - .header(CONTENT_TYPE, "application/json") - .body(request_json) - .send() - .await - }?; + Ok(resp["result"].take()) + } - if !response.status().is_success() { - if response.status() == StatusCode::TOO_MANY_REQUESTS - && too_many_requests_retries > 0 - { - let mut duration = Duration::from_millis(500); - if let Some(retry_after) = response.headers().get(RETRY_AFTER) { - if let Ok(retry_after) = retry_after.to_str() { - if let Ok(retry_after) = retry_after.parse::() { - if retry_after < 120 { - duration = Duration::from_secs(retry_after); - } - } - } - } + async fn send_batch( + &self, + requests_and_params: Vec<(RpcRequest, serde_json::Value)>, + ) -> Result { + let mut batch_request = vec![]; + for (rpc_req, params) in requests_and_params { + let request_id = self.request_id.fetch_add(1, Ordering::Relaxed); + batch_request.push(rpc_req.build_request_json(request_id, params)); + } - too_many_requests_retries -= 1; - debug!( - "Too many requests: server responded with {:?}, {} retries left, pausing for {:?}", - response, too_many_requests_retries, duration - ); + let resp = self + .do_send_with_retry(serde_json::Value::Array(batch_request)) + .await?; - sleep(duration).await; - stats_updater.add_rate_limited_time(duration); - continue; - } - return Err(response.error_for_status().unwrap_err().into()); - } + Ok(resp) + } - let mut json = response.json::().await?; - if json["error"].is_object() { - return match serde_json::from_value::(json["error"].clone()) { - Ok(rpc_error_object) => { - let data = match rpc_error_object.code { - rpc_custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE => { - match serde_json::from_value::(json["error"]["data"].clone()) { - Ok(data) => RpcResponseErrorData::SendTransactionPreflightFailure(data), - Err(err) => { - debug!("Failed to deserialize RpcSimulateTransactionResult: {:?}", err); - RpcResponseErrorData::Empty - } - } - }, - rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY => { - match serde_json::from_value::(json["error"]["data"].clone()) { - Ok(rpc_custom_error::NodeUnhealthyErrorData {num_slots_behind}) => RpcResponseErrorData::NodeUnhealthy {num_slots_behind}, - Err(_err) => { - RpcResponseErrorData::Empty - } - } - }, - _ => RpcResponseErrorData::Empty - }; - - Err(RpcError::RpcResponseError { - code: rpc_error_object.code, - message: rpc_error_object.message, - data, - } - .into()) - } - Err(err) => Err(RpcError::RpcRequestError(format!( - "Failed to deserialize RPC error response: {} [{}]", - serde_json::to_string(&json["error"]).unwrap(), - err - )) - .into()), - }; - } - return Ok(json["result"].take()); - } + fn get_transport_stats(&self) -> RpcTransportStats { + self.stats.read().unwrap().clone() } fn url(&self) -> String { diff --git a/client/src/mock_sender.rs b/client/src/mock_sender.rs index a43ea736cd..3485fb3738 100644 --- a/client/src/mock_sender.rs +++ b/client/src/mock_sender.rs @@ -473,4 +473,11 @@ impl RpcSender for MockSender { fn url(&self) -> String { format!("MockSender: {}", self.url) } + + async fn send_batch( + &self, + _requests_and_params: Vec<(RpcRequest, serde_json::Value)>, + ) -> Result { + todo!() + } } diff --git a/client/src/nonblocking/rpc_client.rs b/client/src/nonblocking/rpc_client.rs index 2d300be0b7..1eca9669ac 100644 --- a/client/src/nonblocking/rpc_client.rs +++ b/client/src/nonblocking/rpc_client.rs @@ -33,6 +33,7 @@ use { }, solana_sdk::{ account::Account, + bundle::VersionedBundle, clock::{Epoch, Slot, UnixTimestamp, DEFAULT_MS_PER_SLOT, MAX_HASH_AGE_IN_SECONDS}, commitment_config::{CommitmentConfig, CommitmentLevel}, epoch_info::EpochInfo, @@ -42,7 +43,7 @@ use { message::Message, pubkey::Pubkey, signature::Signature, - transaction::{self, uses_durable_nonce, Transaction}, + transaction::{self, uses_durable_nonce, Transaction, VersionedTransaction}, }, solana_transaction_status::{ EncodedConfirmedBlock, EncodedConfirmedTransactionWithStatusMeta, TransactionStatus, @@ -943,6 +944,7 @@ impl RpcClient { code, message, data, + .. }) = &err.kind { debug!("{} {}", code, message); @@ -1388,6 +1390,111 @@ impl RpcClient { .await } + pub async fn batch_simulate_bundle( + &self, + bundles: Vec, + ) -> BatchRpcResult { + let configs = bundles + .iter() + .map(|b| RpcSimulateBundleConfig { + simulation_bank: Some(SimulationSlotConfig::Commitment(self.commitment())), + pre_execution_accounts_configs: vec![None; b.transactions.len()], + post_execution_accounts_configs: vec![None; b.transactions.len()], + ..RpcSimulateBundleConfig::default() + }) + .collect::>(); + + self.batch_simulate_bundle_with_config(bundles.into_iter().zip(configs).collect()) + .await + } + + pub async fn batch_simulate_bundle_with_config( + &self, + bundles_and_configs: Vec<(VersionedBundle, RpcSimulateBundleConfig)>, + ) -> BatchRpcResult { + let mut params = vec![]; + for (bundle, config) in bundles_and_configs { + let transaction_encoding = if let Some(encoding) = config.transaction_encoding { + encoding + } else { + self.default_cluster_transaction_encoding().await? + }; + + let simulation_bank = config.simulation_bank.unwrap_or_default(); + + let config = RpcSimulateBundleConfig { + transaction_encoding: Some(transaction_encoding), + simulation_bank: Some(simulation_bank), + ..config + }; + + let encoded_transactions = bundle + .transactions + .iter() + .map(|tx| serialize_and_encode::(tx, transaction_encoding)) + .collect::, ClientError>>()?; + let rpc_bundle_request = RpcBundleRequest { + encoded_transactions, + }; + + params.push(json!([rpc_bundle_request, config])); + } + + let requests_and_params = vec![RpcRequest::SimulateBundle; params.len()] + .into_iter() + .zip(params) + .collect(); + self.send_batch(requests_and_params).await + } + + pub async fn simulate_bundle( + &self, + bundle: &VersionedBundle, + ) -> RpcResult { + self.simulate_bundle_with_config( + bundle, + RpcSimulateBundleConfig { + simulation_bank: Some(SimulationSlotConfig::Commitment(self.commitment())), + ..RpcSimulateBundleConfig::default() + }, + ) + .await + } + + pub async fn simulate_bundle_with_config( + &self, + bundle: &VersionedBundle, + config: RpcSimulateBundleConfig, + ) -> RpcResult { + let transaction_encoding = if let Some(enc) = config.transaction_encoding { + enc + } else { + self.default_cluster_transaction_encoding().await? + }; + let simulation_bank = Some(config.simulation_bank.unwrap_or_default()); + + let encoded_transactions = bundle + .transactions + .iter() + .map(|tx| serialize_and_encode::(tx, transaction_encoding)) + .collect::>>()?; + let rpc_bundle_request = RpcBundleRequest { + encoded_transactions, + }; + + let config = RpcSimulateBundleConfig { + transaction_encoding: Some(transaction_encoding), + simulation_bank, + ..config + }; + + self.send( + RpcRequest::SimulateBundle, + json!([rpc_bundle_request, config]), + ) + .await + } + /// Returns the highest slot information that the node has snapshots for. /// /// This will find the highest full snapshot slot, and the highest incremental snapshot slot @@ -5340,6 +5447,21 @@ impl RpcClient { .map_err(|err| ClientError::new_with_request(err.into(), request)) } + pub async fn send_batch( + &self, + requests_and_params: Vec<(RpcRequest, Value)>, + ) -> ClientResult + where + T: serde::de::DeserializeOwned, + { + let response = self.sender.send_batch(requests_and_params).await?; + + serde_json::from_value(response).map_err(|err| ClientError { + request: None, + kind: err.into(), + }) + } + pub fn get_transport_stats(&self) -> RpcTransportStats { self.sender.get_transport_stats() } diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 564494aa80..510cf3e95d 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -27,6 +27,7 @@ use { }, solana_sdk::{ account::Account, + bundle::VersionedBundle, clock::{Epoch, Slot, UnixTimestamp}, commitment_config::CommitmentConfig, epoch_info::EpochInfo, @@ -1111,6 +1112,35 @@ impl RpcClient { ) } + pub fn batch_simulate_bundle( + &self, + bundles: Vec, + ) -> BatchRpcResult { + self.invoke(self.rpc_client.batch_simulate_bundle(bundles)) + } + + pub fn batch_simulate_bundle_with_config( + &self, + bundles_and_configs: Vec<(VersionedBundle, RpcSimulateBundleConfig)>, + ) -> BatchRpcResult { + self.invoke( + self.rpc_client + .batch_simulate_bundle_with_config(bundles_and_configs), + ) + } + + pub fn simulate_bundle(&self, bundle: &VersionedBundle) -> RpcResult { + self.invoke(self.rpc_client.simulate_bundle(bundle)) + } + + pub fn simulate_bundle_with_config( + &self, + bundle: &VersionedBundle, + config: RpcSimulateBundleConfig, + ) -> RpcResult { + self.invoke(self.rpc_client.simulate_bundle_with_config(bundle, config)) + } + /// Returns the highest slot information that the node has snapshots for. /// /// This will find the highest full snapshot slot, and the highest incremental snapshot slot diff --git a/client/src/rpc_config.rs b/client/src/rpc_config.rs index 4c21b8284e..5daf68fdb8 100644 --- a/client/src/rpc_config.rs +++ b/client/src/rpc_config.rs @@ -46,6 +46,51 @@ pub struct RpcSimulateTransactionConfig { pub min_context_slot: Option, } +#[derive(Serialize, Deserialize, Clone, Copy, Debug, Eq, PartialEq)] +#[serde(rename_all = "camelCase")] +pub enum SimulationSlotConfig { + Commitment(CommitmentConfig), + Slot(Slot), +} + +impl Default for SimulationSlotConfig { + fn default() -> Self { + Self::Commitment(CommitmentConfig { + commitment: CommitmentLevel::Confirmed, + }) + } +} + +#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RpcBundleRequest { + pub encoded_transactions: Vec, +} + +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RpcSimulateBundleConfig { + /// Gives the state of accounts pre/post transaction execution. + /// The length of each of these must be equal to the number transactions. + pub pre_execution_accounts_configs: Vec>, + pub post_execution_accounts_configs: Vec>, + + /// Specifies the encoding scheme of the contained transactions. + pub transaction_encoding: Option, + + /// Specifies the bank to run simulation against. + #[serde(flatten)] + pub simulation_bank: Option, + + /// Opt to skip sig-verify for faster performance. + #[serde(default)] + pub skip_sig_verify: bool, + + /// Replace recent blockhash to simulate old transactions without resigning. + #[serde(default)] + pub replace_recent_blockhash: bool, +} + #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RpcRequestAirdropConfig { diff --git a/client/src/rpc_request.rs b/client/src/rpc_request.rs index 03f4b39100..2009f409ee 100644 --- a/client/src/rpc_request.rs +++ b/client/src/rpc_request.rs @@ -110,6 +110,7 @@ pub enum RpcRequest { RequestAirdrop, SendTransaction, SimulateTransaction, + SimulateBundle, SignVote, } @@ -183,6 +184,7 @@ impl fmt::Display for RpcRequest { RpcRequest::RequestAirdrop => "requestAirdrop", RpcRequest::SendTransaction => "sendTransaction", RpcRequest::SimulateTransaction => "simulateTransaction", + RpcRequest::SimulateBundle => "simulateBundle", RpcRequest::SignVote => "signVote", }; @@ -247,6 +249,7 @@ pub enum RpcError { RpcRequestError(String), #[error("RPC response error {code}: {message} {data}")] RpcResponseError { + request_id: u64, code: i64, message: String, data: RpcResponseErrorData, diff --git a/client/src/rpc_response.rs b/client/src/rpc_response.rs index 75ea95abf7..a74317db2e 100644 --- a/client/src/rpc_response.rs +++ b/client/src/rpc_response.rs @@ -3,6 +3,7 @@ use { serde::{Deserialize, Deserializer, Serialize, Serializer}, solana_account_decoder::{parse_token::UiTokenAmount, UiAccount}, solana_sdk::{ + bundle::error::BundleExecutionError, clock::{Epoch, Slot, UnixTimestamp}, fee_calculator::{FeeCalculator, FeeRateGovernor}, hash::Hash, @@ -35,6 +36,7 @@ impl OptionalContext { } } +pub type BatchRpcResult = client_error::Result>>; pub type RpcResult = client_error::Result>; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -45,7 +47,16 @@ pub struct RpcResponseContext { pub api_version: Option, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BatchRpcResponseContext { + #[serde(skip_serializing_if = "Option::is_none")] + pub slot: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub api_version: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq)] pub struct RpcApiVersion(semver::Version); impl std::ops::Deref for RpcApiVersion { @@ -91,6 +102,12 @@ impl RpcResponseContext { } } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct BatchResponse { + pub id: u64, + pub result: Response, +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Response { pub context: RpcResponseContext, @@ -358,6 +375,24 @@ pub struct RpcIdentity { #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] +pub enum RpcBundleSimulationSummary { + /// error and offending transaction signature + Failed { + error: BundleExecutionError, + tx_signature: String, + }, + Succeeded, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct RpcSimulateBundleResult { + pub summary: RpcBundleSimulationSummary, + pub transaction_results: Vec, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] pub struct RpcVote { /// Vote account address, as base-58 encoded string pub vote_pubkey: String, @@ -410,7 +445,18 @@ pub struct RpcSignatureConfirmation { pub status: Result<()>, } -#[derive(Serialize, Deserialize, Clone, Debug)] +// TODO: consolidate with [RpcSimulateTransactionResult] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct RpcSimulateBundleTransactionResult { + pub err: Option, + pub logs: Option>, + pub pre_execution_accounts: Option>, + pub post_execution_accounts: Option>, + pub units_consumed: Option, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] #[serde(rename_all = "camelCase")] pub struct RpcSimulateTransactionResult { pub err: Option, diff --git a/client/src/rpc_sender.rs b/client/src/rpc_sender.rs index dded04dfc6..d76923af52 100644 --- a/client/src/rpc_sender.rs +++ b/client/src/rpc_sender.rs @@ -31,6 +31,10 @@ pub trait RpcSender { request: RpcRequest, params: serde_json::Value, ) -> Result; + async fn send_batch( + &self, + requests_and_params: Vec<(RpcRequest, serde_json::Value)>, + ) -> Result; fn get_transport_stats(&self) -> RpcTransportStats; fn url(&self) -> String; } diff --git a/core/Cargo.toml b/core/Cargo.toml index 9155c2b698..3faccd79dc 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -15,19 +15,30 @@ codecov = { repository = "solana-labs/solana", branch = "master", service = "git [dependencies] ahash = "0.7.6" +anchor-lang = { path = "../anchor/lang" } base64 = "0.13.0" bincode = "1.3.3" bs58 = "0.4.0" +bytes = "1.1.0" chrono = { version = "0.4.11", features = ["serde"] } +clap = { version = "3.1.15", features = ["derive"] } crossbeam-channel = "0.5" dashmap = { version = "4.0.2", features = ["rayon", "raw-api"] } etcd-client = { version = "0.8.1", features = ["tls"] } fs_extra = "1.2.0" +futures = "0.3" +futures-util = "0.3" histogram = "0.6.9" +indexmap = "1.8.1" itertools = "0.10.3" +jito-protos = { path = "../jito-protos", version = "=1.13.6" } +lazy_static = "1.4.0" log = "0.4.14" lru = "0.7.5" min-max-heap = "1.3.0" +num_enum = "0.5.7" +prost = "0.8.0" +prost-types = "0.8.0" rand = "0.7.0" rand_chacha = "0.2.2" rayon = "1.5.1" @@ -62,12 +73,17 @@ solana-vote-program = { path = "../programs/vote", version = "=1.13.6" } sys-info = "0.9.1" tempfile = "3.3.0" thiserror = "1.0" +tip-distribution = { path = "../jito-programs/tip-payment/programs/tip-distribution", features = ["no-entrypoint"] } +tip-payment = { path = "../jito-programs/tip-payment/programs/tip-payment", features = ["no-entrypoint"] } tokio = { version = "~1.14.1", features = ["full"] } +tokio-stream = "0.1.8" +tonic = { version = "0.5.2", features = ["tls"] } trees = "0.4.2" +uuid = { version = "1.0.0", features = ["v4", "fast-rng"] } [dev-dependencies] matches = "0.1.9" -raptorq = "1.6.5" +raptorq = "=1.6.5" reqwest = { version = "0.11.10", default-features = false, features = ["blocking", "brotli", "deflate", "gzip", "rustls-tls", "json"] } serde_json = "1.0.79" serial_test = "0.6.0" @@ -82,6 +98,7 @@ sysctl = "0.4.4" [build-dependencies] rustc_version = "0.4" +tonic-build = "0.5.2" [[bench]] name = "banking_stage" diff --git a/core/benches/banking_stage.rs b/core/benches/banking_stage.rs index 2cae8e606c..da3503ad45 100644 --- a/core/benches/banking_stage.rs +++ b/core/benches/banking_stage.rs @@ -11,6 +11,7 @@ use { solana_client::connection_cache::ConnectionCache, solana_core::{ banking_stage::{BankingStage, BankingStageStats}, + bundle_account_locker::BundleAccountLocker, leader_slot_banking_stage_metrics::LeaderSlotMetricsTracker, qos_service::QosService, unprocessed_packet_batches::*, @@ -38,6 +39,7 @@ use { }, solana_streamer::socket::SocketAddrSpace, std::{ + collections::HashSet, sync::{atomic::Ordering, Arc, RwLock}, time::{Duration, Instant}, }, @@ -48,8 +50,15 @@ fn check_txs(receiver: &Arc>, ref_tx_count: usize) { let mut total = 0; let now = Instant::now(); loop { - if let Ok((_bank, (entry, _tick_height))) = receiver.recv_timeout(Duration::new(1, 0)) { - total += entry.transactions.len(); + if let Ok(WorkingBankEntry { + bank: _, + entries_ticks, + }) = receiver.recv_timeout(Duration::new(1, 0)) + { + total += entries_ticks + .iter() + .map(|e| e.0.transactions.len()) + .sum::(); } if total >= ref_tx_count { break; @@ -98,6 +107,8 @@ fn bench_consume_buffered(bencher: &mut Bencher) { &recorder, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), &mut LeaderSlotMetricsTracker::new(0), + &HashSet::default(), + &BundleAccountLocker::default(), ); }); @@ -233,6 +244,8 @@ fn bench_banking(bencher: &mut Bencher, tx_type: TransactionType) { Arc::new(RwLock::new(CostModel::default())), Arc::new(ConnectionCache::default()), bank_forks, + HashSet::new(), + BundleAccountLocker::default(), ); poh_recorder.lock().unwrap().set_bank(&bank); diff --git a/core/benches/cluster_info.rs b/core/benches/cluster_info.rs index b1de0380f4..264fd20f72 100644 --- a/core/benches/cluster_info.rs +++ b/core/benches/cluster_info.rs @@ -78,6 +78,7 @@ fn broadcast_shreds_bench(bencher: &mut Bencher) { &cluster_info, &bank_forks, &SocketAddrSpace::Unspecified, + None, ) .unwrap(); }); diff --git a/core/benches/proto_to_packet.rs b/core/benches/proto_to_packet.rs new file mode 100644 index 0000000000..87f85f9c7f --- /dev/null +++ b/core/benches/proto_to_packet.rs @@ -0,0 +1,56 @@ +#![feature(test)] + +extern crate test; + +use { + jito_protos::proto::packet::{ + Meta as PbMeta, Packet as PbPacket, PacketBatch, PacketFlags as PbFlags, + }, + solana_core::proto_packet_to_packet, + solana_sdk::packet::{Packet, PACKET_DATA_SIZE}, + std::iter::repeat, + test::{black_box, Bencher}, +}; + +fn get_proto_packet(i: u8) -> PbPacket { + PbPacket { + data: repeat(i).take(PACKET_DATA_SIZE).collect(), + meta: Some(PbMeta { + size: PACKET_DATA_SIZE as u64, + addr: "255.255.255.255:65535".to_string(), + port: 65535, + flags: Some(PbFlags { + discard: false, + forwarded: false, + repair: false, + simple_vote_tx: false, + tracer_packet: false, + }), + sender_stake: 0, + }), + } +} + +#[bench] +fn bench_proto_to_packet(bencher: &mut Bencher) { + bencher.iter(|| { + black_box(proto_packet_to_packet(get_proto_packet(1))); + }); +} + +#[bench] +fn bench_batch_list_to_packets(bencher: &mut Bencher) { + let packet_batch = PacketBatch { + packets: (0..128).map(get_proto_packet).collect(), + }; + + bencher.iter(|| { + black_box( + packet_batch + .packets + .iter() + .map(|p| proto_packet_to_packet(p.clone())) + .collect::>(), + ); + }); +} diff --git a/core/benches/retransmit_stage.rs b/core/benches/retransmit_stage.rs index 5fbb66b225..5c24615df9 100644 --- a/core/benches/retransmit_stage.rs +++ b/core/benches/retransmit_stage.rs @@ -116,6 +116,7 @@ fn bench_retransmitter(bencher: &mut Bencher) { shreds_receiver, Arc::default(), // solana_rpc::max_slots::MaxSlots None, + None, ); let mut index = 0; diff --git a/core/src/backoff.rs b/core/src/backoff.rs new file mode 100644 index 0000000000..223b3d30ac --- /dev/null +++ b/core/src/backoff.rs @@ -0,0 +1,45 @@ +// BackoffStrategy currently implements a simple +// Fibonacci backoff strategy with hardcoded values. +// Currently the only use case is for retrying long lived +// connection loops in recv_verify_stage, as use cases +// expand more strategies will be added. + +use std::cmp::min; + +const INITIAL_LAST_WAIT: u64 = 0; +const INITIAL_CUR_WAIT: u64 = 100; +const MAX_WAIT: u64 = 1000; + +#[derive(Copy, Clone)] +pub struct BackoffStrategy { + // Wait times in ms + last_wait: u64, + cur_wait: u64, +} + +impl Default for BackoffStrategy { + fn default() -> Self { + Self::new() + } +} + +impl BackoffStrategy { + pub fn new() -> BackoffStrategy { + BackoffStrategy { + last_wait: INITIAL_LAST_WAIT, + cur_wait: INITIAL_CUR_WAIT, + } + } + + pub fn next_wait(&mut self) -> u64 { + let next_wait = min(self.cur_wait + self.last_wait, MAX_WAIT); + self.last_wait = self.cur_wait; + self.cur_wait = next_wait; + next_wait + } + + pub fn reset(&mut self) { + self.last_wait = INITIAL_LAST_WAIT; + self.cur_wait = INITIAL_CUR_WAIT; + } +} diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs index d4958a2532..e0d69fc6a4 100644 --- a/core/src/banking_stage.rs +++ b/core/src/banking_stage.rs @@ -4,6 +4,7 @@ use { crate::{ + bundle_account_locker::BundleAccountLocker, forward_packet_batches_by_accounts::ForwardPacketBatchesByAccounts, leader_slot_banking_stage_metrics::{LeaderSlotMetricsTracker, ProcessTransactionsSummary}, leader_slot_banking_stage_timing_metrics::{ @@ -409,6 +410,8 @@ impl BankingStage { cost_model: Arc>, connection_cache: Arc, bank_forks: Arc>, + blacklisted_accounts: HashSet, + bundle_account_locker: BundleAccountLocker, ) -> Self { Self::new_num_threads( cluster_info, @@ -422,6 +425,8 @@ impl BankingStage { cost_model, connection_cache, bank_forks, + blacklisted_accounts, + bundle_account_locker, ) } @@ -438,6 +443,8 @@ impl BankingStage { cost_model: Arc>, connection_cache: Arc, bank_forks: Arc>, + blacklisted_accounts: HashSet, + bundle_account_locker: BundleAccountLocker, ) -> Self { assert!(num_threads >= MIN_TOTAL_THREADS); // Single thread to generate entries from many banks. @@ -470,6 +477,9 @@ impl BankingStage { let data_budget = data_budget.clone(); let cost_model = cost_model.clone(); let connection_cache = connection_cache.clone(); + let blacklisted_accounts = blacklisted_accounts.clone(); + let bundle_account_locker = bundle_account_locker.clone(); + let bank_forks = bank_forks.clone(); Builder::new() .name(format!("solana-banking-stage-tx-{}", i)) @@ -488,6 +498,8 @@ impl BankingStage { cost_model, connection_cache, &bank_forks, + blacklisted_accounts, + bundle_account_locker, ); }) .unwrap() @@ -655,6 +667,8 @@ impl BankingStage { recorder: &TransactionRecorder, qos_service: &QosService, slot_metrics_tracker: &mut LeaderSlotMetricsTracker, + blacklisted_accounts: &HashSet, + bundle_account_locker: &BundleAccountLocker, ) { let mut rebuffered_packet_count = 0; let mut consumed_buffered_packets_count = 0; @@ -742,6 +756,8 @@ impl BankingStage { banking_stage_stats, qos_service, payload.slot_metrics_tracker, + blacklisted_accounts, + bundle_account_locker ) }, (), @@ -1025,6 +1041,8 @@ impl BankingStage { connection_cache: &ConnectionCache, tracer_packet_stats: &mut TracerPacketStats, bank_forks: &Arc>, + blacklisted_accounts: &HashSet, + bundle_account_locker: &BundleAccountLocker, ) { let (decision, make_decision_time) = Measure::this( |_| { @@ -1077,6 +1095,8 @@ impl BankingStage { recorder, qos_service, slot_metrics_tracker, + blacklisted_accounts, + bundle_account_locker, ) }, (), @@ -1238,6 +1258,8 @@ impl BankingStage { cost_model: Arc>, connection_cache: Arc, bank_forks: &Arc>, + blacklisted_accounts: HashSet, + bundle_account_locker: BundleAccountLocker, ) { let recorder = poh_recorder.lock().unwrap().recorder(); let socket = UdpSocket::bind("0.0.0.0:0").unwrap(); @@ -1273,6 +1295,8 @@ impl BankingStage { &connection_cache, &mut tracer_packet_stats, bank_forks, + &blacklisted_accounts, + &bundle_account_locker, ) }, (), @@ -1398,7 +1422,7 @@ impl BankingStage { // record and unlock will unlock all the successful transactions let (res, poh_record_time) = Measure::this( - |_| recorder.record(bank_slot, hash, processed_transactions), + |_| recorder.record(bank_slot, vec![(hash, processed_transactions)]), (), "hash", ); @@ -1454,7 +1478,7 @@ impl BankingStage { }; let pre_token_balances = if transaction_status_sender.is_some() { - collect_token_balances(bank, batch, &mut mint_decimals) + collect_token_balances(bank, batch, &mut mint_decimals, None) } else { vec![] }; @@ -1602,7 +1626,7 @@ impl BankingStage { let txs = batch.sanitized_transactions().to_vec(); let post_balances = bank.collect_balances(batch); let post_token_balances = - collect_token_balances(bank, batch, &mut mint_decimals); + collect_token_balances(bank, batch, &mut mint_decimals, None); transaction_status_sender.send_transaction_status_batch( bank.clone(), txs, @@ -1660,6 +1684,7 @@ impl BankingStage { transaction_status_sender: Option, gossip_vote_sender: &ReplayVoteSender, qos_service: &QosService, + bundle_account_locker: &BundleAccountLocker, ) -> ProcessTransactionBatchOutput { let mut cost_model_time = Measure::start("cost_model"); @@ -1682,7 +1707,18 @@ impl BankingStage { // Once accounts are locked, other threads cannot encode transactions that will modify the // same account state let mut lock_time = Measure::start("lock_time"); - let batch = bank.prepare_sanitized_batch_with_results(txs, transactions_qos_results.iter()); + + let batch = { + // BundleStage locks ALL accounts in ALL transactions in a bundle to avoid race + // conditions with BankingStage + let account_locks = bundle_account_locker.account_locks(); + bank.prepare_sanitized_batch_with_results( + txs, + transactions_qos_results.iter(), + &account_locks.read_locks(), + &account_locks.write_locks(), + ) + }; lock_time.stop(); // retryable_txs includes AccountInUse, WouldExceedMaxBlockCostLimit @@ -1851,6 +1887,7 @@ impl BankingStage { transaction_status_sender: Option, gossip_vote_sender: &ReplayVoteSender, qos_service: &QosService, + bundle_account_locker: &BundleAccountLocker, ) -> ProcessTransactionsSummary { let mut chunk_start = 0; let mut all_retryable_tx_indexes = vec![]; @@ -1882,6 +1919,7 @@ impl BankingStage { transaction_status_sender.clone(), gossip_vote_sender, qos_service, + bundle_account_locker, ); let ProcessTransactionBatchOutput { @@ -2061,6 +2099,8 @@ impl BankingStage { banking_stage_stats: &'a BankingStageStats, qos_service: &'a QosService, slot_metrics_tracker: &'a mut LeaderSlotMetricsTracker, + blacklisted_accounts: &HashSet, + bundle_account_locker: &BundleAccountLocker, ) -> ProcessTransactionsSummary { // Process transactions let (mut process_transactions_summary, process_transactions_time) = Measure::this( @@ -2073,6 +2113,7 @@ impl BankingStage { transaction_status_sender, gossip_vote_sender, qos_service, + bundle_account_locker, ) }, (), @@ -2350,7 +2391,7 @@ mod tests { super::*, crossbeam_channel::{unbounded, Receiver}, solana_address_lookup_table_program::state::{AddressLookupTable, LookupTableMeta}, - solana_entry::entry::{next_entry, next_versioned_entry, Entry, EntrySlice}, + solana_entry::entry::{next_entry, next_versioned_entry, EntrySlice}, solana_gossip::{cluster_info::Node, contact_info::ContactInfo}, solana_ledger::{ blockstore::{entries_to_test_shreds, Blockstore}, @@ -2436,6 +2477,8 @@ mod tests { let cluster_info = Arc::new(cluster_info); let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); + let banking_stage = BankingStage::new( &cluster_info, &poh_recorder, @@ -2447,6 +2490,8 @@ mod tests { Arc::new(RwLock::new(CostModel::default())), Arc::new(ConnectionCache::default()), bank_forks, + HashSet::default(), + bundle_locker, ); drop(verified_sender); drop(gossip_verified_vote_sender); @@ -2461,6 +2506,7 @@ mod tests { #[test] fn test_banking_stage_tick() { solana_logger::setup(); + let GenesisConfigInfo { mut genesis_config, .. } = create_genesis_config(2); @@ -2489,6 +2535,8 @@ mod tests { let (verified_gossip_vote_sender, verified_gossip_vote_receiver) = unbounded(); let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); + let banking_stage = BankingStage::new( &cluster_info, &poh_recorder, @@ -2500,6 +2548,8 @@ mod tests { Arc::new(RwLock::new(CostModel::default())), Arc::new(ConnectionCache::default()), bank_forks, + HashSet::default(), + bundle_locker, ); trace!("sending bank"); drop(verified_sender); @@ -2512,7 +2562,12 @@ mod tests { trace!("getting entries"); let entries: Vec<_> = entry_receiver .iter() - .map(|(_bank, (entry, _tick_height))| entry) + .flat_map( + |WorkingBankEntry { + bank: _, + entries_ticks, + }| entries_ticks.into_iter().map(|e| e.0), + ) .collect(); trace!("done"); assert_eq!(entries.len(), genesis_config.ticks_per_slot as usize); @@ -2567,6 +2622,7 @@ mod tests { let cluster_info = Arc::new(cluster_info); let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); let banking_stage = BankingStage::new( &cluster_info, &poh_recorder, @@ -2578,6 +2634,8 @@ mod tests { Arc::new(RwLock::new(CostModel::default())), Arc::new(ConnectionCache::default()), bank_forks, + HashSet::default(), + bundle_locker, ); // fund another account so we can send 2 good transactions in a single batch. @@ -2629,9 +2687,14 @@ mod tests { bank.process_transaction(&fund_tx).unwrap(); //receive entries + ticks loop { - let entries: Vec = entry_receiver + let entries: Vec<_> = entry_receiver .iter() - .map(|(_bank, (entry, _tick_height))| entry) + .flat_map( + |WorkingBankEntry { + bank: _, + entries_ticks, + }| entries_ticks.into_iter().map(|e| e.0), + ) .collect(); assert!(entries.verify(&blockhash)); @@ -2721,6 +2784,9 @@ mod tests { create_test_recorder(&bank, &blockstore, Some(poh_config), None); let cluster_info = new_test_cluster_info(Node::new_localhost().info); let cluster_info = Arc::new(cluster_info); + + let bundle_locker = BundleAccountLocker::default(); + let _banking_stage = BankingStage::new_num_threads( &cluster_info, &poh_recorder, @@ -2733,6 +2799,8 @@ mod tests { Arc::new(RwLock::new(CostModel::default())), Arc::new(ConnectionCache::default()), bank_forks, + HashSet::default(), + bundle_locker, ); // wait for banking_stage to eat the packets @@ -2751,7 +2819,12 @@ mod tests { // check that the balance is what we expect. let entries: Vec<_> = entry_receiver .iter() - .map(|(_bank, (entry, _tick_height))| entry) + .flat_map( + |WorkingBankEntry { + bank: _, + entries_ticks, + }| entries_ticks.into_iter().map(|e| e.0), + ) .collect(); let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config); @@ -2819,8 +2892,11 @@ mod tests { let mut results = vec![new_execution_result(Ok(())); 2]; let _ = BankingStage::record_transactions(bank.slot(), &txs, &results, &recorder); - let (_bank, (entry, _tick_height)) = entry_receiver.recv().unwrap(); - assert_eq!(entry.transactions.len(), txs.len()); + let WorkingBankEntry { + bank: _, + entries_ticks, + } = entry_receiver.recv().unwrap(); + assert_eq!(entries_ticks[0].0.transactions.len(), txs.len()); // InstructionErrors should still be recorded results[0] = new_execution_result(Err(TransactionError::InstructionError( @@ -2834,8 +2910,11 @@ mod tests { } = BankingStage::record_transactions(bank.slot(), &txs, &results, &recorder); result.unwrap(); assert!(retryable_indexes.is_empty()); - let (_bank, (entry, _tick_height)) = entry_receiver.recv().unwrap(); - assert_eq!(entry.transactions.len(), txs.len()); + let WorkingBankEntry { + bank: _, + entries_ticks, + } = entry_receiver.recv().unwrap(); + assert_eq!(entries_ticks[0].0.transactions.len(), txs.len()); // Other TransactionErrors should not be recorded results[0] = TransactionExecutionResult::NotExecuted(TransactionError::AccountNotFound); @@ -2846,7 +2925,11 @@ mod tests { } = BankingStage::record_transactions(bank.slot(), &txs, &results, &recorder); result.unwrap(); assert!(retryable_indexes.is_empty()); - let (_bank, (entry, _tick_height)) = entry_receiver.recv().unwrap(); + let WorkingBankEntry { + bank: _, + entries_ticks, + } = entry_receiver.recv().unwrap(); + let entry = entries_ticks.get(0).unwrap().0.clone(); assert_eq!(entry.transactions.len(), txs.len() - 1); // Once bank is set to a new bank (setting bank.slot() + 1 in record_transactions), @@ -3060,6 +3143,8 @@ mod tests { poh_recorder.lock().unwrap().set_bank(&bank); let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); + let process_transactions_batch_output = BankingStage::process_and_record_transactions( &bank, &transactions, @@ -3068,6 +3153,7 @@ mod tests { None, &gossip_vote_sender, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), + &bundle_locker, ); let ExecuteAndCommitTransactionsOutput { @@ -3090,7 +3176,13 @@ mod tests { let mut done = false; // read entries until I find mine, might be ticks... - while let Ok((_bank, (entry, _tick_height))) = entry_receiver.recv() { + while let Ok(WorkingBankEntry { + bank: _, + entries_ticks, + }) = entry_receiver.recv() + { + assert_eq!(entries_ticks.len(), 1); + let entry = entries_ticks.get(0).unwrap().0.clone(); if !entry.is_tick() { trace!("got entry"); assert_eq!(entry.transactions.len(), transactions.len()); @@ -3112,6 +3204,8 @@ mod tests { genesis_config.hash(), )]); + let bundle_locker = BundleAccountLocker::default(); + let process_transactions_batch_output = BankingStage::process_and_record_transactions( &bank, &transactions, @@ -3120,6 +3214,7 @@ mod tests { None, &gossip_vote_sender, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), + &bundle_locker, ); let ExecuteAndCommitTransactionsOutput { @@ -3205,6 +3300,8 @@ mod tests { genesis_config.hash(), )]); + let bundle_locker = BundleAccountLocker::default(); + let process_transactions_batch_output = BankingStage::process_and_record_transactions( &bank, &transactions, @@ -3213,6 +3310,7 @@ mod tests { None, &gossip_vote_sender, &qos_service, + &bundle_locker, ); let ExecuteAndCommitTransactionsOutput { @@ -3252,6 +3350,7 @@ mod tests { None, &gossip_vote_sender, &qos_service, + &bundle_locker, ); let ExecuteAndCommitTransactionsOutput { @@ -3339,6 +3438,7 @@ mod tests { let poh_simulator = simulate_poh(record_receiver, &poh_recorder); let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); let process_transactions_batch_output = BankingStage::process_and_record_transactions( &bank, @@ -3348,6 +3448,7 @@ mod tests { None, &gossip_vote_sender, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), + &bundle_locker, ); poh_recorder @@ -3464,6 +3565,7 @@ mod tests { #[test] fn test_process_transactions_returns_unprocessed_txs() { solana_logger::setup(); + let GenesisConfigInfo { genesis_config, mint_keypair, @@ -3505,6 +3607,8 @@ mod tests { let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); + let process_transactions_summary = BankingStage::process_transactions( &bank, &Instant::now(), @@ -3513,6 +3617,7 @@ mod tests { None, &gossip_vote_sender, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), + &bundle_locker, ); let ProcessTransactionsSummary { @@ -3571,6 +3676,8 @@ mod tests { let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); + let process_transactions_summary = BankingStage::process_transactions( &bank, &Instant::now(), @@ -3579,6 +3686,7 @@ mod tests { None, &gossip_vote_sender, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), + &bundle_locker, ); poh_recorder @@ -3672,7 +3780,7 @@ mod tests { &mint_keypair, &Pubkey::new_unique(), 1, - genesis_config.hash() + genesis_config.hash(), ); MAX_NUM_TRANSACTIONS_PER_BATCH ]; @@ -3791,6 +3899,8 @@ mod tests { let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); + let _ = BankingStage::process_and_record_transactions( &bank, &transactions, @@ -3801,6 +3911,7 @@ mod tests { }), &gossip_vote_sender, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), + &bundle_locker, ); transaction_status_service.join().unwrap(); @@ -3952,6 +4063,8 @@ mod tests { let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); + let _ = BankingStage::process_and_record_transactions( &bank, &[sanitized_tx.clone()], @@ -3962,6 +4075,7 @@ mod tests { }), &gossip_vote_sender, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), + &bundle_locker, ); transaction_status_service.join().unwrap(); @@ -4068,6 +4182,8 @@ mod tests { let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let bundle_locker = BundleAccountLocker::default(); + // When the working bank in poh_recorder is None, no packets should be processed assert!(!poh_recorder.lock().unwrap().has_bank()); let max_tx_processing_ns = std::u128::MAX; @@ -4083,6 +4199,8 @@ mod tests { &recorder, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), &mut LeaderSlotMetricsTracker::new(0), + &HashSet::default(), + &bundle_locker, ); assert_eq!(buffered_packet_batches.len(), num_conflicting_transactions); // When the working bank in poh_recorder is Some, all packets should be processed. @@ -4100,6 +4218,8 @@ mod tests { &recorder, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), &mut LeaderSlotMetricsTracker::new(0), + &HashSet::default(), + &bundle_locker, ); assert!(buffered_packet_batches.is_empty()); poh_recorder @@ -4121,6 +4241,8 @@ mod tests { let (transactions, bank, poh_recorder, _entry_receiver, poh_simulator) = setup_conflicting_transactions(ledger_path.path()); + let bundle_locker = BundleAccountLocker::default(); + let test_fn = Some(move || { finished_packet_sender.send(()).unwrap(); continue_receiver.recv().unwrap(); @@ -4159,6 +4281,8 @@ mod tests { &recorder, &QosService::new(Arc::new(RwLock::new(CostModel::default())), 1), &mut LeaderSlotMetricsTracker::new(0), + &HashSet::default(), + &bundle_locker, ); // Check everything is correct. All valid packets should be processed. diff --git a/core/src/broadcast_stage.rs b/core/src/broadcast_stage.rs index 309466c4c1..ae3fcc82ef 100644 --- a/core/src/broadcast_stage.rs +++ b/core/src/broadcast_stage.rs @@ -33,7 +33,7 @@ use { std::{ collections::{HashMap, HashSet}, iter::repeat, - net::UdpSocket, + net::{SocketAddr, UdpSocket}, sync::{ atomic::{AtomicBool, Ordering}, Arc, Mutex, RwLock, @@ -84,6 +84,7 @@ impl BroadcastStageType { blockstore: Arc, bank_forks: Arc>, shred_version: u16, + shred_receiver_addr: Option, ) -> BroadcastStage { match self { BroadcastStageType::Standard => BroadcastStage::new( @@ -95,6 +96,7 @@ impl BroadcastStageType { blockstore, bank_forks, StandardBroadcastRun::new(shred_version), + shred_receiver_addr, ), BroadcastStageType::FailEntryVerification => BroadcastStage::new( @@ -106,6 +108,7 @@ impl BroadcastStageType { blockstore, bank_forks, FailEntryVerificationBroadcastRun::new(shred_version), + None, ), BroadcastStageType::BroadcastFakeShreds => BroadcastStage::new( @@ -117,6 +120,7 @@ impl BroadcastStageType { blockstore, bank_forks, BroadcastFakeShredsRun::new(0, shred_version), + None, ), BroadcastStageType::BroadcastDuplicates(config) => BroadcastStage::new( @@ -128,6 +132,7 @@ impl BroadcastStageType { blockstore, bank_forks, BroadcastDuplicatesRun::new(shred_version, config.clone()), + None, ), } } @@ -148,6 +153,7 @@ trait BroadcastRun { cluster_info: &ClusterInfo, sock: &UdpSocket, bank_forks: &RwLock, + shred_receiver_addr: Option, ) -> Result<()>; fn record(&mut self, receiver: &Mutex, blockstore: &Blockstore) -> Result<()>; } @@ -243,6 +249,7 @@ impl BroadcastStage { blockstore: Arc, bank_forks: Arc>, broadcast_stage_run: impl BroadcastRun + Send + 'static + Clone, + shred_receiver_addr: Option, ) -> Self { let (socket_sender, socket_receiver) = unbounded(); let (blockstore_sender, blockstore_receiver) = unbounded(); @@ -277,8 +284,13 @@ impl BroadcastStage { let t = Builder::new() .name("solana-broadcaster-transmit".to_string()) .spawn(move || loop { - let res = - bs_transmit.transmit(&socket_receiver, &cluster_info, &sock, &bank_forks); + let res = bs_transmit.transmit( + &socket_receiver, + &cluster_info, + &sock, + &bank_forks, + shred_receiver_addr, + ); let res = Self::handle_error(res, "solana-broadcaster-transmit"); if let Some(res) = res { return res; @@ -394,6 +406,7 @@ pub fn broadcast_shreds( cluster_info: &ClusterInfo, bank_forks: &RwLock, socket_addr_space: &SocketAddrSpace, + shred_receiver_addr: Option, ) -> Result<()> { let mut result = Ok(()); let mut shred_select = Measure::start("shred_select"); @@ -403,22 +416,27 @@ pub fn broadcast_shreds( }; let packets: Vec<_> = shreds .iter() - .group_by(|shred| shred.slot()) - .into_iter() - .flat_map(|(slot, shreds)| { - let cluster_nodes = - cluster_nodes_cache.get(slot, &root_bank, &working_bank, cluster_info); - update_peer_stats(&cluster_nodes, last_datapoint_submit); - let root_bank = root_bank.clone(); - shreds.flat_map(move |shred| { - repeat(&shred.payload).zip(cluster_nodes.get_broadcast_addrs( - shred, - &root_bank, - DATA_PLANE_FANOUT, - socket_addr_space, - )) - }) - }) + .filter_map(|s| Some((&s.payload, shred_receiver_addr?))) + .chain( + shreds + .iter() + .group_by(|shred| shred.slot()) + .into_iter() + .flat_map(|(slot, shreds)| { + let cluster_nodes = + cluster_nodes_cache.get(slot, &root_bank, &working_bank, cluster_info); + update_peer_stats(&cluster_nodes, last_datapoint_submit); + let root_bank = root_bank.clone(); + shreds.flat_map(move |shred| { + repeat(&shred.payload).zip(cluster_nodes.get_broadcast_addrs( + shred, + &root_bank, + DATA_PLANE_FANOUT, + socket_addr_space, + )) + }) + }), + ) .collect(); shred_select.stop(); transmit_stats.shred_select += shred_select.as_us(); @@ -614,6 +632,7 @@ pub mod test { blockstore.clone(), bank_forks, StandardBroadcastRun::new(0), + None, ); MockBroadcastStage { @@ -653,7 +672,10 @@ pub mod test { let ticks = create_ticks(max_tick_height - start_tick_height, 0, Hash::default()); for (i, tick) in ticks.into_iter().enumerate() { entry_sender - .send((bank.clone(), (tick, i as u64 + 1))) + .send(WorkingBankEntry { + bank: bank.clone(), + entries_ticks: vec![(tick, i as u64 + 1)], + }) .expect("Expect successful send to broadcast service"); } } diff --git a/core/src/broadcast_stage/broadcast_duplicates_run.rs b/core/src/broadcast_stage/broadcast_duplicates_run.rs index a6e96409a0..d370f994d8 100644 --- a/core/src/broadcast_stage/broadcast_duplicates_run.rs +++ b/core/src/broadcast_stage/broadcast_duplicates_run.rs @@ -10,7 +10,7 @@ use { signature::{Keypair, Signature, Signer}, system_transaction, }, - std::collections::HashSet, + std::{collections::HashSet, net::SocketAddr}, }; pub const MINIMUM_DUPLICATE_SLOT: Slot = 20; @@ -242,6 +242,7 @@ impl BroadcastRun for BroadcastDuplicatesRun { cluster_info: &ClusterInfo, sock: &UdpSocket, bank_forks: &RwLock, + _shred_receiver_addr: Option, ) -> Result<()> { let (shreds, _) = receiver.lock().unwrap().recv()?; if shreds.is_empty() { diff --git a/core/src/broadcast_stage/broadcast_fake_shreds_run.rs b/core/src/broadcast_stage/broadcast_fake_shreds_run.rs index d1ff80bee5..9d7d599fda 100644 --- a/core/src/broadcast_stage/broadcast_fake_shreds_run.rs +++ b/core/src/broadcast_stage/broadcast_fake_shreds_run.rs @@ -3,6 +3,7 @@ use { solana_entry::entry::Entry, solana_ledger::shred::Shredder, solana_sdk::{hash::Hash, signature::Keypair}, + std::net::SocketAddr, }; #[derive(Clone)] @@ -124,6 +125,7 @@ impl BroadcastRun for BroadcastFakeShredsRun { cluster_info: &ClusterInfo, sock: &UdpSocket, _bank_forks: &RwLock, + _shred_receiver_addr: Option, ) -> Result<()> { for (data_shreds, batch_info) in receiver.lock().unwrap().iter() { let fake = batch_info.is_some(); diff --git a/core/src/broadcast_stage/broadcast_utils.rs b/core/src/broadcast_stage/broadcast_utils.rs index c9135d0a60..4df4395b36 100644 --- a/core/src/broadcast_stage/broadcast_utils.rs +++ b/core/src/broadcast_stage/broadcast_utils.rs @@ -39,16 +39,24 @@ const RECEIVE_ENTRY_COUNT_THRESHOLD: usize = 8; pub(super) fn recv_slot_entries(receiver: &Receiver) -> Result { let timer = Duration::new(1, 0); let recv_start = Instant::now(); - let (mut bank, (entry, mut last_tick_height)) = receiver.recv_timeout(timer)?; + let WorkingBankEntry { + mut bank, + entries_ticks, + } = receiver.recv_timeout(timer)?; - let mut entries = vec![entry]; + let mut last_tick_height = entries_ticks.iter().last().unwrap().1; + let mut entries: Vec = entries_ticks.into_iter().map(|(entry, _)| entry).collect(); let mut slot = bank.slot(); let mut max_tick_height = bank.max_tick_height(); assert!(last_tick_height <= max_tick_height); if last_tick_height != max_tick_height { - while let Ok((try_bank, (entry, tick_height))) = receiver.try_recv() { + while let Ok(WorkingBankEntry { + bank: try_bank, + entries_ticks: new_entries_ticks, + }) = receiver.try_recv() + { // If the bank changed, that implies the previous slot was interrupted and we do not have to // broadcast its entries. if try_bank.slot() != slot { @@ -58,8 +66,8 @@ pub(super) fn recv_slot_entries(receiver: &Receiver) -> Result slot = bank.slot(); max_tick_height = bank.max_tick_height(); } - last_tick_height = tick_height; - entries.push(entry); + last_tick_height = new_entries_ticks.iter().last().unwrap().1; + entries.extend(new_entries_ticks.into_iter().map(|(entry, _)| entry)); if entries.len() >= RECEIVE_ENTRY_COUNT_THRESHOLD { break; @@ -123,7 +131,11 @@ mod tests { .map(|i| { let entry = Entry::new(&last_hash, 1, vec![tx.clone()]); last_hash = entry.hash; - s.send((bank1.clone(), (entry.clone(), i))).unwrap(); + s.send(WorkingBankEntry { + bank: bank1.clone(), + entries_ticks: vec![(entry.clone(), i)], + }) + .unwrap(); entry }) .collect(); @@ -157,11 +169,18 @@ mod tests { last_hash = entry.hash; // Interrupt slot 1 right before the last tick if tick_height == expected_last_height { - s.send((bank2.clone(), (entry.clone(), tick_height))) - .unwrap(); + s.send(WorkingBankEntry { + bank: bank2.clone(), + entries_ticks: vec![(entry.clone(), tick_height)], + }) + .unwrap(); Some(entry) } else { - s.send((bank1.clone(), (entry, tick_height))).unwrap(); + s.send(WorkingBankEntry { + bank: bank1.clone(), + entries_ticks: vec![(entry, tick_height)], + }) + .unwrap(); None } }) diff --git a/core/src/broadcast_stage/fail_entry_verification_broadcast_run.rs b/core/src/broadcast_stage/fail_entry_verification_broadcast_run.rs index a39fd90b23..3044972929 100644 --- a/core/src/broadcast_stage/fail_entry_verification_broadcast_run.rs +++ b/core/src/broadcast_stage/fail_entry_verification_broadcast_run.rs @@ -3,7 +3,7 @@ use { crate::cluster_nodes::ClusterNodesCache, solana_ledger::shred::Shredder, solana_sdk::{hash::Hash, signature::Keypair}, - std::{thread::sleep, time::Duration}, + std::{net::SocketAddr, thread::sleep, time::Duration}, }; pub const NUM_BAD_SLOTS: u64 = 10; @@ -143,6 +143,7 @@ impl BroadcastRun for FailEntryVerificationBroadcastRun { cluster_info: &ClusterInfo, sock: &UdpSocket, bank_forks: &RwLock, + shred_receiver_addr: Option, ) -> Result<()> { let (shreds, _) = receiver.lock().unwrap().recv()?; broadcast_shreds( @@ -154,6 +155,7 @@ impl BroadcastRun for FailEntryVerificationBroadcastRun { cluster_info, bank_forks, cluster_info.socket_addr_space(), + shred_receiver_addr, ) } fn record(&mut self, receiver: &Mutex, blockstore: &Blockstore) -> Result<()> { diff --git a/core/src/broadcast_stage/standard_broadcast_run.rs b/core/src/broadcast_stage/standard_broadcast_run.rs index cfdc0af547..83e4dae827 100644 --- a/core/src/broadcast_stage/standard_broadcast_run.rs +++ b/core/src/broadcast_stage/standard_broadcast_run.rs @@ -17,7 +17,7 @@ use { signature::Keypair, timing::{duration_as_us, AtomicInterval}, }, - std::{sync::RwLock, time::Duration}, + std::{net::SocketAddr, sync::RwLock, time::Duration}, }; #[derive(Clone)] @@ -173,10 +173,10 @@ impl StandardBroadcastRun { let brecv = Arc::new(Mutex::new(brecv)); //data - let _ = self.transmit(&srecv, cluster_info, sock, bank_forks); + let _ = self.transmit(&srecv, cluster_info, sock, bank_forks, None); let _ = self.record(&brecv, blockstore); //coding - let _ = self.transmit(&srecv, cluster_info, sock, bank_forks); + let _ = self.transmit(&srecv, cluster_info, sock, bank_forks, None); let _ = self.record(&brecv, blockstore); Ok(()) } @@ -368,6 +368,7 @@ impl StandardBroadcastRun { shreds: Arc>, broadcast_shred_batch_info: Option, bank_forks: &RwLock, + shred_receiver_addr: Option, ) -> Result<()> { trace!("Broadcasting {:?} shreds", shreds.len()); let mut transmit_stats = TransmitShredsStats::default(); @@ -383,6 +384,7 @@ impl StandardBroadcastRun { cluster_info, bank_forks, cluster_info.socket_addr_space(), + shred_receiver_addr, )?; transmit_time.stop(); @@ -495,9 +497,17 @@ impl BroadcastRun for StandardBroadcastRun { cluster_info: &ClusterInfo, sock: &UdpSocket, bank_forks: &RwLock, + shred_receiver_addr: Option, ) -> Result<()> { let (shreds, batch_info) = receiver.lock().unwrap().recv()?; - self.broadcast(sock, cluster_info, shreds, batch_info, bank_forks) + self.broadcast( + sock, + cluster_info, + shreds, + batch_info, + bank_forks, + shred_receiver_addr, + ) } fn record(&mut self, receiver: &Mutex, blockstore: &Blockstore) -> Result<()> { let (shreds, slot_start_ts) = receiver.lock().unwrap().recv()?; diff --git a/core/src/bundle_account_locker.rs b/core/src/bundle_account_locker.rs new file mode 100644 index 0000000000..955a4dd170 --- /dev/null +++ b/core/src/bundle_account_locker.rs @@ -0,0 +1,334 @@ +///! Handles pre-locking bundle accounts so that accounts bundles touch can be reserved ahead +/// of time for execution. Also, ensures that ALL accounts mentioned across a bundle are locked +/// to avoid race conditions between BundleStage and BankingStage. +/// +/// For instance, imagine a bundle with three transactions and the set of accounts for each transaction +/// is: {{A, B}, {B, C}, {C, D}}. We need to lock A, B, and C even though only one is executed at a time. +/// Imagine BundleStage is in the middle of processing {C, D} and we didn't have a lock on accounts {A, B, C}. +/// In this situation, there's a chance that BankingStage can process a transaction containing A or B +/// and commit the results before the bundle completes. By the time the bundle commits the new account +/// state for {A, B, C}, A and B would be incorrect and the entries containing the bundle would be +/// replayed improperly and that leader would have produced an invalid block. +use { + solana_runtime::bank::Bank, + solana_sdk::{ + bundle::sanitized::SanitizedBundle, pubkey::Pubkey, transaction::TransactionAccountLocks, + }, + std::collections::{hash_map::Entry, HashMap, HashSet}, + std::sync::{Arc, Mutex, MutexGuard}, +}; + +#[derive(Debug)] +pub enum BundleAccountLockerError { + LockingError, +} + +pub type BundleAccountLockerResult = Result; + +pub struct LockedBundle<'a, 'b> { + bundle_account_locker: &'a BundleAccountLocker, + sanitized_bundle: &'b SanitizedBundle, + bank: Arc, +} + +impl<'a, 'b> LockedBundle<'a, 'b> { + pub fn new( + bundle_account_locker: &'a BundleAccountLocker, + sanitized_bundle: &'b SanitizedBundle, + bank: &Arc, + ) -> Self { + Self { + bundle_account_locker, + sanitized_bundle, + bank: bank.clone(), + } + } + + pub fn sanitized_bundle(&self) -> &SanitizedBundle { + self.sanitized_bundle + } +} + +// Automatically unlock bundle accounts when destructed +impl<'a, 'b> Drop for LockedBundle<'a, 'b> { + fn drop(&mut self) { + let _ = self + .bundle_account_locker + .unlock_bundle_accounts(self.sanitized_bundle, &self.bank); + } +} + +#[derive(Default, Clone)] +pub struct BundleAccountLocks { + read_locks: HashMap, + write_locks: HashMap, +} + +impl BundleAccountLocks { + pub fn read_locks(&self) -> HashSet { + self.read_locks.keys().cloned().collect() + } + + pub fn write_locks(&self) -> HashSet { + self.write_locks.keys().cloned().collect() + } + + pub fn lock_accounts( + &mut self, + read_locks: HashMap, + write_locks: HashMap, + ) { + for (acc, count) in read_locks { + *self.read_locks.entry(acc).or_insert(0) += count; + } + for (acc, count) in write_locks { + *self.write_locks.entry(acc).or_insert(0) += count; + } + } + + pub fn unlock_accounts( + &mut self, + read_locks: HashMap, + write_locks: HashMap, + ) { + for (acc, count) in read_locks { + if let Entry::Occupied(mut entry) = self.read_locks.entry(acc) { + let val = entry.get_mut(); + *val = val.saturating_sub(count); + if entry.get() == &0 { + let _ = entry.remove(); + } + } else { + warn!("error unlocking read-locked account, account: {:?}", acc); + } + } + for (acc, count) in write_locks { + if let Entry::Occupied(mut entry) = self.write_locks.entry(acc) { + let val = entry.get_mut(); + *val = val.saturating_sub(count); + if entry.get() == &0 { + let _ = entry.remove(); + } + } else { + warn!("error unlocking write-locked account, account: {:?}", acc); + } + } + } +} + +#[derive(Clone, Default)] +pub struct BundleAccountLocker { + account_locks: Arc>, +} + +impl BundleAccountLocker { + /// used in BankingStage during TransactionBatch construction to ensure that BankingStage + /// doesn't lock anything currently locked in the BundleAccountLocker + pub fn read_locks(&self) -> HashSet { + self.account_locks.lock().unwrap().read_locks() + } + + /// used in BankingStage during TransactionBatch construction to ensure that BankingStage + /// doesn't lock anything currently locked in the BundleAccountLocker + pub fn write_locks(&self) -> HashSet { + self.account_locks.lock().unwrap().write_locks() + } + + /// used in BankingStage during TransactionBatch construction to ensure that BankingStage + /// doesn't lock anything currently locked in the BundleAccountLocker + pub fn account_locks(&self) -> MutexGuard { + self.account_locks.lock().unwrap() + } + + /// Prepares a locked bundle and returns a LockedBundle containing locked accounts. + /// When a LockedBundle is dropped, the accounts are automatically unlocked + pub fn prepare_locked_bundle<'a, 'b>( + &'a self, + sanitized_bundle: &'b SanitizedBundle, + bank: &Arc, + ) -> BundleAccountLockerResult> { + let (read_locks, write_locks) = Self::get_read_write_locks(sanitized_bundle, bank)?; + + self.account_locks + .lock() + .unwrap() + .lock_accounts(read_locks, write_locks); + Ok(LockedBundle::new(self, sanitized_bundle, bank)) + } + + /// Unlocks bundle accounts. Note that LockedBundle::drop will auto-drop the bundle account locks + fn unlock_bundle_accounts( + &self, + sanitized_bundle: &SanitizedBundle, + bank: &Bank, + ) -> BundleAccountLockerResult<()> { + let (read_locks, write_locks) = Self::get_read_write_locks(sanitized_bundle, bank)?; + + self.account_locks + .lock() + .unwrap() + .unlock_accounts(read_locks, write_locks); + Ok(()) + } + + /// Returns the read and write locks for this bundle + /// Each lock type contains a HashMap which maps Pubkey to number of locks held + fn get_read_write_locks( + bundle: &SanitizedBundle, + bank: &Bank, + ) -> BundleAccountLockerResult<(HashMap, HashMap)> { + let transaction_locks: Vec = bundle + .transactions + .iter() + .filter_map(|tx| { + tx.get_account_locks(bank.get_transaction_account_lock_limit()) + .ok() + }) + .collect(); + + if transaction_locks.len() != bundle.transactions.len() { + return Err(BundleAccountLockerError::LockingError); + } + + let bundle_read_locks = transaction_locks + .iter() + .flat_map(|tx| tx.readonly.iter().map(|a| **a)); + let bundle_read_locks = + bundle_read_locks + .into_iter() + .fold(HashMap::new(), |mut map, acc| { + *map.entry(acc).or_insert(0) += 1; + map + }); + + let bundle_write_locks = transaction_locks + .iter() + .flat_map(|tx| tx.writable.iter().map(|a| **a)); + let bundle_write_locks = + bundle_write_locks + .into_iter() + .fold(HashMap::new(), |mut map, acc| { + *map.entry(acc).or_insert(0) += 1; + map + }); + + Ok((bundle_read_locks, bundle_write_locks)) + } +} + +#[cfg(test)] +mod tests { + use { + crate::{ + bundle_account_locker::BundleAccountLocker, bundle_sanitizer::get_sanitized_bundle, + packet_bundle::PacketBundle, + }, + solana_ledger::genesis_utils::create_genesis_config, + solana_perf::packet::PacketBatch, + solana_runtime::{ + bank::Bank, genesis_utils::GenesisConfigInfo, + transaction_error_metrics::TransactionErrorMetrics, + }, + solana_sdk::{ + packet::Packet, signature::Signer, signer::keypair::Keypair, system_program, + system_transaction::transfer, transaction::VersionedTransaction, + }, + std::{collections::HashSet, sync::Arc}, + uuid::Uuid, + }; + + #[test] + fn test_simple_lock_bundles() { + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let bundle_account_locker = BundleAccountLocker::default(); + + let kp0 = Keypair::new(); + let kp1 = Keypair::new(); + + let tx0 = VersionedTransaction::from(transfer( + &mint_keypair, + &kp0.pubkey(), + 1, + genesis_config.hash(), + )); + let tx1 = VersionedTransaction::from(transfer( + &mint_keypair, + &kp1.pubkey(), + 1, + genesis_config.hash(), + )); + + let packet_bundle0 = PacketBundle { + batch: PacketBatch::new(vec![Packet::from_data(None, &tx0).unwrap()]), + uuid: Uuid::new_v4(), + }; + let packet_bundle1 = PacketBundle { + batch: PacketBatch::new(vec![Packet::from_data(None, &tx1).unwrap()]), + uuid: Uuid::new_v4(), + }; + + let mut transaction_errors = TransactionErrorMetrics::default(); + + let sanitized_bundle0 = get_sanitized_bundle( + &packet_bundle0, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors, + ) + .expect("sanitize bundle 0"); + let sanitized_bundle1 = get_sanitized_bundle( + &packet_bundle1, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors, + ) + .expect("sanitize bundle 1"); + + let locked_bundle0 = bundle_account_locker + .prepare_locked_bundle(&sanitized_bundle0, &bank) + .unwrap(); + + assert_eq!( + bundle_account_locker.write_locks(), + HashSet::from_iter([mint_keypair.pubkey(), kp0.pubkey()]) + ); + assert_eq!( + bundle_account_locker.read_locks(), + HashSet::from_iter([system_program::id()]) + ); + + let locked_bundle1 = bundle_account_locker + .prepare_locked_bundle(&sanitized_bundle1, &bank) + .unwrap(); + assert_eq!( + bundle_account_locker.write_locks(), + HashSet::from_iter([mint_keypair.pubkey(), kp0.pubkey(), kp1.pubkey()]) + ); + assert_eq!( + bundle_account_locker.read_locks(), + HashSet::from_iter([system_program::id()]) + ); + + drop(locked_bundle0); + assert_eq!( + bundle_account_locker.write_locks(), + HashSet::from_iter([mint_keypair.pubkey(), kp1.pubkey()]) + ); + assert_eq!( + bundle_account_locker.read_locks(), + HashSet::from_iter([system_program::id()]) + ); + + drop(locked_bundle1); + assert!(bundle_account_locker.write_locks().is_empty()); + assert!(bundle_account_locker.read_locks().is_empty()); + } +} diff --git a/core/src/bundle_sanitizer.rs b/core/src/bundle_sanitizer.rs new file mode 100644 index 0000000000..f27fe9be2a --- /dev/null +++ b/core/src/bundle_sanitizer.rs @@ -0,0 +1,612 @@ +use crate::unprocessed_packet_batches::ImmutableDeserializedPacket; +///! Turns packets into SanitizedTransactions and ensure they pass sanity checks +use { + crate::packet_bundle::PacketBundle, + crate::unprocessed_packet_batches::deserialize_packets, + solana_perf::sigverify::verify_packet, + solana_runtime::{bank::Bank, transaction_error_metrics::TransactionErrorMetrics}, + solana_sdk::{ + bundle::sanitized::SanitizedBundle, + clock::MAX_PROCESSING_AGE, + feature_set::FeatureSet, + pubkey::Pubkey, + signature::Signature, + transaction::{AddressLoader, SanitizedTransaction}, + }, + std::{ + collections::{hash_map::RandomState, HashSet}, + iter::repeat, + sync::Arc, + }, + thiserror::Error, +}; + +pub const MAX_PACKETS_PER_BUNDLE: usize = 5; + +#[derive(Error, Debug, PartialEq, Eq, Clone)] +pub enum BundleSanitizerError { + #[error("Bank is in vote-only mode")] + VoteOnlyMode, + #[error("Bundle packet batch failed pre-check")] + FailedPacketBatchPreCheck, + #[error("Bundle mentions blacklisted account")] + BlacklistedAccount, + #[error("Bundle contains a transaction that failed to serialize")] + FailedToSerializeTransaction, + #[error("Bundle contains a duplicate transaction")] + DuplicateTransaction, + #[error("Bundle failed check_transactions")] + FailedCheckTransactions, +} + +pub type BundleSanitizationResult = Result; + +/// An invalid bundle contains one of the following: +/// No packets. +/// Too many packets. +/// Packets marked for discard (not sure why someone would do this) +/// One of the packets fails signature verification. +/// Mentions an account in consensus or blacklisted accounts. +/// Contains a packet that failed to serialize to a transaction. +/// Contains duplicate transactions within the same bundle. +/// Contains a transaction that was already processed or one with an invalid blockhash. +/// NOTE: bundles need to be sanitized for a given bank. For instance, a bundle sanitized +/// on bank n-1 will be valid for all of bank n-1, and may or may not be valid for bank n +pub fn get_sanitized_bundle( + packet_bundle: &PacketBundle, + bank: &Arc, + consensus_accounts_cache: &HashSet, + blacklisted_accounts: &HashSet, + transaction_error_metrics: &mut TransactionErrorMetrics, +) -> BundleSanitizationResult { + if bank.vote_only_bank() { + return Err(BundleSanitizerError::VoteOnlyMode); + } + + if packet_bundle.batch.is_empty() + || packet_bundle.batch.len() > MAX_PACKETS_PER_BUNDLE + || packet_bundle.batch.iter().any(|p| p.meta.discard()) + || packet_bundle + .batch + .iter() + .any(|p| !verify_packet(&mut p.clone(), false)) + { + return Err(BundleSanitizerError::FailedPacketBatchPreCheck); + } + + let packet_indexes = (0..packet_bundle.batch.len()).collect::>(); + let deserialized_packets = deserialize_packets(&packet_bundle.batch, &packet_indexes); + let transactions: Vec = deserialized_packets + .filter_map(|p| { + let immutable_packet = p.immutable_section().clone(); + transaction_from_deserialized_packet( + &immutable_packet, + &bank.feature_set, + bank.as_ref(), + ) + }) + .collect(); + + let unique_signatures: HashSet<&Signature, RandomState> = + HashSet::from_iter(transactions.iter().map(|tx| tx.signature())); + let contains_blacklisted_account = transactions.iter().any(|tx| { + let accounts = tx.message().account_keys(); + accounts + .iter() + .any(|acc| blacklisted_accounts.contains(acc) || consensus_accounts_cache.contains(acc)) + }); + + if contains_blacklisted_account { + return Err(BundleSanitizerError::BlacklistedAccount); + } + + if transactions.is_empty() || packet_bundle.batch.len() != transactions.len() { + return Err(BundleSanitizerError::FailedToSerializeTransaction); + } + + if unique_signatures.len() != transactions.len() { + return Err(BundleSanitizerError::DuplicateTransaction); + } + + // assume everything locks okay to check for already-processed transaction or expired/invalid blockhash + let lock_results: Vec<_> = repeat(Ok(())).take(transactions.len()).collect(); + let check_results = bank.check_transactions( + &transactions, + &lock_results, + MAX_PROCESSING_AGE, + transaction_error_metrics, + ); + if check_results.iter().any(|r| r.0.is_err()) { + return Err(BundleSanitizerError::FailedCheckTransactions); + } + + Ok(SanitizedBundle { transactions }) +} + +// This function deserializes packets into transactions, computes the blake3 hash of transaction +// messages, and verifies secp256k1 instructions. A list of sanitized transactions are returned +// with their packet indexes. +// NOTES on tx v2: +// - tx v2 can only load addresses set in previous slots +// - tx v2 can't reorg indices in a lookup table +// - tx v2 transaction loading fails if it tries to access an invalid index (either doesn't exist +// or exists but was set in the current slot +#[allow(clippy::needless_collect)] +fn transaction_from_deserialized_packet( + deserialized_packet: &ImmutableDeserializedPacket, + feature_set: &Arc, + address_loader: impl AddressLoader, +) -> Option { + let tx = SanitizedTransaction::try_new( + deserialized_packet.transaction().clone(), + *deserialized_packet.message_hash(), + deserialized_packet.is_simple_vote(), + address_loader, + ) + .ok()?; + tx.verify_precompiles(feature_set).ok()?; + Some(tx) +} + +#[cfg(test)] +mod tests { + use { + crate::{ + bundle_sanitizer::{get_sanitized_bundle, MAX_PACKETS_PER_BUNDLE}, + packet_bundle::PacketBundle, + tip_manager::{TipDistributionAccountConfig, TipManager, TipManagerConfig}, + }, + solana_address_lookup_table_program::instruction::create_lookup_table, + solana_ledger::genesis_utils::create_genesis_config, + solana_perf::packet::PacketBatch, + solana_runtime::{ + bank::Bank, genesis_utils::GenesisConfigInfo, + transaction_error_metrics::TransactionErrorMetrics, + }, + solana_sdk::{ + hash::Hash, + instruction::Instruction, + packet::Packet, + pubkey::Pubkey, + signature::{Keypair, Signer}, + system_transaction::transfer, + transaction::{SanitizedTransaction, Transaction, VersionedTransaction}, + }, + std::{collections::HashSet, sync::Arc}, + uuid::Uuid, + }; + + #[test] + fn test_simple_get_sanitized_bundle() { + solana_logger::setup(); + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let kp = Keypair::new(); + + let tx = VersionedTransaction::from(transfer( + &mint_keypair, + &kp.pubkey(), + 1, + genesis_config.hash(), + )); + let packet = Packet::from_data(None, &tx).unwrap(); + + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + + let mut transaction_errors = TransactionErrorMetrics::default(); + let sanitized_bundle = get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors, + ) + .unwrap(); + assert_eq!(sanitized_bundle.transactions.len(), 1); + assert_eq!( + sanitized_bundle.transactions[0].signature(), + &tx.signatures[0] + ); + } + + #[test] + fn test_fail_to_sanitize_consensus_account() { + solana_logger::setup(); + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let kp = Keypair::new(); + + let tx = VersionedTransaction::from(transfer( + &mint_keypair, + &kp.pubkey(), + 1, + genesis_config.hash(), + )); + let packet = Packet::from_data(None, &tx).unwrap(); + + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + + let consensus_accounts_cache = HashSet::from([kp.pubkey()]); + let mut transaction_errors = TransactionErrorMetrics::default(); + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &consensus_accounts_cache, + &HashSet::default(), + &mut transaction_errors + ) + .is_err()); + } + + #[test] + fn test_fail_to_sanitize_duplicate_transaction() { + solana_logger::setup(); + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let kp = Keypair::new(); + + let tx = VersionedTransaction::from(transfer( + &mint_keypair, + &kp.pubkey(), + 1, + genesis_config.hash(), + )); + let packet = Packet::from_data(None, &tx).unwrap(); + + // bundle with a duplicate transaction + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet.clone(), packet]), + uuid: Uuid::new_v4(), + }; + + // fails to pop because bundle it locks the same transaction twice + let mut transaction_errors = TransactionErrorMetrics::default(); + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors + ) + .is_err()); + } + + #[test] + fn test_fails_to_sanitize_bad_blockhash() { + solana_logger::setup(); + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let kp = Keypair::new(); + + let tx = + VersionedTransaction::from(transfer(&mint_keypair, &kp.pubkey(), 1, Hash::default())); + let packet = Packet::from_data(None, &tx).unwrap(); + + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet.clone(), packet]), + uuid: Uuid::new_v4(), + }; + + // fails to pop because bundle has bad blockhash + let mut transaction_errors = TransactionErrorMetrics::default(); + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors + ) + .is_err()); + } + + #[test] + fn test_fails_to_sanitize_already_processed() { + solana_logger::setup(); + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let kp = Keypair::new(); + + let tx = VersionedTransaction::from(transfer( + &mint_keypair, + &kp.pubkey(), + 1, + genesis_config.hash(), + )); + let packet = Packet::from_data(None, &tx).unwrap(); + + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet.clone()]), + uuid: Uuid::new_v4(), + }; + + let mut transaction_errors = TransactionErrorMetrics::default(); + let sanitized_bundle = get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors, + ) + .unwrap(); + + let results = bank.process_entry_transactions( + sanitized_bundle + .transactions + .into_iter() + .map(|tx| tx.to_versioned_transaction()) + .collect(), + ); + assert_eq!(results.len(), 1); + assert_eq!(results[0], Ok(())); + + // try to process the same one again shall fail + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors + ) + .is_err()); + } + + #[test] + fn test_fails_to_sanitize_bundle_tip_program() { + solana_logger::setup(); + let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let tip_manager = TipManager::new(TipManagerConfig { + tip_payment_program_id: Pubkey::new_unique(), + tip_distribution_program_id: Pubkey::new_unique(), + tip_distribution_account_config: TipDistributionAccountConfig { + payer: Arc::new(Keypair::new()), + merkle_root_upload_authority: Pubkey::new_unique(), + vote_account: Pubkey::new_unique(), + commission_bps: 0, + }, + }); + + let kp = Keypair::new(); + let tx = + SanitizedTransaction::try_from_legacy_transaction(Transaction::new_signed_with_payer( + &[Instruction::new_with_bytes( + tip_manager.tip_payment_program_id(), + &[0], + vec![], + )], + Some(&kp.pubkey()), + &[&kp], + genesis_config.hash(), + )) + .unwrap(); + + let packet = Packet::from_data(None, &tx.to_versioned_transaction()).unwrap(); + + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + + // fails to pop because bundle mentions tip program + let mut transaction_errors = TransactionErrorMetrics::default(); + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::from_iter([tip_manager.tip_payment_program_id()]), + &mut transaction_errors + ) + .is_err()); + } + + #[test] + fn test_txv2_sanitized_bundle_ok() { + solana_logger::setup(); + let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let kp = Keypair::new(); + let tx = + SanitizedTransaction::try_from_legacy_transaction(Transaction::new_signed_with_payer( + &[create_lookup_table(kp.pubkey(), kp.pubkey(), bank.slot()).0], + Some(&kp.pubkey()), + &[&kp], + genesis_config.hash(), + )) + .unwrap(); + + let packet = Packet::from_data(None, &tx.to_versioned_transaction()).unwrap(); + + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + + let mut transaction_errors = TransactionErrorMetrics::default(); + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors + ) + .is_ok()); + } + + #[test] + fn test_fails_to_sanitize_empty_bundle() { + solana_logger::setup(); + let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![]), + uuid: Uuid::new_v4(), + }; + // fails to pop because empty bundle + let mut transaction_errors = TransactionErrorMetrics::default(); + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors + ) + .is_err()); + } + + #[test] + fn test_fails_to_sanitize_too_many_packets() { + solana_logger::setup(); + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let kp = Keypair::new(); + + let packets = (0..MAX_PACKETS_PER_BUNDLE + 1).map(|i| { + let tx = VersionedTransaction::from(transfer( + &mint_keypair, + &kp.pubkey(), + i as u64, + genesis_config.hash(), + )); + Packet::from_data(None, &tx).unwrap() + }); + let packet_bundle = PacketBundle { + batch: PacketBatch::new(packets.collect()), + uuid: Uuid::new_v4(), + }; + // fails to pop because too many packets in a bundle + let mut transaction_errors = TransactionErrorMetrics::default(); + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors + ) + .is_err()); + } + + #[test] + fn test_fails_to_sanitize_discarded() { + solana_logger::setup(); + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let kp = Keypair::new(); + + let tx = VersionedTransaction::from(transfer( + &mint_keypair, + &kp.pubkey(), + 1, + genesis_config.hash(), + )); + let mut packet = Packet::from_data(None, &tx).unwrap(); + packet.meta.set_discard(true); + + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + + // fails to pop because one of the packets is marked as discard + let mut transaction_errors = TransactionErrorMetrics::default(); + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors + ) + .is_err()); + } + + #[test] + fn test_fails_to_sanitize_bad_sigverify() { + solana_logger::setup(); + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(2); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + + let kp = Keypair::new(); + + let mut tx = VersionedTransaction::from(transfer( + &mint_keypair, + &kp.pubkey(), + 1, + genesis_config.hash(), + )); + + let _ = tx.signatures.pop(); + + let bad_kp = Keypair::new(); + let serialized = tx.message.serialize(); + let bad_sig = bad_kp.sign_message(&serialized); + tx.signatures.push(bad_sig); + + let packet = Packet::from_data(None, &tx).unwrap(); + + let packet_bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + let mut transaction_errors = TransactionErrorMetrics::default(); + assert!(get_sanitized_bundle( + &packet_bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + &mut transaction_errors + ) + .is_err()); + } +} diff --git a/core/src/bundle_stage.rs b/core/src/bundle_stage.rs new file mode 100644 index 0000000000..455f09a244 --- /dev/null +++ b/core/src/bundle_stage.rs @@ -0,0 +1,1943 @@ +//! The `banking_stage` processes Transaction messages. It is intended to be used +//! to contruct a software pipeline. The stage uses all available CPU cores and +//! can do its processing in parallel with signature verification on the GPU. +use { + crate::{ + banking_stage::{BatchedTransactionDetails, CommitTransactionDetails}, + bundle_account_locker::{BundleAccountLocker, BundleAccountLockerResult, LockedBundle}, + bundle_sanitizer::{get_sanitized_bundle, BundleSanitizerError}, + bundle_stage_leader_stats::{BundleStageLeaderSlotTrackingMetrics, BundleStageLeaderStats}, + consensus_cache_updater::ConsensusCacheUpdater, + leader_slot_banking_stage_timing_metrics::RecordTransactionsTimings, + packet_bundle::PacketBundle, + proxy::block_engine_stage::BlockBuilderFeeInfo, + qos_service::QosService, + tip_manager::TipManager, + }, + crossbeam_channel::{Receiver, RecvTimeoutError}, + solana_entry::entry::hash_transactions, + solana_gossip::cluster_info::ClusterInfo, + solana_ledger::{ + blockstore_processor::TransactionStatusSender, token_balances::collect_token_balances, + }, + solana_measure::measure, + solana_poh::poh_recorder::{ + BankStart, PohRecorder, + PohRecorderError::{self}, + TransactionRecorder, + }, + solana_program_runtime::timings::ExecuteTimings, + solana_runtime::{ + account_overrides::AccountOverrides, + accounts::TransactionLoadResult, + bank::{ + Bank, CommitTransactionCounts, LoadAndExecuteTransactionsOutput, TransactionBalances, + TransactionBalancesSet, TransactionExecutionResult, + }, + bank_utils, + cost_model::{CostModel, TransactionCost}, + transaction_batch::TransactionBatch, + vote_sender_types::ReplayVoteSender, + }, + solana_sdk::{ + bundle::{ + error::BundleExecutionError, sanitized::SanitizedBundle, + utils::check_bundle_lock_results, + }, + clock::{Slot, DEFAULT_TICKS_PER_SLOT, MAX_PROCESSING_AGE}, + hash::Hash, + pubkey::Pubkey, + saturating_add_assign, + transaction::{self, SanitizedTransaction, TransactionError, VersionedTransaction}, + }, + solana_transaction_status::token_balances::{ + TransactionTokenBalances, TransactionTokenBalancesSet, + }, + std::{ + collections::{HashMap, HashSet, VecDeque}, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, RwLock, + }, + thread::{self, Builder, JoinHandle}, + time::{Duration, Instant}, + }, +}; + +const MAX_BUNDLE_RETRY_DURATION: Duration = Duration::from_millis(10); +const SLOT_BOUNDARY_CHECK_PERIOD: Duration = Duration::from_millis(10); + +type BundleStageResult = Result; + +// Stats emitted periodically +struct BundleStageLoopStats { + last_report: Instant, + + num_bundles_received: u64, + num_bundles_dropped: u64, + receive_and_buffer_bundles_elapsed_us: u64, + process_buffered_bundles_elapsed_us: u64, +} + +impl Default for BundleStageLoopStats { + fn default() -> Self { + BundleStageLoopStats { + last_report: Instant::now(), + num_bundles_received: 0, + num_bundles_dropped: 0, + receive_and_buffer_bundles_elapsed_us: 0, + process_buffered_bundles_elapsed_us: 0, + } + } +} + +impl BundleStageLoopStats { + fn maybe_report(&mut self, id: u32, period: Duration) { + if self.last_report.elapsed() > period { + datapoint_info!( + "bundle_stage-loop_stats", + ("id", id, i64), + ("num_bundles_received", self.num_bundles_received, i64), + ("num_bundles_dropped", self.num_bundles_dropped, i64), + ( + "receive_and_buffer_bundles_elapsed_us", + self.receive_and_buffer_bundles_elapsed_us, + i64 + ), + ( + "process_buffered_bundles_elapsed_us", + self.process_buffered_bundles_elapsed_us, + i64 + ), + ); + *self = BundleStageLoopStats::default(); + } + } +} + +struct AllExecutionResults { + pub load_and_execute_tx_output: LoadAndExecuteTransactionsOutput, + pub sanitized_txs: Vec, + pub pre_balances: (TransactionBalances, TransactionTokenBalances), + pub post_balances: (TransactionBalances, TransactionTokenBalances), +} + +pub struct BundleStage { + bundle_thread: JoinHandle<()>, +} + +impl BundleStage { + #[allow(clippy::new_ret_no_self)] + #[allow(clippy::too_many_arguments)] + pub fn new( + cluster_info: &Arc, + poh_recorder: &Arc>, + transaction_status_sender: Option, + gossip_vote_sender: ReplayVoteSender, + cost_model: Arc>, + bundle_receiver: Receiver>, + exit: Arc, + tip_manager: TipManager, + bundle_account_locker: BundleAccountLocker, + block_builder_fee_info: &Arc>, + ) -> Self { + Self::start_bundle_thread( + cluster_info, + poh_recorder, + transaction_status_sender, + gossip_vote_sender, + cost_model, + bundle_receiver, + exit, + tip_manager, + bundle_account_locker, + MAX_BUNDLE_RETRY_DURATION, + block_builder_fee_info, + ) + } + + #[allow(clippy::too_many_arguments)] + fn start_bundle_thread( + cluster_info: &Arc, + poh_recorder: &Arc>, + transaction_status_sender: Option, + gossip_vote_sender: ReplayVoteSender, + cost_model: Arc>, + bundle_receiver: Receiver>, + exit: Arc, + tip_manager: TipManager, + bundle_account_locker: BundleAccountLocker, + max_bundle_retry_duration: Duration, + block_builder_fee_info: &Arc>, + ) -> Self { + const BUNDLE_STAGE_ID: u32 = 10_000; + let poh_recorder = poh_recorder.clone(); + let cluster_info = cluster_info.clone(); + let block_builder_fee_info = block_builder_fee_info.clone(); + + let bundle_thread = Builder::new() + .name("solana-bundle-stage".to_string()) + .spawn(move || { + Self::process_loop( + cluster_info, + &poh_recorder, + transaction_status_sender, + bundle_receiver, + gossip_vote_sender, + BUNDLE_STAGE_ID, + cost_model, + exit, + tip_manager, + bundle_account_locker, + max_bundle_retry_duration, + block_builder_fee_info, + ); + }) + .unwrap(); + + Self { bundle_thread } + } + + // rollup transaction cost details, eg signature_cost, write_lock_cost, data_bytes_cost and + // execution_cost from the batch of transactions selected for block. + fn accumulate_batched_transaction_costs<'a>( + transactions_costs: impl Iterator, + transaction_results: impl Iterator>, + ) -> BatchedTransactionDetails { + let mut batched_transaction_details = BatchedTransactionDetails::default(); + transactions_costs + .zip(transaction_results) + .for_each(|(cost, result)| match result { + Ok(_) => { + saturating_add_assign!( + batched_transaction_details.costs.batched_signature_cost, + cost.signature_cost + ); + saturating_add_assign!( + batched_transaction_details.costs.batched_write_lock_cost, + cost.write_lock_cost + ); + saturating_add_assign!( + batched_transaction_details.costs.batched_data_bytes_cost, + cost.data_bytes_cost + ); + saturating_add_assign!( + batched_transaction_details + .costs + .batched_builtins_execute_cost, + cost.builtins_execution_cost + ); + saturating_add_assign!( + batched_transaction_details.costs.batched_bpf_execute_cost, + cost.bpf_execution_cost + ); + } + Err(transaction_error) => match transaction_error { + TransactionError::WouldExceedMaxBlockCostLimit => { + saturating_add_assign!( + batched_transaction_details + .errors + .batched_retried_txs_per_block_limit_count, + 1 + ); + } + TransactionError::WouldExceedMaxVoteCostLimit => { + saturating_add_assign!( + batched_transaction_details + .errors + .batched_retried_txs_per_vote_limit_count, + 1 + ); + } + TransactionError::WouldExceedMaxAccountCostLimit => { + saturating_add_assign!( + batched_transaction_details + .errors + .batched_retried_txs_per_account_limit_count, + 1 + ); + } + TransactionError::WouldExceedAccountDataBlockLimit => { + saturating_add_assign!( + batched_transaction_details + .errors + .batched_retried_txs_per_account_data_block_limit_count, + 1 + ); + } + TransactionError::WouldExceedAccountDataTotalLimit => { + saturating_add_assign!( + batched_transaction_details + .errors + .batched_dropped_txs_per_account_data_total_limit_count, + 1 + ); + } + _ => {} + }, + }); + batched_transaction_details + } + + /// Calculates QoS and reserves compute space for the bundle. If the bundle succeeds, commits + /// the results to the cost tracker. If the bundle fails, rolls back any QoS changes made. + /// Ensure that SanitizedBundle was returned by BundleAccountLocker to avoid parallelism issues + /// with banking stage + fn update_qos_and_execute_record_commit_bundle( + sanitized_bundle: &SanitizedBundle, + recorder: &TransactionRecorder, + transaction_status_sender: &Option, + gossip_vote_sender: &ReplayVoteSender, + qos_service: &QosService, + bank_start: &BankStart, + bundle_stage_leader_stats: &mut BundleStageLeaderStats, + max_bundle_retry_duration: &Duration, + ) -> BundleStageResult<()> { + if sanitized_bundle.transactions.is_empty() { + return Ok(()); + } + + let tx_costs = qos_service.compute_transaction_costs(sanitized_bundle.transactions.iter()); + let (transactions_qos_results, num_included) = qos_service.select_transactions_per_cost( + sanitized_bundle.transactions.iter(), + tx_costs.iter(), + &bank_start.working_bank, + ); + + // qos rate-limited a tx in here, drop the bundle + if sanitized_bundle.transactions.len() != num_included { + QosService::remove_transaction_costs( + tx_costs.iter(), + transactions_qos_results.iter(), + &bank_start.working_bank, + ); + return Err(BundleExecutionError::ExceedsCostModel); + } + + // accumulates QoS to metrics + qos_service.accumulate_estimated_transaction_costs( + &Self::accumulate_batched_transaction_costs( + tx_costs.iter(), + transactions_qos_results.iter(), + ), + ); + + match Self::execute_record_commit_bundle( + sanitized_bundle, + recorder, + transaction_status_sender, + gossip_vote_sender, + bank_start, + bundle_stage_leader_stats, + max_bundle_retry_duration, + ) { + Ok(commit_transaction_details) => { + // NOTE: Assumptions made on the QoS transaction costs: + // - commit_transaction_details are returned in the same ordering as the transactions + // in the sanitized_bundle, which is the same ordering as tx_costs. + // - all contents in the bundle are committed (it's executed all or nothing). + // When fancier execution algorithms are made that may execute transactions out of + // order (but resulting in same result as if they were executed sequentially), or + // allow failures in bundles, one should revisit this and the code that returns + // commit_transaction_details. + QosService::update_or_remove_transaction_costs( + tx_costs.iter(), + transactions_qos_results.iter(), + Some(&commit_transaction_details), + &bank_start.working_bank, + ); + let (cu, us) = Self::accumulate_execute_units_and_time( + &bundle_stage_leader_stats + .execute_and_commit_timings() + .execute_timings, + ); + qos_service.accumulate_actual_execute_cu(cu); + qos_service.accumulate_actual_execute_time(us); + qos_service.report_metrics(bank_start.working_bank.clone()); + Ok(()) + } + Err(e) => { + QosService::remove_transaction_costs( + tx_costs.iter(), + transactions_qos_results.iter(), + &bank_start.working_bank, + ); + qos_service.report_metrics(bank_start.working_bank.clone()); + Err(e) + } + } + } + + fn execute_bundle( + sanitized_bundle: &SanitizedBundle, + transaction_status_sender: &Option, + bank_start: &BankStart, + bundle_stage_leader_stats: &mut BundleStageLeaderStats, + max_bundle_retry_duration: &Duration, + ) -> BundleStageResult> { + let mut account_overrides = AccountOverrides::default(); + + let mut execution_results = Vec::new(); + let mut mint_decimals: HashMap = HashMap::new(); + + let BankStart { + working_bank: bank, + bank_creation_time, + } = bank_start; + + let mut chunk_start = 0; + let start_time = Instant::now(); + while chunk_start != sanitized_bundle.transactions.len() { + if !Bank::should_bank_still_be_processing_txs(bank_creation_time, bank.ns_per_slot) { + return Err(BundleExecutionError::PohMaxHeightError); + } + + // ************************************************************************ + // Build a TransactionBatch that ensures transactions in the bundle + // are executed sequentially. + // NOTE: The TransactionBatch is dropped before the results are committed, which + // would normally open up race conditions between this stage and BankingStage where + // a transaction here could read and execute state on a transaction and BankingStage + // could read-execute-store, invaliding the state produced by the bundle. + // Assuming the SanitizedBundle was locked with the BundleAccountLocker, that race + // condition shall be prevented as it holds an extra set of locks until the entire + // bundle is processed. + // ************************************************************************ + let chunk_end = std::cmp::min(sanitized_bundle.transactions.len(), chunk_start + 128); + let chunk = &sanitized_bundle.transactions[chunk_start..chunk_end]; + let batch = bank.prepare_sequential_sanitized_batch_with_results(chunk, None); + + // Ensures that bundle lock results only return either: + // Ok(()) + // Err(TransactionError::AccountInUse) + // Err(TransactionError::BundleNotContinuous) + // if unexpected failure case, the bundle can't be executed + // NOTE: previous logging around batch here caused issues with + // unit tests failing due to PoH hitting max height. Unknown why. Be advised. + if let Some((e, _)) = check_bundle_lock_results(batch.lock_results()) { + return Err(e.into()); + } + + let ((pre_balances, pre_token_balances), collect_balances_elapsed) = measure!( + Self::collect_balances( + bank, + &batch, + &account_overrides, + transaction_status_sender, + &mut mint_decimals, + ), + "collect_balances", + ); + saturating_add_assign!( + bundle_stage_leader_stats + .execute_and_commit_timings() + .collect_balances_us, + collect_balances_elapsed.as_us() + ); + + let (mut load_and_execute_transactions_output, load_execute_time) = measure!( + bank.load_and_execute_transactions( + &batch, + MAX_PROCESSING_AGE, + transaction_status_sender.is_some(), + transaction_status_sender.is_some(), + &mut bundle_stage_leader_stats + .execute_and_commit_timings() + .execute_timings, + Some(&account_overrides), + ), + "load_execute", + ); + + saturating_add_assign!( + bundle_stage_leader_stats + .execute_and_commit_timings() + .load_execute_us, + load_execute_time.as_us() + ); + bundle_stage_leader_stats + .transaction_errors() + .accumulate(&load_and_execute_transactions_output.error_counters); + + debug!( + "execution results: {:?}", + load_and_execute_transactions_output.execution_results + ); + // Return error if executed and failed or didn't execute because of an unexpected reason. + // The only acceptable reasons for not executing would be failure to lock errors from: + // Ok(()) + // Err(TransactionError::AccountInUse) + // Err(TransactionError::BundleNotContinuous) + // If there's another error (AlreadyProcessed, InsufficientFundsForFee, etc.), bail out + if let Err((e, _)) = TransactionExecutionResult::check_bundle_execution_results( + load_and_execute_transactions_output + .execution_results + .as_slice(), + batch.sanitized_transactions(), + ) { + debug!("execution error"); + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_num_execution_failures(1); + + return Err(e); + } + + // The errors have been checked above, now check to see if any were executed at all + // If none were executed, check to see if the bundle timed out and if so, return timeout + // error + if !load_and_execute_transactions_output + .execution_results + .iter() + .any(|r| r.was_executed()) + { + debug!("retrying bundle"); + + let bundle_execution_elapsed = start_time.elapsed(); + if bundle_execution_elapsed >= *max_bundle_retry_duration { + warn!("bundle timed out: {:?}", sanitized_bundle); + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_num_execution_timeouts(1); + return Err(BundleExecutionError::MaxRetriesExceeded( + bundle_execution_elapsed, + )); + } + + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_num_execution_retries(1); + continue; + } + + // ********************************************************************************* + // Cache results so next iterations of bundle execution can load cached state + // instead of using AccountsDB which contains stale execution data. + // ********************************************************************************* + Self::cache_accounts( + bank, + batch.sanitized_transactions(), + &load_and_execute_transactions_output.execution_results, + &mut load_and_execute_transactions_output.loaded_transactions, + &mut account_overrides, + ); + + let ((post_balances, post_token_balances), collect_balances_elapsed) = measure!( + Self::collect_balances( + bank, + &batch, + &account_overrides, + transaction_status_sender, + &mut mint_decimals, + ), + "collect_balances", + ); + + saturating_add_assign!( + bundle_stage_leader_stats + .execute_and_commit_timings() + .collect_balances_us, + collect_balances_elapsed.as_us() + ); + + execution_results.push(AllExecutionResults { + load_and_execute_tx_output: load_and_execute_transactions_output, + sanitized_txs: batch.sanitized_transactions().to_vec(), + pre_balances: (pre_balances, pre_token_balances), + post_balances: (post_balances, post_token_balances), + }); + + // start at the next available transaction in the batch that threw an error + let processing_end = batch.lock_results().iter().position(|lr| lr.is_err()); + if let Some(end) = processing_end { + chunk_start += end; + } else { + chunk_start = chunk_end; + } + + drop(batch); + } + Ok(execution_results) + } + + /// Executes a bundle, where all transactions in the bundle are executed all-or-nothing. + /// Executes all transactions until the end or the first failure. The account state between + /// iterations is cached to a temporary HashMap to be used on successive runs + #[allow(clippy::too_many_arguments)] + fn execute_record_commit_bundle( + sanitized_bundle: &SanitizedBundle, + recorder: &TransactionRecorder, + transaction_status_sender: &Option, + gossip_vote_sender: &ReplayVoteSender, + bank_start: &BankStart, + bundle_stage_leader_stats: &mut BundleStageLeaderStats, + max_bundle_retry_duration: &Duration, + ) -> BundleStageResult> { + let execution_results = Self::execute_bundle( + sanitized_bundle, + transaction_status_sender, + bank_start, + bundle_stage_leader_stats, + max_bundle_retry_duration, + )?; + // in order for bundle to succeed, it most have something to record + commit + assert!(!execution_results.is_empty()); + + Self::record_commit_bundle( + execution_results, + &bank_start.working_bank, + recorder, + bundle_stage_leader_stats, + transaction_status_sender, + gossip_vote_sender, + ) + } + + /// Records the entire bundle to PoH and if successful, commits all transactions to the Bank + /// Note that the BundleAccountLocker still has a lock on these accounts in the bank + fn record_commit_bundle( + execution_results: Vec, + bank: &Arc, + recorder: &TransactionRecorder, + bundle_stage_leader_stats: &mut BundleStageLeaderStats, + transaction_status_sender: &Option, + gossip_vote_sender: &ReplayVoteSender, + ) -> BundleStageResult> { + // ********************************************************************************* + // All transactions are executed in the bundle. + // Record to PoH and send the saved execution results to the Bank. + // Note: Ensure that bank.commit_transactions is called on a per-batch basis and + // not all together + // ********************************************************************************* + debug!("grabbing freeze lock"); + let (_freeze_lock, freeze_lock_time) = measure!(bank.freeze_lock(), "freeze_lock"); + saturating_add_assign!( + bundle_stage_leader_stats + .execute_and_commit_timings() + .freeze_lock_us, + freeze_lock_time.as_us() + ); + + let (slot, mixins) = Self::prepare_poh_record_bundle( + &bank.slot(), + &execution_results, + &mut bundle_stage_leader_stats + .execute_and_commit_timings() + .record_transactions_timings, + ); + + debug!("recording bundle"); + let (_, record_elapsed) = measure!( + Self::try_record(recorder, slot, mixins).map_err(|e| { + error!("error recording bundle: {:?}", e); + e + })?, + "record_elapsed" + ); + debug!("bundle recorded"); + + saturating_add_assign!( + bundle_stage_leader_stats + .execute_and_commit_timings() + .record_us, + record_elapsed.as_us() + ); + bundle_stage_leader_stats + .execute_and_commit_timings() + .record_transactions_timings + .accumulate(&RecordTransactionsTimings { + execution_results_to_transactions_us: 0, + hash_us: 0, + poh_record_us: record_elapsed.as_us(), + }); + + let mut commit_transaction_details = Vec::new(); + for r in execution_results { + let mut output = r.load_and_execute_tx_output; + let sanitized_txs = r.sanitized_txs; + + let (last_blockhash, lamports_per_signature) = + bank.last_blockhash_and_lamports_per_signature(); + + let (transaction_results, commit_elapsed) = measure!( + bank.commit_transactions( + &sanitized_txs, + &mut output.loaded_transactions, + output.execution_results.clone(), + last_blockhash, + lamports_per_signature, + CommitTransactionCounts { + committed_transactions_count: output.executed_transactions_count as u64, + committed_with_failure_result_count: output + .executed_transactions_count + .saturating_sub(output.executed_with_successful_result_count) + as u64, + signature_count: output.signature_count, + }, + &mut bundle_stage_leader_stats + .execute_and_commit_timings() + .execute_timings, + ), + "commit_elapsed" + ); + saturating_add_assign!( + bundle_stage_leader_stats + .execute_and_commit_timings() + .commit_us, + commit_elapsed.as_us() + ); + + let (_, find_and_send_votes_elapsed) = measure!( + { + bank_utils::find_and_send_votes( + &sanitized_txs, + &transaction_results, + Some(gossip_vote_sender), + ); + if let Some(transaction_status_sender) = transaction_status_sender { + transaction_status_sender.send_transaction_status_batch( + bank.clone(), + sanitized_txs, + output.execution_results, + TransactionBalancesSet::new(r.pre_balances.0, r.post_balances.0), + TransactionTokenBalancesSet::new(r.pre_balances.1, r.post_balances.1), + transaction_results.rent_debits.clone(), + ); + } + }, + "find_and_send_votes", + ); + + saturating_add_assign!( + bundle_stage_leader_stats + .execute_and_commit_timings() + .find_and_send_votes_us, + find_and_send_votes_elapsed.as_us() + ); + + for tx_results in transaction_results.execution_results { + if let Some(details) = tx_results.details() { + commit_transaction_details.push(CommitTransactionDetails::Committed { + compute_units: details.executed_units, + }); + } + } + } + Ok(commit_transaction_details) + } + + /// Returns true if any of the transactions in a bundle mention one of the tip PDAs + fn bundle_touches_tip_pdas( + transactions: &[SanitizedTransaction], + tip_pdas: &HashSet, + ) -> bool { + let mut bundle_touches_tip_pdas = false; + for tx in transactions { + if tx + .message() + .account_keys() + .iter() + .any(|a| tip_pdas.contains(a)) + { + bundle_touches_tip_pdas = true; + break; + } + } + bundle_touches_tip_pdas + } + + fn accumulate_execute_units_and_time(execute_timings: &ExecuteTimings) -> (u64, u64) { + let (units, times): (Vec<_>, Vec<_>) = execute_timings + .details + .per_program_timings + .iter() + .map(|(_program_id, program_timings)| { + ( + program_timings.accumulated_units, + program_timings.accumulated_us, + ) + }) + .unzip(); + (units.iter().sum(), times.iter().sum()) + } + + fn cache_accounts( + bank: &Arc, + txs: &[SanitizedTransaction], + res: &[TransactionExecutionResult], + loaded: &mut [TransactionLoadResult], + cached_accounts: &mut AccountOverrides, + ) { + let accounts = bank.collect_accounts_to_store(txs, res, loaded); + for (pubkey, data) in accounts { + cached_accounts.set_account(pubkey, Some(data.clone())); + } + } + + fn collect_balances( + bank: &Arc, + batch: &TransactionBatch, + cached_accounts: &AccountOverrides, + transaction_status_sender: &Option, + mint_decimals: &mut HashMap, + ) -> (TransactionBalances, TransactionTokenBalances) { + if transaction_status_sender.is_some() { + let balances = bank.collect_balances_with_cache(batch, Some(cached_accounts)); + let token_balances = + collect_token_balances(bank, batch, mint_decimals, Some(cached_accounts)); + (balances, token_balances) + } else { + (vec![], vec![]) + } + } + + /// When executed the first time, there's some accounts that need to be initialized. + /// This is only helpful for local testing, on testnet and mainnet these will never be executed. + /// TODO (LB): consider removing this for mainnet/testnet and move to program deployment? + fn get_initialize_tip_accounts_transactions( + bank: &Bank, + tip_manager: &TipManager, + cluster_info: &Arc, + ) -> BundleStageResult> { + let maybe_init_tip_payment_config_tx = + if tip_manager.should_initialize_tip_payment_program(bank) { + info!("building initialize_tip_payment_program_tx"); + Some(tip_manager.initialize_tip_payment_program_tx( + bank.last_blockhash(), + &cluster_info.keypair(), + )) + } else { + None + }; + + let maybe_init_tip_distro_config_tx = + if tip_manager.should_initialize_tip_distribution_config(bank) { + info!("building initialize_tip_distribution_config_tx"); + Some(tip_manager.initialize_tip_distribution_config_tx( + bank.last_blockhash(), + &cluster_info.keypair(), + )) + } else { + None + }; + + let maybe_init_tip_distro_account_tx = if tip_manager + .should_init_tip_distribution_account(bank) + { + info!("building init_tip_distribution_account_tx"); + Some(tip_manager.init_tip_distribution_account_tx(bank.last_blockhash(), bank.epoch())) + } else { + None + }; + + let transactions = [ + maybe_init_tip_payment_config_tx, + maybe_init_tip_distro_config_tx, + maybe_init_tip_distro_account_tx, + ] + .into_iter() + .flatten() + .collect::>(); + + Ok(transactions) + } + + /// Execute all unprocessed bundles until no more left or POH max tick height is reached. + /// For any bundles that didn't execute due to POH max tick height reached, add them + /// back onto the front of unprocessed_bundles in reverse order to preserve original ordering + #[allow(clippy::too_many_arguments)] + fn execute_bundles_until_empty_or_end_of_slot( + bundle_account_locker: &BundleAccountLocker, + unprocessed_bundles: &mut VecDeque, + blacklisted_accounts: &HashSet, + bank_start: &BankStart, + consensus_accounts_cache: &HashSet, + cluster_info: &Arc, + recorder: &TransactionRecorder, + transaction_status_sender: &Option, + gossip_vote_sender: &ReplayVoteSender, + qos_service: &QosService, + tip_manager: &TipManager, + max_bundle_retry_duration: &Duration, + last_tip_update_slot: &mut Slot, + bundle_stage_leader_stats: &mut BundleStageLeaderStats, + block_builder_fee_info: &Arc>, + ) { + let (sanitized_bundles, sanitized_bundle_elapsed) = measure!( + unprocessed_bundles + .drain(..) + .into_iter() + .filter_map(|packet_bundle| { + match get_sanitized_bundle( + &packet_bundle, + &bank_start.working_bank, + consensus_accounts_cache, + blacklisted_accounts, + bundle_stage_leader_stats.transaction_errors(), + ) { + Ok(sanitized_bundle) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_sanitize_transaction_ok(1); + Some((packet_bundle, sanitized_bundle)) + } + Err(BundleSanitizerError::VoteOnlyMode) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_sanitize_transaction_vote_only_mode(1); + None + } + Err(BundleSanitizerError::FailedPacketBatchPreCheck) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_sanitize_transaction_failed_precheck(1); + None + } + Err(BundleSanitizerError::BlacklistedAccount) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_sanitize_transaction_blacklisted_account(1); + None + } + Err(BundleSanitizerError::FailedToSerializeTransaction) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_sanitize_transaction_failed_to_serialize(1); + None + } + Err(BundleSanitizerError::DuplicateTransaction) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_sanitize_transaction_duplicate_transaction(1); + None + } + Err(BundleSanitizerError::FailedCheckTransactions) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_sanitize_transaction_failed_check(1); + None + } + } + }) + .collect::>(), + "sanitized_bundle_elapsed" + ); + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_sanitize_bundle_elapsed_us(sanitized_bundle_elapsed.as_us()); + + // Prepare locked bundles, which will RW lock accounts in sanitized_bundles so + // BankingStage can't lock them. This adds a layer of protection since a transaction in a bundle + // will not hold the AccountLocks through TransactionBatch across load-execute-commit cycle. + // We collect here to ensure that all of the bundles are locked ahead of time for priority over + // BankingStage + #[allow(clippy::needless_collect)] + let (locked_bundles, locked_bundles_elapsed) = measure!( + sanitized_bundles + .iter() + .map(|(_, sanitized_bundle)| { + bundle_account_locker + .prepare_locked_bundle(sanitized_bundle, &bank_start.working_bank) + }) + .collect::>>(), + "locked_bundles_elapsed" + ); + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_locked_bundle_elapsed_us(locked_bundles_elapsed.as_us()); + + let (execution_results, execute_locked_bundles_elapsed) = measure!( + Self::execute_locked_bundles( + bundle_account_locker, + locked_bundles, + bank_start, + cluster_info, + recorder, + transaction_status_sender, + gossip_vote_sender, + qos_service, + tip_manager, + max_bundle_retry_duration, + last_tip_update_slot, + bundle_stage_leader_stats, + block_builder_fee_info + ), + "execute_locked_bundles_elapsed" + ); + + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_execute_locked_bundles_elapsed_us(execute_locked_bundles_elapsed.as_us()); + + execution_results + .into_iter() + .zip(sanitized_bundles.into_iter()) + .for_each( + |(bundle_execution_result, (packet_bundle, _))| match bundle_execution_result { + Ok(_) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_execution_results_ok(1); + } + Err(BundleExecutionError::PohMaxHeightError) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_execution_results_poh_max_height(1); + // retry the bundle + unprocessed_bundles.push_back(packet_bundle); + } + Err(BundleExecutionError::TransactionFailure(_)) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_execution_results_transaction_failures(1); + } + Err(BundleExecutionError::ExceedsCostModel) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_execution_results_exceeds_cost_model(1); + } + Err(BundleExecutionError::TipError(_)) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_execution_results_tip_errors(1); + } + Err(BundleExecutionError::Shutdown) => {} + Err(BundleExecutionError::MaxRetriesExceeded(_)) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_execution_results_max_retries(1); + } + Err(BundleExecutionError::LockError) => { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_execution_results_lock_errors(1); + } + }, + ); + } + + /// This only needs to be done once on program initialization + /// TODO (LB): may make sense to remove this and move to program deployment instead, but helpful + /// during development + #[allow(clippy::too_many_arguments)] + fn maybe_initialize_tip_accounts( + bundle_account_locker: &BundleAccountLocker, + bank_start: &BankStart, + cluster_info: &Arc, + recorder: &TransactionRecorder, + transaction_status_sender: &Option, + gossip_vote_sender: &ReplayVoteSender, + qos_service: &QosService, + tip_manager: &TipManager, + max_bundle_retry_duration: &Duration, + bundle_stage_leader_stats: &mut BundleStageLeaderStats, + ) -> BundleStageResult<()> { + let initialize_tip_accounts_bundle = SanitizedBundle { + transactions: Self::get_initialize_tip_accounts_transactions( + &bank_start.working_bank, + tip_manager, + cluster_info, + )?, + }; + if !initialize_tip_accounts_bundle.transactions.is_empty() { + debug!("initialize tip account"); + + let locked_init_tip_bundle = bundle_account_locker + .prepare_locked_bundle(&initialize_tip_accounts_bundle, &bank_start.working_bank) + .map_err(|_| BundleExecutionError::LockError)?; + let result = Self::update_qos_and_execute_record_commit_bundle( + locked_init_tip_bundle.sanitized_bundle(), + recorder, + transaction_status_sender, + gossip_vote_sender, + qos_service, + bank_start, + bundle_stage_leader_stats, + max_bundle_retry_duration, + ); + + match &result { + Ok(_) => { + debug!("initialize tip account: success"); + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_num_init_tip_account_ok(1); + } + Err(e) => { + error!("initialize tip account error: {:?}", e); + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_num_init_tip_account_errors(1); + } + } + result + } else { + Ok(()) + } + } + + /// change tip receiver, draining tips to the previous tip_receiver in the process + /// note that this needs to happen after the above tip-related bundle initializes + /// config accounts because get_configured_tip_receiver relies on an account + /// existing in the bank + #[allow(clippy::too_many_arguments)] + fn maybe_change_tip_receiver( + bundle_account_locker: &BundleAccountLocker, + bank_start: &BankStart, + cluster_info: &Arc, + recorder: &TransactionRecorder, + transaction_status_sender: &Option, + gossip_vote_sender: &ReplayVoteSender, + qos_service: &QosService, + tip_manager: &TipManager, + max_bundle_retry_duration: &Duration, + bundle_stage_leader_stats: &mut BundleStageLeaderStats, + block_builder_fee_info: &Arc>, + ) -> BundleStageResult<()> { + let start_handle_tips = Instant::now(); + + let configured_tip_receiver = + tip_manager.get_configured_tip_receiver(&bank_start.working_bank)?; + let my_tip_distribution_pda = + tip_manager.get_my_tip_distribution_pda(bank_start.working_bank.epoch()); + if configured_tip_receiver != my_tip_distribution_pda { + info!( + "changing tip receiver from {} to {}", + configured_tip_receiver, my_tip_distribution_pda + ); + + let bb_info = block_builder_fee_info.lock().unwrap(); + let change_tip_receiver_tx = tip_manager.change_tip_receiver_and_block_builder_tx( + &my_tip_distribution_pda, + &bank_start.working_bank, + &cluster_info.keypair(), + &bb_info.block_builder, + bb_info.block_builder_commission, + )?; + + let change_tip_receiver_bundle = SanitizedBundle { + transactions: vec![change_tip_receiver_tx], + }; + let locked_change_tip_receiver_bundle = bundle_account_locker + .prepare_locked_bundle(&change_tip_receiver_bundle, &bank_start.working_bank) + .map_err(|_| BundleExecutionError::LockError)?; + let result = Self::update_qos_and_execute_record_commit_bundle( + locked_change_tip_receiver_bundle.sanitized_bundle(), + recorder, + transaction_status_sender, + gossip_vote_sender, + qos_service, + bank_start, + bundle_stage_leader_stats, + max_bundle_retry_duration, + ); + + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_change_tip_receiver_elapsed_us( + start_handle_tips.elapsed().as_micros() as u64 + ); + + match &result { + Ok(_) => { + debug!("change tip receiver: success"); + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_num_change_tip_receiver_ok(1); + } + Err(e) => { + error!("change tip receiver: error {:?}", e); + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_num_change_tip_receiver_errors(1); + } + } + result + } else { + Ok(()) + } + } + + #[allow(clippy::too_many_arguments)] + fn execute_locked_bundles( + bundle_account_locker: &BundleAccountLocker, + locked_bundles: Vec>, + bank_start: &BankStart, + cluster_info: &Arc, + recorder: &TransactionRecorder, + transaction_status_sender: &Option, + gossip_vote_sender: &ReplayVoteSender, + qos_service: &QosService, + tip_manager: &TipManager, + max_bundle_retry_duration: &Duration, + last_tip_update_slot: &mut Slot, + bundle_stage_leader_stats: &mut BundleStageLeaderStats, + block_builder_fee_info: &Arc>, + ) -> Vec> { + let tip_pdas = tip_manager.get_tip_accounts(); + + // make sure each locked_bundle is dropped after processing to unlock BankingStage + locked_bundles + .into_iter() + .map(|maybe_locked_bundle| { + let locked_bundle = maybe_locked_bundle.as_ref().map_err(|_| { + bundle_stage_leader_stats + .bundle_stage_stats() + .increment_num_lock_errors(1); + + BundleExecutionError::LockError + })?; + + if !Bank::should_bank_still_be_processing_txs( + &bank_start.bank_creation_time, + bank_start.working_bank.ns_per_slot, + ) { + Err(BundleExecutionError::PohMaxHeightError) + } else { + let sanitized_bundle = locked_bundle.sanitized_bundle(); + + if Self::bundle_touches_tip_pdas(&sanitized_bundle.transactions, &tip_pdas) + && bank_start.working_bank.slot() != *last_tip_update_slot + { + Self::maybe_initialize_tip_accounts( + bundle_account_locker, + bank_start, + cluster_info, + recorder, + transaction_status_sender, + gossip_vote_sender, + qos_service, + tip_manager, + max_bundle_retry_duration, + bundle_stage_leader_stats, + )?; + + Self::maybe_change_tip_receiver( + bundle_account_locker, + bank_start, + cluster_info, + recorder, + transaction_status_sender, + gossip_vote_sender, + qos_service, + tip_manager, + max_bundle_retry_duration, + bundle_stage_leader_stats, + block_builder_fee_info, + )?; + + *last_tip_update_slot = bank_start.working_bank.slot(); + } + + Self::update_qos_and_execute_record_commit_bundle( + sanitized_bundle, + recorder, + transaction_status_sender, + gossip_vote_sender, + qos_service, + bank_start, + bundle_stage_leader_stats, + max_bundle_retry_duration, + ) + } + }) + .collect() + } + + fn receive_and_buffer_bundles( + bundle_receiver: &Receiver>, + unprocessed_bundles: &mut VecDeque, + timeout: Duration, + ) -> Result { + let bundles = bundle_receiver.recv_timeout(timeout)?; + let num_bundles_before = unprocessed_bundles.len(); + unprocessed_bundles.extend(bundles); + unprocessed_bundles.extend(bundle_receiver.try_iter().flatten()); + let num_bundles_after = unprocessed_bundles.len(); + Ok(num_bundles_after - num_bundles_before) + } + + #[allow(clippy::too_many_arguments)] + fn process_buffered_bundles( + bundle_account_locker: &BundleAccountLocker, + unprocessed_bundles: &mut VecDeque, + blacklisted_accounts: &HashSet, + consensus_cache_updater: &mut ConsensusCacheUpdater, + cluster_info: &Arc, + recorder: &TransactionRecorder, + poh_recorder: &Arc>, + transaction_status_sender: &Option, + gossip_vote_sender: &ReplayVoteSender, + qos_service: &QosService, + tip_manager: &TipManager, + max_bundle_retry_duration: &Duration, + last_tip_update_slot: &mut u64, + bundle_stage_leader_stats: &mut BundleStageLeaderSlotTrackingMetrics, + bundle_stage_stats: &mut BundleStageLoopStats, + id: u32, + block_builder_fee_info: &Arc>, + ) { + const DROP_BUNDLE_SLOT_OFFSET: u64 = 4; + + let r_poh_recorder = poh_recorder.lock().unwrap(); + let poh_recorder_bank = r_poh_recorder.get_poh_recorder_bank(); + let working_bank_start = poh_recorder_bank.working_bank_start(); + let would_be_leader_soon = + r_poh_recorder.would_be_leader(DROP_BUNDLE_SLOT_OFFSET * DEFAULT_TICKS_PER_SLOT); + drop(r_poh_recorder); + + bundle_stage_leader_stats.maybe_report(id, &working_bank_start); + + match (working_bank_start, would_be_leader_soon) { + // leader now, insert new read bundles + as many as can read then return bank + (Some(bank_start), _) => { + consensus_cache_updater.maybe_update(&bank_start.working_bank); + + Self::execute_bundles_until_empty_or_end_of_slot( + bundle_account_locker, + unprocessed_bundles, + blacklisted_accounts, + bank_start, + consensus_cache_updater.consensus_accounts_cache(), + cluster_info, + recorder, + transaction_status_sender, + gossip_vote_sender, + qos_service, + tip_manager, + max_bundle_retry_duration, + last_tip_update_slot, + bundle_stage_leader_stats.bundle_stage_leader_stats(), + block_builder_fee_info, + ); + } + // not leader now and not soon, clear bundles + (None, false) => { + saturating_add_assign!( + bundle_stage_stats.num_bundles_dropped, + unprocessed_bundles.len() as u64 + ); + + unprocessed_bundles.clear(); + } + _ => {} + } + } + + #[allow(clippy::too_many_arguments)] + fn process_loop( + cluster_info: Arc, + poh_recorder: &Arc>, + transaction_status_sender: Option, + bundle_receiver: Receiver>, + gossip_vote_sender: ReplayVoteSender, + id: u32, + cost_model: Arc>, + exit: Arc, + tip_manager: TipManager, + bundle_account_locker: BundleAccountLocker, + max_bundle_retry_duration: Duration, + block_builder_fee_info: Arc>, + ) { + const LOOP_STATS_METRICS_PERIOD: Duration = Duration::from_secs(1); + + let recorder = poh_recorder.lock().unwrap().recorder(); + let qos_service = QosService::new(cost_model, id); + + // Bundles can't mention any accounts related to consensus + let mut consensus_cache_updater = ConsensusCacheUpdater::default(); + let mut last_tip_update_slot = Slot::default(); + + let mut last_leader_slots_update_time = Instant::now(); + let mut bundle_stage_leader_stats = BundleStageLeaderSlotTrackingMetrics::default(); + let mut bundle_stage_stats = BundleStageLoopStats::default(); + + // Bundles can't mention the tip payment program to ensure that a malicious entity doesn't + // steal tips mid-slot + let blacklisted_accounts = HashSet::from_iter([tip_manager.tip_payment_program_id()]); + + let mut unprocessed_bundles: VecDeque = VecDeque::with_capacity(1000); + while !exit.load(Ordering::Relaxed) { + if !unprocessed_bundles.is_empty() + || last_leader_slots_update_time.elapsed() >= SLOT_BOUNDARY_CHECK_PERIOD + { + let (_, process_buffered_bundles_elapsed) = measure!( + Self::process_buffered_bundles( + &bundle_account_locker, + &mut unprocessed_bundles, + &blacklisted_accounts, + &mut consensus_cache_updater, + &cluster_info, + &recorder, + poh_recorder, + &transaction_status_sender, + &gossip_vote_sender, + &qos_service, + &tip_manager, + &max_bundle_retry_duration, + &mut last_tip_update_slot, + &mut bundle_stage_leader_stats, + &mut bundle_stage_stats, + id, + &block_builder_fee_info + ), + "process_buffered_bundles_elapsed" + ); + + saturating_add_assign!( + bundle_stage_stats.process_buffered_bundles_elapsed_us, + process_buffered_bundles_elapsed.as_us() + ); + last_leader_slots_update_time = Instant::now(); + } + + bundle_stage_stats.maybe_report(id, LOOP_STATS_METRICS_PERIOD); + + // ensure bundle stage can run immediately if bundles to process, otherwise okay + // chilling for a few + let sleep_time = if !unprocessed_bundles.is_empty() { + Duration::from_millis(0) + } else { + Duration::from_millis(10) + }; + + let (res, receive_and_buffer_elapsed) = measure!( + Self::receive_and_buffer_bundles( + &bundle_receiver, + &mut unprocessed_bundles, + sleep_time, + ), + "receive_and_buffer_elapsed" + ); + saturating_add_assign!( + bundle_stage_stats.receive_and_buffer_bundles_elapsed_us, + receive_and_buffer_elapsed.as_us() + ); + + match res { + Ok(num_bundles_received) => { + saturating_add_assign!( + bundle_stage_stats.num_bundles_received, + num_bundles_received as u64 + ); + } + Err(RecvTimeoutError::Timeout) => {} + Err(RecvTimeoutError::Disconnected) => { + break; + } + } + } + } + + fn prepare_poh_record_bundle( + bank_slot: &Slot, + execution_results_txs: &[AllExecutionResults], + record_transactions_timings: &mut RecordTransactionsTimings, + ) -> (Slot, Vec<(Hash, Vec)>) { + let mut new_record_transaction_timings = RecordTransactionsTimings::default(); + + let mixins_txs = execution_results_txs + .iter() + .map(|r| { + let (processed_transactions, results_to_transactions_elapsed) = measure!( + { + r.load_and_execute_tx_output + .execution_results + .iter() + .zip(r.sanitized_txs.iter()) + .filter_map(|(execution_result, tx)| { + if execution_result.was_executed() { + Some(tx.to_versioned_transaction()) + } else { + None + } + }) + .collect::>() + }, + "results_to_transactions_elapsed" + ); + + let (hash, hash_elapsed) = measure!( + hash_transactions(&processed_transactions[..]), + "hash_elapsed" + ); + + saturating_add_assign!( + new_record_transaction_timings.execution_results_to_transactions_us, + results_to_transactions_elapsed.as_us() + ); + saturating_add_assign!( + new_record_transaction_timings.hash_us, + hash_elapsed.as_us() + ); + + (hash, processed_transactions) + }) + .collect(); + + record_transactions_timings.accumulate(&new_record_transaction_timings); + + (*bank_slot, mixins_txs) + } + + pub fn join(self) -> thread::Result<()> { + self.bundle_thread.join() + } + + fn try_record( + recorder: &TransactionRecorder, + bank_slot: Slot, + mixins_txs: Vec<(Hash, Vec)>, + ) -> BundleStageResult<()> { + match recorder.record(bank_slot, mixins_txs) { + Ok(()) => Ok(()), + Err(PohRecorderError::MaxHeightReached) => Err(BundleExecutionError::PohMaxHeightError), + Err(e) => panic!("Poh recorder returned unexpected error: {:?}", e), + } + } +} + +#[cfg(test)] +mod tests { + use { + super::*, + crate::bundle_stage::tests::TestOption::{ + AssertDuplicateInBundleDropped, AssertNonZeroCostModel, AssertZeroedCostModel, + LowComputeBudget, + }, + crossbeam_channel::unbounded, + solana_ledger::{ + blockstore::Blockstore, + genesis_utils::{create_genesis_config, GenesisConfigInfo}, + get_tmp_ledger_path_auto_delete, + }, + solana_perf::packet::PacketBatch, + solana_poh::poh_recorder::create_test_recorder, + solana_sdk::{ + bundle::error::BundleExecutionError::{ + ExceedsCostModel, PohMaxHeightError, TransactionFailure, + }, + compute_budget::ComputeBudgetInstruction, + genesis_config::GenesisConfig, + instruction::InstructionError, + message::Message, + packet::Packet, + poh_config::PohConfig, + signature::{Keypair, Signer}, + system_instruction, + system_transaction::{self, transfer}, + transaction::{ + Transaction, + TransactionError::{self, AccountNotFound}, + }, + }, + std::{collections::HashSet, sync::atomic::Ordering}, + uuid::Uuid, + }; + + const TEST_MAX_RETRY_DURATION: Duration = Duration::from_millis(500); + + enum TestOption { + LowComputeBudget, + AssertZeroedCostModel, + AssertNonZeroCostModel, + AssertDuplicateInBundleDropped, + } + + #[cfg(test)] + fn test_single_bundle( + genesis_config: GenesisConfig, + bundle: PacketBundle, + options: Option>, + ) -> Result<(), BundleExecutionError> { + solana_logger::setup(); + let ledger_path = get_tmp_ledger_path_auto_delete!(); + let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + // start a banking_stage to eat verified receiver + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + if options.is_some() + && options + .as_ref() + .unwrap() + .iter() + .any(|option| matches!(option, LowComputeBudget)) + { + bank.write_cost_tracker().unwrap().set_limits(1, 1, 1); + } + let blockstore = Arc::new( + Blockstore::open(ledger_path.path()) + .expect("Expected to be able to open database ledger"), + ); + let poh_config = PohConfig { + // limit tick count to avoid clearing working_bank at + // PohRecord then PohRecorderError(MaxHeightReached) at BankingStage + target_tick_count: Some(bank.max_tick_height() - 1), // == 1, only enough for ticks, not txs + ..PohConfig::default() + }; + let (exit, poh_recorder, poh_service, _entry_receiver) = + create_test_recorder(&bank, &blockstore, Some(poh_config), None); + let recorder = poh_recorder.lock().unwrap().recorder(); + let cost_model = Arc::new(RwLock::new(CostModel::default())); + let qos_service = QosService::new(cost_model, 0); + let mut bundle_stage_leader_stats = BundleStageLeaderStats::default(); + let bank_start = poh_recorder.lock().unwrap().bank_start().unwrap(); + let sanitized_bundle = get_sanitized_bundle( + &bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + bundle_stage_leader_stats.transaction_errors(), + ) + .unwrap(); + + let results = BundleStage::update_qos_and_execute_record_commit_bundle( + &sanitized_bundle, + &recorder, + &None, + &gossip_vote_sender, + &qos_service, + &bank_start, + &mut bundle_stage_leader_stats, + &TEST_MAX_RETRY_DURATION, + ); + + // This is ugly, not really an option for testing but a test itself. + // Still preferable to duplicating the entirety of this method + // just to test duplicate txs are dropped. + if options.is_some() + && options + .as_ref() + .unwrap() + .iter() + .any(|option| matches!(option, AssertDuplicateInBundleDropped)) + { + assert_eq!(results, Ok(())); + assert!(get_sanitized_bundle( + &bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + bundle_stage_leader_stats.transaction_errors(), + ) + .is_err()); + } + + // Transaction rolled back successfully if + // cost tracker has 0 transaction count + // cost tracker as 0 block cost + if options.is_some() + && options + .as_ref() + .unwrap() + .iter() + .any(|option| matches!(option, AssertZeroedCostModel)) + { + assert_eq!(bank.read_cost_tracker().unwrap().transaction_count(), 0); + assert_eq!(bank.read_cost_tracker().unwrap().block_cost(), 0); + } + + if options.is_some() + && options + .as_ref() + .unwrap() + .iter() + .any(|option| matches!(option, AssertNonZeroCostModel)) + { + assert_ne!(bank.read_cost_tracker().unwrap().transaction_count(), 0); + assert_ne!(bank.read_cost_tracker().unwrap().block_cost(), 0); + } + + exit.store(true, Ordering::Relaxed); + poh_service.join().unwrap(); + results + } + + #[test] + fn test_successful_bundle() { + let (genesis_config, bundle) = setup_successful_tx(); + assert_eq!( + test_single_bundle(genesis_config, bundle, Some(vec![AssertNonZeroCostModel])), + Ok(()) + ); + } + + #[test] + fn test_bundle_contains_processed_transaction() { + let (genesis_config, bundle) = setup_successful_tx(); + assert_eq!( + test_single_bundle( + genesis_config, + bundle, + Some(vec![AssertDuplicateInBundleDropped]), + ), + Ok(()) + ); + } + + #[cfg(test)] + fn setup_successful_tx() -> (GenesisConfig, PacketBundle) { + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(5); + + let kp_a = Keypair::new(); + let kp_b = Keypair::new(); + let ix_mint_a = system_instruction::transfer(&mint_keypair.pubkey(), &kp_a.pubkey(), 1); + let ix_mint_b = system_instruction::transfer(&mint_keypair.pubkey(), &kp_b.pubkey(), 1); + let message = Message::new(&[ix_mint_a, ix_mint_b], Some(&mint_keypair.pubkey())); + let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash()); + let packet = Packet::from_data(None, tx).unwrap(); + + ( + genesis_config, + PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }, + ) + } + + #[test] + fn test_txs_exceed_cost_model() { + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(5); + + let kp = Keypair::new(); + let instruction = system_instruction::transfer(&mint_keypair.pubkey(), &kp.pubkey(), 1); + let message = Message::new( + &[ + ComputeBudgetInstruction::set_compute_unit_limit(1), + instruction, + ], + Some(&mint_keypair.pubkey()), + ); + let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash()); + let packet = Packet::from_data(None, tx).unwrap(); + + let bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + assert_eq!( + test_single_bundle(genesis_config, bundle, Some(vec![LowComputeBudget])), + Err(ExceedsCostModel) + ); + } + + #[test] + fn test_nonce_tx_failure() { + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(4); + + let kp_a = Keypair::new(); + let kp_nonce = Keypair::new(); + let kp_nonce_authority = Keypair::new(); + let packet = Packet::from_data( + None, + system_transaction::nonced_transfer( + &mint_keypair, + &kp_a.pubkey(), + 1, + &kp_nonce.pubkey(), + &kp_nonce_authority, + genesis_config.hash(), + ), + ) + .unwrap(); + let bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + + assert_eq!( + test_single_bundle(genesis_config, bundle, None), + Err(TransactionFailure(TransactionError::InstructionError( + 0, + InstructionError::InvalidAccountData, + ))) + ); + } + + #[test] + fn test_qos_rollback() { + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(4); + + let kp_a = Keypair::new(); + let kp_b = Keypair::new(); + let successful_packet = Packet::from_data( + None, + system_transaction::transfer(&mint_keypair, &kp_b.pubkey(), 1, genesis_config.hash()), + ) + .unwrap(); + let failed_packet = Packet::from_data( + None, + system_transaction::transfer(&kp_a, &kp_b.pubkey(), 1, genesis_config.hash()), + ) + .unwrap(); + let bundle = PacketBundle { + batch: PacketBatch::new(vec![successful_packet, failed_packet]), + uuid: Uuid::new_v4(), + }; + + assert_eq!( + test_single_bundle(genesis_config, bundle, Some(vec![AssertZeroedCostModel])), + Err(TransactionFailure(AccountNotFound)) + ); + } + + #[test] + fn test_zero_balance_account() { + let GenesisConfigInfo { + genesis_config, + mint_keypair: _, + .. + } = create_genesis_config(4); + + let kp_a = Keypair::new(); + let kp_b = Keypair::new(); + let packet = Packet::from_data( + None, + system_transaction::transfer(&kp_a, &kp_b.pubkey(), 1, genesis_config.hash()), + ) + .unwrap(); + let bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + + assert_eq!( + test_single_bundle(genesis_config, bundle, None), + Err(TransactionFailure(AccountNotFound)) + ); + } + + #[test] + fn test_bundle_fails_poh_record() { + solana_logger::setup(); + let GenesisConfigInfo { + mut genesis_config, + mint_keypair, + .. + } = create_genesis_config(4); + genesis_config.ticks_per_slot = 1; // Reduce ticks so that POH fails + + let kp_b = Keypair::new(); + let packet = Packet::from_data( + None, + system_transaction::transfer(&mint_keypair, &kp_b.pubkey(), 1, genesis_config.hash()), + ) + .unwrap(); + let bundle = PacketBundle { + batch: PacketBatch::new(vec![packet]), + uuid: Uuid::new_v4(), + }; + assert_eq!( + test_single_bundle(genesis_config, bundle, None), + Err(PohMaxHeightError) + ); + } + + #[test] + fn test_bundle_max_retries() { + solana_logger::setup_with_default("INFO"); + + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(100_000_000); + let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config)); + bank.write_cost_tracker() + .unwrap() + .set_limits(u64::MAX, u64::MAX, u64::MAX); + + let ledger_path = get_tmp_ledger_path_auto_delete!(); + let blockstore = Arc::new( + Blockstore::open(ledger_path.path()) + .expect("Expected to be able to open database ledger"), + ); + let poh_config = PohConfig { + // limit tick count to avoid clearing working_bank at + // PohRecord then PohRecorderError(MaxHeightReached) at BankingStage + target_tick_count: Some(bank.max_tick_height() - 1), // == 1, only enough for ticks, not txs + ..PohConfig::default() + }; + let (exit, poh_recorder, poh_service, _entry_receiver) = + create_test_recorder(&bank, &blockstore, Some(poh_config), None); + let recorder = poh_recorder.lock().unwrap().recorder(); + let (gossip_vote_sender, _gossip_vote_receiver) = unbounded(); + let cost_model = Arc::new(RwLock::new(CostModel::default())); + let qos_service = QosService::new(cost_model, 0); + let mut bundle_stage_leader_stats = BundleStageLeaderStats::default(); + let bank_start = poh_recorder.lock().unwrap().bank_start().unwrap(); + + // Create two transfers + // 0. mint_keypair -> keypair0 + // 1. keypair0 -> keypair 1 + // Lock the accounts through the bank for tx1 and try to process tx0. + // It should timeout because BundleStage will continue to fail to get locks on keypair0. + + let keypair0 = Keypair::new(); + let keypair1 = Keypair::new(); + + let tx0 = VersionedTransaction::from(transfer( + &mint_keypair, + &keypair0.pubkey(), + 100_000, + genesis_config.hash(), + )); + + let tx1 = transfer(&keypair0, &keypair1.pubkey(), 50_000, genesis_config.hash()); + let sanitized_txs_1 = vec![SanitizedTransaction::from_transaction_for_tests(tx1)]; + + // grab lock on tx1 + let _batch = bank.prepare_sanitized_batch(&sanitized_txs_1); + + // push and pop tx0 + let bundle = PacketBundle { + batch: PacketBatch::new(vec![Packet::from_data(None, tx0).unwrap()]), + uuid: Uuid::new_v4(), + }; + info!("test_bundle_max_retries uuid: {:?}", bundle.uuid); + + let sanitized_bundle = get_sanitized_bundle( + &bundle, + &bank, + &HashSet::default(), + &HashSet::default(), + bundle_stage_leader_stats.transaction_errors(), + ) + .unwrap(); + + let result = BundleStage::update_qos_and_execute_record_commit_bundle( + &sanitized_bundle, + &recorder, + &None, + &gossip_vote_sender, + &qos_service, + &bank_start, + &mut bundle_stage_leader_stats, + &TEST_MAX_RETRY_DURATION, + ); + info!("test_bundle_max_retries result: {:?}", result); + assert!(matches!( + result, + Err(BundleExecutionError::MaxRetriesExceeded(_)) + )); + + exit.store(true, Ordering::Relaxed); + poh_service.join().unwrap(); + } +} diff --git a/core/src/bundle_stage_leader_stats.rs b/core/src/bundle_stage_leader_stats.rs new file mode 100644 index 0000000000..1381140707 --- /dev/null +++ b/core/src/bundle_stage_leader_stats.rs @@ -0,0 +1,326 @@ +use { + crate::leader_slot_banking_stage_timing_metrics::LeaderExecuteAndCommitTimings, + solana_poh::poh_recorder::BankStart, + solana_runtime::transaction_error_metrics::TransactionErrorMetrics, + solana_sdk::{clock::Slot, saturating_add_assign}, +}; + +// Stats emitted only during leader slots +#[derive(Default)] +pub struct BundleStageLeaderSlotTrackingMetrics { + current_slot: Option, + bundle_stage_leader_stats: BundleStageLeaderStats, +} + +impl BundleStageLeaderSlotTrackingMetrics { + pub fn maybe_report(&mut self, id: u32, bank_start: &Option<&BankStart>) { + match (self.current_slot, bank_start) { + // not was leader, not is leader + (None, None) => {} + // was leader, not leader anymore + (Some(current_slot), None) => { + self.bundle_stage_leader_stats.report(id, current_slot); + self.bundle_stage_leader_stats = BundleStageLeaderStats::default(); + } + // was leader, is leader + (Some(current_slot), Some(bank_start)) => { + if current_slot != bank_start.working_bank.slot() { + self.bundle_stage_leader_stats.report(id, current_slot); + self.bundle_stage_leader_stats = BundleStageLeaderStats::default(); + } + } + // not was leader, is leader + (None, Some(_)) => { + self.bundle_stage_leader_stats = BundleStageLeaderStats::default(); + } + } + + self.current_slot = bank_start + .as_ref() + .map(|bank_start| bank_start.working_bank.slot()); + } + + pub fn bundle_stage_leader_stats(&mut self) -> &mut BundleStageLeaderStats { + &mut self.bundle_stage_leader_stats + } +} + +#[derive(Default)] +pub struct BundleStageLeaderStats { + transaction_errors: TransactionErrorMetrics, + execute_and_commit_timings: LeaderExecuteAndCommitTimings, + bundle_stage_stats: BundleStageStats, +} + +impl BundleStageLeaderStats { + pub fn transaction_errors(&mut self) -> &mut TransactionErrorMetrics { + &mut self.transaction_errors + } + + pub fn execute_and_commit_timings(&mut self) -> &mut LeaderExecuteAndCommitTimings { + &mut self.execute_and_commit_timings + } + + pub fn bundle_stage_stats(&mut self) -> &mut BundleStageStats { + &mut self.bundle_stage_stats + } + + pub fn report(&self, id: u32, slot: Slot) { + self.transaction_errors.report(id, slot); + self.execute_and_commit_timings.report(id, slot); + self.bundle_stage_stats.report(id, slot); + } +} + +#[derive(Default)] +pub struct BundleStageStats { + sanitize_transaction_ok: u64, + sanitize_transaction_vote_only_mode: u64, + sanitize_transaction_failed_precheck: u64, + sanitize_transaction_blacklisted_account: u64, + sanitize_transaction_failed_to_serialize: u64, + sanitize_transaction_duplicate_transaction: u64, + sanitize_transaction_failed_check: u64, + sanitize_bundle_elapsed_us: u64, + + locked_bundle_elapsed_us: u64, + + num_lock_errors: u64, + + num_init_tip_account_errors: u64, + num_init_tip_account_ok: u64, + + num_change_tip_receiver_errors: u64, + num_change_tip_receiver_ok: u64, + change_tip_receiver_elapsed_us: u64, + + num_execution_failures: u64, + num_execution_timeouts: u64, + num_execution_retries: u64, + + execute_locked_bundles_elapsed_us: u64, + + execution_results_ok: u64, + execution_results_poh_max_height: u64, + execution_results_transaction_failures: u64, + execution_results_exceeds_cost_model: u64, + execution_results_tip_errors: u64, + execution_results_max_retries: u64, + execution_results_lock_errors: u64, +} + +impl BundleStageStats { + pub fn report(&self, id: u32, slot: Slot) { + datapoint_info!( + "bundle_stage-stats", + ("id", id, i64), + ("slot", slot, i64), + ("num_sanitized_ok", self.sanitize_transaction_ok, i64), + ( + "sanitize_transaction_vote_only_mode", + self.sanitize_transaction_vote_only_mode, + i64 + ), + ( + "sanitize_transaction_failed_precheck", + self.sanitize_transaction_failed_precheck, + i64 + ), + ( + "sanitize_transaction_blacklisted_account", + self.sanitize_transaction_blacklisted_account, + i64 + ), + ( + "sanitize_transaction_failed_to_serialize", + self.sanitize_transaction_failed_to_serialize, + i64 + ), + ( + "sanitize_transaction_duplicate_transaction", + self.sanitize_transaction_duplicate_transaction, + i64 + ), + ( + "sanitize_transaction_failed_check", + self.sanitize_transaction_failed_check, + i64 + ), + ( + "sanitize_bundle_elapsed_us", + self.sanitize_bundle_elapsed_us, + i64 + ), + ( + "locked_bundle_elapsed_us", + self.locked_bundle_elapsed_us, + i64 + ), + ("num_lock_errors", self.num_lock_errors, i64), + ( + "num_init_tip_account_errors", + self.num_init_tip_account_errors, + i64 + ), + ("num_init_tip_account_ok", self.num_init_tip_account_ok, i64), + ( + "num_change_tip_receiver_errors", + self.num_change_tip_receiver_errors, + i64 + ), + ( + "num_change_tip_receiver_ok", + self.num_change_tip_receiver_ok, + i64 + ), + ( + "change_tip_receiver_elapsed_us", + self.change_tip_receiver_elapsed_us, + i64 + ), + ("num_execution_failures", self.num_execution_failures, i64), + ("num_execution_timeouts", self.num_execution_timeouts, i64), + ("num_execution_retries", self.num_execution_retries, i64), + ( + "execute_locked_bundles_elapsed_us", + self.execute_locked_bundles_elapsed_us, + i64 + ), + ("execution_results_ok", self.execution_results_ok, i64), + ( + "execution_results_poh_max_height", + self.execution_results_poh_max_height, + i64 + ), + ( + "execution_results_transaction_failures", + self.execution_results_transaction_failures, + i64 + ), + ( + "execution_results_exceeds_cost_model", + self.execution_results_exceeds_cost_model, + i64 + ), + ( + "execution_results_tip_errors", + self.execution_results_tip_errors, + i64 + ), + ( + "execution_results_max_retries", + self.execution_results_max_retries, + i64 + ), + ( + "execution_results_lock_errors", + self.execution_results_lock_errors, + i64 + ), + ); + } + + pub fn increment_sanitize_transaction_ok(&mut self, num: u64) { + saturating_add_assign!(self.sanitize_transaction_ok, num); + } + + pub fn increment_sanitize_transaction_vote_only_mode(&mut self, num: u64) { + saturating_add_assign!(self.sanitize_transaction_vote_only_mode, num); + } + + pub fn increment_sanitize_transaction_failed_precheck(&mut self, num: u64) { + saturating_add_assign!(self.sanitize_transaction_failed_precheck, num); + } + + pub fn increment_sanitize_transaction_blacklisted_account(&mut self, num: u64) { + saturating_add_assign!(self.sanitize_transaction_blacklisted_account, num); + } + + pub fn increment_sanitize_transaction_failed_to_serialize(&mut self, num: u64) { + saturating_add_assign!(self.sanitize_transaction_failed_to_serialize, num); + } + + pub fn increment_sanitize_transaction_duplicate_transaction(&mut self, num: u64) { + saturating_add_assign!(self.sanitize_transaction_duplicate_transaction, num); + } + + pub fn increment_sanitize_transaction_failed_check(&mut self, num: u64) { + saturating_add_assign!(self.sanitize_transaction_failed_check, num); + } + + pub fn increment_sanitize_bundle_elapsed_us(&mut self, num: u64) { + saturating_add_assign!(self.sanitize_bundle_elapsed_us, num); + } + + pub fn increment_locked_bundle_elapsed_us(&mut self, num: u64) { + saturating_add_assign!(self.locked_bundle_elapsed_us, num); + } + + pub fn increment_num_lock_errors(&mut self, num: u64) { + saturating_add_assign!(self.num_lock_errors, num); + } + + pub fn increment_num_init_tip_account_errors(&mut self, num: u64) { + saturating_add_assign!(self.num_init_tip_account_errors, num); + } + + pub fn increment_num_init_tip_account_ok(&mut self, num: u64) { + saturating_add_assign!(self.num_init_tip_account_ok, num); + } + + pub fn increment_num_change_tip_receiver_errors(&mut self, num: u64) { + saturating_add_assign!(self.num_change_tip_receiver_errors, num); + } + + pub fn increment_num_change_tip_receiver_ok(&mut self, num: u64) { + saturating_add_assign!(self.num_change_tip_receiver_ok, num); + } + + pub fn increment_change_tip_receiver_elapsed_us(&mut self, num: u64) { + saturating_add_assign!(self.change_tip_receiver_elapsed_us, num); + } + + pub fn increment_num_execution_failures(&mut self, num: u64) { + saturating_add_assign!(self.num_execution_failures, num); + } + + pub fn increment_num_execution_timeouts(&mut self, num: u64) { + saturating_add_assign!(self.num_execution_timeouts, num); + } + + pub fn increment_num_execution_retries(&mut self, num: u64) { + saturating_add_assign!(self.num_execution_retries, num); + } + + pub fn increment_execute_locked_bundles_elapsed_us(&mut self, num: u64) { + saturating_add_assign!(self.execute_locked_bundles_elapsed_us, num); + } + + pub fn increment_execution_results_ok(&mut self, num: u64) { + saturating_add_assign!(self.execution_results_ok, num); + } + + pub fn increment_execution_results_poh_max_height(&mut self, num: u64) { + saturating_add_assign!(self.execution_results_poh_max_height, num); + } + + pub fn increment_execution_results_transaction_failures(&mut self, num: u64) { + saturating_add_assign!(self.execution_results_transaction_failures, num); + } + + pub fn increment_execution_results_exceeds_cost_model(&mut self, num: u64) { + saturating_add_assign!(self.execution_results_exceeds_cost_model, num); + } + + pub fn increment_execution_results_tip_errors(&mut self, num: u64) { + saturating_add_assign!(self.execution_results_tip_errors, num); + } + + pub fn increment_execution_results_max_retries(&mut self, num: u64) { + saturating_add_assign!(self.execution_results_max_retries, num); + } + + pub fn increment_execution_results_lock_errors(&mut self, num: u64) { + saturating_add_assign!(self.execution_results_lock_errors, num); + } +} diff --git a/core/src/consensus_cache_updater.rs b/core/src/consensus_cache_updater.rs new file mode 100644 index 0000000000..0514f4133b --- /dev/null +++ b/core/src/consensus_cache_updater.rs @@ -0,0 +1,52 @@ +use { + solana_runtime::bank::Bank, + solana_sdk::{clock::Epoch, pubkey::Pubkey}, + std::collections::HashSet, +}; + +#[derive(Default)] +pub(crate) struct ConsensusCacheUpdater { + last_epoch_updated: Epoch, + consensus_accounts_cache: HashSet, +} + +impl ConsensusCacheUpdater { + pub(crate) fn consensus_accounts_cache(&self) -> &HashSet { + &self.consensus_accounts_cache + } + + /// Builds a HashSet of all consensus related accounts for the Bank's epoch + fn get_consensus_accounts(bank: &Bank) -> HashSet { + let mut consensus_accounts: HashSet = HashSet::new(); + if let Some(epoch_stakes) = bank.epoch_stakes(bank.epoch()) { + // votes use the following accounts: + // - vote_account pubkey: writeable + // - authorized_voter_pubkey: read-only + // - node_keypair pubkey: payer (writeable) + let node_id_vote_accounts = epoch_stakes.node_id_to_vote_accounts(); + + let vote_accounts = node_id_vote_accounts + .values() + .into_iter() + .flat_map(|v| v.vote_accounts.clone()); + + // vote_account + consensus_accounts.extend(vote_accounts.into_iter()); + // authorized_voter_pubkey + consensus_accounts.extend(epoch_stakes.epoch_authorized_voters().keys().into_iter()); + // node_keypair + consensus_accounts.extend(epoch_stakes.node_id_to_vote_accounts().keys().into_iter()); + } + consensus_accounts + } + + /// Updates consensus-related accounts on epoch boundaries + /// Bundles must not contain any consensus related accounts in order to prevent starvation + /// of voting related transactions + pub(crate) fn maybe_update(&mut self, bank: &Bank) { + if bank.epoch() > self.last_epoch_updated { + self.consensus_accounts_cache = Self::get_consensus_accounts(bank); + self.last_epoch_updated = bank.epoch(); + } + } +} diff --git a/core/src/lib.rs b/core/src/lib.rs index 0ff026d808..f3d3f5da71 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -9,8 +9,13 @@ pub mod accounts_hash_verifier; pub mod ancestor_hashes_service; +mod backoff; pub mod banking_stage; pub mod broadcast_stage; +pub mod bundle_account_locker; +pub mod bundle_sanitizer; +pub mod bundle_stage; +mod bundle_stage_leader_stats; pub mod cache_block_meta_service; pub mod cluster_info_vote_listener; pub mod cluster_nodes; @@ -20,6 +25,7 @@ pub mod cluster_slots_service; pub mod commitment_service; pub mod completed_data_sets_service; pub mod consensus; +pub mod consensus_cache_updater; pub mod cost_update_service; pub mod drop_bank_service; pub mod duplicate_repair_status; @@ -37,9 +43,11 @@ pub mod ledger_metric_report_service; pub mod multi_iterator_scanner; pub mod optimistic_confirmation_verifier; pub mod outstanding_requests; +pub mod packet_bundle; pub mod packet_hasher; pub mod packet_threshold; pub mod progress_map; +pub mod proxy; pub mod qos_service; pub mod repair_generic_traversal; pub mod repair_response; @@ -62,6 +70,7 @@ pub mod snapshot_packager_service; pub mod staked_nodes_updater_service; pub mod stats_reporter_service; pub mod system_monitor_service; +pub mod tip_manager; mod tower1_7_14; pub mod tower_storage; pub mod tpu; @@ -93,3 +102,42 @@ extern crate solana_frozen_abi_macro; #[cfg(test)] #[macro_use] extern crate matches; + +use { + solana_sdk::packet::{Meta, Packet, PacketFlags, PACKET_DATA_SIZE}, + std::{ + cmp::min, + net::{IpAddr, Ipv4Addr}, + }, +}; + +const UNKNOWN_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)); + +// NOTE: last profiled at around 180ns +pub fn proto_packet_to_packet(p: jito_protos::proto::packet::Packet) -> Packet { + let mut data = [0; PACKET_DATA_SIZE]; + let copy_len = min(data.len(), p.data.len()); + data[..copy_len].copy_from_slice(&p.data[..copy_len]); + let mut packet = Packet::new(data, Meta::default()); + if let Some(meta) = p.meta { + packet.meta.size = meta.size as usize; + packet.meta.addr = meta.addr.parse().unwrap_or(UNKNOWN_IP); + packet.meta.port = meta.port as u16; + if let Some(flags) = meta.flags { + if flags.simple_vote_tx { + packet.meta.flags.insert(PacketFlags::SIMPLE_VOTE_TX); + } + if flags.forwarded { + packet.meta.flags.insert(PacketFlags::FORWARDED); + } + if flags.tracer_packet { + packet.meta.flags.insert(PacketFlags::TRACER_PACKET); + } + if flags.repair { + packet.meta.flags.insert(PacketFlags::REPAIR); + } + } + packet.meta.sender_stake = meta.sender_stake; + } + packet +} diff --git a/core/src/packet_bundle.rs b/core/src/packet_bundle.rs new file mode 100644 index 0000000000..f5a6a7ac6d --- /dev/null +++ b/core/src/packet_bundle.rs @@ -0,0 +1,7 @@ +use {solana_perf::packet::PacketBatch, uuid::Uuid}; + +#[derive(Clone, Debug)] +pub struct PacketBundle { + pub batch: PacketBatch, + pub uuid: Uuid, +} diff --git a/core/src/proxy/auth.rs b/core/src/proxy/auth.rs new file mode 100644 index 0000000000..b25edd4343 --- /dev/null +++ b/core/src/proxy/auth.rs @@ -0,0 +1,247 @@ +use { + chrono::Utc, + jito_protos::proto::auth::{ + auth_service_client::AuthServiceClient, GenerateAuthChallengeRequest, + GenerateAuthTokensRequest, RefreshAccessTokenRequest, Role, Token, + }, + solana_gossip::cluster_info::ClusterInfo, + solana_sdk::signature::{Keypair, Signer}, + std::{ + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, + }, + time::Duration, + }, + tokio::time::sleep, + tonic::{service::Interceptor, transport::Channel, Request, Status}, +}; + +/// Interceptor responsible for adding the access token to request headers. +pub(crate) struct AuthInterceptor { + /// The token added to each request header. + access_token: Arc>, +} + +impl AuthInterceptor { + pub(crate) fn new(access_token: Arc>) -> Self { + Self { access_token } + } +} + +impl Interceptor for AuthInterceptor { + fn call(&mut self, mut request: Request<()>) -> Result, Status> { + request.metadata_mut().insert( + "authorization", + format!("Bearer {}", self.access_token.lock().unwrap().value) + .parse() + .unwrap(), + ); + + Ok(request) + } +} + +/// Contains collection of utility functions responsible for generating and refreshing new tokens. +pub(crate) mod token_manager { + use {super::*, crate::proxy::ProxyError, tonic::transport::Endpoint}; + + /// Control loop responsible for making sure access and refresh tokens are updated. + pub(crate) async fn auth_tokens_update_loop( + auth_service_endpoint: Endpoint, + access_token: Arc>, + cluster_info: Arc, + exit: Arc, + ) { + const RETRY_INTERVAL: Duration = Duration::from_secs(5); + const SLEEP_INTERVAL: Duration = Duration::from_secs(60); + + let mut num_refresh_loop_errors: u64 = 0; + let mut num_connect_errors: u64 = 0; + while !exit.load(Ordering::Relaxed) { + sleep(RETRY_INTERVAL).await; + + match auth_service_endpoint.connect().await { + Ok(channel) => { + if let Err(e) = auth_tokens_update_loop_helper( + AuthServiceClient::new(channel), + auth_service_endpoint.uri().to_string(), + (access_token.clone(), Token::default()), + cluster_info.clone(), + SLEEP_INTERVAL, + exit.clone(), + ) + .await + { + num_refresh_loop_errors += 1; + datapoint_error!( + "auth_tokens_update_loop-refresh_loop_error", + ("url", auth_service_endpoint.uri().to_string(), String), + ("count", num_refresh_loop_errors, i64), + ("error", e.to_string(), String) + ); + } + } + Err(e) => { + num_connect_errors += 1; + datapoint_error!( + "auth_tokens_update_loop-refresh_connect_error", + ("url", auth_service_endpoint.uri().to_string(), String), + ("count", num_connect_errors, i64), + ("error", e.to_string(), String) + ); + } + } + } + } + + /// Responsible for keeping generating and refreshing the access token. + async fn auth_tokens_update_loop_helper( + mut auth_service_client: AuthServiceClient, + url: String, + (access_token, mut refresh_token): (Arc>, Token), + cluster_info: Arc, + sleep_interval: Duration, + exit: Arc, + ) -> crate::proxy::Result<()> { + const REFRESH_WITHIN_SECS: i64 = 300; + let mut num_full_refreshes = 0; + let mut num_refresh_access_token = 0; + + while !exit.load(Ordering::Relaxed) { + let access_token_expiry: i64 = access_token + .lock() + .unwrap() + .expires_at_utc + .as_ref() + .map(|ts| ts.seconds) + .unwrap_or_default(); + let refresh_token_expiry = refresh_token + .expires_at_utc + .as_ref() + .map(|ts| ts.seconds) + .unwrap_or_default(); + + let now = Utc::now().timestamp(); + + let should_refresh_access = access_token_expiry.checked_sub(now).ok_or_else(|| { + ProxyError::InvalidData("Received invalid access_token expiration".to_string()) + })? <= REFRESH_WITHIN_SECS; + let should_generate_new_tokens = + refresh_token_expiry.checked_sub(now).ok_or_else(|| { + ProxyError::InvalidData("Received invalid refresh_token expiration".to_string()) + })? <= REFRESH_WITHIN_SECS; + + match (should_refresh_access, should_generate_new_tokens) { + // Generate new tokens if the refresh_token is close to being expired. + (_, true) => { + let kp = cluster_info.keypair().clone(); + + let (new_access_token, new_refresh_token) = + generate_auth_tokens(&mut auth_service_client, kp.as_ref()).await?; + + *access_token.lock().unwrap() = new_access_token.clone(); + refresh_token = new_refresh_token; + + num_full_refreshes += 1; + datapoint_info!( + "auth_tokens_update_loop-tokens_generated", + ("url", url, String), + ("count", num_full_refreshes, i64), + ); + } + // Invoke the refresh_access_token method if the access_token is close to being expired. + (true, _) => { + let new_access_token = + refresh_access_token(&mut auth_service_client, refresh_token.clone()) + .await?; + *access_token.lock().unwrap() = new_access_token; + + num_refresh_access_token += 1; + datapoint_info!( + "auth_tokens_update_loop-refresh_access_token", + ("url", url, String), + ("count", num_refresh_access_token, i64), + ); + } + // Sleep and do nothing if neither token is close to expired, + (false, false) => sleep(sleep_interval).await, + } + } + + Ok(()) + } + + /// Invokes the refresh_access_token gRPC method. + /// Returns a new access_token. + async fn refresh_access_token( + auth_service_client: &mut AuthServiceClient, + refresh_token: Token, + ) -> crate::proxy::Result { + match auth_service_client + .refresh_access_token(RefreshAccessTokenRequest { + refresh_token: refresh_token.value, + }) + .await + { + Ok(resp) => get_validated_token(resp.into_inner().access_token), + Err(e) => Err(ProxyError::GrpcError(e)), + } + } + + /// Generates an auth challenge then generates and returns validated auth tokens. + async fn generate_auth_tokens( + auth_service_client: &mut AuthServiceClient, + // used to sign challenges + keypair: &Keypair, + ) -> crate::proxy::Result<( + Token, /* access_token */ + Token, /* refresh_token */ + )> { + let challenge_response = auth_service_client + .generate_auth_challenge(GenerateAuthChallengeRequest { + role: Role::Validator as i32, + pubkey: keypair.pubkey().as_ref().to_vec(), + }) + .await?; + + let formatted_challenge = format!( + "{}-{}", + keypair.pubkey(), + challenge_response.into_inner().challenge + ); + let signed_challenge = keypair + .sign_message(formatted_challenge.as_bytes()) + .as_ref() + .to_vec(); + + let auth_tokens = auth_service_client + .generate_auth_tokens(GenerateAuthTokensRequest { + challenge: formatted_challenge, + client_pubkey: keypair.pubkey().as_ref().to_vec(), + signed_challenge, + }) + .await?; + + let inner = auth_tokens.into_inner(); + let access_token = get_validated_token(inner.access_token)?; + let refresh_token = get_validated_token(inner.refresh_token)?; + + Ok((access_token, refresh_token)) + } + + /// An invalid token is one where any of its fields are None or the token itself is None. + /// Performs the necessary validations on the auth tokens before returning, + /// i.e. it is safe to call .unwrap() on the token fields from the call-site. + fn get_validated_token(maybe_token: Option) -> crate::proxy::Result { + let token = maybe_token + .ok_or_else(|| ProxyError::InvalidData("received a null token".to_string()))?; + if token.expires_at_utc.is_none() { + Err(ProxyError::InvalidData( + "expires_at_utc field is null".to_string(), + )) + } else { + Ok(token) + } + } +} diff --git a/core/src/proxy/block_engine_stage.rs b/core/src/proxy/block_engine_stage.rs new file mode 100644 index 0000000000..954bdf153f --- /dev/null +++ b/core/src/proxy/block_engine_stage.rs @@ -0,0 +1,383 @@ +//! Maintains a connection to the Block Engine. +//! +//! The Block Engine is responsible for the following: +//! - Acts as a system that sends high profit bundles and transactions to a validator. +//! - Sends transactions and bundles to the validator. + +use { + crate::{ + backoff::BackoffStrategy, + packet_bundle::PacketBundle, + proto_packet_to_packet, + proxy::{ + auth::{token_manager::auth_tokens_update_loop, AuthInterceptor}, + ProxyError, + }, + sigverify::SigverifyTracerPacketStats, + }, + crossbeam_channel::Sender, + jito_protos::proto::{ + auth::Token, + block_engine::{ + self, block_engine_validator_client::BlockEngineValidatorClient, + BlockBuilderFeeInfoRequest, + }, + }, + solana_gossip::cluster_info::ClusterInfo, + solana_perf::packet::PacketBatch, + solana_sdk::{pubkey::Pubkey, saturating_add_assign}, + std::{ + str::FromStr, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, + }, + thread::{self, Builder, JoinHandle}, + time::Duration, + }, + tokio::time::{interval, sleep}, + tonic::{ + codegen::InterceptedService, + transport::{Channel, Endpoint}, + Status, Streaming, + }, + uuid::Uuid, +}; + +#[derive(Default)] +struct BlockEngineStageStats { + num_bundles: u64, + num_bundle_packets: u64, + num_packets: u64, + num_empty_packets: u64, +} + +impl BlockEngineStageStats { + pub(crate) fn report(&self) { + datapoint_info!( + "block_engine_stage-stats", + ("num_bundles", self.num_bundles, i64), + ("num_bundle_packets", self.num_bundle_packets, i64), + ("num_packets", self.num_packets, i64), + ("num_empty_packets", self.num_empty_packets, i64) + ); + } +} + +pub struct BlockBuilderFeeInfo { + pub block_builder: Pubkey, + pub block_builder_commission: u64, +} + +#[derive(Clone, Debug)] +pub struct BlockEngineConfig { + /// Address to the external auth-service responsible for generating access tokens. + pub auth_service_endpoint: Endpoint, + + /// Primary backend endpoint. + pub backend_endpoint: Endpoint, + + /// If set then it will be assumed the backend verified packets so signature verification will be bypassed in the validator. + pub trust_packets: bool, +} + +pub struct BlockEngineStage { + t_hdls: Vec>, +} + +impl BlockEngineStage { + pub fn new( + block_engine_config: BlockEngineConfig, + // Channel that bundles get piped through. + bundle_tx: Sender>, + // The keypair stored here is used to sign auth challenges. + cluster_info: Arc, + // Channel that non-trusted packets get piped through. + packet_tx: Sender, + // Channel that trusted packets get piped through. + verified_packet_tx: Sender<(Vec, Option)>, + exit: Arc, + block_builder_fee_info: &Arc>, + ) -> Self { + let BlockEngineConfig { + auth_service_endpoint, + backend_endpoint, + trust_packets, + } = block_engine_config; + + let access_token = Arc::new(Mutex::new(Token::default())); + let block_builder_fee_info = block_builder_fee_info.clone(); + + let thread = Builder::new() + .name("block-engine-stage".into()) + .spawn(move || { + let rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap(); + rt.spawn(auth_tokens_update_loop( + auth_service_endpoint, + access_token.clone(), + cluster_info.clone(), + exit.clone(), + )); + rt.block_on(Self::start( + access_token, + backend_endpoint, + bundle_tx, + packet_tx, + trust_packets, + verified_packet_tx, + exit, + block_builder_fee_info, + )); + }) + .unwrap(); + + Self { + t_hdls: vec![thread], + } + } + + pub fn join(self) -> thread::Result<()> { + for t in self.t_hdls { + t.join()?; + } + Ok(()) + } + + #[allow(clippy::too_many_arguments)] + async fn start( + access_token: Arc>, + block_engine_endpoint: Endpoint, + bundle_tx: Sender>, + packet_tx: Sender, + trust_packets: bool, + verified_packet_tx: Sender<(Vec, Option)>, + exit: Arc, + block_builder_fee_info: Arc>, + ) { + const WAIT_FOR_FIRST_AUTH: Duration = Duration::from_secs(5); + + let mut num_wait_for_auth: usize = 0; + let mut num_stream_errors: usize = 0; + let mut num_connect_errors: usize = 0; + + while access_token.lock().unwrap().value.is_empty() { + if exit.load(Ordering::Relaxed) { + return; + } + num_wait_for_auth += 1; + datapoint_info!( + "block_engine_stage-wait_for_auth", + ("wait_count", num_wait_for_auth, i64) + ); + sleep(WAIT_FOR_FIRST_AUTH).await; + } + + let mut backoff = BackoffStrategy::new(); + while !exit.load(Ordering::Relaxed) { + match block_engine_endpoint.connect().await { + Ok(channel) => { + match Self::start_consuming_block_engine_bundles_and_packets( + &mut backoff, + &bundle_tx, + BlockEngineValidatorClient::with_interceptor( + channel, + AuthInterceptor::new(access_token.clone()), + ), + &packet_tx, + trust_packets, + &verified_packet_tx, + &exit, + &block_builder_fee_info, + ) + .await + { + Ok(_) => {} + Err(e) => { + num_stream_errors += 1; + datapoint_error!( + "block_engine_stage-stream_error", + ("count", num_stream_errors, i64), + ("error", e.to_string(), String), + ); + } + } + } + Err(e) => { + num_connect_errors += 1; + datapoint_error!( + "block_engine_stage-connect_error", + ("count", num_connect_errors, i64), + ("error", e.to_string(), String), + ); + } + } + + sleep(Duration::from_millis(backoff.next_wait())).await; + } + } + + async fn start_consuming_block_engine_bundles_and_packets( + backoff: &mut BackoffStrategy, + bundle_tx: &Sender>, + mut client: BlockEngineValidatorClient>, + packet_tx: &Sender, + trust_packets: bool, + verified_packet_tx: &Sender<(Vec, Option)>, + exit: &Arc, + block_builder_fee_info: &Arc>, + ) -> crate::proxy::Result<()> { + let subscribe_packets_stream = client + .subscribe_packets(block_engine::SubscribePacketsRequest {}) + .await? + .into_inner(); + let subscribe_bundles_stream = client + .subscribe_bundles(block_engine::SubscribeBundlesRequest {}) + .await? + .into_inner(); + + let block_builder_info = client + .get_block_builder_fee_info(BlockBuilderFeeInfoRequest {}) + .await? + .into_inner(); + { + let mut bb_fee = block_builder_fee_info.lock().unwrap(); + bb_fee.block_builder_commission = block_builder_info.commission; + bb_fee.block_builder = + Pubkey::from_str(&block_builder_info.pubkey).unwrap_or(bb_fee.block_builder); + } + + backoff.reset(); + + Self::consume_bundle_and_packet_stream( + client, + (subscribe_bundles_stream, subscribe_packets_stream), + bundle_tx, + packet_tx, + trust_packets, + verified_packet_tx, + exit, + block_builder_fee_info, + ) + .await + } + + async fn consume_bundle_and_packet_stream( + mut client: BlockEngineValidatorClient>, + (mut bundle_stream, mut packet_stream): ( + Streaming, + Streaming, + ), + bundle_tx: &Sender>, + packet_tx: &Sender, + trust_packets: bool, + verified_packet_tx: &Sender<(Vec, Option)>, + exit: &Arc, + block_builder_fee_info: &Arc>, + ) -> crate::proxy::Result<()> { + const METRICS_TICK: Duration = Duration::from_secs(1); + const MAINTENANCE_TICK: Duration = Duration::from_secs(10 * 60); + + let mut block_engine_stats = BlockEngineStageStats::default(); + let mut metrics_tick = interval(METRICS_TICK); + let mut maintenance_tick = interval(MAINTENANCE_TICK); + + info!("connected to packet and bundle stream"); + + while !exit.load(Ordering::Relaxed) { + tokio::select! { + maybe_msg = packet_stream.message() => { + let resp = maybe_msg?.ok_or(ProxyError::GrpcStreamDisconnected)?; + Self::handle_block_engine_packets(resp, packet_tx, verified_packet_tx, trust_packets, &mut block_engine_stats)?; + } + maybe_bundles = bundle_stream.message() => { + Self::handle_block_engine_maybe_bundles(maybe_bundles, bundle_tx, &mut block_engine_stats)?; + } + _ = metrics_tick.tick() => { + block_engine_stats.report(); + block_engine_stats = BlockEngineStageStats::default(); + } + _ = maintenance_tick.tick() => { + let block_builder_info = client.get_block_builder_fee_info(BlockBuilderFeeInfoRequest{}).await?.into_inner(); + let mut bb_fee = block_builder_fee_info.lock().unwrap(); + bb_fee.block_builder_commission = block_builder_info.commission; + bb_fee.block_builder = Pubkey::from_str(&block_builder_info.pubkey).unwrap_or(bb_fee.block_builder); + } + } + } + + Ok(()) + } + + fn handle_block_engine_maybe_bundles( + maybe_bundles_response: Result, Status>, + bundle_sender: &Sender>, + block_engine_stats: &mut BlockEngineStageStats, + ) -> crate::proxy::Result<()> { + let bundles_response = maybe_bundles_response?.ok_or(ProxyError::GrpcStreamDisconnected)?; + let bundles: Vec = bundles_response + .bundles + .into_iter() + .filter_map(|bundle| { + Some(PacketBundle { + batch: PacketBatch::new( + bundle + .bundle? + .packets + .into_iter() + .map(proto_packet_to_packet) + .collect(), + ), + uuid: Uuid::from_str(&bundle.uuid).ok()?, + }) + }) + .collect(); + + saturating_add_assign!(block_engine_stats.num_bundles, bundles.len() as u64); + saturating_add_assign!( + block_engine_stats.num_bundle_packets, + bundles.iter().map(|bundle| bundle.batch.len() as u64).sum() + ); + + // NOTE: bundles are sanitized in bundle_sanitizer module + bundle_sender + .send(bundles) + .map_err(|_| ProxyError::PacketForwardError) + } + + fn handle_block_engine_packets( + resp: block_engine::SubscribePacketsResponse, + packet_tx: &Sender, + verified_packet_tx: &Sender<(Vec, Option)>, + trust_packets: bool, + block_engine_stats: &mut BlockEngineStageStats, + ) -> crate::proxy::Result<()> { + if let Some(batch) = resp.batch { + let packet_batch = PacketBatch::new( + batch + .packets + .into_iter() + .map(proto_packet_to_packet) + .collect(), + ); + + saturating_add_assign!(block_engine_stats.num_packets, packet_batch.len() as u64); + + if trust_packets { + verified_packet_tx + .send((vec![packet_batch], None)) + .map_err(|_| ProxyError::PacketForwardError)?; + } else { + packet_tx + .send(packet_batch) + .map_err(|_| ProxyError::PacketForwardError)?; + } + } else { + saturating_add_assign!(block_engine_stats.num_empty_packets, 1); + } + + Ok(()) + } +} diff --git a/core/src/proxy/fetch_stage_manager.rs b/core/src/proxy/fetch_stage_manager.rs new file mode 100644 index 0000000000..8f5b95bc2c --- /dev/null +++ b/core/src/proxy/fetch_stage_manager.rs @@ -0,0 +1,161 @@ +use { + crate::proxy::{HeartbeatEvent, ProxyError}, + crossbeam_channel::{select, tick, Receiver, Sender}, + solana_gossip::cluster_info::ClusterInfo, + solana_perf::packet::PacketBatch, + std::{ + net::SocketAddr, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + thread::{self, Builder, JoinHandle}, + time::{Duration, Instant}, + }, +}; + +const HEARTBEAT_TIMEOUT: Duration = Duration::from_millis(1500); // Empirically determined from load testing +const DISCONNECT_DELAY: Duration = Duration::from_secs(60); +const METRICS_CADENCE: Duration = Duration::from_secs(1); + +/// Manages switching between the validator's tpu ports and that of the proxy's. +/// Switch-overs are triggered by late and missed heartbeats. +pub struct FetchStageManager { + t_hdl: JoinHandle<()>, +} + +impl FetchStageManager { + pub fn new( + // ClusterInfo is used to switch between advertising the proxy's TPU ports and that of this validator's. + cluster_info: Arc, + // Channel that heartbeats are received from. Entirely responsible for triggering switch-overs. + heartbeat_rx: Receiver, + // Channel that packets from FetchStage are intercepted from. + packet_intercept_rx: Receiver, + // Intercepted packets get piped through here. + packet_tx: Sender, + exit: Arc, + ) -> Self { + let t_hdl = Self::start( + cluster_info, + heartbeat_rx, + packet_intercept_rx, + packet_tx, + exit, + ); + + Self { t_hdl } + } + + /// Disconnect fetch behaviour + /// Starts connected + /// When connected and a packet is received, forward it + /// When disconnected, packet is dropped + /// When receiving heartbeat while connected and not pending disconnect + /// Sets pending_disconnect to true and records time + /// When receiving heartbeat while connected, and pending for > DISCONNECT_DELAY_SEC + /// Sets fetch_connected to false, pending_disconnect to false + /// Advertises TPU ports sent in heartbeat + /// When tick is received without heartbeat_received + /// Sets fetch_connected to true, pending_disconnect to false + /// Advertises saved contact info + fn start( + cluster_info: Arc, + heartbeat_rx: Receiver, + packet_intercept_rx: Receiver, + packet_tx: Sender, + exit: Arc, + ) -> JoinHandle<()> { + Builder::new().name("fetch-stage-manager".into()).spawn(move || { + let my_fallback_contact_info = cluster_info.my_contact_info(); + + let mut fetch_connected = true; + let mut heartbeat_received = false; + let mut pending_disconnect = false; + + let mut pending_disconnect_ts = Instant::now(); + + let heartbeat_tick = tick(HEARTBEAT_TIMEOUT); + let metrics_tick = tick(METRICS_CADENCE); + let mut packets_forwarded = 0; + let mut heartbeats_received = 0; + loop { + select! { + recv(packet_intercept_rx) -> pkt => { + match pkt { + Ok(pkt) => { + if fetch_connected { + if packet_tx.send(pkt).is_err() { + error!("{:?}", ProxyError::PacketForwardError); + return; + } + packets_forwarded += 1; + } + } + Err(_) => { + warn!("packet intercept receiver disconnected, shutting down"); + return; + } + } + } + recv(heartbeat_tick) -> _ => { + if exit.load(Ordering::Relaxed) { + break; + } + if !heartbeat_received && (!fetch_connected || pending_disconnect) { + warn!("heartbeat late, reconnecting fetch stage"); + fetch_connected = true; + pending_disconnect = false; + Self::set_tpu_addresses(&cluster_info, my_fallback_contact_info.tpu, my_fallback_contact_info.tpu_forwards); + heartbeats_received = 0; + } + heartbeat_received = false; + } + recv(heartbeat_rx) -> tpu_info => { + if let Ok((tpu_addr, tpu_forward_addr)) = tpu_info { + heartbeats_received += 1; + heartbeat_received = true; + if fetch_connected && !pending_disconnect { + info!("received heartbeat while fetch stage connected, pending disconnect after delay"); + pending_disconnect_ts = Instant::now(); + pending_disconnect = true; + } + if fetch_connected && pending_disconnect && pending_disconnect_ts.elapsed() > DISCONNECT_DELAY { + info!("disconnecting fetch stage"); + fetch_connected = false; + pending_disconnect = false; + Self::set_tpu_addresses(&cluster_info, tpu_addr, tpu_forward_addr); + } + } else { + // see comment on heartbeat_sender clone in new() + unreachable!(); + } + } + recv(metrics_tick) -> _ => { + datapoint_info!( + "relayer-heartbeat", + ("fetch_stage_packets_forwarded", packets_forwarded, i64), + ("heartbeats_received", heartbeats_received, i64), + ); + + } + } + } + }).unwrap() + } + + fn set_tpu_addresses( + cluster_info: &Arc, + tpu_address: SocketAddr, + tpu_forward_address: SocketAddr, + ) { + let mut new_contact_info = cluster_info.my_contact_info(); + new_contact_info.tpu = tpu_address; + new_contact_info.tpu_forwards = tpu_forward_address; + cluster_info.set_my_contact_info(new_contact_info); + } + + pub fn join(self) -> thread::Result<()> { + self.t_hdl.join() + } +} diff --git a/core/src/proxy/mod.rs b/core/src/proxy/mod.rs new file mode 100644 index 0000000000..a5fcf9cdb5 --- /dev/null +++ b/core/src/proxy/mod.rs @@ -0,0 +1,55 @@ +//! This module contains logic for connecting to an external Relayer and Block Engine. +//! The Relayer acts as an external TPU and TPU Forward socket while the Block Engine +//! is tasked with streaming high value bundles to the validator. The validator can run +//! in one of 3 modes: +//! 1. Connected to Relayer and Block Engine. +//! - This is the ideal mode as it increases the probability of building the most profitable blocks. +//! 2. Connected only to Relayer. +//! - A validator may choose to run in this mode if the main concern is to offload ingress traffic deduplication and sig-verification. +//! 3. Connected only to Block Engine. +//! - Running in this mode means pending transactions are not exposed to external actors. This mode is ideal if the validator wishes +//! to accept bundles while maintaining some level of privacy for in-flight transactions. + +mod auth; +pub mod block_engine_stage; +pub mod fetch_stage_manager; +pub mod relayer_stage; + +use { + std::{ + net::{AddrParseError, SocketAddr}, + result, + }, + thiserror::Error, + tonic::Status, +}; + +type Result = result::Result; +type HeartbeatEvent = (SocketAddr, SocketAddr); + +#[derive(Error, Debug)] +pub enum ProxyError { + #[error("grpc error: {0}")] + GrpcError(#[from] Status), + + #[error("stream disconnected")] + GrpcStreamDisconnected, + + #[error("heartbeat error")] + HeartbeatChannelError, + + #[error("heartbeat expired")] + HeartbeatExpired, + + #[error("error forwarding packet to banking stage")] + PacketForwardError, + + #[error("missing tpu config: {0:?}")] + MissingTpuSocket(String), + + #[error("invalid socket address: {0:?}")] + InvalidSocketAddress(#[from] AddrParseError), + + #[error("invalid gRPC data: {0:?}")] + InvalidData(String), +} diff --git a/core/src/proxy/relayer_stage.rs b/core/src/proxy/relayer_stage.rs new file mode 100644 index 0000000000..7f4961d5eb --- /dev/null +++ b/core/src/proxy/relayer_stage.rs @@ -0,0 +1,362 @@ +//! Maintains a connection to the Relayer. +//! +//! The external Relayer is responsible for the following: +//! - Acts as a TPU proxy. +//! - Sends transactions to the validator. +//! - Does not bundles to avoid DOS vector. +//! - When validator connects, it changes its TPU and TPU forward address to the relayer. +//! - Expected to send heartbeat to validator as watchdog. If watchdog times out, the validator +//! disconnects and reverts the TPU and TPU forward settings. + +use { + crate::{ + backoff::BackoffStrategy, + proto_packet_to_packet, + proxy::{ + auth::{token_manager::auth_tokens_update_loop, AuthInterceptor}, + HeartbeatEvent, ProxyError, + }, + sigverify::SigverifyTracerPacketStats, + }, + crossbeam_channel::Sender, + jito_protos::proto::{ + auth::Token, + relayer::{self, relayer_client::RelayerClient}, + }, + solana_gossip::cluster_info::ClusterInfo, + solana_perf::packet::PacketBatch, + solana_sdk::saturating_add_assign, + std::{ + net::{IpAddr, Ipv4Addr, SocketAddr}, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, + }, + thread::{self, Builder, JoinHandle}, + time::{Duration, Instant}, + }, + tokio::time::{interval, sleep}, + tonic::{ + codegen::InterceptedService, + transport::{Channel, Endpoint}, + Streaming, + }, +}; + +#[derive(Default)] +struct RelayerStageStats { + num_empty_messages: u64, + num_packets: u64, + num_heartbeats: u64, +} + +impl RelayerStageStats { + pub(crate) fn report(&self) { + datapoint_info!( + "relayer_stage-stats", + ("num_empty_messages", self.num_empty_messages, i64), + ("num_packets", self.num_packets, i64), + ("num_heartbeats", self.num_heartbeats, i64), + ); + } +} + +#[derive(Clone, Debug)] +pub struct RelayerConfig { + /// Address to the external auth-service responsible for generating access tokens. + pub auth_service_endpoint: Endpoint, + + /// Primary backend endpoint. + pub backend_endpoint: Endpoint, + + /// Interval at which heartbeats are expected. + pub expected_heartbeat_interval: Duration, + + /// The max tolerable age of the last heartbeat. + pub oldest_allowed_heartbeat: Duration, + + /// If set then it will be assumed the backend verified packets so signature verification will be bypassed in the validator. + pub trust_packets: bool, +} + +pub struct RelayerStage { + t_hdls: Vec>, +} + +impl RelayerStage { + pub fn new( + relayer_config: RelayerConfig, + // The keypair stored here is used to sign auth challenges. + cluster_info: Arc, + // Channel that server-sent heartbeats are piped through. + heartbeat_tx: Sender, + // Channel that non-trusted streamed packets are piped through. + packet_tx: Sender, + // Channel that trusted streamed packets are piped through. + verified_packet_tx: Sender<(Vec, Option)>, + exit: Arc, + ) -> Self { + let RelayerConfig { + auth_service_endpoint, + backend_endpoint, + expected_heartbeat_interval, + oldest_allowed_heartbeat, + trust_packets, + } = relayer_config; + + let access_token = Arc::new(Mutex::new(Token::default())); + let thread = Builder::new() + .name("relayer-stage".into()) + .spawn(move || { + let rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap(); + + rt.spawn(auth_tokens_update_loop( + auth_service_endpoint, + access_token.clone(), + cluster_info.clone(), + exit.clone(), + )); + rt.block_on(Self::start( + access_token, + heartbeat_tx, + expected_heartbeat_interval, + oldest_allowed_heartbeat, + packet_tx, + backend_endpoint, + verified_packet_tx, + trust_packets, + exit, + )); + }) + .unwrap(); + + Self { + t_hdls: vec![thread], + } + } + + pub fn join(self) -> thread::Result<()> { + for t in self.t_hdls { + t.join()?; + } + Ok(()) + } + + #[allow(clippy::too_many_arguments)] + async fn start( + access_token: Arc>, + heartbeat_tx: Sender, + expected_heartbeat_interval: Duration, + oldest_allowed_heartbeat: Duration, + packet_tx: Sender, + relayer_endpoint: Endpoint, + verified_packet_tx: Sender<(Vec, Option)>, + trust_packets: bool, + exit: Arc, + ) { + const WAIT_FOR_FIRST_AUTH: Duration = Duration::from_secs(5); + + let mut wait_count: usize = 0; + let mut stream_error_count: usize = 0; + let mut connect_error_count: usize = 0; + while access_token.lock().unwrap().value.is_empty() { + if exit.load(Ordering::Relaxed) { + return; + } + wait_count += 1; + datapoint_info!( + "relayer_stage-wait_for_auth", + ("wait_count", wait_count, i64) + ); + sleep(WAIT_FOR_FIRST_AUTH).await; + } + + let mut backoff = BackoffStrategy::new(); + while !exit.load(Ordering::Relaxed) { + match relayer_endpoint.connect().await { + Ok(channel) => { + match Self::start_consuming_relayer_packets( + &mut backoff, + RelayerClient::with_interceptor( + channel, + AuthInterceptor::new(access_token.clone()), + ), + &heartbeat_tx, + expected_heartbeat_interval, + oldest_allowed_heartbeat, + &packet_tx, + &verified_packet_tx, + trust_packets, + &exit, + ) + .await + { + Ok(_) => {} + Err(e) => { + stream_error_count += 1; + datapoint_error!( + "relayer_stage-stream_error", + ("count", stream_error_count, i64), + ("error", e.to_string(), String), + ); + } + } + } + Err(e) => { + connect_error_count += 1; + datapoint_error!( + "relayer_stage-connect_error", + ("count", connect_error_count, i64), + ("error", e.to_string(), String), + ); + } + } + sleep(Duration::from_millis(backoff.next_wait())).await; + } + } + + async fn start_consuming_relayer_packets( + backoff: &mut BackoffStrategy, + mut client: RelayerClient>, + heartbeat_tx: &Sender, + expected_heartbeat_interval: Duration, + oldest_allowed_heartbeat: Duration, + packet_tx: &Sender, + verified_packet_tx: &Sender<(Vec, Option)>, + trust_packets: bool, + exit: &Arc, + ) -> crate::proxy::Result<()> { + let heartbeat_event: HeartbeatEvent = { + let tpu_config = client + .get_tpu_configs(relayer::GetTpuConfigsRequest {}) + .await? + .into_inner(); + let tpu_addr = tpu_config + .tpu + .ok_or_else(|| ProxyError::MissingTpuSocket("tpu".into()))?; + let tpu_forward_addr = tpu_config + .tpu_forward + .ok_or_else(|| ProxyError::MissingTpuSocket("tpu_fwd".into()))?; + + let tpu_ip = IpAddr::from(tpu_addr.ip.parse::()?); + let tpu_forward_ip = IpAddr::from(tpu_forward_addr.ip.parse::()?); + + let tpu_socket = SocketAddr::new(tpu_ip, tpu_addr.port as u16); + let tpu_forward_socket = SocketAddr::new(tpu_forward_ip, tpu_forward_addr.port as u16); + (tpu_socket, tpu_forward_socket) + }; + + let packet_stream = client + .subscribe_packets(relayer::SubscribePacketsRequest {}) + .await? + .into_inner(); + + // assume it's all good here + backoff.reset(); + + Self::consume_packet_stream( + heartbeat_event, + heartbeat_tx, + expected_heartbeat_interval, + oldest_allowed_heartbeat, + packet_stream, + packet_tx, + trust_packets, + verified_packet_tx, + exit, + ) + .await + } + + async fn consume_packet_stream( + heartbeat_event: HeartbeatEvent, + heartbeat_tx: &Sender, + expected_heartbeat_interval: Duration, + oldest_allowed_heartbeat: Duration, + mut packet_stream: Streaming, + packet_tx: &Sender, + trust_packets: bool, + verified_packet_tx: &Sender<(Vec, Option)>, + exit: &Arc, + ) -> crate::proxy::Result<()> { + const METRICS_TICK: Duration = Duration::from_secs(1); + + let mut relayer_stats = RelayerStageStats::default(); + let mut metrics_tick = interval(METRICS_TICK); + + let mut heartbeat_check_interval = interval(expected_heartbeat_interval); + let mut last_heartbeat_ts = Instant::now(); + + info!("connected to packet stream"); + + while !exit.load(Ordering::Relaxed) { + tokio::select! { + maybe_msg = packet_stream.message() => { + let resp = maybe_msg?.ok_or(ProxyError::GrpcStreamDisconnected)?; + Self::handle_relayer_packets(resp, heartbeat_event, heartbeat_tx, &mut last_heartbeat_ts, packet_tx, trust_packets, verified_packet_tx, &mut relayer_stats)?; + } + _ = heartbeat_check_interval.tick() => { + if last_heartbeat_ts.elapsed() > oldest_allowed_heartbeat { + return Err(ProxyError::HeartbeatExpired); + } + } + _ = metrics_tick.tick() => { + relayer_stats.report(); + relayer_stats = RelayerStageStats::default(); + } + } + } + + Ok(()) + } + + fn handle_relayer_packets( + subscribe_packets_resp: relayer::SubscribePacketsResponse, + heartbeat_event: HeartbeatEvent, + heartbeat_tx: &Sender, + last_heartbeat_ts: &mut Instant, + packet_tx: &Sender, + trust_packets: bool, + verified_packet_tx: &Sender<(Vec, Option)>, + relayer_stats: &mut RelayerStageStats, + ) -> crate::proxy::Result<()> { + match subscribe_packets_resp.msg { + None => { + saturating_add_assign!(relayer_stats.num_empty_messages, 1); + } + Some(relayer::subscribe_packets_response::Msg::Batch(proto_batch)) => { + let packet_batch = PacketBatch::new( + proto_batch + .packets + .into_iter() + .map(proto_packet_to_packet) + .collect(), + ); + + saturating_add_assign!(relayer_stats.num_packets, packet_batch.len() as u64); + + if trust_packets { + verified_packet_tx + .send((vec![packet_batch], None)) + .map_err(|_| ProxyError::PacketForwardError)?; + } else { + packet_tx + .send(packet_batch) + .map_err(|_| ProxyError::PacketForwardError)?; + } + } + Some(relayer::subscribe_packets_response::Msg::Heartbeat(_)) => { + saturating_add_assign!(relayer_stats.num_heartbeats, 1); + + *last_heartbeat_ts = Instant::now(); + heartbeat_tx + .send(heartbeat_event) + .map_err(|_| ProxyError::HeartbeatChannelError)?; + } + } + Ok(()) + } +} diff --git a/core/src/qos_service.rs b/core/src/qos_service.rs index fb493f6743..e9b67591ed 100644 --- a/core/src/qos_service.rs +++ b/core/src/qos_service.rs @@ -219,7 +219,7 @@ impl QosService { ); } - fn remove_transaction_costs<'a>( + pub fn remove_transaction_costs<'a>( transaction_costs: impl Iterator, transaction_qos_results: impl Iterator>, bank: &Arc, diff --git a/core/src/retransmit_stage.rs b/core/src/retransmit_stage.rs index 07d36a2b4e..189fa77b2c 100644 --- a/core/src/retransmit_stage.rs +++ b/core/src/retransmit_stage.rs @@ -35,7 +35,7 @@ use { solana_streamer::sendmmsg::{multi_target_send, SendPktsError}, std::{ collections::{BTreeSet, HashMap, HashSet}, - net::UdpSocket, + net::{SocketAddr, UdpSocket}, ops::{AddAssign, DerefMut}, sync::{ atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}, @@ -206,6 +206,7 @@ fn retransmit( max_slots: &MaxSlots, first_shreds_received: &Mutex>, rpc_subscriptions: Option<&RpcSubscriptions>, + shred_receiver_addr: Option, ) -> Result<(), RecvTimeoutError> { const RECV_TIMEOUT: Duration = Duration::from_secs(1); let mut shreds = shreds_receiver.recv_timeout(RECV_TIMEOUT)?; @@ -264,8 +265,11 @@ fn retransmit( }; let cluster_nodes = cluster_nodes_cache.get(shred_slot, &root_bank, &working_bank, cluster_info); - let (root_distance, addrs) = + let (root_distance, mut addrs) = cluster_nodes.get_retransmit_addrs(slot_leader, shred, &root_bank, DATA_PLANE_FANOUT); + if let Some(shred_receiver_addr) = shred_receiver_addr { + addrs.push(shred_receiver_addr); + } let addrs: Vec<_> = addrs .into_iter() .filter(|addr| ContactInfo::is_valid_address(addr, socket_addr_space)) @@ -341,6 +345,7 @@ pub fn retransmitter( shreds_receiver: Receiver>, max_slots: Arc, rpc_subscriptions: Option>, + shred_receiver_addr: Option, ) -> JoinHandle<()> { let cluster_nodes_cache = ClusterNodesCache::::new( CLUSTER_NODES_CACHE_NUM_EPOCH_CAP, @@ -375,6 +380,7 @@ pub fn retransmitter( &max_slots, &first_shreds_received, rpc_subscriptions.as_deref(), + shred_receiver_addr, ) { Ok(()) => (), Err(RecvTimeoutError::Timeout) => (), @@ -418,6 +424,7 @@ impl RetransmitStage { rpc_subscriptions: Option>, duplicate_slots_sender: Sender, ancestor_hashes_replay_update_receiver: AncestorHashesReplayUpdateReceiver, + shred_receiver_addr: Option, ) -> Self { let (retransmit_sender, retransmit_receiver) = unbounded(); @@ -429,6 +436,7 @@ impl RetransmitStage { retransmit_receiver, max_slots, rpc_subscriptions, + shred_receiver_addr, ); let cluster_slots_service = ClusterSlotsService::new( diff --git a/core/src/tip_manager.rs b/core/src/tip_manager.rs new file mode 100644 index 0000000000..06198331ff --- /dev/null +++ b/core/src/tip_manager.rs @@ -0,0 +1,473 @@ +use { + anchor_lang::{ + solana_program::hash::Hash, AccountDeserialize, InstructionData, ToAccountMetas, + }, + log::warn, + solana_runtime::bank::Bank, + solana_sdk::{ + account::ReadableAccount, + bundle::error::TipPaymentError, + instruction::Instruction, + pubkey::Pubkey, + signature::Keypair, + signer::Signer, + stake_history::Epoch, + system_program, + transaction::{SanitizedTransaction, Transaction}, + }, + std::{ + collections::HashSet, + sync::{Arc, Mutex, MutexGuard}, + }, + tip_distribution::sdk::{ + derive_config_account_address, derive_tip_distribution_account_address, + instruction::{ + init_tip_distribution_account_ix, initialize_ix, InitTipDistributionAccountAccounts, + InitTipDistributionAccountArgs, InitializeAccounts, InitializeArgs, + }, + }, + tip_payment::{ + Config, InitBumps, TipPaymentAccount, CONFIG_ACCOUNT_SEED, TIP_ACCOUNT_SEED_0, + TIP_ACCOUNT_SEED_1, TIP_ACCOUNT_SEED_2, TIP_ACCOUNT_SEED_3, TIP_ACCOUNT_SEED_4, + TIP_ACCOUNT_SEED_5, TIP_ACCOUNT_SEED_6, TIP_ACCOUNT_SEED_7, + }, +}; + +pub type Result = std::result::Result; + +#[derive(Debug, Clone)] +struct TipPaymentProgramInfo { + program_id: Pubkey, + + config_pda_bump: (Pubkey, u8), + tip_pda_0: (Pubkey, u8), + tip_pda_1: (Pubkey, u8), + tip_pda_2: (Pubkey, u8), + tip_pda_3: (Pubkey, u8), + tip_pda_4: (Pubkey, u8), + tip_pda_5: (Pubkey, u8), + tip_pda_6: (Pubkey, u8), + tip_pda_7: (Pubkey, u8), +} + +/// Contains metadata regarding the tip-distribution account. +/// The PDAs contained in this struct are presumed to be owned by the program. +#[derive(Debug, Clone)] +struct TipDistributionProgramInfo { + /// The tip-distribution program_id. + program_id: Pubkey, + + /// Singleton [Config] PDA and bump tuple. + config_pda_and_bump: (Pubkey, u8), +} + +/// This config is used on each invocation to the `init_tip_distribution_account` instruction. +#[derive(Debug, Clone)] +pub struct TipDistributionAccountConfig { + /// The keypair paying and signing each init tx. + pub payer: Arc, + + /// The account with authority to upload merkle-roots to this validator's [TipDistributionAccount]. + pub merkle_root_upload_authority: Pubkey, + + /// This validator's vote account. + pub vote_account: Pubkey, + + /// This validator's commission rate BPS for tips in the [TipDistributionAccount]. + pub commission_bps: u16, +} + +impl Default for TipDistributionAccountConfig { + fn default() -> Self { + Self { + payer: Arc::new(Keypair::new()), + merkle_root_upload_authority: Pubkey::new_unique(), + vote_account: Pubkey::new_unique(), + commission_bps: 0, + } + } +} + +#[derive(Debug, Clone)] +pub struct TipManager { + tip_payment_program_info: TipPaymentProgramInfo, + tip_distribution_program_info: TipDistributionProgramInfo, + tip_distribution_account_config: TipDistributionAccountConfig, + lock: Arc>, +} + +#[derive(Clone)] +pub struct TipManagerConfig { + pub tip_payment_program_id: Pubkey, + pub tip_distribution_program_id: Pubkey, + pub tip_distribution_account_config: TipDistributionAccountConfig, +} + +impl Default for TipManagerConfig { + fn default() -> Self { + TipManagerConfig { + tip_payment_program_id: Pubkey::new_unique(), + tip_distribution_program_id: Pubkey::new_unique(), + tip_distribution_account_config: TipDistributionAccountConfig::default(), + } + } +} + +impl TipManager { + pub fn new(config: TipManagerConfig) -> TipManager { + let TipManagerConfig { + tip_payment_program_id, + tip_distribution_program_id, + tip_distribution_account_config, + } = config; + + let config_pda_bump = + Pubkey::find_program_address(&[CONFIG_ACCOUNT_SEED], &tip_payment_program_id); + + let tip_pda_0 = + Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_0], &tip_payment_program_id); + let tip_pda_1 = + Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_1], &tip_payment_program_id); + let tip_pda_2 = + Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_2], &tip_payment_program_id); + let tip_pda_3 = + Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_3], &tip_payment_program_id); + let tip_pda_4 = + Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_4], &tip_payment_program_id); + let tip_pda_5 = + Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_5], &tip_payment_program_id); + let tip_pda_6 = + Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_6], &tip_payment_program_id); + let tip_pda_7 = + Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_7], &tip_payment_program_id); + + let config_pda_and_bump = derive_config_account_address(&tip_distribution_program_id); + + TipManager { + tip_payment_program_info: TipPaymentProgramInfo { + program_id: tip_payment_program_id, + config_pda_bump, + tip_pda_0, + tip_pda_1, + tip_pda_2, + tip_pda_3, + tip_pda_4, + tip_pda_5, + tip_pda_6, + tip_pda_7, + }, + tip_distribution_program_info: TipDistributionProgramInfo { + program_id: tip_distribution_program_id, + config_pda_and_bump, + }, + tip_distribution_account_config, + lock: Arc::new(Mutex::new(())), + } + } + + pub fn tip_payment_program_id(&self) -> Pubkey { + self.tip_payment_program_info.program_id + } + + /// Returns the [Config] account owned by the tip-payment program. + pub fn tip_payment_config_pubkey(&self) -> Pubkey { + self.tip_payment_program_info.config_pda_bump.0 + } + + /// Returns the [Config] account owned by the tip-distribution program. + pub fn tip_distribution_config_pubkey(&self) -> Pubkey { + self.tip_distribution_program_info.config_pda_and_bump.0 + } + + /// Given a bank, returns the current `tip_receiver` configured with the tip-payment program. + pub fn get_configured_tip_receiver(&self, bank: &Bank) -> Result { + Ok(self.get_tip_payment_config_account(bank)?.tip_receiver) + } + + pub fn get_tip_accounts(&self) -> HashSet { + HashSet::from([ + self.tip_payment_program_info.tip_pda_0.0, + self.tip_payment_program_info.tip_pda_1.0, + self.tip_payment_program_info.tip_pda_2.0, + self.tip_payment_program_info.tip_pda_3.0, + self.tip_payment_program_info.tip_pda_4.0, + self.tip_payment_program_info.tip_pda_5.0, + self.tip_payment_program_info.tip_pda_6.0, + self.tip_payment_program_info.tip_pda_7.0, + ]) + } + + pub fn get_tip_payment_config_account(&self, bank: &Bank) -> Result { + let config_data = bank + .get_account(&self.tip_payment_program_info.config_pda_bump.0) + .ok_or(TipPaymentError::AccountMissing( + self.tip_payment_program_info.config_pda_bump.0, + ))?; + + Ok(Config::try_deserialize(&mut config_data.data())?) + } + + /// Only called once during contract creation. + pub fn initialize_tip_payment_program_tx( + &self, + recent_blockhash: Hash, + keypair: &Keypair, + ) -> SanitizedTransaction { + let init_ix = Instruction { + program_id: self.tip_payment_program_info.program_id, + data: tip_payment::instruction::Initialize { + _bumps: InitBumps { + config: self.tip_payment_program_info.config_pda_bump.1, + tip_payment_account_0: self.tip_payment_program_info.tip_pda_0.1, + tip_payment_account_1: self.tip_payment_program_info.tip_pda_1.1, + tip_payment_account_2: self.tip_payment_program_info.tip_pda_2.1, + tip_payment_account_3: self.tip_payment_program_info.tip_pda_3.1, + tip_payment_account_4: self.tip_payment_program_info.tip_pda_4.1, + tip_payment_account_5: self.tip_payment_program_info.tip_pda_5.1, + tip_payment_account_6: self.tip_payment_program_info.tip_pda_6.1, + tip_payment_account_7: self.tip_payment_program_info.tip_pda_7.1, + }, + } + .data(), + accounts: tip_payment::accounts::Initialize { + config: self.tip_payment_program_info.config_pda_bump.0, + tip_payment_account_0: self.tip_payment_program_info.tip_pda_0.0, + tip_payment_account_1: self.tip_payment_program_info.tip_pda_1.0, + tip_payment_account_2: self.tip_payment_program_info.tip_pda_2.0, + tip_payment_account_3: self.tip_payment_program_info.tip_pda_3.0, + tip_payment_account_4: self.tip_payment_program_info.tip_pda_4.0, + tip_payment_account_5: self.tip_payment_program_info.tip_pda_5.0, + tip_payment_account_6: self.tip_payment_program_info.tip_pda_6.0, + tip_payment_account_7: self.tip_payment_program_info.tip_pda_7.0, + system_program: system_program::id(), + payer: keypair.pubkey(), + } + .to_account_metas(None), + }; + SanitizedTransaction::try_from_legacy_transaction(Transaction::new_signed_with_payer( + &[init_ix], + Some(&keypair.pubkey()), + &[keypair], + recent_blockhash, + )) + .unwrap() + } + + pub fn lock(&self) -> MutexGuard<()> { + self.lock.lock().unwrap() + } + + /// Returns this validator's [TipDistributionAccount] PDA derived from the provided epoch. + pub fn get_my_tip_distribution_pda(&self, epoch: Epoch) -> Pubkey { + derive_tip_distribution_account_address( + &self.tip_distribution_program_info.program_id, + &self.tip_distribution_account_config.vote_account, + epoch, + ) + .0 + } + + /// Returns whether or not the tip-payment program should be initialized. + pub fn should_initialize_tip_payment_program(&self, bank: &Bank) -> bool { + match bank.get_account(&self.tip_payment_config_pubkey()) { + None => true, + Some(account) => account.owner() != &self.tip_payment_program_info.program_id, + } + } + + /// Returns whether or not the tip-distribution program's [Config] PDA should be initialized. + pub fn should_initialize_tip_distribution_config(&self, bank: &Bank) -> bool { + match bank.get_account(&self.tip_distribution_config_pubkey()) { + None => true, + Some(account) => account.owner() != &self.tip_distribution_program_info.program_id, + } + } + + /// Returns whether or not the current [TipDistributionAccount] PDA should be initialized for this epoch. + pub fn should_init_tip_distribution_account(&self, bank: &Bank) -> bool { + let pda = derive_tip_distribution_account_address( + &self.tip_distribution_program_info.program_id, + &self.tip_distribution_account_config.vote_account, + bank.epoch(), + ) + .0; + match bank.get_account(&pda) { + None => true, + // Since anyone can derive the PDA and send it lamports we must also check the owner is the program. + Some(account) => account.owner() != &self.tip_distribution_program_info.program_id, + } + } + + /// Creates an [Initialize] transaction object. + pub fn initialize_tip_distribution_config_tx( + &self, + recent_blockhash: Hash, + my_keypair: &Keypair, + ) -> SanitizedTransaction { + let ix = initialize_ix( + self.tip_distribution_program_info.program_id, + InitializeArgs { + authority: my_keypair.pubkey(), + expired_funds_account: my_keypair.pubkey(), + num_epochs_valid: 10, + max_validator_commission_bps: 10_000, + bump: self.tip_distribution_program_info.config_pda_and_bump.1, + }, + InitializeAccounts { + config: self.tip_distribution_program_info.config_pda_and_bump.0, + system_program: system_program::id(), + initializer: my_keypair.pubkey(), + }, + ); + + SanitizedTransaction::try_from_legacy_transaction(Transaction::new_signed_with_payer( + &[ix], + Some(&my_keypair.pubkey()), + &[my_keypair], + recent_blockhash, + )) + .unwrap() + } + + /// Creates an [InitTipDistributionAccount] transaction object using the provided Epoch. + pub fn init_tip_distribution_account_tx( + &self, + recent_blockhash: Hash, + epoch: Epoch, + ) -> SanitizedTransaction { + let (tip_distribution_account, bump) = derive_tip_distribution_account_address( + &self.tip_distribution_program_info.program_id, + &self.tip_distribution_account_config.vote_account, + epoch, + ); + + let ix = init_tip_distribution_account_ix( + self.tip_distribution_program_info.program_id, + InitTipDistributionAccountArgs { + validator_vote_account: self.tip_distribution_account_config.vote_account, + merkle_root_upload_authority: self + .tip_distribution_account_config + .merkle_root_upload_authority, + validator_commission_bps: self.tip_distribution_account_config.commission_bps, + bump, + }, + InitTipDistributionAccountAccounts { + config: self.tip_distribution_program_info.config_pda_and_bump.0, + tip_distribution_account, + payer: self.tip_distribution_account_config.payer.pubkey(), + system_program: system_program::id(), + }, + ); + + SanitizedTransaction::try_from_legacy_transaction(Transaction::new_signed_with_payer( + &[ix], + Some(&self.tip_distribution_account_config.payer.pubkey()), + &[self.tip_distribution_account_config.payer.as_ref()], + recent_blockhash, + )) + .unwrap() + } + + /// Builds a transaction that changes the current tip receiver to new_tip_receiver. + /// The on-chain program will transfer tips sitting in the tip accounts to the tip receiver + /// before changing ownership. + pub fn change_tip_receiver_and_block_builder_tx( + &self, + new_tip_receiver: &Pubkey, + bank: &Bank, + keypair: &Keypair, + block_builder: &Pubkey, + block_builder_commission: u64, + ) -> Result { + let config = self.get_tip_payment_config_account(bank)?; + + let change_tip_ix = Instruction { + program_id: self.tip_payment_program_info.program_id, + data: tip_payment::instruction::ChangeTipReceiver {}.data(), + accounts: tip_payment::accounts::ChangeTipReceiver { + config: self.tip_payment_program_info.config_pda_bump.0, + old_tip_receiver: config.tip_receiver, + new_tip_receiver: *new_tip_receiver, + block_builder: config.block_builder, + tip_payment_account_0: self.tip_payment_program_info.tip_pda_0.0, + tip_payment_account_1: self.tip_payment_program_info.tip_pda_1.0, + tip_payment_account_2: self.tip_payment_program_info.tip_pda_2.0, + tip_payment_account_3: self.tip_payment_program_info.tip_pda_3.0, + tip_payment_account_4: self.tip_payment_program_info.tip_pda_4.0, + tip_payment_account_5: self.tip_payment_program_info.tip_pda_5.0, + tip_payment_account_6: self.tip_payment_program_info.tip_pda_6.0, + tip_payment_account_7: self.tip_payment_program_info.tip_pda_7.0, + signer: keypair.pubkey(), + } + .to_account_metas(None), + }; + let change_block_builder_ix = Instruction { + program_id: self.tip_payment_program_info.program_id, + data: tip_payment::instruction::ChangeBlockBuilder { + block_builder_commission, + } + .data(), + accounts: tip_payment::accounts::ChangeBlockBuilder { + config: self.tip_payment_program_info.config_pda_bump.0, + tip_receiver: *new_tip_receiver, // tip receiver will have just changed in previous ix + old_block_builder: config.block_builder, + new_block_builder: *block_builder, + tip_payment_account_0: self.tip_payment_program_info.tip_pda_0.0, + tip_payment_account_1: self.tip_payment_program_info.tip_pda_1.0, + tip_payment_account_2: self.tip_payment_program_info.tip_pda_2.0, + tip_payment_account_3: self.tip_payment_program_info.tip_pda_3.0, + tip_payment_account_4: self.tip_payment_program_info.tip_pda_4.0, + tip_payment_account_5: self.tip_payment_program_info.tip_pda_5.0, + tip_payment_account_6: self.tip_payment_program_info.tip_pda_6.0, + tip_payment_account_7: self.tip_payment_program_info.tip_pda_7.0, + signer: keypair.pubkey(), + } + .to_account_metas(None), + }; + Ok( + SanitizedTransaction::try_from_legacy_transaction(Transaction::new_signed_with_payer( + &[change_tip_ix, change_block_builder_ix], + Some(&keypair.pubkey()), + &[keypair], + bank.last_blockhash(), + )) + .unwrap(), + ) + } + + /// Returns the balance of all the MEV tip accounts + pub fn get_tip_account_balances(&self, bank: &Arc) -> Vec<(Pubkey, u64)> { + let accounts = self.get_tip_accounts(); + accounts + .into_iter() + .map(|account| { + let balance = bank.get_balance(&account); + (account, balance) + }) + .collect() + } + + /// Returns the balance of all the MEV tip accounts above the rent-exempt amount. + /// NOTE: the on-chain program has rent_exempt = force + pub fn get_tip_account_balances_above_rent_exempt( + &self, + bank: &Arc, + ) -> Vec<(Pubkey, u64)> { + let accounts = self.get_tip_accounts(); + accounts + .into_iter() + .map(|account| { + let account_data = bank.get_account(&account).unwrap_or_default(); + let balance = bank.get_balance(&account); + let rent_exempt = + bank.get_minimum_balance_for_rent_exemption(account_data.data().len()); + // NOTE: don't unwrap here in case bug in on-chain program, don't want all validators to crash + // if program gets stuck in bad state + (account, balance.checked_sub(rent_exempt).unwrap_or_else(|| { + warn!("balance is below rent exempt amount. balance: {} rent_exempt: {} acc size: {}", balance, rent_exempt, TipPaymentAccount::SIZE); + 0 + })) + }) + .collect() + } +} diff --git a/core/src/tpu.rs b/core/src/tpu.rs index 7623babda0..59b069720c 100644 --- a/core/src/tpu.rs +++ b/core/src/tpu.rs @@ -5,15 +5,23 @@ use { crate::{ banking_stage::BankingStage, broadcast_stage::{BroadcastStage, BroadcastStageType, RetransmitSlotsReceiver}, + bundle_account_locker::BundleAccountLocker, + bundle_stage::BundleStage, cluster_info_vote_listener::{ ClusterInfoVoteListener, GossipDuplicateConfirmedSlotsSender, GossipVerifiedVoteHashSender, VerifiedVoteSender, VoteTracker, }, fetch_stage::FetchStage, find_packet_sender_stake_stage::FindPacketSenderStakeStage, + proxy::{ + block_engine_stage::{BlockBuilderFeeInfo, BlockEngineConfig, BlockEngineStage}, + fetch_stage_manager::FetchStageManager, + relayer_stage::{RelayerConfig, RelayerStage}, + }, sigverify::TransactionSigVerifier, sigverify_stage::SigVerifyStage, staked_nodes_updater_service::StakedNodesUpdaterService, + tip_manager::{TipManager, TipManagerConfig}, }, crossbeam_channel::{bounded, unbounded, Receiver, RecvTimeoutError}, solana_client::connection_cache::ConnectionCache, @@ -29,13 +37,14 @@ use { cost_model::CostModel, vote_sender_types::{ReplayVoteReceiver, ReplayVoteSender}, }, - solana_sdk::signature::Keypair, + solana_sdk::signature::{Keypair, Signer}, solana_streamer::{ quic::{spawn_server, StreamStats, MAX_STAKED_CONNECTIONS, MAX_UNSTAKED_CONNECTIONS}, streamer::StakedNodes, }, std::{ - net::UdpSocket, + collections::HashSet, + net::{SocketAddr, UdpSocket}, sync::{atomic::AtomicBool, Arc, Mutex, RwLock}, thread, time::Duration, @@ -63,6 +72,9 @@ pub struct Tpu { fetch_stage: FetchStage, sigverify_stage: SigVerifyStage, vote_sigverify_stage: SigVerifyStage, + maybe_relayer_stage: Option, + maybe_block_engine_stage: Option, + maybe_fetch_stage_manager: Option, banking_stage: BankingStage, cluster_info_vote_listener: ClusterInfoVoteListener, broadcast_stage: BroadcastStage, @@ -71,6 +83,7 @@ pub struct Tpu { find_packet_sender_stake_stage: FindPacketSenderStakeStage, vote_find_packet_sender_stake_stage: FindPacketSenderStakeStage, staked_nodes_updater_service: StakedNodesUpdaterService, + bundle_stage: BundleStage, } impl Tpu { @@ -101,6 +114,10 @@ impl Tpu { keypair: &Keypair, staked_nodes: &Arc>, tpu_enable_udp: bool, + maybe_block_engine_config: Option, + maybe_relayer_config: Option, + tip_manager_config: TipManagerConfig, + shred_receiver_address: Option, ) -> Self { let TpuSockets { transactions: transactions_sockets, @@ -111,7 +128,17 @@ impl Tpu { transactions_forwards_quic: transactions_forwards_quic_sockets, } = sockets; + let (packet_intercept_sender, packet_intercept_receiver) = unbounded(); let (packet_sender, packet_receiver) = unbounded(); + + // If there's a relayer, we need to redirect packets to the interceptor + // If not, they can flow straight through + let packet_send_channel = if maybe_relayer_config.is_some() { + packet_intercept_sender + } else { + packet_sender.clone() + }; + let (vote_packet_sender, vote_packet_receiver) = unbounded(); let (forwarded_packet_sender, forwarded_packet_receiver) = unbounded(); let fetch_stage = FetchStage::new_with_sender( @@ -119,7 +146,7 @@ impl Tpu { tpu_forwards_sockets, tpu_vote_sockets, exit, - &packet_sender, + &packet_send_channel, &vote_packet_sender, &forwarded_packet_sender, forwarded_packet_receiver, @@ -162,7 +189,7 @@ impl Tpu { transactions_quic_sockets, keypair, cluster_info.my_contact_info().tpu.ip(), - packet_sender, + packet_send_channel, exit.clone(), MAX_QUIC_CONNECTIONS_PER_PEER, staked_nodes.clone(), @@ -187,7 +214,7 @@ impl Tpu { .unwrap(); let sigverify_stage = { - let verifier = TransactionSigVerifier::new(verified_sender); + let verifier = TransactionSigVerifier::new(verified_sender.clone()); SigVerifyStage::new(find_packet_sender_stake_receiver, verifier, "tpu-verifier") }; @@ -203,6 +230,45 @@ impl Tpu { ) }; + let block_builder_fee_info = Arc::new(Mutex::new(BlockBuilderFeeInfo { + block_builder: cluster_info.keypair().pubkey(), + block_builder_commission: 0, + })); + + let (bundle_sender, bundle_receiver) = unbounded(); + let maybe_block_engine_stage = maybe_block_engine_config.map(|block_engine_config| { + BlockEngineStage::new( + block_engine_config, + bundle_sender, + cluster_info.clone(), + packet_sender.clone(), + verified_sender.clone(), + exit.clone(), + &block_builder_fee_info, + ) + }); + + let (heartbeat_tx, heartbeat_rx) = unbounded(); + let maybe_fetch_stage_manager = maybe_relayer_config.as_ref().map(|_| { + FetchStageManager::new( + cluster_info.clone(), + heartbeat_rx, + packet_intercept_receiver, + packet_sender.clone(), + exit.clone(), + ) + }); + let maybe_relayer_stage = maybe_relayer_config.map(|relayer_config| { + RelayerStage::new( + relayer_config, + cluster_info.clone(), + heartbeat_tx, + packet_sender, + verified_sender, + exit.clone(), + ) + }); + let (verified_gossip_vote_packets_sender, verified_gossip_vote_packets_receiver) = unbounded(); let cluster_info_vote_listener = ClusterInfoVoteListener::new( @@ -221,17 +287,41 @@ impl Tpu { cluster_confirmed_slot_sender, ); + let tip_manager = TipManager::new(tip_manager_config); + + let bundle_account_locker = BundleAccountLocker::default(); + + // tip accounts can't be used in BankingStage to avoid someone from stealing tips mid-slot. + // it also helps reduce surface area for potential account contention + let mut blacklisted_accounts = HashSet::new(); + blacklisted_accounts.insert(tip_manager.tip_payment_config_pubkey()); + blacklisted_accounts.extend(tip_manager.get_tip_accounts()); let banking_stage = BankingStage::new( cluster_info, poh_recorder, verified_receiver, verified_tpu_vote_packets_receiver, verified_gossip_vote_packets_receiver, - transaction_status_sender, - replay_vote_sender, + transaction_status_sender.clone(), + replay_vote_sender.clone(), cost_model.clone(), connection_cache.clone(), bank_forks.clone(), + blacklisted_accounts, + bundle_account_locker.clone(), + ); + + let bundle_stage = BundleStage::new( + cluster_info, + poh_recorder, + transaction_status_sender, + replay_vote_sender, + cost_model.clone(), + bundle_receiver, + exit.clone(), + tip_manager, + bundle_account_locker, + &block_builder_fee_info, ); let broadcast_stage = broadcast_type.new_broadcast_stage( @@ -243,12 +333,16 @@ impl Tpu { blockstore.clone(), bank_forks, shred_version, + shred_receiver_address, ); Self { fetch_stage, sigverify_stage, vote_sigverify_stage, + maybe_block_engine_stage, + maybe_relayer_stage, + maybe_fetch_stage_manager, banking_stage, cluster_info_vote_listener, broadcast_stage, @@ -257,6 +351,7 @@ impl Tpu { find_packet_sender_stake_stage, vote_find_packet_sender_stake_stage, staked_nodes_updater_service, + bundle_stage, } } @@ -288,7 +383,19 @@ impl Tpu { self.staked_nodes_updater_service.join(), self.tpu_quic_t.join(), self.tpu_forwards_quic_t.join(), + self.bundle_stage.join(), ]; + + if let Some(relayer_stage) = self.maybe_relayer_stage { + relayer_stage.join()?; + } + if let Some(block_engine_stage) = self.maybe_block_engine_stage { + block_engine_stage.join()?; + } + if let Some(fetch_stage_manager) = self.maybe_fetch_stage_manager { + fetch_stage_manager.join()?; + } + let broadcast_result = self.broadcast_stage.join(); for result in results { result?; diff --git a/core/src/tvu.rs b/core/src/tvu.rs index 78d8e76e0d..b3349b68dd 100644 --- a/core/src/tvu.rs +++ b/core/src/tvu.rs @@ -61,9 +61,9 @@ use { solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Keypair}, std::{ collections::HashSet, - net::UdpSocket, + net::{SocketAddr, UdpSocket}, sync::{atomic::AtomicBool, Arc, Mutex, RwLock}, - thread, + thread::{self}, time::Duration, }, }; @@ -157,6 +157,7 @@ impl Tvu { wait_to_vote_slot: Option, pruned_banks_receiver: DroppedSlotsReceiver, connection_cache: &Arc, + shred_receiver_addr: Option, ) -> Self { let TvuSockets { repair: repair_socket, @@ -225,6 +226,7 @@ impl Tvu { Some(rpc_subscriptions.clone()), duplicate_slots_sender, ancestor_hashes_replay_update_receiver, + shred_receiver_addr, ); let (ledger_cleanup_slot_sender, ledger_cleanup_slot_receiver) = unbounded(); @@ -544,6 +546,7 @@ pub mod tests { None, pruned_banks_receiver, &Arc::new(ConnectionCache::default()), + None, ); exit.store(true, Ordering::Relaxed); tvu.join().unwrap(); diff --git a/core/src/validator.rs b/core/src/validator.rs index 86a6aa5f57..47424c8400 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -8,6 +8,7 @@ use { cluster_info_vote_listener::VoteTracker, completed_data_sets_service::CompletedDataSetsService, consensus::{reconcile_blockstore_roots_with_tower, Tower}, + proxy::{block_engine_stage::BlockEngineConfig, relayer_stage::RelayerConfig}, rewards_recorder_service::{RewardsRecorderSender, RewardsRecorderService}, sample_performance_service::SamplePerformanceService, serve_repair::ServeRepair, @@ -16,6 +17,7 @@ use { snapshot_packager_service::SnapshotPackagerService, stats_reporter_service::StatsReporterService, system_monitor_service::{verify_udp_stats_access, SystemMonitorService}, + tip_manager::TipManagerConfig, tower_storage::TowerStorage, tpu::{Tpu, TpuSockets, DEFAULT_TPU_COALESCE_MS}, tvu::{Tvu, TvuConfig, TvuSockets}, @@ -172,6 +174,10 @@ pub struct ValidatorConfig { pub accounts_shrink_ratio: AccountShrinkThreshold, pub wait_to_vote_slot: Option, pub ledger_column_options: LedgerColumnOptions, + pub maybe_relayer_config: Option, + pub maybe_block_engine_config: Option, + pub shred_receiver_address: Option, + pub tip_manager_config: TipManagerConfig, } impl Default for ValidatorConfig { @@ -235,6 +241,10 @@ impl Default for ValidatorConfig { accounts_db_config: None, wait_to_vote_slot: None, ledger_column_options: LedgerColumnOptions::default(), + maybe_relayer_config: None, + maybe_block_engine_config: None, + shred_receiver_address: None, + tip_manager_config: TipManagerConfig::default(), } } } @@ -962,6 +972,7 @@ impl Validator { config.wait_to_vote_slot, pruned_banks_receiver, &connection_cache, + config.shred_receiver_address, ); let tpu = Tpu::new( @@ -997,12 +1008,20 @@ impl Validator { &identity_keypair, &staked_nodes, tpu_enable_udp, + config.maybe_block_engine_config.clone(), + config.maybe_relayer_config.clone(), + config.tip_manager_config.clone(), + config.shred_receiver_address, ); datapoint_info!( "validator-new", ("id", id.to_string(), String), - ("version", solana_version::version!(), String) + ( + "version", + format!("jito-{}", solana_version::version!()), + String + ) ); *start_progress.write().unwrap() = ValidatorStartProgress::Running; @@ -1884,7 +1903,7 @@ mod tests { Arc::new(validator_keypair), &validator_ledger_path, &voting_keypair.pubkey(), - Arc::new(RwLock::new(vec![voting_keypair.clone()])), + Arc::new(RwLock::new(vec![voting_keypair])), vec![leader_node.info], &config, true, // should_check_duplicate_instance diff --git a/core/tests/snapshots.rs b/core/tests/snapshots.rs index d86d26bc92..3abb534ecf 100644 --- a/core/tests/snapshots.rs +++ b/core/tests/snapshots.rs @@ -837,6 +837,7 @@ mod tests { false, Some(ACCOUNTS_DB_CONFIG_FOR_TESTING), None, + None, )?; assert_eq!(bank, &deserialized_bank); @@ -1016,6 +1017,7 @@ mod tests { false, Some(ACCOUNTS_DB_CONFIG_FOR_TESTING), None, + None, ) .unwrap(); diff --git a/deploy_programs b/deploy_programs new file mode 100755 index 0000000000..cbdf837e92 --- /dev/null +++ b/deploy_programs @@ -0,0 +1,17 @@ +#!/usr/bin/env sh +# Deploys the tip payment and tip distribution programs on local validator at predetermined address +set -eux + +WALLET_LOCATION=~/.config/solana/id.json + +# build this solana binary to ensure we're using a version compatible with the validator +cargo b --release --bin solana + +./target/release/solana airdrop -ul 1000 $WALLET_LOCATION + +(cd jito-programs/tip-payment && anchor build) + +# NOTE: make sure the declare_id! is set correctly in the programs +# Also, || true to make sure if fails the first time around, tip_payment can still be deployed +RUST_INFO=trace ./target/release/solana deploy --keypair $WALLET_LOCATION -ul ./jito-programs/tip-payment/target/deploy/tip_distribution.so ./jito-programs/tip-payment/dev/dev_tip_distribution.json || true +RUST_INFO=trace ./target/release/solana deploy --keypair $WALLET_LOCATION -ul ./jito-programs/tip-payment/target/deploy/tip_payment.so ./jito-programs/tip-payment/dev/dev_tip_payment.json diff --git a/dev/Dockerfile b/dev/Dockerfile new file mode 100644 index 0000000000..0f3c3e38f8 --- /dev/null +++ b/dev/Dockerfile @@ -0,0 +1,44 @@ +FROM rust:1.63.0 + +# Add Google Protocol Buffers for Libra's metrics library. +ENV PROTOC_VERSION 3.8.0 +ENV PROTOC_ZIP protoc-$PROTOC_VERSION-linux-x86_64.zip + +RUN set -x \ + && apt update \ + && apt install -y \ + clang \ + cmake \ + libudev-dev \ + make \ + unzip \ + libssl-dev \ + pkg-config \ + zlib1g-dev \ + make \ + && rustup component add rustfmt \ + && rustup component add clippy \ + && rustc --version \ + && cargo --version \ + && curl -OL https://github.com/google/protobuf/releases/download/v$PROTOC_VERSION/$PROTOC_ZIP \ + && unzip -o $PROTOC_ZIP -d /usr/local bin/protoc \ + && unzip -o $PROTOC_ZIP -d /usr/local include/* \ + && rm -f $PROTOC_ZIP + + +WORKDIR /solana +COPY . . +RUN mkdir -p docker-output + +ARG ci_commit +ENV CI_COMMIT=$ci_commit + +# Uses docker buildkit to cache the image. +# /usr/local/cargo/git needed for crossbeam patch +RUN --mount=type=cache,mode=0777,target=/solana/target \ + --mount=type=cache,mode=0777,target=/usr/local/cargo/registry \ + --mount=type=cache,mode=0777,target=/usr/local/cargo/git \ + cargo build --release && cp target/release/solana* ./docker-output && \ + cargo build --release --manifest-path solana-accountsdb-connector/Cargo.toml && \ + cp solana-accountsdb-connector/target/release/libsolana* ./docker-output + diff --git a/dos/Cargo.toml b/dos/Cargo.toml index 98f9b69df2..17850a72b5 100644 --- a/dos/Cargo.toml +++ b/dos/Cargo.toml @@ -11,7 +11,7 @@ description = "Tool to send various requests to cluster in order to evaluate the [dependencies] bincode = "1.3.3" -clap = {version = "3.1.5", features = ["derive", "cargo"]} +clap = { version = "3.1.5", features = ["derive", "cargo"] } log = "0.4.14" rand = "0.7.0" serde = "1.0.136" diff --git a/entry/src/entry.rs b/entry/src/entry.rs index 637ad52f1b..9fc337731f 100644 --- a/entry/src/entry.rs +++ b/entry/src/entry.rs @@ -202,7 +202,7 @@ pub fn hash_transactions(transactions: &[VersionedTransaction]) -> Hash { .iter() .flat_map(|tx| tx.signatures.iter()) .collect(); - let merkle_tree = MerkleTree::new(&signatures); + let merkle_tree = MerkleTree::new(&signatures, false); if let Some(root_hash) = merkle_tree.get_root() { *root_hash } else { diff --git a/entry/src/poh.rs b/entry/src/poh.rs index 28126276f3..3fbebe30df 100644 --- a/entry/src/poh.rs +++ b/entry/src/poh.rs @@ -75,19 +75,30 @@ impl Poh { } pub fn record(&mut self, mixin: Hash) -> Option { - if self.remaining_hashes == 1 { + let entries = self.record_bundle(&[mixin]); + entries.unwrap_or_default().pop() + } + + pub fn record_bundle(&mut self, mixins: &[Hash]) -> Option> { + if self.remaining_hashes <= mixins.len() as u64 { return None; // Caller needs to `tick()` first } - self.hash = hashv(&[self.hash.as_ref(), mixin.as_ref()]); - let num_hashes = self.num_hashes + 1; - self.num_hashes = 0; - self.remaining_hashes -= 1; + let entries = mixins + .iter() + .map(|m| { + self.hash = hashv(&[self.hash.as_ref(), m.as_ref()]); + let num_hashes = self.num_hashes + 1; + self.num_hashes = 0; + self.remaining_hashes -= 1; + PohEntry { + num_hashes, + hash: self.hash, + } + }) + .collect(); - Some(PohEntry { - num_hashes, - hash: self.hash, - }) + Some(entries) } pub fn tick(&mut self) -> Option { diff --git a/f b/f new file mode 100755 index 0000000000..9f276a138f --- /dev/null +++ b/f @@ -0,0 +1,25 @@ +#!/usr/bin/env sh +# Builds jito-solana in a docker container. +# Useful for running on machines that might not have cargo installed but can run docker (Flatcar Linux). +set -eux + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" + +GIT_SHA="$(git describe --always --dirty)" + +echo $GIT_SHA + +DOCKER_BUILDKIT=1 docker build \ + --build-arg ci_commit=$GIT_SHA \ + -t jitolabs/build-solana \ + -f dev/Dockerfile . \ + --progress=plain + +# Creates a temporary container, copies solana-validator built inside container there and +# removes the temporary container. +docker rm temp || true +docker container create --name temp jitolabs/build-solana +mkdir -p $SCRIPT_DIR/docker-output +# Outputs the solana-validator binary to $SOLANA/docker-output/solana-validator +docker container cp temp:/solana/docker-output $SCRIPT_DIR/ +docker rm temp diff --git a/frozen-abi/Cargo.toml b/frozen-abi/Cargo.toml index 1dae2d09da..fd5945b294 100644 --- a/frozen-abi/Cargo.toml +++ b/frozen-abi/Cargo.toml @@ -15,8 +15,8 @@ bv = { version = "0.11.1", features = ["serde"] } lazy_static = "1.4.0" log = "0.4.14" serde = "1.0.136" -serde_derive = "1.0.103" serde_bytes = "0.11" +serde_derive = "1.0.103" sha2 = "0.10.2" solana-frozen-abi-macro = { path = "macro", version = "=1.13.6" } thiserror = "1.0" diff --git a/gossip/src/cluster_info.rs b/gossip/src/cluster_info.rs index 39be4162fa..cbbf257e9f 100644 --- a/gossip/src/cluster_info.rs +++ b/gossip/src/cluster_info.rs @@ -510,6 +510,10 @@ impl ClusterInfo { *self.entrypoints.write().unwrap() = entrypoints; } + pub fn set_my_contact_info(&self, my_contact_info: ContactInfo) { + *self.my_contact_info.write().unwrap() = my_contact_info; + } + pub fn save_contact_info(&self) { let nodes = { let entrypoint_gossip_addrs = self diff --git a/jito-programs b/jito-programs new file mode 160000 index 0000000000..f94e71d8f4 --- /dev/null +++ b/jito-programs @@ -0,0 +1 @@ +Subproject commit f94e71d8f4950f46ccc04e4a66394b4c207d6be0 diff --git a/jito-protos/Cargo.toml b/jito-protos/Cargo.toml new file mode 100644 index 0000000000..f4177c67e2 --- /dev/null +++ b/jito-protos/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "jito-protos" +version = "1.13.6" +edition = "2021" +publish = false + +[dependencies] +bytes = "1.1.0" +crossbeam-epoch = "=0.9.5" # TODO (LB): this allows compliation on rust_nightly in ci +lock_api = "=0.4.6" # TODO (LB): this allows compliation on rust_nightly in ci due to +prost = "0.8.0" +prost-types = "0.8.0" +tonic = "0.5.2" + +[build-dependencies] +tonic-build = "0.5.2" diff --git a/jito-protos/build.rs b/jito-protos/build.rs new file mode 100644 index 0000000000..54c8b8d5e7 --- /dev/null +++ b/jito-protos/build.rs @@ -0,0 +1,17 @@ +use tonic_build::configure; + +fn main() { + configure() + .compile( + &[ + "protos/auth.proto", + "protos/block_engine.proto", + "protos/bundle.proto", + "protos/packet.proto", + "protos/relayer.proto", + "protos/shared.proto", + ], + &["protos"], + ) + .unwrap(); +} diff --git a/jito-protos/protos b/jito-protos/protos new file mode 160000 index 0000000000..05d210980f --- /dev/null +++ b/jito-protos/protos @@ -0,0 +1 @@ +Subproject commit 05d210980f34a7c974d7ed1a4dbcb2ce1fca00b3 diff --git a/jito-protos/src/lib.rs b/jito-protos/src/lib.rs new file mode 100644 index 0000000000..cf630c53d2 --- /dev/null +++ b/jito-protos/src/lib.rs @@ -0,0 +1,25 @@ +pub mod proto { + pub mod auth { + tonic::include_proto!("auth"); + } + + pub mod block_engine { + tonic::include_proto!("block_engine"); + } + + pub mod bundle { + tonic::include_proto!("bundle"); + } + + pub mod packet { + tonic::include_proto!("packet"); + } + + pub mod relayer { + tonic::include_proto!("relayer"); + } + + pub mod shared { + tonic::include_proto!("shared"); + } +} diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index 674a19778f..f494cded01 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -824,6 +824,11 @@ fn load_bank_forks( vec![non_primary_accounts_path] }; + info!( + "load_bank_forks halt_at_slot: {:?}", + process_options.halt_at_slot + ); + let (accounts_package_sender, _) = unbounded(); bank_forks_utils::load( genesis_config, @@ -2328,6 +2333,7 @@ fn main() { dev_halt_at_slot: Some(snapshot_slot), new_hard_forks, poh_verify: false, + halt_at_slot: Some(snapshot_slot), ..ProcessOptions::default() }, snapshot_archive_path, diff --git a/ledger/src/bank_forks_utils.rs b/ledger/src/bank_forks_utils.rs index efaf5aca99..068ac54c19 100644 --- a/ledger/src/bank_forks_utils.rs +++ b/ledger/src/bank_forks_utils.rs @@ -102,6 +102,7 @@ pub fn load_bank_forks( if snapshot_utils::get_highest_full_snapshot_archive_info( &snapshot_config.snapshot_archives_dir, + process_options.halt_at_slot, ) .is_some() { @@ -198,7 +199,7 @@ pub fn load_bank_forks( } #[allow(clippy::too_many_arguments)] -fn bank_forks_from_snapshot( +pub fn bank_forks_from_snapshot( genesis_config: &GenesisConfig, account_paths: Vec, shrink_paths: Option>, @@ -212,6 +213,13 @@ fn bank_forks_from_snapshot( process::exit(1); } + info!( + "halt_at_slot: {:?} bank_snapshots_dir: {:?}, snapshot_archives_dir: {:?}", + process_options.halt_at_slot, + snapshot_config.bank_snapshots_dir, + snapshot_config.snapshot_archives_dir + ); + let (deserialized_bank, full_snapshot_archive_info, incremental_snapshot_archive_info) = snapshot_utils::bank_from_latest_snapshot_archives( &snapshot_config.bank_snapshots_dir, @@ -229,6 +237,7 @@ fn bank_forks_from_snapshot( process_options.verify_index, process_options.accounts_db_config.clone(), accounts_update_notifier, + process_options.halt_at_slot, ) .expect("Load from snapshot failed"); diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index 6ea3684f21..b2f8085200 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -168,7 +168,7 @@ fn execute_batch( let mut mint_decimals: HashMap = HashMap::new(); let pre_token_balances = if record_token_balances { - collect_token_balances(bank, batch, &mut mint_decimals) + collect_token_balances(bank, batch, &mut mint_decimals, None) } else { vec![] }; @@ -225,7 +225,7 @@ fn execute_batch( if let Some(transaction_status_sender) = transaction_status_sender { let transactions = batch.sanitized_transactions().to_vec(); let post_token_balances = if record_token_balances { - collect_token_balances(bank, batch, &mut mint_decimals) + collect_token_balances(bank, batch, &mut mint_decimals, None) } else { vec![] }; @@ -570,6 +570,7 @@ pub struct ProcessOptions { pub accounts_db_config: Option, pub verify_index: bool, pub shrink_ratio: AccountShrinkThreshold, + pub halt_at_slot: Option, } pub fn test_process_blockstore( diff --git a/ledger/src/token_balances.rs b/ledger/src/token_balances.rs index 673cc5556b..586bbd8526 100644 --- a/ledger/src/token_balances.rs +++ b/ledger/src/token_balances.rs @@ -5,7 +5,9 @@ use { }, solana_measure::measure::Measure, solana_metrics::datapoint_debug, - solana_runtime::{bank::Bank, transaction_batch::TransactionBatch}, + solana_runtime::{ + account_overrides::AccountOverrides, bank::Bank, transaction_batch::TransactionBatch, + }, solana_sdk::{account::ReadableAccount, pubkey::Pubkey}, solana_transaction_status::{ token_balances::TransactionTokenBalances, TransactionTokenBalance, @@ -39,6 +41,7 @@ pub fn collect_token_balances( bank: &Bank, batch: &TransactionBatch, mint_decimals: &mut HashMap, + cached_accounts: Option<&AccountOverrides>, ) -> TransactionTokenBalances { let mut balances: TransactionTokenBalances = vec![]; let mut collect_time = Measure::start("collect_token_balances"); @@ -59,8 +62,12 @@ pub fn collect_token_balances( ui_token_amount, owner, program_id, - }) = collect_token_balance_from_account(bank, account_id, mint_decimals) - { + }) = collect_token_balance_from_account( + bank, + account_id, + mint_decimals, + cached_accounts, + ) { transaction_balances.push(TransactionTokenBalance { account_index: index as u8, mint, @@ -93,8 +100,17 @@ fn collect_token_balance_from_account( bank: &Bank, account_id: &Pubkey, mint_decimals: &mut HashMap, + account_overrides: Option<&AccountOverrides>, ) -> Option { - let account = bank.get_account(account_id)?; + let account = { + if let Some(account_override) = + account_overrides.and_then(|overrides| overrides.get(account_id)) + { + Some(account_override.clone()) + } else { + bank.get_account(account_id) + } + }?; if !is_known_spl_token_id(account.owner()) { return None; @@ -237,13 +253,13 @@ mod test { // Account is not owned by spl_token (nor does it have TokenAccount state) assert_eq!( - collect_token_balance_from_account(&bank, &account_pubkey, &mut mint_decimals), + collect_token_balance_from_account(&bank, &account_pubkey, &mut mint_decimals, None), None ); // Mint does not have TokenAccount state assert_eq!( - collect_token_balance_from_account(&bank, &mint_pubkey, &mut mint_decimals), + collect_token_balance_from_account(&bank, &mint_pubkey, &mut mint_decimals, None), None ); @@ -252,7 +268,8 @@ mod test { collect_token_balance_from_account( &bank, &spl_token_account_pubkey, - &mut mint_decimals + &mut mint_decimals, + None ), Some(TokenBalanceData { mint: mint_pubkey.to_string(), @@ -269,7 +286,12 @@ mod test { // TokenAccount is not owned by known spl-token program_id assert_eq!( - collect_token_balance_from_account(&bank, &other_account_pubkey, &mut mint_decimals), + collect_token_balance_from_account( + &bank, + &other_account_pubkey, + &mut mint_decimals, + None + ), None ); @@ -278,7 +300,8 @@ mod test { collect_token_balance_from_account( &bank, &other_mint_account_pubkey, - &mut mint_decimals + &mut mint_decimals, + None ), None ); @@ -428,13 +451,13 @@ mod test { // Account is not owned by spl_token (nor does it have TokenAccount state) assert_eq!( - collect_token_balance_from_account(&bank, &account_pubkey, &mut mint_decimals), + collect_token_balance_from_account(&bank, &account_pubkey, &mut mint_decimals, None), None ); // Mint does not have TokenAccount state assert_eq!( - collect_token_balance_from_account(&bank, &mint_pubkey, &mut mint_decimals), + collect_token_balance_from_account(&bank, &mint_pubkey, &mut mint_decimals, None), None ); @@ -443,7 +466,8 @@ mod test { collect_token_balance_from_account( &bank, &spl_token_account_pubkey, - &mut mint_decimals + &mut mint_decimals, + None ), Some(TokenBalanceData { mint: mint_pubkey.to_string(), @@ -460,7 +484,12 @@ mod test { // TokenAccount is not owned by known spl-token program_id assert_eq!( - collect_token_balance_from_account(&bank, &other_account_pubkey, &mut mint_decimals), + collect_token_balance_from_account( + &bank, + &other_account_pubkey, + &mut mint_decimals, + None + ), None ); @@ -469,7 +498,8 @@ mod test { collect_token_balance_from_account( &bank, &other_mint_account_pubkey, - &mut mint_decimals + &mut mint_decimals, + None ), None ); diff --git a/local-cluster/src/local_cluster_snapshot_utils.rs b/local-cluster/src/local_cluster_snapshot_utils.rs index 1cdf9ef938..ed27f969a8 100644 --- a/local-cluster/src/local_cluster_snapshot_utils.rs +++ b/local-cluster/src/local_cluster_snapshot_utils.rs @@ -69,7 +69,7 @@ impl LocalCluster { ); loop { if let Some(full_snapshot_archive_info) = - snapshot_utils::get_highest_full_snapshot_archive_info(&snapshot_archives_dir) + snapshot_utils::get_highest_full_snapshot_archive_info(&snapshot_archives_dir, None) { match next_snapshot_type { NextSnapshotType::FullSnapshot => { @@ -82,6 +82,7 @@ impl LocalCluster { snapshot_utils::get_highest_incremental_snapshot_archive_info( &snapshot_archives_dir, full_snapshot_archive_info.slot(), + None, ) { if incremental_snapshot_archive_info.slot() >= last_slot { diff --git a/local-cluster/src/validator_configs.rs b/local-cluster/src/validator_configs.rs index bd7bb45dda..9d531c42e0 100644 --- a/local-cluster/src/validator_configs.rs +++ b/local-cluster/src/validator_configs.rs @@ -65,6 +65,10 @@ pub fn safe_clone_config(config: &ValidatorConfig) -> ValidatorConfig { accounts_db_config: config.accounts_db_config.clone(), wait_to_vote_slot: config.wait_to_vote_slot, ledger_column_options: config.ledger_column_options.clone(), + maybe_relayer_config: config.maybe_relayer_config.clone(), + maybe_block_engine_config: config.maybe_block_engine_config.clone(), + shred_receiver_address: config.shred_receiver_address, + tip_manager_config: config.tip_manager_config.clone(), } } diff --git a/local-cluster/tests/local_cluster.rs b/local-cluster/tests/local_cluster.rs index f672e17d2c..b3def2c572 100644 --- a/local-cluster/tests/local_cluster.rs +++ b/local-cluster/tests/local_cluster.rs @@ -785,6 +785,7 @@ fn test_incremental_snapshot_download_with_crossing_full_snapshot_interval_at_st let downloaded_full_snapshot_archive_info = snapshot_utils::get_highest_full_snapshot_archive_info( validator_snapshot_test_config.snapshot_archives_dir.path(), + None, ) .unwrap(); debug!( @@ -821,6 +822,7 @@ fn test_incremental_snapshot_download_with_crossing_full_snapshot_interval_at_st snapshot_utils::get_highest_incremental_snapshot_archive_info( validator_snapshot_test_config.snapshot_archives_dir.path(), full_snapshot_archive_info.slot(), + None, ) .unwrap(); debug!( @@ -940,6 +942,7 @@ fn test_incremental_snapshot_download_with_crossing_full_snapshot_interval_at_st let leader_full_snapshot_archive_info_for_comparison = { let validator_full_snapshot = snapshot_utils::get_highest_full_snapshot_archive_info( validator_snapshot_test_config.snapshot_archives_dir.path(), + None, ) .unwrap(); @@ -982,6 +985,7 @@ fn test_incremental_snapshot_download_with_crossing_full_snapshot_interval_at_st let validator_full_snapshot_slot_at_startup = snapshot_utils::get_highest_full_snapshot_archive_slot( validator_snapshot_test_config.snapshot_archives_dir.path(), + None, ) .unwrap(); @@ -1003,6 +1007,7 @@ fn test_incremental_snapshot_download_with_crossing_full_snapshot_interval_at_st if let Some(highest_full_snapshot_info) = snapshot_utils::get_highest_full_snapshot_archive_info( validator_snapshot_test_config.snapshot_archives_dir.path(), + None, ) { if highest_full_snapshot_info.slot() > validator_full_snapshot_slot_at_startup { @@ -1010,6 +1015,7 @@ fn test_incremental_snapshot_download_with_crossing_full_snapshot_interval_at_st snapshot_utils::get_highest_incremental_snapshot_archive_info( validator_snapshot_test_config.snapshot_archives_dir.path(), highest_full_snapshot_info.slot(), + None, ) { info!("Success! Made new full and incremental snapshots!"); @@ -1195,7 +1201,7 @@ fn test_snapshots_blockstore_floor() { let archive_info = loop { let archive = - snapshot_utils::get_highest_full_snapshot_archive_info(&snapshot_archives_dir); + snapshot_utils::get_highest_full_snapshot_archive_info(&snapshot_archives_dir, None); if archive.is_some() { trace!("snapshot exists"); break archive.unwrap(); diff --git a/logger/Cargo.toml b/logger/Cargo.toml index aa36da0768..d801dd8134 100644 --- a/logger/Cargo.toml +++ b/logger/Cargo.toml @@ -10,7 +10,7 @@ documentation = "https://docs.rs/solana-logger" edition = "2021" [dependencies] -env_logger = "0.9.0" +env_logger = "=0.9.0" lazy_static = "1.4.0" log = "0.4.14" diff --git a/measure/src/lib.rs b/measure/src/lib.rs index 5b42bfa9d1..8fd0b24444 100644 --- a/measure/src/lib.rs +++ b/measure/src/lib.rs @@ -1,2 +1,3 @@ #![allow(clippy::integer_arithmetic)] +pub mod macros; pub mod measure; diff --git a/measure/src/macros.rs b/measure/src/macros.rs new file mode 100644 index 0000000000..e688a631a6 --- /dev/null +++ b/measure/src/macros.rs @@ -0,0 +1,143 @@ +/// Measure this expression +/// +/// Use `measure!()` when you have an expression that you want to measure. `measure!()` will start +/// a new [`Measure`], evaluate your expression, stop the [`Measure`], and then return the +/// [`Measure`] object along with your expression's return value. +/// +/// [`Measure`]: crate::measure::Measure +/// +/// # Examples +/// +/// ``` +/// // Measure functions +/// # use solana_measure::measure; +/// # fn foo() {} +/// # fn bar(x: i32) {} +/// # fn add(x: i32, y: i32) -> i32 {x + y} +/// let (result, measure) = measure!(foo(), "foo takes no parameters"); +/// let (result, measure) = measure!(bar(42), "bar takes one parameter"); +/// let (result, measure) = measure!(add(1, 2), "add takes two parameters and returns a value"); +/// # assert_eq!(result, 1 + 2); +/// ``` +/// +/// ``` +/// // Measure methods +/// # use solana_measure::measure; +/// # struct Foo { +/// # f: i32, +/// # } +/// # impl Foo { +/// # fn frobnicate(&self, bar: i32) -> i32 { +/// # self.f * bar +/// # } +/// # } +/// let foo = Foo { f: 42 }; +/// let (result, measure) = measure!(foo.frobnicate(2), "measure methods"); +/// # assert_eq!(result, 42 * 2); +/// ``` +/// +/// ``` +/// // Measure expression blocks +/// # use solana_measure::measure; +/// # fn complex_calculation() -> i32 { 42 } +/// # fn complex_transform(x: i32) -> i32 { x + 3 } +/// # fn record_result(y: i32) {} +/// let (result, measure) = measure!( +/// { +/// let x = complex_calculation(); +/// # assert_eq!(x, 42); +/// let y = complex_transform(x); +/// # assert_eq!(y, 42 + 3); +/// record_result(y); +/// y +/// }, +/// "measure a block of many operations", +/// ); +/// # assert_eq!(result, 42 + 3); +/// ``` +/// +/// ``` +/// // The `name` parameter is optional +/// # use solana_measure::measure; +/// # fn meow() {}; +/// let (result, measure) = measure!(meow()); +/// ``` +#[macro_export] +macro_rules! measure { + ($val:expr, $name:tt $(,)?) => {{ + let mut measure = $crate::measure::Measure::start($name); + let result = $val; + measure.stop(); + (result, measure) + }}; + ($val:expr) => { + measure!($val, "") + }; +} + +#[cfg(test)] +mod tests { + use std::{thread::sleep, time::Duration}; + + fn my_multiply(x: i32, y: i32) -> i32 { + x * y + } + + fn square(x: i32) -> i32 { + my_multiply(x, x) + } + + struct SomeStruct { + x: i32, + } + impl SomeStruct { + fn add_to(&self, x: i32) -> i32 { + x + self.x + } + } + + #[test] + fn test_measure_macro() { + // Ensure that the measurement side actually works + { + let (_result, measure) = measure!(sleep(Duration::from_secs(1)), "test"); + assert!(measure.as_s() >= 0.99f32 && measure.as_s() <= 1.01f32); + assert!(measure.as_ms() >= 990 && measure.as_ms() <= 1_010); + assert!(measure.as_us() >= 999_000 && measure.as_us() <= 1_010_000); + } + + // Ensure that the macro can be called with functions + { + let (result, _measure) = measure!(my_multiply(3, 4), "test"); + assert_eq!(result, 3 * 4); + + let (result, _measure) = measure!(square(5), "test"); + assert_eq!(result, 5 * 5) + } + + // Ensure that the macro can be called with methods + { + let some_struct = SomeStruct { x: 42 }; + let (result, _measure) = measure!(some_struct.add_to(4), "test"); + assert_eq!(result, 42 + 4); + } + + // Ensure that the macro can be called with blocks + { + let (result, _measure) = measure!({ 1 + 2 }, "test"); + assert_eq!(result, 3); + } + + // Ensure that the macro can be called with a trailing comma + { + let (result, _measure) = measure!(square(5), "test",); + assert_eq!(result, 5 * 5) + } + + // Ensure that the macro can be called without a name + { + let (result, _measure) = measure!(square(5)); + assert_eq!(result, 5 * 5) + } + } +} diff --git a/merkle-tree/src/merkle_tree.rs b/merkle-tree/src/merkle_tree.rs index 2834fbee90..c79c177477 100644 --- a/merkle-tree/src/merkle_tree.rs +++ b/merkle-tree/src/merkle_tree.rs @@ -18,7 +18,7 @@ macro_rules! hash_intermediate { } } -#[derive(Debug)] +#[derive(Default, Debug, Eq, Hash, PartialEq)] pub struct MerkleTree { leaf_count: usize, nodes: Vec, @@ -36,6 +36,14 @@ impl<'a> ProofEntry<'a> { assert!((None == left_sibling) ^ (None == right_sibling)); Self(target, left_sibling, right_sibling) } + + pub fn get_left_sibling(&self) -> Option<&'a Hash> { + self.1 + } + + pub fn get_right_sibling(&self) -> Option<&'a Hash> { + self.2 + } } #[derive(Debug, Default, PartialEq)] @@ -60,6 +68,10 @@ impl<'a> Proof<'a> { }); matches!(result, Some(_)) } + + pub fn get_proof_entries(self) -> Vec> { + self.0 + } } impl MerkleTree { @@ -95,7 +107,7 @@ impl MerkleTree { } } - pub fn new>(items: &[T]) -> Self { + pub fn new>(items: &[T], sorted_hashes: bool) -> Self { let cap = MerkleTree::calculate_vec_capacity(items.len()); let mut mt = MerkleTree { leaf_count: items.len(), @@ -123,8 +135,20 @@ impl MerkleTree { &mt.nodes[prev_level_start + prev_level_idx] }; - let hash = hash_intermediate!(lsib, rsib); - mt.nodes.push(hash); + // tip-distribution verification uses sorted hashing + if sorted_hashes { + if lsib <= rsib { + let hash = hash_intermediate!(lsib, rsib); + mt.nodes.push(hash); + } else { + let hash = hash_intermediate!(rsib, lsib); + mt.nodes.push(hash); + } + } else { + // hashing for solana internals + let hash = hash_intermediate!(lsib, rsib); + mt.nodes.push(hash); + } } prev_level_start = level_start; prev_level_len = level_len; @@ -189,21 +213,21 @@ mod tests { #[test] fn test_tree_from_empty() { - let mt = MerkleTree::new::<[u8; 0]>(&[]); + let mt = MerkleTree::new::<[u8; 0]>(&[], false); assert_eq!(mt.get_root(), None); } #[test] fn test_tree_from_one() { let input = b"test"; - let mt = MerkleTree::new(&[input]); + let mt = MerkleTree::new(&[input], false); let expected = hash_leaf!(input); assert_eq!(mt.get_root(), Some(&expected)); } #[test] fn test_tree_from_many() { - let mt = MerkleTree::new(TEST); + let mt = MerkleTree::new(TEST, false); // This golden hash will need to be updated whenever the contents of `TEST` change in any // way, including addition, removal and reordering or any of the tree calculation algo // changes @@ -215,7 +239,7 @@ mod tests { #[test] fn test_path_creation() { - let mt = MerkleTree::new(TEST); + let mt = MerkleTree::new(TEST, false); for (i, _s) in TEST.iter().enumerate() { let _path = mt.find_path(i).unwrap(); } @@ -223,13 +247,13 @@ mod tests { #[test] fn test_path_creation_bad_index() { - let mt = MerkleTree::new(TEST); + let mt = MerkleTree::new(TEST, false); assert_eq!(mt.find_path(TEST.len()), None); } #[test] fn test_path_verify_good() { - let mt = MerkleTree::new(TEST); + let mt = MerkleTree::new(TEST, false); for (i, s) in TEST.iter().enumerate() { let hash = hash_leaf!(s); let path = mt.find_path(i).unwrap(); @@ -239,7 +263,7 @@ mod tests { #[test] fn test_path_verify_bad() { - let mt = MerkleTree::new(TEST); + let mt = MerkleTree::new(TEST, false); for (i, s) in BAD.iter().enumerate() { let hash = hash_leaf!(s); let path = mt.find_path(i).unwrap(); diff --git a/multinode-demo/bootstrap-validator.sh b/multinode-demo/bootstrap-validator.sh index c11d9fd995..84790e4bcb 100755 --- a/multinode-demo/bootstrap-validator.sh +++ b/multinode-demo/bootstrap-validator.sh @@ -103,6 +103,36 @@ while [[ -n $1 ]]; do elif [[ $1 == --skip-require-tower ]]; then maybeRequireTower=false shift + elif [[ $1 == --trust-relayer-packets ]]; then + args+=("$1") + shift + elif [[ $1 == --trust-block-engine-packets ]]; then + args+=("$1") + shift + elif [[ $1 == --relayer-address ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --block-engine-address ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --block-engine-auth-service-address ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --relayer-auth-service-address ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --tip-payment-program-pubkey ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --tip-distribution-program-pubkey ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --commission-bps ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --shred-receiver-address ]]; then + args+=("$1" "$2") + shift 2 else echo "Unknown argument: $1" $program --help @@ -117,6 +147,7 @@ done # These keypairs are created by ./setup.sh and included in the genesis config identity=$SOLANA_CONFIG_DIR/bootstrap-validator/identity.json +tip_distribution_account_payer=$SOLANA_CONFIG_DIR/bootstrap-validator/identity.json vote_account="$SOLANA_CONFIG_DIR"/bootstrap-validator/vote-account.json ledger_dir="$SOLANA_CONFIG_DIR"/bootstrap-validator @@ -138,6 +169,8 @@ args+=( --no-incremental-snapshots --identity "$identity" --vote-account "$vote_account" + --tip-distribution-account-payer "$tip_distribution_account_payer" + --merkle-root-upload-authority "$identity" --rpc-faucet-address 127.0.0.1:9900 --no-poh-speed-test --no-os-network-limits-test @@ -146,6 +179,9 @@ args+=( ) default_arg --gossip-port 8001 default_arg --log - +default_arg --tip-payment-program-pubkey "DThZmRNNXh7kvTQW9hXeGoWGPKktK8pgVAyoTLjH7UrT" +default_arg --tip-distribution-program-pubkey "FjrdANjvo76aCYQ4kf9FM1R8aESUcEE6F8V7qyoVUQcM" +default_arg --commission-bps 0 pid= diff --git a/multinode-demo/validator.sh b/multinode-demo/validator.sh index 7c766a1beb..9862e08330 100755 --- a/multinode-demo/validator.sh +++ b/multinode-demo/validator.sh @@ -86,6 +86,33 @@ while [[ -n $1 ]]; do vote_account=$2 args+=("$1" "$2") shift 2 + elif [[ $1 == --relayer-address ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --block-engine-address ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --block-engine-auth-service-address ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --relayer-auth-service-address ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 = --tip-distribution-account-payer ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 = --merkle-root-upload-authority ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --tip-payment-program-pubkey ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --tip-distribution-program-pubkey ]]; then + args+=("$1" "$2") + shift 2 + elif [[ $1 == --commission-bps ]]; then + args+=("$1" "$2") + shift 2 elif [[ $1 = --init-complete-file ]]; then args+=("$1" "$2") shift 2 @@ -258,6 +285,11 @@ fi default_arg --identity "$identity" default_arg --vote-account "$vote_account" +default_arg --merkle-root-upload-authority "$identity" +default_arg --tip-distribution-account-payer "$identity" +default_arg --tip-payment-program-pubkey "DThZmRNNXh7kvTQW9hXeGoWGPKktK8pgVAyoTLjH7UrT" +default_arg --tip-distribution-program-pubkey "FjrdANjvo76aCYQ4kf9FM1R8aESUcEE6F8V7qyoVUQcM" +default_arg --commission-bps 0 default_arg --ledger "$ledger_dir" default_arg --log - default_arg --full-rpc-api diff --git a/perf/src/sigverify.rs b/perf/src/sigverify.rs index d812b170c6..b7dbe5cbf8 100644 --- a/perf/src/sigverify.rs +++ b/perf/src/sigverify.rs @@ -120,7 +120,7 @@ pub fn init() { /// Returns true if the signatrue on the packet verifies. /// Caller must do packet.set_discard(true) if this returns false. #[must_use] -fn verify_packet(packet: &mut Packet, reject_non_vote: bool) -> bool { +pub fn verify_packet(packet: &mut Packet, reject_non_vote: bool) -> bool { // If this packet was already marked as discard, drop it if packet.meta.discard() { return false; diff --git a/poh/src/poh_recorder.rs b/poh/src/poh_recorder.rs index 480d377d2a..509a9b266d 100644 --- a/poh/src/poh_recorder.rs +++ b/poh/src/poh_recorder.rs @@ -56,9 +56,14 @@ pub enum PohRecorderError { SendError(#[from] SendError), } -type Result = std::result::Result; +pub type Result = std::result::Result; -pub type WorkingBankEntry = (Arc, (Entry, u64)); +#[derive(Clone, Debug)] +pub struct WorkingBankEntry { + pub bank: Arc, + // normal entries have len == 1, bundles have len > 1 + pub entries_ticks: Vec<(Entry, u64)>, +} #[derive(Clone)] pub struct BankStart { @@ -80,21 +85,19 @@ impl BankStart { } pub struct Record { - pub mixin: Hash, - pub transactions: Vec, + // non-bundles shall have mixins_txs.len() == 1, bundles shall have mixins_txs.len() > 1 + pub mixins_txs: Vec<(Hash, Vec)>, pub slot: Slot, pub sender: Sender>, } impl Record { pub fn new( - mixin: Hash, - transactions: Vec, + mixins_txs: Vec<(Hash, Vec)>, slot: Slot, sender: Sender>, ) -> Self { Self { - mixin, - transactions, + mixins_txs, slot, sender, } @@ -125,14 +128,13 @@ impl TransactionRecorder { pub fn record( &self, bank_slot: Slot, - mixin: Hash, - transactions: Vec, + mixins_txs: Vec<(Hash, Vec)>, ) -> Result<()> { // create a new channel so that there is only 1 sender and when it goes out of scope, the receiver fails let (result_sender, result_receiver) = unbounded(); - let res = - self.record_sender - .send(Record::new(mixin, transactions, bank_slot, result_sender)); + let res = self + .record_sender + .send(Record::new(mixins_txs, bank_slot, result_sender)); if res.is_err() { // If the channel is dropped, then the validator is shutting down so return that we are hitting // the max tick height to stop transaction processing and flush any transactions in the pipeline. @@ -510,7 +512,10 @@ impl PohRecorder { for tick in &self.tick_cache[..entry_count] { working_bank.bank.register_tick(&tick.0.hash); - send_result = self.sender.send((working_bank.bank.clone(), tick.clone())); + send_result = self.sender.send(WorkingBankEntry { + bank: working_bank.bank.clone(), + entries_ticks: vec![tick.clone()], + }); if send_result.is_err() { break; } @@ -634,17 +639,24 @@ impl PohRecorder { pub fn record( &mut self, bank_slot: Slot, - mixin: Hash, - transactions: Vec, + mixins_txs: &[(Hash, Vec)], ) -> Result<()> { // Entries without transactions are used to track real-time passing in the ledger and // cannot be generated by `record()` - assert!(!transactions.is_empty(), "No transactions provided"); + assert!(!mixins_txs.is_empty(), "No transactions provided"); + assert!( + !mixins_txs.iter().any(|(_, txs)| txs.is_empty()), + "One of mixins is missing txs" + ); let ((), report_metrics_time) = Measure::this(|_| self.report_metrics(bank_slot), (), "report_metrics"); self.report_metrics_us += report_metrics_time.as_us(); + let mixins: Vec = mixins_txs.iter().map(|(m, _)| *m).collect(); + let transactions: Vec> = + mixins_txs.iter().map(|(_, tx)| tx.clone()).collect(); + loop { let (flush_cache_res, flush_cache_time) = Measure::this(|_| self.flush_cache(false), (), "flush_cache"); @@ -664,21 +676,34 @@ impl PohRecorder { self.record_lock_contention_us += poh_lock_time.as_us(); let (record_mixin_res, record_mixin_time) = - Measure::this(|_| poh_lock.record(mixin), (), "record_mixin"); + Measure::this(|_| poh_lock.record_bundle(&mixins), (), "record_mixin"); self.record_us += record_mixin_time.as_us(); drop(poh_lock); - if let Some(poh_entry) = record_mixin_res { + if let Some(entries) = record_mixin_res { + assert_eq!(entries.len(), transactions.len()); let (send_entry_res, send_entry_time) = Measure::this( |_| { - let entry = Entry { - num_hashes: poh_entry.num_hashes, - hash: poh_entry.hash, - transactions, - }; + let entries_tick_heights: Vec<(Entry, u64)> = entries + .into_iter() + .zip(transactions.into_iter()) + .map(|(poh_entry, transactions)| { + ( + Entry { + num_hashes: poh_entry.num_hashes, + hash: poh_entry.hash, + transactions, + }, + self.tick_height, + ) + }) + .collect(); let bank_clone = working_bank.bank.clone(); - self.sender.send((bank_clone, (entry, self.tick_height))) + self.sender.send(WorkingBankEntry { + bank: bank_clone, + entries_ticks: entries_tick_heights, + }) }, (), "send_poh_entry", @@ -1046,13 +1071,17 @@ mod tests { assert_eq!(poh_recorder.tick_height, tick_height_before + 1); assert_eq!(poh_recorder.tick_cache.len(), 0); let mut num_entries = 0; - while let Ok((wbank, (_entry, _tick_height))) = entry_receiver.try_recv() { + while let Ok(WorkingBankEntry { + bank: wbank, + entries_ticks, + }) = entry_receiver.try_recv() + { assert_eq!(wbank.slot(), bank1.slot()); - num_entries += 1; + num_entries += entries_ticks.len(); } // All the cached ticks, plus the new tick above should have been flushed - assert_eq!(num_entries, num_new_ticks + 1); + assert_eq!(num_entries as u64, num_new_ticks + 1); } Blockstore::destroy(&ledger_path).unwrap(); } @@ -1141,7 +1170,7 @@ mod tests { // We haven't yet reached the minimum tick height for the working bank, // so record should fail assert_matches!( - poh_recorder.record(bank1.slot(), h1, vec![tx.into()]), + poh_recorder.record(bank1.slot(), &[(h1, vec![tx.into()])]), Err(PohRecorderError::MinHeightNotReached) ); assert!(entry_receiver.try_recv().is_err()); @@ -1184,7 +1213,7 @@ mod tests { // However we hand over a bad slot so record fails let bad_slot = bank.slot() + 1; assert_matches!( - poh_recorder.record(bad_slot, h1, vec![tx.into()]), + poh_recorder.record(bad_slot, &[(h1, vec![tx.into()])]), Err(PohRecorderError::MaxHeightReached) ); } @@ -1231,17 +1260,27 @@ mod tests { let tx = test_tx(); let h1 = hash(b"hello world!"); assert!(poh_recorder - .record(bank1.slot(), h1, vec![tx.into()]) + .record(bank1.slot(), &[(h1, vec![tx.into()])]) .is_ok()); assert_eq!(poh_recorder.tick_cache.len(), 0); //tick in the cache + entry for _ in 0..min_tick_height { - let (_bank, (e, _tick_height)) = entry_receiver.recv().unwrap(); + let WorkingBankEntry { + bank: _, + entries_ticks, + } = entry_receiver.recv().unwrap(); + assert_eq!(entries_ticks.len(), 1); + let e = entries_ticks.get(0).unwrap().0.clone(); assert!(e.is_tick()); } - let (_bank, (e, _tick_height)) = entry_receiver.recv().unwrap(); + let WorkingBankEntry { + bank: _, + entries_ticks, + } = entry_receiver.recv().unwrap(); + assert_eq!(entries_ticks.len(), 1); + let e = entries_ticks.get(0).unwrap().0.clone(); assert!(!e.is_tick()); } Blockstore::destroy(&ledger_path).unwrap(); @@ -1277,10 +1316,16 @@ mod tests { let tx = test_tx(); let h1 = hash(b"hello world!"); assert!(poh_recorder - .record(bank.slot(), h1, vec![tx.into()]) + .record(bank.slot(), &[(h1, vec![tx.into()])]) .is_err()); + for _ in 0..num_ticks_to_max { - let (_bank, (entry, _tick_height)) = entry_receiver.recv().unwrap(); + let WorkingBankEntry { + bank: _, + entries_ticks, + } = entry_receiver.recv().unwrap(); + assert_eq!(entries_ticks.len(), 1); + let entry = entries_ticks.get(0).unwrap().0.clone(); assert!(entry.is_tick()); } } @@ -1536,7 +1581,7 @@ mod tests { let tx = test_tx(); let h1 = hash(b"hello world!"); assert!(poh_recorder - .record(bank.slot(), h1, vec![tx.into()]) + .record(bank.slot(), &[(h1, vec![tx.into()])]) .is_err()); assert!(poh_recorder.working_bank.is_none()); diff --git a/poh/src/poh_service.rs b/poh/src/poh_service.rs index 7ce52844bf..4301f23f49 100644 --- a/poh/src/poh_service.rs +++ b/poh/src/poh_service.rs @@ -194,11 +194,12 @@ impl PohService { if let Ok(record) = record { if record .sender - .send(poh_recorder.lock().unwrap().record( - record.slot, - record.mixin, - record.transactions, - )) + .send( + poh_recorder + .lock() + .unwrap() + .record(record.slot, &record.mixins_txs), + ) .is_err() { panic!("Error returning mixin hash"); @@ -257,11 +258,7 @@ impl PohService { timing.total_lock_time_ns += lock_time.as_ns(); let mut record_time = Measure::start("record"); loop { - let res = poh_recorder_l.record( - record.slot, - record.mixin, - std::mem::take(&mut record.transactions), - ); + let res = poh_recorder_l.record(record.slot, &record.mixins_txs); // what do we do on failure here? Ignore for now. let (_send_res, send_record_result_time) = Measure::this(|_| record.sender.send(res), (), "send_record_result"); @@ -383,6 +380,7 @@ impl PohService { mod tests { use { super::*, + crate::poh_recorder::WorkingBankEntry, rand::{thread_rng, Rng}, solana_ledger::{ blockstore::Blockstore, @@ -462,11 +460,10 @@ mod tests { loop { // send some data let mut time = Measure::start("record"); - let _ = poh_recorder.lock().unwrap().record( - bank_slot, - h1, - vec![tx.clone()], - ); + let _ = poh_recorder + .lock() + .unwrap() + .record(bank_slot, &[(h1, vec![tx.clone()])]); time.stop(); total_us += time.as_us(); total_times += 1; @@ -511,7 +508,12 @@ mod tests { let time = Instant::now(); while run_time != 0 || need_tick || need_entry || need_partial { - let (_bank, (entry, _tick_height)) = entry_receiver.recv().unwrap(); + let WorkingBankEntry { + bank: _, + entries_ticks, + } = entry_receiver.recv().unwrap(); + assert_eq!(entries_ticks.len(), 0); + let entry = entries_ticks.get(0).unwrap().0.clone(); if entry.is_tick() { num_ticks += 1; diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 71a53cea88..1f4dbaf14e 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -24,7 +24,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -36,7 +36,7 @@ dependencies = [ "cfg-if 1.0.0", "cipher 0.3.0", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -60,16 +60,16 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.4", + "getrandom 0.2.8", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -82,39 +82,187 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" [[package]] name = "alloc-no-stdlib" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "anchor-attribute-access-control" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "regex", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-account" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "bs58 0.4.0", + "proc-macro2 1.0.47", + "quote 1.0.21", + "rustversion", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-constant" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "proc-macro2 1.0.47", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-error" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-event" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-interface" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "heck 0.3.3", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-program" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-attribute-state" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-derive-accounts" +version = "0.24.2" +dependencies = [ + "anchor-syn", + "anyhow", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "anchor-lang" +version = "0.24.2" +dependencies = [ + "anchor-attribute-access-control", + "anchor-attribute-account", + "anchor-attribute-constant", + "anchor-attribute-error", + "anchor-attribute-event", + "anchor-attribute-interface", + "anchor-attribute-program", + "anchor-attribute-state", + "anchor-derive-accounts", + "arrayref", + "base64 0.13.1", + "bincode", + "borsh", + "bytemuck", + "solana-program 1.13.6", + "thiserror", +] + +[[package]] +name = "anchor-syn" +version = "0.24.2" +dependencies = [ + "anyhow", + "bs58 0.3.1", + "heck 0.3.3", + "proc-macro2 1.0.47", + "proc-macro2-diagnostics", + "quote 1.0.21", + "serde", + "serde_json", + "sha2 0.9.9", + "syn 1.0.103", + "thiserror", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ "winapi 0.3.9", ] [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "arc-swap" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f" +checksum = "983cd8b9d4b02a6dc6ffa557262eb5858a27a0038ffffe21a0f133eaa819a164" [[package]] name = "arrayref" @@ -124,9 +272,9 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "ascii" @@ -147,7 +295,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.7", + "time 0.3.17", ] [[package]] @@ -156,9 +304,9 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "synstructure", ] @@ -168,9 +316,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -181,9 +329,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-compression" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345fd392ab01f746c717b1357165b76f0b67a60192007b234058c9045fdcf695" +checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" dependencies = [ "brotli", "flate2", @@ -218,20 +366,20 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "async-trait" -version = "0.1.52" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -247,15 +395,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.5.3" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f523b4e98ba6897ae90994bc18423d9877c54f9047b06a00ddc8122a957b1c70" +checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43" dependencies = [ "async-trait", "axum-core", @@ -269,7 +417,7 @@ dependencies = [ "matchit", "memchr", "mime", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project-lite", "serde", "sync_wrapper", @@ -282,9 +430,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c0a60006f2a293d82d571f635042a72edf927539b7685bd62d361963839b" +checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc" dependencies = [ "async-trait", "bytes", @@ -303,18 +451,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ "futures-core", - "getrandom 0.2.4", + "getrandom 0.2.8", "instant", "pin-project-lite", - "rand 0.8.2", + "rand 0.8.5", "tokio", ] [[package]] name = "base-x" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] name = "base64" @@ -324,15 +472,15 @@ checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64ct" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71acf5509fc522cce1b100ac0121c635129bfd4d91cdf036bcc9b9935f97ccf5" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" [[package]] name = "bincode" @@ -355,8 +503,8 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "proc-macro2 1.0.36", - "quote 1.0.6", + "proc-macro2 1.0.47", + "quote 1.0.21", "regex", "rustc-hash", "shlex", @@ -388,19 +536,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "constant_time_eq", - "digest 0.10.3", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding 0.1.5", - "byte-tools", - "byteorder 1.4.3", - "generic-array 0.12.3", + "digest 0.10.6", ] [[package]] @@ -409,26 +545,17 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1", - "generic-array 0.14.5", + "block-padding", + "generic-array", ] [[package]] name = "block-buffer" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" -dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "block-padding" -version = "0.1.5" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -444,7 +571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ "borsh-derive", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -456,8 +583,8 @@ dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.36", - "syn 1.0.91", + "proc-macro2 1.0.47", + "syn 1.0.103", ] [[package]] @@ -466,9 +593,9 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -477,9 +604,9 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -503,6 +630,12 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bs58" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" + [[package]] name = "bs58" version = "0.4.0" @@ -520,9 +653,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.3.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bv" @@ -534,30 +667,24 @@ dependencies = [ "serde", ] -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - [[package]] name = "bytemuck" -version = "1.8.0" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e851ca7c24871e7336801608a4797d7376545b6928a10d32d75685687141ead" +checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.0.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" +checksum = "5fe233b960f12f8007e3db2d136e3cb1c291bfd7396e384ee76025fc1a3932b4" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -574,9 +701,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "bzip2" @@ -601,20 +728,19 @@ dependencies = [ [[package]] name = "caps" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61bf7211aad104ce2769ec05efcdfabf85ee84ac92461d142f22cf8badd0e54c" +checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" dependencies = [ - "errno", "libc", "thiserror", ] [[package]] name = "cc" -version = "1.0.67" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f" dependencies = [ "jobserver", ] @@ -642,23 +768,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.43", + "time 0.1.44", + "wasm-bindgen", "winapi 0.3.9", ] [[package]] name = "chrono-humanize" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eddc119501d583fd930cb92144e605f44e0252c38dd89d9247fffa1993375cb" +checksum = "32dce1ea1988dbdf9f9815ff11425828523bd2a134ec0805d2ac8af26ee6096e" dependencies = [ "chrono", ] @@ -669,7 +797,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -684,9 +812,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", @@ -695,28 +823,77 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", - "textwrap", + "strsim 0.8.0", + "textwrap 0.11.0", "unicode-width", "vec_map", ] +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim 0.10.0", + "termcolor", + "textwrap 0.16.0", +] + +[[package]] +name = "clap_derive" +version = "3.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cmake" -version = "0.1.46" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b858541263efe664aead4a5209a4ae5c5d2811167d4ed4ee0944503f8d2089" +checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" dependencies = [ "cc", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "combine" version = "3.8.1" @@ -732,14 +909,13 @@ dependencies = [ [[package]] name = "console" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", - "regex", "terminal_size", "unicode-width", "winapi 0.3.9", @@ -819,27 +995,27 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] name = "crossbeam-channel" -version = "0.5.3" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdbfe11fe19ff083c48923cf179540e8cd0535903dc35e178a1fdeeb59aef51f" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -847,9 +1023,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", @@ -871,12 +1047,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if 1.0.0", - "lazy_static", ] [[package]] @@ -887,11 +1062,11 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.5", + "generic-array", "typenum", ] @@ -901,7 +1076,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.5", + "generic-array", "subtle", ] @@ -928,6 +1103,50 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cxx" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2 1.0.47", + "quote 1.0.21", + "scratch", + "syn 1.0.103", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" +dependencies = [ + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + [[package]] name = "dashmap" version = "4.0.2" @@ -963,7 +1182,7 @@ dependencies = [ "asn1-rs", "displaydoc", "nom", - "num-bigint 0.4.2", + "num-bigint 0.4.3", "num-traits", "rusticata-macros", ] @@ -981,48 +1200,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", - "proc-macro2 1.0.36", - "quote 1.0.6", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustc_version 0.4.0", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] name = "dialoguer" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d6b4fabcd9e97e1df1ae15395ac7e49fb144946a0d453959dc2696273b9da" +checksum = "a92e7e37ecef6857fdc0c0c5d42fd5b0938e46590c2183cc92dd310a6d078eb1" dependencies = [ "console", "tempfile", "zeroize", ] -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.3", -] - [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] name = "digest" -version = "0.10.3" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "block-buffer 0.10.0", + "block-buffer 0.10.3", "crypto-common", "subtle", ] @@ -1069,9 +1279,9 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -1099,9 +1309,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.0.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf038a7b6fd7ef78ad3348b63f3a17550877b0e28f8d68bcc94894d1412158bc" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" dependencies = [ "signature", ] @@ -1129,26 +1339,26 @@ dependencies = [ "derivation-path", "ed25519-dalek", "hmac 0.12.1", - "sha2 0.10.2", + "sha2 0.10.6", ] [[package]] name = "educe" -version = "0.4.18" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86b50932a01e7ec5c06160492ab660fb19b6bb2a7878030dd6cd68d21df9d4d" +checksum = "cb0188e3c3ba8df5753894d54461f0e39bc91741dc5b22e1c46999ec2c71f4e4" dependencies = [ "enum-ordinalize", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "elf" @@ -1167,11 +1377,11 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.23" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -1189,22 +1399,23 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "enum-ordinalize" -version = "3.1.10" +version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b166c9e378360dd5a6666a9604bb4f54ae0cac39023ffbac425e917a2a04fef" +checksum = "a62bb1df8b45ecb7ffa78dca1c17a438fb193eb083db0b1b494d2a61bcb5096a" dependencies = [ - "num-bigint 0.4.2", + "num-bigint 0.4.3", "num-traits", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "rustc_version 0.4.0", + "syn 1.0.103", ] [[package]] @@ -1214,9 +1425,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eb359f1476bf611266ac1f5355bc14aeca37b299d0ebccc038ee7058891c9cb" dependencies = [ "once_cell", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -1270,15 +1481,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fast-math" @@ -1291,22 +1496,22 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] [[package]] name = "fd-lock" -version = "3.0.5" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46e245f4c8ec30c6415c56cb132c07e69e74f1942f6b4a4061da748b49f486ca" +checksum = "bb21c69b9fea5e15dbc1049e4b77145dd0ba1c84019c488102de0dc4ea4b0a27" dependencies = [ "cfg-if 1.0.0", "rustix", - "windows-sys 0.30.0", + "windows-sys 0.42.0", ] [[package]] @@ -1317,31 +1522,35 @@ checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" [[package]] name = "filetime" -version = "0.2.10" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695" +checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "redox_syscall 0.1.56", - "winapi 0.3.9", + "redox_syscall", + "windows-sys 0.42.0", ] [[package]] name = "fixedbitset" -version = "0.4.1" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" + +[[package]] +name = "fixedbitset" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ - "cfg-if 1.0.0", "crc32fast", - "libc", "miniz_oxide", ] @@ -1368,12 +1577,11 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", ] [[package]] @@ -1390,9 +1598,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", @@ -1405,9 +1613,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", "futures-sink", @@ -1415,15 +1623,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" dependencies = [ "futures-core", "futures-task", @@ -1433,38 +1641,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures 0.1.31", "futures-channel", @@ -1490,18 +1698,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "serde", "typenum", @@ -1520,11 +1719,12 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", + "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", "wasm-bindgen", @@ -1532,13 +1732,15 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.4" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", - "wasi 0.10.1+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1549,9 +1751,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "globset" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" dependencies = [ "aho-corasick", "bstr", @@ -1567,7 +1769,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38f3d68c8343245dc047982651b5afb8bd659c9959ed72efe5a73bf22684e5fd" dependencies = [ "arc-swap", - "futures 0.3.21", + "futures 0.3.25", "log", "reqwest", "serde", @@ -1575,15 +1777,15 @@ dependencies = [ "serde_json", "simpl", "smpl_jwt", - "time 0.3.7", + "time 0.3.17", "tokio", ] [[package]] name = "goblin" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b1800b95efee8ad4ef04517d4d69f8e209e763b1668f1179aeeedd0e454da55" +checksum = "32401e89c6446dcd28185931a01b1093726d0356820ac744023e6850689bf926" dependencies = [ "log", "plain", @@ -1592,9 +1794,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.11" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -1605,7 +1807,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.6.4", + "tokio-util 0.7.2", "tracing", ] @@ -1627,20 +1829,29 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + [[package]] name = "headers" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bitflags", "bytes", "headers-core", "http", "httpdate", "mime", - "sha-1 0.10.0", + "sha1 0.10.5", ] [[package]] @@ -1669,9 +1880,9 @@ checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" -version = "0.1.13" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] @@ -1698,7 +1909,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.3", + "digest 0.10.6", ] [[package]] @@ -1708,7 +1919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array 0.14.5", + "generic-array", "hmac 0.8.1", ] @@ -1742,27 +1953,27 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" [[package]] name = "httparse" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6330e8a36bd8c859f3fa6d9382911fbb7147ec39807f63b923933a247240b9ba" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "humantime" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.18" +version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ "bytes", "futures-channel", @@ -1789,7 +2000,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" dependencies = [ "bytes", - "futures 0.3.21", + "futures 0.3.25", "headers", "http", "hyper", @@ -1802,15 +2013,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d" dependencies = [ "http", "hyper", - "rustls 0.20.4", + "rustls 0.20.7", "tokio", - "tokio-rustls 0.23.2", + "tokio-rustls 0.23.4", ] [[package]] @@ -1826,16 +2037,40 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi 0.3.9", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", + "cxx", + "cxx-build", ] [[package]] @@ -1851,11 +2086,10 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -1873,7 +2107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" dependencies = [ "bitmaps", - "rand_core 0.6.3", + "rand_core 0.6.4", "rand_xoshiro", "rayon", "serde", @@ -1890,12 +2124,12 @@ checksum = "5a9d968042a4902e08810946fc7cd5851eb75e80301342305af755ca06cb82ce" [[package]] name = "indexmap" -version = "1.8.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", "rayon", ] @@ -1913,63 +2147,80 @@ dependencies = [ [[package]] name = "inout" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1f03d4ab4d5dc9ec2d219f86c15d2a15fc08239d1cd3b2d6a19717c0a2f443" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] name = "instant" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "io-lifetimes" -version = "0.6.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9448015e586b611e5d322f6703812bbca2f1e709d5773ecd38ddb4e3bb649504" +checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87" +dependencies = [ + "libc", + "windows-sys 0.42.0", +] [[package]] name = "ipnet" -version = "2.3.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" + +[[package]] +name = "jito-protos" +version = "1.13.6" +dependencies = [ + "bytes", + "crossbeam-epoch", + "lock_api", + "prost 0.8.0", + "prost-types 0.8.0", + "tonic 0.5.2", + "tonic-build 0.5.2", +] [[package]] name = "jobserver" -version = "0.1.21" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1992,7 +2243,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.21", + "futures 0.3.25", "jsonrpc-core", "jsonrpc-pubsub", "jsonrpc-server-utils", @@ -2010,7 +2261,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "futures-executor", "futures-util", "log", @@ -2025,7 +2276,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "jsonrpc-client-transports", ] @@ -2036,9 +2287,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2" dependencies = [ "proc-macro-crate 0.1.5", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -2047,7 +2298,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "hyper", "jsonrpc-core", "jsonrpc-server-utils", @@ -2063,7 +2314,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "jsonrpc-core", "jsonrpc-server-utils", "log", @@ -2078,7 +2329,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "jsonrpc-core", "lazy_static", "log", @@ -2094,22 +2345,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes", - "futures 0.3.21", + "futures 0.3.25", "globset", "jsonrpc-core", "lazy_static", "log", "tokio", "tokio-stream", - "tokio-util 0.6.4", + "tokio-util 0.6.10", "unicase", ] [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] [[package]] name = "kernel32-sys" @@ -2135,15 +2389,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.120" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad5c14e80759d0939d013e6ca49930e59fc53dd8e5009132f76240c179380c09" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if 1.0.0", "winapi 0.3.9", @@ -2151,9 +2405,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.2" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "librocksdb-sys" @@ -2219,26 +2473,35 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "pkg-config", "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.0.42" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5284f00d480e1c39af34e72f8ad60b94f47007e3481cd3b731c1d67190ddc7b7" +checksum = "bb68f22743a3fb35785f1e7f844ca5a3de2dde5bd0c0ef5b372065814699b121" [[package]] name = "lock_api" @@ -2251,20 +2514,20 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "lru" -version = "0.7.5" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32613e41de4c47ab04970c348ca7ae7382cf116625755af070b008a15516a889" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" dependencies = [ - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -2287,12 +2550,6 @@ dependencies = [ "libc", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matches" version = "0.1.9" @@ -2307,24 +2564,24 @@ checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.3" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] @@ -2337,7 +2594,7 @@ checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder 1.4.3", "keccak", - "rand_core 0.6.3", + "rand_core 0.6.4", "zeroize", ] @@ -2361,12 +2618,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", - "autocfg", ] [[package]] @@ -2407,9 +2663,9 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -2420,9 +2676,9 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -2438,9 +2694,9 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" dependencies = [ "cfg-if 0.1.10", "libc", @@ -2472,9 +2728,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a31937dea023539c72ddae0e3571deadc1414b300483fa7aaec176168cfa9d2" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ "winapi 0.3.9", ] @@ -2506,9 +2762,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", @@ -2527,20 +2783,20 @@ dependencies = [ [[package]] name = "num-derive" -version = "0.3.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -2571,18 +2827,18 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi", "libc", @@ -2603,19 +2859,10 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ - "proc-macro-crate 1.1.3", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", -] - -[[package]] -name = "num_threads" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" -dependencies = [ - "libc", + "proc-macro-crate 1.2.1", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -2635,15 +2882,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" - -[[package]] -name = "opaque-debug" -version = "0.2.3" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "opaque-debug" @@ -2653,9 +2894,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -2672,9 +2913,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -2685,18 +2926,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.22.0+1.1.1q" +version = "111.24.0+1.1.1s" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f31f0d509d1c1ae9cada2f9539ff8f37933831fd5098879e482aa687d659853" +checksum = "3498f259dab01178c6228c6b00dcef0ed2a2d5e20d648c017861227773ea4abd" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.74" +version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ "autocfg", "cc", @@ -2714,15 +2955,21 @@ checksum = "e1cf9b1c4e9a6c4de793c632496fa490bdc0e1eea73f0c91394f7b6990935d22" dependencies = [ "async-trait", "crossbeam-channel", - "futures 0.3.21", + "futures 0.3.25", "js-sys", "lazy_static", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project", - "rand 0.8.2", + "rand 0.8.5", "thiserror", ] +[[package]] +name = "os_str_bytes" +version = "6.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5bf27447411e9ee3ff51186bf7a08e16c341efdde93f4d823e8844429bed7e" + [[package]] name = "ouroboros" version = "0.14.2" @@ -2742,9 +2989,9 @@ checksum = "ed9a247206016d424fe8497bc611e510887af5c261fbbf977877c4bb55ca4d82" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -2753,7 +3000,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ - "futures 0.3.21", + "futures 0.3.25", "libc", "log", "rand 0.7.3", @@ -2774,12 +3021,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.1", + "parking_lot_core 0.9.4", ] [[package]] @@ -2791,22 +3038,22 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.10", + "redox_syscall", "smallvec", "winapi 0.3.9", ] [[package]] name = "parking_lot_core" -version = "0.9.1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.10", + "redox_syscall", "smallvec", - "windows-sys 0.32.0", + "windows-sys 0.42.0", ] [[package]] @@ -2824,7 +3071,16 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" dependencies = [ - "digest 0.10.3", + "digest 0.10.6", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.6", ] [[package]] @@ -2835,11 +3091,11 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pem" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" +checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] @@ -2850,9 +3106,9 @@ checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "percentage" @@ -2865,18 +3121,19 @@ dependencies = [ [[package]] name = "pest" -version = "2.1.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "a528564cc62c19a7acac4d81e01f39e53e25e17b934878f4c6d25cc2836e62f8" dependencies = [ + "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "d5fd9bc6500181952d34bd0b2b0163a54d794227b498be0b7afa7698d0a7b18f" dependencies = [ "pest", "pest_generator", @@ -2884,63 +3141,73 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "d2610d5ac5156217b4ff8e46ddcef7cdf44b273da2ac5bca2ecbfa86a330e7c4" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "824749bf7e21dd66b36fbe26b3f45c713879cccd4a009a917ab8e045ca8246fe" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1 0.8.2", + "sha1 0.10.5", ] [[package]] name = "petgraph" -version = "0.6.0" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +dependencies = [ + "fixedbitset 0.2.0", + "indexmap", +] + +[[package]] +name = "petgraph" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ - "fixedbitset", + "fixedbitset 0.4.2", "indexmap", ] [[package]] name = "pin-project" -version = "1.0.5" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.5" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -2961,9 +3228,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plain" @@ -2979,24 +3246,24 @@ checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug", "universal-hash", ] [[package]] name = "ppv-lite86" -version = "0.2.8" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.1.9" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b83ec2d0af5c5c556257ff52c9f98934e243b9fd39604bfb2a9b75ec2e97f18" +checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" dependencies = [ - "proc-macro2 1.0.36", - "syn 1.0.91", + "proc-macro2 1.0.47", + "syn 1.0.103", ] [[package]] @@ -3010,10 +3277,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ + "once_cell", "thiserror", "toml", ] @@ -3025,9 +3293,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "version_check", ] @@ -3037,8 +3305,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", + "proc-macro2 1.0.47", + "quote 1.0.21", "version_check", ] @@ -3059,11 +3327,34 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" +dependencies = [ + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", + "version_check", + "yansi", +] + +[[package]] +name = "prost" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" dependencies = [ - "unicode-xid 0.2.0", + "bytes", + "prost-derive 0.8.0", ] [[package]] @@ -3078,14 +3369,32 @@ dependencies = [ [[package]] name = "prost" -version = "0.10.1" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07b0857a71a8cb765763950499cae2413c3f9cede1133478c43600d9e146890" +checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" dependencies = [ "bytes", "prost-derive 0.10.1", ] +[[package]] +name = "prost-build" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603" +dependencies = [ + "bytes", + "heck 0.3.3", + "itertools", + "log", + "multimap", + "petgraph 0.5.1", + "prost 0.8.0", + "prost-types 0.8.0", + "tempfile", + "which", +] + [[package]] name = "prost-build" version = "0.9.0" @@ -3098,7 +3407,7 @@ dependencies = [ "lazy_static", "log", "multimap", - "petgraph", + "petgraph 0.6.2", "prost 0.9.0", "prost-types 0.9.0", "regex", @@ -3108,9 +3417,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.10.1" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120fbe7988713f39d780a58cf1a7ef0d7ef66c6d87e5aa3438940c05357929f4" +checksum = "8ae5a4388762d5815a9fc0dea33c56b021cdc8dde0c55e0c9ca57197254b0cab" dependencies = [ "bytes", "cfg-if 1.0.0", @@ -3120,14 +3429,27 @@ dependencies = [ "lazy_static", "log", "multimap", - "petgraph", - "prost 0.10.1", + "petgraph 0.6.2", + "prost 0.10.4", "prost-types 0.10.1", "regex", "tempfile", "which", ] +[[package]] +name = "prost-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + [[package]] name = "prost-derive" version = "0.9.0" @@ -3136,9 +3458,9 @@ checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -3149,9 +3471,19 @@ checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "prost-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b" +dependencies = [ + "bytes", + "prost 0.8.0", ] [[package]] @@ -3171,7 +3503,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ "bytes", - "prost 0.10.1", + "prost 0.10.4", ] [[package]] @@ -3180,14 +3512,14 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" dependencies = [ - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", ] [[package]] name = "quinn" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7542006acd6e057ff632307d219954c44048f818898da03113d6c0086bfddd9" +checksum = "5b435e71d9bfa0d8889927231970c51fb89c58fa63bffcab117c9c7a41e5ef8f" dependencies = [ "bytes", "futures-channel", @@ -3195,7 +3527,7 @@ dependencies = [ "fxhash", "quinn-proto", "quinn-udp", - "rustls 0.20.4", + "rustls 0.20.7", "thiserror", "tokio", "tracing", @@ -3204,16 +3536,16 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a13a5c0a674c1ce7150c9df7bc4a1e46c2fbbe7c710f56c0dc78b1a810e779e" +checksum = "3fce546b9688f767a57530652488420d419a8b1f44a478b451c3d1ab6d992a55" dependencies = [ "bytes", "fxhash", - "rand 0.8.2", + "rand 0.8.5", "ring", - "rustls 0.20.4", - "rustls-native-certs", + "rustls 0.20.7", + "rustls-native-certs 0.6.2", "rustls-pemfile 0.2.1", "slab", "thiserror", @@ -3224,13 +3556,12 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df185e5e5f7611fa6e628ed8f9633df10114b03bbaecab186ec55822c44ac727" +checksum = "9f832d8958db3e84d2ec93b5eb2272b45aa23cf7f8fe6e79f578896f4e6c231b" dependencies = [ "futures-util", "libc", - "mio", "quinn-proto", "socket2", "tokio", @@ -3248,11 +3579,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.6" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ - "proc-macro2 1.0.36", + "proc-macro2 1.0.47", ] [[package]] @@ -3261,24 +3592,23 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom 0.1.14", + "getrandom 0.1.16", "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", "rand_pcg", ] [[package]] name = "rand" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18519b42a40024d661e1714153e9ad0c3de27cd495760ceb09710920f1098b1e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.0", - "rand_core 0.6.3", - "rand_hc 0.3.0", + "rand_chacha 0.3.1", + "rand_core 0.6.4", ] [[package]] @@ -3293,12 +3623,12 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -3307,16 +3637,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.14", + "getrandom 0.1.16", ] [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.4", + "getrandom 0.2.8", ] [[package]] @@ -3328,15 +3658,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "rand_pcg" version = "0.2.1" @@ -3352,14 +3673,14 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] name = "rayon" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ "autocfg", "crossbeam-deque", @@ -3369,73 +3690,67 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", "num_cpus", ] [[package]] name = "rcgen" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fa2d386df8533b02184941c76ae2e0d0c1d053f5d43339169d80f21275fc5e" +checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" dependencies = [ "pem", "ring", - "time 0.3.7", + "time 0.3.17", "yasna", ] [[package]] name = "redox_syscall" -version = "0.1.56" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" - -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.4", - "redox_syscall 0.2.10", + "getrandom 0.2.8", + "redox_syscall", + "thiserror", ] [[package]] name = "reed-solomon-erasure" -version = "5.0.1" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170bac0d8306941e101df0caaa6518b10bc4232dd36c34f1cb78b8a063024db" +checksum = "c2fe31452b684b8b33f65f8730c8b8812c3f5a0bb8a096934717edb1ac488641" dependencies = [ "cc", "libc", "libm", "parking_lot 0.11.2", "smallvec", - "spin 0.9.3", + "spin 0.9.4", ] [[package]] name = "regex" -version = "1.5.5" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -3444,27 +3759,27 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ "winapi 0.3.9", ] [[package]] name = "reqwest" -version = "0.11.10" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" +checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" dependencies = [ "async-compression", - "base64 0.13.0", + "base64 0.13.1", "bytes", "encoding_rs", "futures-core", @@ -3477,34 +3792,35 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", - "percent-encoding 2.1.0", + "once_cell", + "percent-encoding 2.2.0", "pin-project-lite", - "rustls 0.20.4", - "rustls-pemfile 0.3.0", + "rustls 0.20.7", + "rustls-pemfile 1.0.1", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", - "tokio-rustls 0.23.2", - "tokio-util 0.6.4", - "url 2.2.2", + "tokio-rustls 0.23.4", + "tokio-util 0.7.2", + "tower-service", + "url 2.3.1", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.22.5", "winreg", ] [[package]] name = "retain_mut" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c31b5c4033f8fdde8700e4657be2c497e7288f01515be52168c631e2e4d4086" +checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" [[package]] name = "ring" @@ -3545,9 +3861,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.16" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustc-hash" @@ -3570,7 +3886,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.6", + "semver 1.0.14", ] [[package]] @@ -3584,16 +3900,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.34.4" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f5d1c6ed6d1c6915aa64749b809fc1bafff49d160f5d927463658093d7d62ab" +checksum = "203974af07ea769452490ee8de3e5947971efc3a090dca8a779dd432d3fa46a7" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -3602,7 +3918,7 @@ version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "log", "ring", "sct 0.6.1", @@ -3611,9 +3927,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.4" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" dependencies = [ "log", "ring", @@ -3623,12 +3939,24 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" +checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" dependencies = [ "openssl-probe", - "rustls-pemfile 0.2.1", + "rustls 0.19.1", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.1", "schannel", "security-framework", ] @@ -3639,29 +3967,29 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] name = "rustls-pemfile" -version = "0.3.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] name = "rustversion" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.4" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -3674,12 +4002,12 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "winapi 0.3.9", + "windows-sys 0.36.1", ] [[package]] @@ -3688,24 +4016,30 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "scroll" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1" +checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" dependencies = [ "scroll_derive", ] [[package]] name = "scroll_derive" -version = "0.10.2" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9" +checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -3730,9 +4064,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -3762,9 +4096,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.6" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" @@ -3774,38 +4108,38 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.136" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.5" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" +checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "8e8b3801309262e8184d9687fb697586833e939767aea0dda89f5a8e650e8bd7" dependencies = [ "itoa", "ryu", @@ -3826,26 +4160,14 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.23" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap", "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", + "serde", + "yaml-rust", ] [[package]] @@ -3858,7 +4180,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -3869,7 +4191,7 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.10.6", ] [[package]] @@ -3881,6 +4203,17 @@ dependencies = [ "sha1_smol", ] +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.6", +] + [[package]] name = "sha1_smol" version = "1.0.0" @@ -3897,18 +4230,18 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.10.6", ] [[package]] @@ -3920,24 +4253,24 @@ dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", "keccak", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] name = "sha3" -version = "0.10.1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881bf8156c87b6301fc5ca6b27f11eeb2761224c7081e69b409d5a1951a70c86" +checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" dependencies = [ - "digest 0.10.3", + "digest 0.10.6", "keccak", ] [[package]] name = "sharded-slab" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" dependencies = [ "lazy_static", ] @@ -3950,9 +4283,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "signal-hook" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" dependencies = [ "libc", "signal-hook-registry", @@ -3969,9 +4302,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.1.0" +version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65211b7b6fc3f14ff9fc7a2011a434e3e6880585bd2e9e9396315ae24cbf7852" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" [[package]] name = "simpl" @@ -3991,15 +4324,18 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.2" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smpl_jwt" @@ -4007,7 +4343,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4370044f8b20f944e05c35d77edd3518e6f21fc4de77e593919f287c6a3f428a" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "log", "openssl", "serde", @@ -4019,9 +4355,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi 0.3.9", @@ -4033,12 +4369,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bytes", - "futures 0.3.21", + "futures 0.3.25", "httparse", "log", - "rand 0.8.2", + "rand 0.8.5", "sha-1 0.9.8", ] @@ -4047,9 +4383,9 @@ name = "solana-account-decoder" version = "1.13.6" dependencies = [ "Inflector", - "base64 0.13.0", + "base64 0.13.1", "bincode", - "bs58", + "bs58 0.4.0", "bv", "lazy_static", "serde", @@ -4088,7 +4424,7 @@ name = "solana-banks-client" version = "1.13.6" dependencies = [ "borsh", - "futures 0.3.21", + "futures 0.3.25", "solana-banks-interface", "solana-program 1.13.6", "solana-sdk 1.13.6", @@ -4113,9 +4449,10 @@ version = "1.13.6" dependencies = [ "bincode", "crossbeam-channel", - "futures 0.3.21", + "futures 0.3.25", "solana-banks-interface", "solana-client", + "solana-gossip", "solana-runtime", "solana-sdk 1.13.6", "solana-send-transaction-service", @@ -4408,7 +4745,7 @@ dependencies = [ name = "solana-bpf-rust-rand" version = "1.13.6" dependencies = [ - "getrandom 0.1.14", + "getrandom 0.1.16", "rand 0.7.3", "solana-program 1.13.6", ] @@ -4556,7 +4893,7 @@ name = "solana-clap-utils" version = "1.13.6" dependencies = [ "chrono", - "clap", + "clap 2.34.0", "rpassword", "solana-perf", "solana-remote-wallet", @@ -4564,7 +4901,7 @@ dependencies = [ "thiserror", "tiny-bip39", "uriparse", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -4578,7 +4915,7 @@ dependencies = [ "serde_yaml", "solana-clap-utils", "solana-sdk 1.13.6", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -4586,13 +4923,13 @@ name = "solana-cli-output" version = "1.13.6" dependencies = [ "Inflector", - "base64 0.13.0", + "base64 0.13.1", "chrono", - "clap", + "clap 2.34.0", "console", "humantime", "indicatif", - "semver 1.0.6", + "semver 1.0.14", "serde", "serde_json", "solana-account-decoder", @@ -4611,14 +4948,14 @@ version = "1.13.6" dependencies = [ "async-mutex", "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bincode", - "bs58", + "bs58 0.4.0", "bytes", - "clap", + "clap 2.34.0", "crossbeam-channel", "enum_dispatch", - "futures 0.3.21", + "futures 0.3.25", "futures-util", "indexmap", "indicatif", @@ -4633,8 +4970,8 @@ dependencies = [ "rand_chacha 0.2.2", "rayon", "reqwest", - "rustls 0.20.4", - "semver 1.0.6", + "rustls 0.20.7", + "semver 1.0.14", "serde", "serde_derive", "serde_json", @@ -4655,7 +4992,7 @@ dependencies = [ "tokio-stream", "tokio-tungstenite", "tungstenite", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -4683,19 +5020,30 @@ name = "solana-core" version = "1.13.6" dependencies = [ "ahash", - "base64 0.13.0", + "anchor-lang", + "base64 0.13.1", "bincode", - "bs58", + "bs58 0.4.0", + "bytes", "chrono", + "clap 3.2.23", "crossbeam-channel", "dashmap", "etcd-client", "fs_extra", + "futures 0.3.25", + "futures-util", "histogram", + "indexmap", "itertools", + "jito-protos", + "lazy_static", "log", "lru", "min-max-heap", + "num_enum", + "prost 0.8.0", + "prost-types 0.8.0", "rand 0.7.3", "rand_chacha 0.2.2", "rayon", @@ -4732,8 +5080,14 @@ dependencies = [ "sysctl", "tempfile", "thiserror", + "tip-distribution", + "tip-payment", "tokio", + "tokio-stream", + "tonic 0.5.2", + "tonic-build 0.5.2", "trees", + "uuid", ] [[package]] @@ -4774,7 +5128,7 @@ version = "1.13.6" dependencies = [ "bincode", "byteorder 1.4.3", - "clap", + "clap 2.34.0", "crossbeam-channel", "log", "serde", @@ -4792,13 +5146,11 @@ dependencies = [ [[package]] name = "solana-frozen-abi" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a5d3280421bb53fc12bdba1eaa505153fb4f99a06b5609dae22192652ead3b" +version = "1.13.6" dependencies = [ - "bs58", + "bs58 0.4.0", "bv", - "generic-array 0.14.5", + "generic-array", "im", "lazy_static", "log", @@ -4807,51 +5159,65 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "sha2 0.10.2", - "solana-frozen-abi-macro 1.10.33", + "sha2 0.10.6", + "solana-frozen-abi-macro 1.13.6", "thiserror", ] [[package]] name = "solana-frozen-abi" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9d5107e663df4a87c658ee764e9f0e4d15adf8bc1d1c9088b45ed8eaaf4958" dependencies = [ - "bs58", + "ahash", + "blake3", + "block-buffer 0.9.0", + "bs58 0.4.0", "bv", - "generic-array 0.14.5", + "byteorder 1.4.3", + "cc", + "either", + "generic-array", + "getrandom 0.1.16", + "hashbrown 0.12.3", "im", "lazy_static", "log", "memmap2", + "once_cell", + "rand_core 0.6.4", "rustc_version 0.4.0", "serde", "serde_bytes", "serde_derive", - "sha2 0.10.2", - "solana-frozen-abi-macro 1.13.6", + "serde_json", + "sha2 0.10.6", + "solana-frozen-abi-macro 1.14.7", + "subtle", "thiserror", ] [[package]] name = "solana-frozen-abi-macro" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "635c60ac96b1347af272c625465068b908aff919d19f29b5795a44310310494d" +version = "1.13.6" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustc_version 0.4.0", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] name = "solana-frozen-abi-macro" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4600fe5ae28cec848debc4ea3b41f34d9d8fd088aca209fbb1e8205489d08d" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustc_version 0.4.0", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] @@ -4877,7 +5243,7 @@ dependencies = [ name = "solana-geyser-plugin-manager" version = "1.13.6" dependencies = [ - "bs58", + "bs58 0.4.0", "crossbeam-channel", "json5", "libloading", @@ -4899,7 +5265,7 @@ version = "1.13.6" dependencies = [ "bincode", "bv", - "clap", + "clap 2.34.0", "crossbeam-channel", "flate2", "indexmap", @@ -4947,7 +5313,7 @@ dependencies = [ "chrono-humanize", "crossbeam-channel", "fs_extra", - "futures 0.3.21", + "futures 0.3.25", "itertools", "lazy_static", "libc", @@ -4955,7 +5321,7 @@ dependencies = [ "lru", "num_cpus", "num_enum", - "prost 0.10.1", + "prost 0.10.4", "rand 0.7.3", "rand_chacha 0.2.2", "rayon", @@ -4964,7 +5330,7 @@ dependencies = [ "rustc_version 0.4.0", "serde", "serde_bytes", - "sha2 0.10.2", + "sha2 0.10.6", "solana-account-decoder", "solana-bpf-loader-program", "solana-entry", @@ -4992,9 +5358,7 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b12cb6e6f1f9c9876d356c928b8c2ac532f6715e7cd2a1b4343d747bee3eca73" +version = "1.13.6" dependencies = [ "env_logger", "lazy_static", @@ -5003,7 +5367,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f78a1849908659ed28696b92f030b1048b8ddafadfad0e95e79dcd21fe31072" dependencies = [ "env_logger", "lazy_static", @@ -5044,7 +5410,7 @@ name = "solana-net-utils" version = "1.13.6" dependencies = [ "bincode", - "clap", + "clap 2.34.0", "crossbeam-channel", "log", "nix", @@ -5056,7 +5422,7 @@ dependencies = [ "solana-sdk 1.13.6", "solana-version", "tokio", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -5103,23 +5469,21 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeecf504cee2821b006871f70e7a1f54db15f914cedf259eaf5976fe606470f0" +version = "1.13.6" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "blake3", "borsh", "borsh-derive", - "bs58", + "bs58 0.4.0", "bv", "bytemuck", "console_error_panic_hook", "console_log", "curve25519-dalek", - "getrandom 0.1.14", + "getrandom 0.1.16", "itertools", "js-sys", "lazy_static", @@ -5127,67 +5491,76 @@ dependencies = [ "log", "num-derive", "num-traits", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", "rustc_version 0.4.0", "rustversion", "serde", "serde_bytes", "serde_derive", - "sha2 0.10.2", - "sha3 0.10.1", - "solana-frozen-abi 1.10.33", - "solana-frozen-abi-macro 1.10.33", - "solana-sdk-macro 1.10.33", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.13.6", + "solana-frozen-abi-macro 1.13.6", + "solana-sdk-macro 1.13.6", "thiserror", "wasm-bindgen", ] [[package]] name = "solana-program" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512475cccb7e13f96ba76ed091b2d79a8431a485c73be728cd2235f9adba5a4e" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "blake3", "borsh", "borsh-derive", - "bs58", + "bs58 0.4.0", "bv", "bytemuck", + "cc", "console_error_panic_hook", "console_log", "curve25519-dalek", - "getrandom 0.1.14", + "getrandom 0.2.8", "itertools", "js-sys", "lazy_static", + "libc", "libsecp256k1", "log", + "memoffset", "num-derive", "num-traits", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "rand 0.7.3", + "rand_chacha 0.2.2", "rustc_version 0.4.0", "rustversion", "serde", "serde_bytes", "serde_derive", - "sha2 0.10.2", - "sha3 0.10.1", - "solana-frozen-abi 1.13.6", - "solana-frozen-abi-macro 1.13.6", - "solana-sdk-macro 1.13.6", + "serde_json", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.14.7", + "solana-frozen-abi-macro 1.14.7", + "solana-sdk-macro 1.14.7", "thiserror", + "tiny-bip39", "wasm-bindgen", + "zeroize", ] [[package]] name = "solana-program-runtime" version = "1.13.6" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bincode", "enum-iterator", "itertools", @@ -5210,7 +5583,7 @@ name = "solana-program-test" version = "1.13.6" dependencies = [ "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bincode", "chrono-humanize", "log", @@ -5244,9 +5617,9 @@ dependencies = [ "log", "num-derive", "num-traits", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "qstring", - "semver 1.0.6", + "semver 1.0.14", "solana-sdk 1.13.6", "thiserror", "uriparse", @@ -5259,22 +5632,22 @@ dependencies = [ "crossbeam-channel", "futures-util", "log", - "prost 0.10.1", + "prost 0.10.4", "solana-rpc", "solana-runtime", "solana-sdk 1.13.6", "tokio", - "tonic 0.7.1", - "tonic-build 0.7.0", + "tonic 0.7.2", + "tonic-build 0.7.2", ] [[package]] name = "solana-rpc" version = "1.13.6" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bincode", - "bs58", + "bs58 0.4.0", "crossbeam-channel", "dashmap", "itertools", @@ -5315,7 +5688,7 @@ dependencies = [ "stream-cancel", "thiserror", "tokio", - "tokio-util 0.6.4", + "tokio-util 0.6.10", ] [[package]] @@ -5377,24 +5750,23 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "636f6c615aca6f75e22b6baceaf0ffed9d74367f9320b07ed57cd9b5ce2e4ff9" +version = "1.13.6" dependencies = [ + "anchor-lang", "assert_matches", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "borsh", - "bs58", + "bs58 0.4.0", "bytemuck", "byteorder 1.4.3", "chrono", "derivation-path", - "digest 0.10.3", + "digest 0.10.6", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array 0.14.5", + "generic-array", "hmac 0.12.1", "itertools", "js-sys", @@ -5414,36 +5786,39 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.2", - "sha3 0.10.1", - "solana-frozen-abi 1.10.33", - "solana-frozen-abi-macro 1.10.33", - "solana-logger 1.10.33", - "solana-program 1.10.33", - "solana-sdk-macro 1.10.33", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.13.6", + "solana-frozen-abi-macro 1.13.6", + "solana-logger 1.13.6", + "solana-program 1.13.6", + "solana-sdk-macro 1.13.6", "thiserror", "uriparse", + "uuid", "wasm-bindgen", ] [[package]] name = "solana-sdk" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cb45fd782d3793c3821dd961b9c7a28b675e187f7f22cff06e694c7743904ce" dependencies = [ "assert_matches", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "borsh", - "bs58", + "bs58 0.4.0", "bytemuck", "byteorder 1.4.3", "chrono", "derivation-path", - "digest 0.10.3", + "digest 0.10.6", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array 0.14.5", + "generic-array", "hmac 0.12.1", "itertools", "js-sys", @@ -5453,7 +5828,7 @@ dependencies = [ "memmap2", "num-derive", "num-traits", - "pbkdf2 0.10.1", + "pbkdf2 0.11.0", "qstring", "rand 0.7.3", "rand_chacha 0.2.2", @@ -5463,13 +5838,13 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.2", - "sha3 0.10.1", - "solana-frozen-abi 1.13.6", - "solana-frozen-abi-macro 1.13.6", - "solana-logger 1.13.6", - "solana-program 1.13.6", - "solana-sdk-macro 1.13.6", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.14.7", + "solana-frozen-abi-macro 1.14.7", + "solana-logger 1.14.7", + "solana-program 1.14.7", + "solana-sdk-macro 1.14.7", "thiserror", "uriparse", "wasm-bindgen", @@ -5477,26 +5852,26 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8bcac4394644f21dc013e932a7df9f536fcecef3e5df43fe362b4ec532ce30" +version = "1.13.6" dependencies = [ - "bs58", - "proc-macro2 1.0.36", - "quote 1.0.6", + "bs58 0.4.0", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustversion", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] name = "solana-sdk-macro" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08cc4804804ecb9eb07a16c7ff2d4a770fe0533298f36f867a5efc2e3284745" dependencies = [ - "bs58", - "proc-macro2 1.0.36", - "quote 1.0.6", + "bs58 0.4.0", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustversion", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] @@ -5506,6 +5881,7 @@ dependencies = [ "crossbeam-channel", "log", "solana-client", + "solana-gossip", "solana-measure", "solana-metrics", "solana-runtime", @@ -5543,14 +5919,14 @@ dependencies = [ "bzip2", "enum-iterator", "flate2", - "futures 0.3.21", + "futures 0.3.25", "goauth", "http", "hyper", "hyper-proxy", "log", "openssl", - "prost 0.10.1", + "prost 0.10.4", "prost-types 0.10.1", "serde", "serde_derive", @@ -5561,7 +5937,7 @@ dependencies = [ "solana-transaction-status", "thiserror", "tokio", - "tonic 0.7.1", + "tonic 0.7.2", "zstd", ] @@ -5570,13 +5946,13 @@ name = "solana-storage-proto" version = "1.13.6" dependencies = [ "bincode", - "bs58", - "prost 0.10.1", + "bs58 0.4.0", + "prost 0.10.4", "serde", "solana-account-decoder", "solana-sdk 1.13.6", "solana-transaction-status", - "tonic-build 0.7.0", + "tonic-build 0.7.2", ] [[package]] @@ -5597,7 +5973,7 @@ dependencies = [ "quinn", "rand 0.7.3", "rcgen", - "rustls 0.20.4", + "rustls 0.20.7", "solana-metrics", "solana-perf", "solana-sdk 1.13.6", @@ -5610,7 +5986,7 @@ dependencies = [ name = "solana-sys-tuner" version = "1.13.6" dependencies = [ - "clap", + "clap 2.34.0", "libc", "log", "nix", @@ -5625,7 +6001,7 @@ dependencies = [ name = "solana-test-validator" version = "1.13.6" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "log", "serde_derive", "serde_json", @@ -5649,10 +6025,10 @@ name = "solana-transaction-status" version = "1.13.6" dependencies = [ "Inflector", - "base64 0.13.0", + "base64 0.13.1", "bincode", "borsh", - "bs58", + "bs58 0.4.0", "lazy_static", "log", "serde", @@ -5675,7 +6051,7 @@ name = "solana-validator" version = "1.13.6" dependencies = [ "chrono", - "clap", + "clap 2.34.0", "console", "core_affinity", "crossbeam-channel", @@ -5720,6 +6096,7 @@ dependencies = [ "solana-vote-program", "symlink", "tikv-jemallocator", + "tonic 0.5.2", ] [[package]] @@ -5728,7 +6105,7 @@ version = "1.13.6" dependencies = [ "log", "rustc_version 0.4.0", - "semver 1.0.6", + "semver 1.0.14", "serde", "serde_derive", "solana-frozen-abi 1.13.6", @@ -5760,7 +6137,7 @@ name = "solana-zk-token-proof-program" version = "1.13.6" dependencies = [ "bytemuck", - "getrandom 0.1.14", + "getrandom 0.1.16", "num-derive", "num-traits", "solana-program-runtime", @@ -5770,19 +6147,17 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "1.10.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410ee53a26ac91098c289c983863535d4fbb6604b229ae1159503f48fa4fc90f" +version = "1.13.6" dependencies = [ "aes-gcm-siv", "arrayref", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bytemuck", "byteorder 1.4.3", "cipher 0.4.3", "curve25519-dalek", - "getrandom 0.1.14", + "getrandom 0.1.16", "lazy_static", "merlin", "num-derive", @@ -5791,8 +6166,8 @@ dependencies = [ "serde", "serde_json", "sha3 0.9.1", - "solana-program 1.10.33", - "solana-sdk 1.10.33", + "solana-program 1.13.6", + "solana-sdk 1.13.6", "subtle", "thiserror", "zeroize", @@ -5800,17 +6175,20 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "1.13.6" +version = "1.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4f9818b158e7a49266b83e0c06e551ba429d2395a55de5803eb6e2daa1260c" dependencies = [ "aes-gcm-siv", "arrayref", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bytemuck", "byteorder 1.4.3", "cipher 0.4.3", "curve25519-dalek", - "getrandom 0.1.14", + "getrandom 0.1.16", + "itertools", "lazy_static", "merlin", "num-derive", @@ -5819,8 +6197,8 @@ dependencies = [ "serde", "serde_json", "sha3 0.9.1", - "solana-program 1.13.6", - "solana-sdk 1.13.6", + "solana-program 1.14.7", + "solana-sdk 1.14.7", "subtle", "thiserror", "zeroize", @@ -5842,7 +6220,7 @@ dependencies = [ "rustc-demangle", "scroll", "thiserror", - "time 0.1.43", + "time 0.1.44", ] [[package]] @@ -5853,9 +6231,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" [[package]] name = "spki" @@ -5877,7 +6255,7 @@ dependencies = [ "borsh", "num-derive", "num-traits", - "solana-program 1.10.33", + "solana-program 1.14.7", "spl-token", "spl-token-2022", "thiserror", @@ -5889,7 +6267,7 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" dependencies = [ - "solana-program 1.10.33", + "solana-program 1.14.7", ] [[package]] @@ -5903,7 +6281,7 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-program 1.10.33", + "solana-program 1.14.7", "thiserror", ] @@ -5918,8 +6296,8 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-program 1.10.33", - "solana-zk-token-sdk 1.10.33", + "solana-program 1.14.7", + "solana-zk-token-sdk 1.14.7", "spl-memo", "spl-token", "thiserror", @@ -5966,11 +6344,11 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", + "proc-macro2 1.0.47", + "quote 1.0.21", "serde", "serde_derive", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] @@ -5980,13 +6358,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ "base-x", - "proc-macro2 1.0.36", - "quote 1.0.6", + "proc-macro2 1.0.47", + "quote 1.0.21", "serde", "serde_derive", "serde_json", - "sha1", - "syn 1.0.91", + "sha1 0.6.1", + "syn 1.0.103", ] [[package]] @@ -6012,26 +6390,32 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.24.0" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.0", - "proc-macro2 1.0.36", - "quote 1.0.6", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustversion", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] @@ -6059,13 +6443,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.91" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "unicode-xid 0.2.0", + "proc-macro2 1.0.47", + "quote 1.0.21", + "unicode-ident", ] [[package]] @@ -6076,14 +6460,14 @@ checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" [[package]] name = "synstructure" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", - "unicode-xid 0.2.0", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", + "unicode-xid 0.2.4", ] [[package]] @@ -6098,9 +6482,9 @@ dependencies = [ [[package]] name = "sysctl" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1123645dfaf2b5eac6b6c88addafc359c789b8ef2a770ecaef758c1ddf363ea4" +checksum = "225e483f02d0ad107168dc57381a8a40c3aeea6abe47f37506931f861643cfa8" dependencies = [ "bitflags", "byteorder 1.4.3", @@ -6128,18 +6512,18 @@ checksum = "b85d0a9369a919ba0db919b142a2b704cd207dfc676f7a43c2d105d0bc225487" dependencies = [ "anyhow", "fnv", - "futures 0.3.21", + "futures 0.3.25", "humantime", "opentelemetry", "pin-project", - "rand 0.8.2", + "rand 0.8.5", "serde", "static_assertions", "tarpc-plugins", "thiserror", "tokio", "tokio-serde", - "tokio-util 0.6.4", + "tokio-util 0.6.10", "tracing", "tracing-opentelemetry", ] @@ -6150,9 +6534,9 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee42b4e559f17bce0385ebf511a7beb67d5cc33c12c96b7f4e9789919d9c10f" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -6164,25 +6548,25 @@ dependencies = [ "cfg-if 1.0.0", "fastrand", "libc", - "redox_syscall 0.2.10", + "redox_syscall", "remove_dir_all", "winapi 0.3.9", ] [[package]] name = "termcolor" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd2d183bd3fac5f5fe38ddbeb4dc9aec4a39a9d7d59e7491d900302da01cbe1" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" dependencies = [ "libc", "winapi 0.3.9", @@ -6197,24 +6581,30 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -6249,11 +6639,12 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi 0.3.9", ] @@ -6274,16 +6665,22 @@ dependencies = [ [[package]] name = "time" -version = "0.3.7" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ "itoa", - "libc", - "num_threads", - "time-macros 0.2.3", + "serde", + "time-core", + "time-macros 0.2.6", ] +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + [[package]] name = "time-macros" version = "0.1.1" @@ -6296,9 +6693,12 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] [[package]] name = "time-macros-impl" @@ -6307,10 +6707,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.36", - "quote 1.0.6", + "proc-macro2 1.0.47", + "quote 1.0.21", "standback", - "syn 1.0.91", + "syn 1.0.103", ] [[package]] @@ -6334,9 +6734,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.1.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -6347,6 +6747,21 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[package]] +name = "tip-distribution" +version = "0.1.0" +dependencies = [ + "anchor-lang", + "solana-program 1.13.6", +] + +[[package]] +name = "tip-payment" +version = "0.1.0" +dependencies = [ + "anchor-lang", +] + [[package]] name = "tokio" version = "1.14.1" @@ -6379,13 +6794,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -6411,11 +6826,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.2" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "rustls 0.20.4", + "rustls 0.20.7", "tokio", "webpki 0.22.0", ] @@ -6438,9 +6853,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite", @@ -6449,25 +6864,25 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.17.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06cda1232a49558c46f8a504d5b93101d42c0bf7f911f12a105ba48168f821ae" +checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" dependencies = [ "futures-util", "log", - "rustls 0.20.4", + "rustls 0.20.7", "tokio", - "tokio-rustls 0.23.2", + "tokio-rustls 0.23.4", "tungstenite", "webpki 0.22.0", - "webpki-roots", + "webpki-roots 0.22.5", ] [[package]] name = "tokio-util" -version = "0.6.4" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec31e5cc6b46e653cf57762f36f71d5e6386391d88a72fd6db4508f8f676fb29" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ "bytes", "futures-core", @@ -6481,9 +6896,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" dependencies = [ "bytes", "futures-core", @@ -6495,13 +6910,47 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] +[[package]] +name = "tonic" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "796c5e1cd49905e65dd8e700d4cb1dffcbfdb4fc9d017de08c1a537afd83627c" +dependencies = [ + "async-stream", + "async-trait", + "base64 0.13.1", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding 2.2.0", + "pin-project", + "prost 0.8.0", + "prost-derive 0.8.0", + "rustls-native-certs 0.5.0", + "tokio", + "tokio-rustls 0.22.0", + "tokio-stream", + "tokio-util 0.6.10", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", + "webpki-roots 0.21.1", +] + [[package]] name = "tonic" version = "0.6.2" @@ -6510,7 +6959,7 @@ checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a" dependencies = [ "async-stream", "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bytes", "futures-core", "futures-util", @@ -6519,14 +6968,14 @@ dependencies = [ "http-body", "hyper", "hyper-timeout", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project", "prost 0.9.0", "prost-derive 0.9.0", "tokio", "tokio-rustls 0.22.0", "tokio-stream", - "tokio-util 0.6.4", + "tokio-util 0.6.10", "tower", "tower-layer", "tower-service", @@ -6536,14 +6985,14 @@ dependencies = [ [[package]] name = "tonic" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30fb54bf1e446f44d870d260d99957e7d11fb9d0a0f5bd1a662ad1411cc103f9" +checksum = "5be9d60db39854b30b835107500cf0aca0b0d14d6e1c3de124217c23a29c2ddb" dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.13.0", + "base64 0.13.1", "bytes", "futures-core", "futures-util", @@ -6552,15 +7001,15 @@ dependencies = [ "http-body", "hyper", "hyper-timeout", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project", - "prost 0.10.1", + "prost 0.10.4", "prost-derive 0.10.1", - "rustls-pemfile 0.3.0", + "rustls-pemfile 1.0.1", "tokio", - "tokio-rustls 0.23.2", + "tokio-rustls 0.23.4", "tokio-stream", - "tokio-util 0.7.1", + "tokio-util 0.7.2", "tower", "tower-layer", "tower-service", @@ -6568,46 +7017,58 @@ dependencies = [ "tracing-futures", ] +[[package]] +name = "tonic-build" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b52d07035516c2b74337d2ac7746075e7dcae7643816c1b12c5ff8a7484c08" +dependencies = [ + "proc-macro2 1.0.47", + "prost-build 0.8.0", + "quote 1.0.21", + "syn 1.0.103", +] + [[package]] name = "tonic-build" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757" dependencies = [ - "proc-macro2 1.0.36", + "proc-macro2 1.0.47", "prost-build 0.9.0", - "quote 1.0.6", - "syn 1.0.91", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "tonic-build" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d17087af5c80e5d5fc8ba9878e60258065a0a757e35efe7a05b7904bece1943" +checksum = "d9263bf4c9bfaae7317c1c2faf7f18491d2fe476f70c414b73bf5d445b00ffa1" dependencies = [ "prettyplease", - "proc-macro2 1.0.36", - "prost-build 0.10.1", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "prost-build 0.10.4", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "tower" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", "indexmap", "pin-project", "pin-project-lite", - "rand 0.8.2", + "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.1", + "tokio-util 0.7.2", "tower-layer", "tower-service", "tracing", @@ -6615,9 +7076,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.2.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8" +checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba" dependencies = [ "bitflags", "bytes", @@ -6634,21 +7095,21 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "log", @@ -6659,22 +7120,23 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.18" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "lazy_static", + "once_cell", + "valuable", ] [[package]] @@ -6701,9 +7163,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.2.18" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa5553bf0883ba7c9cbe493b085c29926bd41b66afc31ff72cf17ff4fb60dcd5" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" dependencies = [ "sharded-slab", "thread_local", @@ -6718,30 +7180,30 @@ checksum = "0de5f738ceab88e2491a94ddc33c3feeadfa95fedc60363ef110845df12f3878" [[package]] name = "try-lock" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "tungstenite" -version = "0.17.2" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5" +checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "byteorder 1.4.3", "bytes", "http", "httparse", "log", - "rand 0.8.2", - "rustls 0.20.4", + "rand 0.8.5", + "rustls 0.20.7", "sha-1 0.10.0", "thiserror", - "url 2.2.2", + "url 2.3.1", "utf-8", "webpki 0.22.0", - "webpki-roots", + "webpki-roots 0.22.5", ] [[package]] @@ -6752,9 +7214,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "unicase" @@ -6767,33 +7229,36 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.4" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -dependencies = [ - "matches", -] +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" -version = "0.1.16" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" @@ -6803,9 +7268,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "universal-hash" @@ -6813,7 +7278,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" dependencies = [ - "generic-array 0.14.5", + "generic-array", "subtle", ] @@ -6843,9 +7308,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "uriparse" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e515b1ada404168e145ac55afba3c42f04cf972201a8552d42e2abb17c1b7221" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" dependencies = [ "fnv", "lazy_static", @@ -6864,14 +7329,13 @@ dependencies = [ [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", - "idna 0.2.0", - "matches", - "percent-encoding 2.1.0", + "idna 0.3.0", + "percent-encoding 2.2.0", ] [[package]] @@ -6886,9 +7350,25 @@ dependencies = [ [[package]] name = "utf-8" -version = "0.7.5" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" +dependencies = [ + "getrandom 0.2.8", + "rand 0.8.5", +] + +[[package]] +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vcpkg" @@ -6904,9 +7384,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "void" @@ -6916,9 +7396,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "walkdir" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", "winapi 0.3.9", @@ -6943,15 +7423,21 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.1+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -6959,24 +7445,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", "log", - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "once_cell", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.22" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73157efb9af26fb564bb59a009afd1c7c334a44db171d280690d0c3faaec3468" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -6986,38 +7472,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote 1.0.6", + "quote 1.0.21", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.40" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -7045,22 +7531,31 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.1" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki 0.21.4", +] + +[[package]] +name = "webpki-roots" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c475786c6f47219345717a043a37ec04cb4bc185e28853adcc4fa0a947eba630" +checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" dependencies = [ "webpki 0.22.0", ] [[package]] name = "which" -version = "4.2.4" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" dependencies = [ "either", - "lazy_static", "libc", + "once_cell", ] [[package]] @@ -7108,89 +7603,103 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030b7ff91626e57a05ca64a07c481973cbb2db774e4852c9c7ca342408c6a99a" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc 0.30.0", - "windows_i686_gnu 0.30.0", - "windows_i686_msvc 0.30.0", - "windows_x86_64_gnu 0.30.0", - "windows_x86_64_msvc 0.30.0", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] [[package]] name = "windows-sys" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc 0.32.0", - "windows_i686_gnu 0.32.0", - "windows_i686_msvc 0.32.0", - "windows_x86_64_gnu 0.32.0", - "windows_x86_64_msvc 0.32.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_aarch64_msvc" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_gnu" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_i686_msvc" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_gnu" -version = "0.32.0" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] name = "windows_x86_64_msvc" -version = "0.32.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "winreg" @@ -7208,7 +7717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" dependencies = [ "asn1-rs", - "base64 0.13.0", + "base64 0.13.1", "data-encoding", "der-parser", "lazy_static", @@ -7216,14 +7725,14 @@ dependencies = [ "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.7", + "time 0.3.17", ] [[package]] name = "xattr" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" dependencies = [ "libc", ] @@ -7237,13 +7746,19 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "yasna" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346d34a236c9d3e5f3b9b74563f238f955bbd05fa0b8b4efa53c130c43982f4c" dependencies = [ - "time 0.3.7", + "time 0.3.17", ] [[package]] @@ -7257,30 +7772,30 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.6", - "syn 1.0.91", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "synstructure", ] [[package]] name = "zstd" -version = "0.11.1+zstd.1.5.2" +version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a16b8414fde0414e90c612eba70985577451c4c504b99885ebed24762cb81a" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "5.0.1+zstd.1.5.2" +version = "5.0.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c12659121420dd6365c5c3de4901f97145b79651fb1d25814020ed2ed0585ae" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" dependencies = [ "libc", "zstd-sys", diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 7e59d0271f..592bb44a1c 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -348,7 +348,7 @@ fn execute_transactions( let batch = bank.prepare_batch_for_tests(txs.clone()); let mut timings = ExecuteTimings::default(); let mut mint_decimals = HashMap::new(); - let tx_pre_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals); + let tx_pre_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals, None); let ( TransactionResults { execution_results, .. @@ -366,7 +366,7 @@ fn execute_transactions( true, &mut timings, ); - let tx_post_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals); + let tx_post_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals, None); izip!( txs.iter(), diff --git a/replica-node/src/replica_node.rs b/replica-node/src/replica_node.rs index 29ba56cf81..1b6b772483 100644 --- a/replica-node/src/replica_node.rs +++ b/replica-node/src/replica_node.rs @@ -105,6 +105,7 @@ fn initialize_from_snapshot( let archive_info = snapshot_utils::get_highest_full_snapshot_archive_info( &replica_config.snapshot_archives_dir, + None, ) .unwrap(); diff --git a/replica-node/src/replica_util.rs b/replica-node/src/replica_util.rs index 5c5dc461cc..b697256438 100644 --- a/replica-node/src/replica_util.rs +++ b/replica-node/src/replica_util.rs @@ -113,11 +113,10 @@ fn get_rpc_peer_node( ); let mut highest_snapshot_info: Option<(Slot, Hash)> = - snapshot_utils::get_highest_full_snapshot_archive_info(snapshot_archives_dir).map( - |snapshot_archive_info| { + snapshot_utils::get_highest_full_snapshot_archive_info(snapshot_archives_dir, None) + .map(|snapshot_archive_info| { (snapshot_archive_info.slot(), *snapshot_archive_info.hash()) - }, - ); + }); let eligible_rpc_peers = { let mut eligible_rpc_peers = vec![]; diff --git a/replica-node/tests/local_replica.rs b/replica-node/tests/local_replica.rs index 372de06c9d..1932b89448 100644 --- a/replica-node/tests/local_replica.rs +++ b/replica-node/tests/local_replica.rs @@ -62,7 +62,7 @@ fn wait_for_next_snapshot( ); loop { if let Some(full_snapshot_archive_info) = - snapshot_utils::get_highest_full_snapshot_archive_info(snapshot_archives_dir) + snapshot_utils::get_highest_full_snapshot_archive_info(snapshot_archives_dir, None) { trace!( "full snapshot for slot {} exists", diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index 930303a869..277bf91af7 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -63,7 +63,7 @@ use { feature_set::{self, nonce_must_be_writable}, fee_calculator::FeeCalculator, hash::Hash, - message::SanitizedMessage, + message::{SanitizedMessage, SanitizedVersionedMessage, VersionedMessage}, pubkey::{Pubkey, PUBKEY_BYTES}, signature::{Keypair, Signature, Signer}, stake::state::{StakeActivationStatus, StakeState}, @@ -220,6 +220,13 @@ impl JsonRpcRequestProcessor { Ok(bank) } + fn bank_from_slot(&self, slot: Slot) -> Option> { + debug!("Slot: {:?}", slot); + + let r_bank_forks = self.bank_forks.read().unwrap(); + r_bank_forks.get(slot) + } + #[allow(deprecated)] fn bank(&self, commitment: Option) -> Arc { debug!("RPC commitment_config: {:?}", commitment); @@ -347,10 +354,9 @@ impl JsonRpcRequestProcessor { Arc::new(Keypair::new()), socket_addr_space, )); - let tpu_address = cluster_info.my_contact_info().tpu; let (sender, receiver) = unbounded(); SendTransactionService::new::( - tpu_address, + cluster_info.clone(), &bank_forks, None, receiver, @@ -2634,13 +2640,16 @@ pub mod rpc_minimal { .map(|snapshot_config| snapshot_config.snapshot_archives_dir) .unwrap(); - let full_snapshot_slot = - snapshot_utils::get_highest_full_snapshot_archive_slot(&snapshot_archives_dir) - .ok_or(RpcCustomError::NoSnapshot)?; + let full_snapshot_slot = snapshot_utils::get_highest_full_snapshot_archive_slot( + &snapshot_archives_dir, + None, + ) + .ok_or(RpcCustomError::NoSnapshot)?; let incremental_snapshot_slot = snapshot_utils::get_highest_incremental_snapshot_archive_slot( &snapshot_archives_dir, full_snapshot_slot, + None, ); Ok(RpcSnapshotSlotInfo { @@ -3231,13 +3240,164 @@ pub mod rpc_accounts { } } +pub mod utils { + use { + crate::rpc::{encode_account, sanitize_transaction, verify_pubkey}, + jsonrpc_core::Error, + solana_account_decoder::{UiAccount, UiAccountEncoding}, + solana_client::{ + self, + rpc_config::{RpcSimulateBundleConfig, RpcSimulateTransactionAccountsConfig}, + rpc_response::{ + RpcBundleSimulationSummary, RpcSimulateBundleResult, + RpcSimulateBundleTransactionResult, + }, + }, + solana_runtime::bank::{Bank, BundleSimulationResult, BundleSimulationSummary}, + solana_sdk::{ + pubkey::Pubkey, + transaction::{SanitizedTransaction, VersionedTransaction}, + transaction_context::TransactionAccount, + }, + }; + + pub type BundleSimulationParams = ( + Vec, + Vec>>, + Vec>>, + ); + + fn try_build_pubkeys_from_config( + maybe_config: &Option, + sanitized_tx: &SanitizedTransaction, + ) -> Result>, Error> { + if let Some(config) = maybe_config { + if config.addresses.len() > sanitized_tx.message().account_keys().len() { + return Err(Error::invalid_params( + "too many pre execution addresses requested", + )); + } + + Ok(Some( + config + .addresses + .iter() + .map(|address_string| verify_pubkey(address_string)) + .collect::, Error>>()?, + )) + } else { + Ok(None) + } + } + + pub fn build_simulate_bundle_params( + txs_and_configs: Vec<( + VersionedTransaction, + Option, + Option, + )>, + bank: &Bank, + ) -> Result { + let mut sanitized_txs = Vec::with_capacity(txs_and_configs.len()); + let mut pre_accounts = Vec::with_capacity(txs_and_configs.len()); + let mut post_accounts = Vec::with_capacity(txs_and_configs.len()); + + for (tx, pre_cfg, post_cfg) in txs_and_configs { + let sanitized_tx = sanitize_transaction(tx, bank)?; + pre_accounts.push(try_build_pubkeys_from_config(&pre_cfg, &sanitized_tx)?); + post_accounts.push(try_build_pubkeys_from_config(&post_cfg, &sanitized_tx)?); + sanitized_txs.push(sanitized_tx); + } + + Ok((sanitized_txs, pre_accounts, post_accounts)) + } + + fn try_encode_accounts( + accounts: Option>, + encoding: Option, + ) -> Result>, Error> { + if let Some(accounts) = accounts { + let encoding = encoding.unwrap_or(UiAccountEncoding::Base64); + Ok(Some( + accounts + .iter() + .map(|a| encode_account(&a.1, &a.0, encoding, None)) + .collect::, Error>>()?, + )) + } else { + Ok(None) + } + } + + /// create a [RpcSimulateBundleResult] from a given bank [BundleSimulationResult] + pub fn rpc_bundle_result_from_bank_result( + bank_result: BundleSimulationResult, + rpc_config: RpcSimulateBundleConfig, + ) -> Result { + let BundleSimulationResult { + ref summary, + ref transaction_results, + } = bank_result; + + let summary = match summary.clone() { + BundleSimulationSummary::Failed { + error, + tx_signature, + } => RpcBundleSimulationSummary::Failed { + error, + tx_signature: tx_signature.to_string(), + }, + BundleSimulationSummary::Succeeded => RpcBundleSimulationSummary::Succeeded, + }; + + let mut transaction_results = Vec::with_capacity(transaction_results.len()); + for (i, res) in bank_result.transaction_results.into_iter().enumerate() { + let logs = if res.logs.is_empty() { + None + } else { + Some(res.logs) + }; + + transaction_results.push(RpcSimulateBundleTransactionResult { + err: res.result.err(), + logs, + pre_execution_accounts: try_encode_accounts( + res.pre_execution_accounts, + rpc_config + .pre_execution_accounts_configs + .get(i) + .cloned() + .unwrap_or_default() + .and_then(|c| c.encoding), + )?, + post_execution_accounts: try_encode_accounts( + res.post_execution_accounts, + rpc_config + .post_execution_accounts_configs + .get(i) + .cloned() + .unwrap_or_default() + .and_then(|c| c.encoding), + )?, + units_consumed: Some(res.units_consumed), + }); + } + + Ok(RpcSimulateBundleResult { + summary, + transaction_results, + }) + } +} // Full RPC interface that an API node is expected to provide // (rpc_minimal should also be provided by an API node) pub mod rpc_full { use { super::*, - solana_sdk::message::{SanitizedVersionedMessage, VersionedMessage}, + crate::rpc::utils::{build_simulate_bundle_params, rpc_bundle_result_from_bank_result}, + itertools::izip, }; + #[rpc] pub trait Full { type Metadata; @@ -3299,6 +3459,14 @@ pub mod rpc_full { config: Option, ) -> Result>; + #[rpc(meta, name = "simulateBundle")] + fn simulate_bundle( + &self, + meta: Self::Metadata, + rpc_bundle_request: RpcBundleRequest, + config: Option, + ) -> Result>; + #[rpc(meta, name = "minimumLedgerSlot")] fn minimum_ledger_slot(&self, meta: Self::Metadata) -> Result; @@ -3584,7 +3752,6 @@ pub mod rpc_full { commitment: preflight_commitment, min_context_slot, })?; - let transaction = sanitize_transaction(unsanitized_tx, preflight_bank)?; let signature = *transaction.signature(); @@ -3775,6 +3942,108 @@ pub mod rpc_full { )) } + fn simulate_bundle( + &self, + meta: Self::Metadata, + rpc_bundle_request: RpcBundleRequest, + config: Option, + ) -> Result> { + debug!("simulate_bundle rpc request received"); + + let config = config.unwrap_or_else(|| RpcSimulateBundleConfig { + pre_execution_accounts_configs: vec![ + None; + rpc_bundle_request.encoded_transactions.len() + ], + post_execution_accounts_configs: vec![ + None; + rpc_bundle_request.encoded_transactions.len() + ], + ..RpcSimulateBundleConfig::default() + }); + + // Run some request validations + if !(config.pre_execution_accounts_configs.len() + == rpc_bundle_request.encoded_transactions.len() + && config.post_execution_accounts_configs.len() + == rpc_bundle_request.encoded_transactions.len()) + { + return Err(Error::invalid_params( + "pre/post_execution_accounts_configs must be equal in length to the number of transactions", + )); + } + + let bank = match config.simulation_bank.unwrap_or_default() { + SimulationSlotConfig::Commitment(commitment) => Ok(meta.bank(Some(commitment))), + SimulationSlotConfig::Slot(slot) => meta.bank_from_slot(slot).ok_or_else(|| { + Error::invalid_params(format!("bank not found for the provided slot: {}", slot)) + }), + }?; + + // TODO: Come back to this and allow unfrozen bank as long as the parent is frozen. + if !bank.is_frozen() { + return Err(Error::invalid_params(format!( + "bank at slot {} is not frozen", + bank.slot() + ))); + } + + let tx_encoding = config + .transaction_encoding + .unwrap_or(UiTransactionEncoding::Base64); + let binary_encoding = tx_encoding.into_binary_encoding().ok_or_else(|| { + Error::invalid_params(format!( + "Unsupported encoding: {}. Supported encodings are: base58 & base64", + tx_encoding + )) + })?; + let mut decoded_transactions = rpc_bundle_request + .encoded_transactions + .into_iter() + .map(|encoded_tx| { + decode_and_deserialize::(encoded_tx, binary_encoding) + .map(|de| de.1) + }) + .collect::>>()?; + + if config.replace_recent_blockhash { + if !config.skip_sig_verify { + return Err(Error::invalid_params( + "sigVerify may not be used with replaceRecentBlockhash", + )); + } + decoded_transactions.iter_mut().for_each(|tx| { + tx.message.set_recent_blockhash(bank.last_blockhash()); + }); + } + + let zipped = izip!( + decoded_transactions, + config.pre_execution_accounts_configs.clone(), + config.post_execution_accounts_configs.clone(), + ); + let (sanitized_txs, pre_execution_pks, post_execution_pks) = + build_simulate_bundle_params(zipped.collect(), &*bank)?; + + if !config.skip_sig_verify { + for tx in &sanitized_txs { + verify_transaction(tx, &bank.feature_set)?; + } + } + + // TODO (LB): fix simulate_bundle + let bank_result = bank + .simulate_bundle(sanitized_txs, pre_execution_pks, post_execution_pks) + .map_err(|e| { + error!("bank error {}", e); + Error::internal_error() + })?; + + let rpc_bundle_result = rpc_bundle_result_from_bank_result(bank_result, config)?; + + Ok(new_response(&*bank, rpc_bundle_result)) + } + fn minimum_ledger_slot(&self, meta: Self::Metadata) -> Result { debug!("minimum_ledger_slot rpc request received"); meta.minimum_ledger_slot() @@ -4046,6 +4315,7 @@ pub mod rpc_deprecated_v1_9 { .and_then(|snapshot_config| { snapshot_utils::get_highest_full_snapshot_archive_slot( &snapshot_config.snapshot_archives_dir, + None, ) }) .ok_or_else(|| RpcCustomError::NoSnapshot.into()) @@ -5669,6 +5939,143 @@ pub mod tests { assert_eq!(result.len(), 0); } + #[test] + fn test_rpc_simulate_bundle_happy_path() { + // 1. setup + let rpc = RpcHandler::start(); + let bank = rpc.working_bank(); + + let recent_blockhash = bank.confirmed_last_blockhash(); + let RpcHandler { + ref meta, ref io, .. + } = rpc; + + let data_len = 100; + let lamports = bank.get_minimum_balance_for_rent_exemption(data_len); + let leader_pubkey = solana_sdk::pubkey::new_rand(); + let leader_account_data = AccountSharedData::new(lamports, data_len, &system_program::id()); + bank.store_account(&leader_pubkey, &leader_account_data); + bank.freeze(); + + // 2. build bundle + + // let's pretend the RPC keypair is a searcher + let searcher_keypair = rpc.mint_keypair; + + // create tip tx + let tip_amount = 10000; + let tip_tx = VersionedTransaction::from(system_transaction::transfer( + &searcher_keypair, + &leader_pubkey, + tip_amount, + recent_blockhash, + )); + + // some random mev tx + let mev_amount = 20000; + let goku_pubkey = solana_sdk::pubkey::new_rand(); + let mev_tx = VersionedTransaction::from(system_transaction::transfer( + &searcher_keypair, + &goku_pubkey, + mev_amount, + recent_blockhash, + )); + + let encoded_mev_tx = base64::encode(serialize(&mev_tx).unwrap()); + let encoded_tip_tx = base64::encode(serialize(&tip_tx).unwrap()); + + let b64_data = base64::encode(leader_account_data.data()); + + // 3. test and assert + let skip_sig_verify = true; + let replace_recent_blockhash = false; + let expected_response = json!({ + "jsonrpc": "2.0", + "result": { + "context": {"slot": bank.slot(), "apiVersion": RpcApiVersion::default()}, + "value":{ + "summary": "succeeded", + "transactionResults": [ + { + "err": null, + "logs": ["Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success"], + "unitsConsumed": 0, + "postExecutionAccounts": [], + "preExecutionAccounts": [ + { + "data": [b64_data, "base64"], + "executable": false, + "lamports": leader_account_data.lamports(), + "owner": "11111111111111111111111111111111", + "rentEpoch": 0, + } + ], + }, + { + "err": null, + "logs": ["Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success"], + "unitsConsumed": 0, + "preExecutionAccounts": [], + "postExecutionAccounts": [ + { + "data": [b64_data, "base64"], + "executable": false, + "lamports": leader_account_data.lamports() + tip_amount, + "owner": "11111111111111111111111111111111", + "rentEpoch": 0, + } + ] + }, + ], + } + }, + "id": 1, + }); + + let request = format!( + r#"{{"jsonrpc":"2.0", + "id":1, + "method":"simulateBundle", + "params":[ + {{ + "encodedTransactions": ["{}", "{}"] + }}, + {{ + "skipSigVerify": {}, + "replaceRecentBlockhash": {}, + "slot": {}, + "preExecutionAccountsConfigs": [ + {{ "encoding": "base64", "addresses": ["{}"] }}, + {{ "encoding": "base64", "addresses": [] }} + ], + "postExecutionAccountsConfigs": [ + {{ "encoding": "base64", "addresses": [] }}, + {{ "encoding": "base64", "addresses": ["{}"] }} + ] + }} + ] + }}"#, + encoded_mev_tx, + encoded_tip_tx, + skip_sig_verify, + replace_recent_blockhash, + bank.slot(), + leader_pubkey, + leader_pubkey, + ); + + let actual_response = io + .handle_request_sync(&request, meta.clone()) + .expect("response"); + + let expected_response = serde_json::from_value::(expected_response) + .expect("expected_response deserialization"); + let actual_response = serde_json::from_str::(&actual_response) + .expect("actual_response deserialization"); + + assert_eq!(expected_response, actual_response); + } + #[test] fn test_rpc_simulate_transaction() { let rpc = RpcHandler::start(); @@ -6062,7 +6469,7 @@ pub mod tests { "value":{ "blockhash": recent_blockhash.to_string(), "feeCalculator": { - "lamportsPerSignature": TEST_SIGNATURE_FEE, + "lamportsPerSignature": 5000, } }, }, @@ -6248,7 +6655,6 @@ pub mod tests { Arc::new(Keypair::new()), SocketAddrSpace::Unspecified, )); - let tpu_address = cluster_info.my_contact_info().tpu; let (meta, receiver) = JsonRpcRequestProcessor::new( JsonRpcConfig::default(), None, @@ -6257,7 +6663,7 @@ pub mod tests { blockstore, validator_exit, health.clone(), - cluster_info, + cluster_info.clone(), Hash::default(), None, OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -6268,7 +6674,7 @@ pub mod tests { ); let connection_cache = Arc::new(ConnectionCache::default()); SendTransactionService::new::( - tpu_address, + cluster_info, &bank_forks, None, receiver, @@ -6516,7 +6922,6 @@ pub mod tests { Arc::new(Keypair::new()), SocketAddrSpace::Unspecified, )); - let tpu_address = cluster_info.my_contact_info().tpu; let (request_processor, receiver) = JsonRpcRequestProcessor::new( JsonRpcConfig::default(), None, @@ -6525,7 +6930,7 @@ pub mod tests { blockstore, validator_exit, RpcHealth::stub(), - cluster_info, + cluster_info.clone(), Hash::default(), None, OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -6536,7 +6941,7 @@ pub mod tests { ); let connection_cache = Arc::new(ConnectionCache::default()); SendTransactionService::new::( - tpu_address, + cluster_info, &bank_forks, None, receiver, diff --git a/rpc/src/rpc_service.rs b/rpc/src/rpc_service.rs index 7e32bf81ea..f3be4ac1e8 100644 --- a/rpc/src/rpc_service.rs +++ b/rpc/src/rpc_service.rs @@ -238,6 +238,7 @@ impl RequestMiddleware for RpcRequestMiddleware { let full_snapshot_archive_info = snapshot_utils::get_highest_full_snapshot_archive_info( &snapshot_config.snapshot_archives_dir, + None, ); let snapshot_archive_info = if let Some(full_snapshot_archive_info) = full_snapshot_archive_info { @@ -247,6 +248,7 @@ impl RequestMiddleware for RpcRequestMiddleware { snapshot_utils::get_highest_incremental_snapshot_archive_info( &snapshot_config.snapshot_archives_dir, full_snapshot_archive_info.slot(), + None, ) .map(|incremental_snapshot_archive_info| { incremental_snapshot_archive_info @@ -356,8 +358,6 @@ impl JsonRpcService { LARGEST_ACCOUNTS_CACHE_DURATION, ))); - let tpu_address = cluster_info.my_contact_info().tpu; - // sadly, some parts of our current rpc implemention block the jsonrpc's // _socket-listening_ event loop for too long, due to (blocking) long IO or intesive CPU, // causing no further processing of incoming requests and ultimatily innocent clients timing-out. @@ -448,7 +448,7 @@ impl JsonRpcService { let leader_info = poh_recorder.map(|recorder| ClusterTpuInfo::new(cluster_info.clone(), recorder)); let _send_transaction_service = Arc::new(SendTransactionService::new_with_config( - tpu_address, + cluster_info, &bank_forks, leader_info, receiver, diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 66ae3c0cee..7aeaf6d420 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -27,6 +27,7 @@ index_list = "0.2.7" itertools = "0.10.3" lazy_static = "1.4.0" log = "0.4.14" +lz4 = "1.24.0" memmap2 = "0.5.3" num-derive = { version = "0.3" } num-traits = { version = "0.2" } @@ -52,14 +53,13 @@ solana-stake-program = { path = "../programs/stake", version = "=1.13.6" } solana-vote-program = { path = "../programs/vote", version = "=1.13.6" } solana-zk-token-proof-program = { path = "../programs/zk-token-proof", version = "=1.13.6" } solana-zk-token-sdk = { path = "../zk-token-sdk", version = "=1.13.6" } +strum = { version = "0.24", features = ["derive"] } +strum_macros = "0.24" symlink = "0.1.0" tar = "0.4.38" tempfile = "3.3.0" thiserror = "1.0" zstd = "0.11.1" -lz4 = "1.24.0" -strum_macros = "0.24" -strum = { version = "0.24", features = ["derive"] } [lib] crate-type = ["lib"] diff --git a/runtime/src/account_overrides.rs b/runtime/src/account_overrides.rs index 62ee494ff2..ee8e7ec9e2 100644 --- a/runtime/src/account_overrides.rs +++ b/runtime/src/account_overrides.rs @@ -1,25 +1,31 @@ -use solana_sdk::{account::AccountSharedData, pubkey::Pubkey, sysvar}; +use { + solana_sdk::{account::AccountSharedData, pubkey::Pubkey, sysvar}, + std::collections::HashMap, +}; /// Encapsulates overridden accounts, typically used for transaction simulations #[derive(Default)] pub struct AccountOverrides { - pub slot_history: Option, + accounts: HashMap, } impl AccountOverrides { + pub fn set_account(&mut self, pubkey: &Pubkey, account: Option) { + match account { + Some(account) => self.accounts.insert(*pubkey, account), + None => self.accounts.remove(pubkey), + }; + } + /// Sets in the slot history /// /// Note: no checks are performed on the correctness of the contained data pub fn set_slot_history(&mut self, slot_history: Option) { - self.slot_history = slot_history; + self.set_account(&sysvar::slot_history::id(), slot_history); } /// Gets the account if it's found in the list of overrides pub fn get(&self, pubkey: &Pubkey) -> Option<&AccountSharedData> { - if pubkey == &sysvar::slot_history::id() { - self.slot_history.as_ref() - } else { - None - } + self.accounts.get(pubkey) } } diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index e8859b8522..90e022e750 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -1049,15 +1049,21 @@ impl Accounts { account_locks: &mut AccountLocks, writable_keys: Vec<&Pubkey>, readonly_keys: Vec<&Pubkey>, + additional_read_locks: &HashSet, + additional_write_locks: &HashSet, ) -> Result<()> { for k in writable_keys.iter() { - if account_locks.is_locked_write(k) || account_locks.is_locked_readonly(k) { + if account_locks.is_locked_write(k) + || account_locks.is_locked_readonly(k) + || additional_write_locks.contains(k) + || additional_read_locks.contains(k) + { debug!("Writable account in use: {:?}", k); return Err(TransactionError::AccountInUse); } } for k in readonly_keys.iter() { - if account_locks.is_locked_write(k) { + if account_locks.is_locked_write(k) || additional_write_locks.contains(k) { debug!("Read-only account in use: {:?}", k); return Err(TransactionError::AccountInUse); } @@ -1117,7 +1123,23 @@ impl Accounts { let tx_account_locks_results: Vec> = txs .map(|tx| tx.get_account_locks(tx_account_lock_limit)) .collect(); - self.lock_accounts_inner(tx_account_locks_results) + self.lock_accounts_inner( + tx_account_locks_results, + &HashSet::default(), + &HashSet::default(), + ) + } + + pub fn lock_accounts_sequential_with_results<'a>( + &self, + txs: impl Iterator, + tx_account_lock_limit: usize, + account_locks_override: Option>, + ) -> Vec> { + let tx_account_locks_results: Vec> = txs + .map(|tx| tx.get_account_locks(tx_account_lock_limit)) + .collect(); + self.lock_accounts_sequential_inner(tx_account_locks_results, account_locks_override) } #[must_use] @@ -1127,6 +1149,8 @@ impl Accounts { txs: impl Iterator, results: impl Iterator>, tx_account_lock_limit: usize, + additional_read_locks: &HashSet, + additional_write_locks: &HashSet, ) -> Vec> { let tx_account_locks_results: Vec> = txs .zip(results) @@ -1135,13 +1159,19 @@ impl Accounts { Err(err) => Err(err.clone()), }) .collect(); - self.lock_accounts_inner(tx_account_locks_results) + self.lock_accounts_inner( + tx_account_locks_results, + additional_read_locks, + additional_write_locks, + ) } #[must_use] fn lock_accounts_inner( &self, tx_account_locks_results: Vec>, + additional_read_locks: &HashSet, + additional_write_locks: &HashSet, ) -> Vec> { let account_locks = &mut self.account_locks.lock().unwrap(); tx_account_locks_results @@ -1151,12 +1181,51 @@ impl Accounts { account_locks, tx_account_locks.writable, tx_account_locks.readonly, + additional_read_locks, + additional_write_locks, ), Err(err) => Err(err), }) .collect() } + #[must_use] + fn lock_accounts_sequential_inner( + &self, + tx_account_locks_results: Vec>, + account_locks_override: Option>, + ) -> Vec> { + let mut l_account_locks = if let Some(ref account_locks) = account_locks_override { + account_locks.lock().unwrap() + } else { + self.account_locks.lock().unwrap() + }; + + let mut account_in_use_set = false; + tx_account_locks_results + .into_iter() + .map(|tx_account_locks_result| match tx_account_locks_result { + Ok(tx_account_locks) => match account_in_use_set { + true => Err(TransactionError::BundleNotContinuous), + false => { + let locked = self.lock_account( + &mut l_account_locks, + tx_account_locks.writable, + tx_account_locks.readonly, + &HashSet::default(), + &HashSet::default(), + ); + if matches!(locked, Err(TransactionError::AccountInUse)) { + account_in_use_set = true; + } + locked + } + }, + Err(err) => Err(err), + }) + .collect() + } + /// Once accounts are unlocked, new transactions that modify that state can enter the pipeline #[allow(clippy::needless_collect)] pub fn unlock_accounts<'a>( @@ -1169,6 +1238,7 @@ impl Accounts { .filter_map(|(tx, res)| match res { Err(TransactionError::AccountLoadedTwice) | Err(TransactionError::AccountInUse) + | Err(TransactionError::BundleNotContinuous) | Err(TransactionError::SanitizeFailure) | Err(TransactionError::TooManyAccountLocks) | Err(TransactionError::WouldExceedMaxBlockCostLimit) @@ -1201,7 +1271,7 @@ impl Accounts { leave_nonce_on_success: bool, preserve_rent_epoch_for_rent_exempt_accounts: bool, ) { - let accounts_to_store = self.collect_accounts_to_store( + let accounts_to_store = Self::collect_accounts_to_store( txs, res, loaded, @@ -1227,8 +1297,7 @@ impl Accounts { } #[allow(clippy::too_many_arguments)] - fn collect_accounts_to_store<'a>( - &self, + pub fn collect_accounts_to_store<'a>( txs: &'a [SanitizedTransaction], execution_results: &'a [TransactionExecutionResult], load_results: &'a mut [TransactionLoadResult], @@ -1431,6 +1500,7 @@ mod tests { sync::atomic::{AtomicBool, AtomicU64, Ordering}, thread, time, }, + Accounts, }; fn new_sanitized_tx( @@ -2893,6 +2963,8 @@ mod tests { txs.iter(), qos_results.iter(), MAX_TX_ACCOUNT_LOCKS, + &HashSet::default(), + &HashSet::default(), ); assert!(results[0].is_ok()); // Read-only account (keypair0) can be referenced multiple times @@ -3015,7 +3087,7 @@ mod tests { } let txs = vec![tx0, tx1]; let execution_results = vec![new_execution_result(Ok(()), None); 2]; - let collected_accounts = accounts.collect_accounts_to_store( + let collected_accounts = Accounts::collect_accounts_to_store( &txs, &execution_results, loaded.as_mut_slice(), @@ -3500,7 +3572,7 @@ mod tests { let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique(), /*separate_domains:*/ true); - let accounts = Accounts::new_with_config_for_tests( + let _accounts = Accounts::new_with_config_for_tests( Vec::new(), &ClusterType::Development, AccountSecondaryIndexes::default(), @@ -3515,7 +3587,7 @@ mod tests { )), nonce.as_ref(), )]; - let collected_accounts = accounts.collect_accounts_to_store( + let collected_accounts = Accounts::collect_accounts_to_store( &txs, &execution_results, loaded.as_mut_slice(), @@ -3629,7 +3701,7 @@ mod tests { let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique(), /*separate_domains:*/ true); - let accounts = Accounts::new_with_config_for_tests( + let _accounts = Accounts::new_with_config_for_tests( Vec::new(), &ClusterType::Development, AccountSecondaryIndexes::default(), @@ -3644,7 +3716,7 @@ mod tests { )), nonce.as_ref(), )]; - let collected_accounts = accounts.collect_accounts_to_store( + let collected_accounts = Accounts::collect_accounts_to_store( &txs, &execution_results, loaded.as_mut_slice(), diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index d8af3939d2..ab78d50c9c 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -39,7 +39,9 @@ pub use solana_sdk::reward_type::RewardType; use { crate::{ account_overrides::AccountOverrides, - accounts::{AccountAddressFilter, Accounts, LoadedTransaction, TransactionLoadResult}, + accounts::{ + AccountAddressFilter, AccountLocks, Accounts, LoadedTransaction, TransactionLoadResult, + }, accounts_db::{ AccountShrinkThreshold, AccountsDbConfig, SnapshotStorages, ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING, @@ -94,6 +96,7 @@ use { AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount, }, account_utils::StateMut, + bundle::{error::BundleExecutionError, utils::check_bundle_lock_results}, clock::{ BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_TICKS_PER_SECOND, INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE, MAX_RECENT_BLOCKHASHES, @@ -145,19 +148,22 @@ use { std::{ borrow::Cow, cell::RefCell, + cmp::min, collections::{HashMap, HashSet}, convert::{TryFrom, TryInto}, + error::Error, fmt, mem, ops::{Div, RangeInclusive}, path::PathBuf, ptr, rc::Rc, + result, sync::{ atomic::{ AtomicBool, AtomicI64, AtomicU64, Ordering::{AcqRel, Acquire, Relaxed}, }, - Arc, LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard, + Arc, LockResult, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard, }, time::{Duration, Instant}, }, @@ -230,7 +236,7 @@ impl RentDebits { } type BankStatusCache = StatusCache>; -#[frozen_abi(digest = "2YZk2K45HmmAafmxPJnYVXyQ7uA7WuBrRkpwrCawdK31")] +#[frozen_abi(digest = "82WhodJTtPtYR1R3XnVAn8iMJAMJvcWAGuoorbjSSRUb")] pub type BankSlotDelta = SlotDelta>; // Eager rent collection repeats in cyclic manner. @@ -660,8 +666,40 @@ impl TransactionExecutionResult { Self::NotExecuted(err) => Err(err.clone()), } } + + /// Return an Error if a transaction was executed and reverted + /// NOTE: `execution_results` are zipped with `sanitized_txs` so it's expected a sanitized tx at + /// position i has a corresponding execution result at position i within the `execution_results` + /// slice + pub fn check_bundle_execution_results<'a>( + execution_results: &[TransactionExecutionResult], + sanitized_txs: &'a [SanitizedTransaction], + ) -> result::Result<(), (BundleExecutionError, &'a Signature)> { + for (exec_results, sanitized_tx) in execution_results.iter().zip(sanitized_txs) { + match exec_results { + TransactionExecutionResult::Executed { + details, + executors: _, + } => { + if let Err(e) = &details.status { + return Err((e.clone().into(), sanitized_tx.signature())); + } + } + TransactionExecutionResult::NotExecuted(e) => { + if !matches!( + e, + TransactionError::AccountInUse | TransactionError::BundleNotContinuous + ) { + return Err((e.clone().into(), sanitized_tx.signature())); + } + } + } + } + Ok(()) + } } +#[derive(Debug)] pub struct LoadAndExecuteTransactionsOutput { pub loaded_transactions: Vec, // Vector of results indicating whether a transaction was executed or could not @@ -701,6 +739,32 @@ impl DurableNonceFee { } } +#[derive(Debug, Clone, PartialEq)] +pub enum BundleSimulationSummary { + // error and transaction signature responsible + Failed { + error: BundleExecutionError, + tx_signature: Signature, + }, + Succeeded, +} + +#[derive(Clone)] +pub struct BundleSimulationResult { + /// Gives high level summary of bundle. + pub summary: BundleSimulationSummary, + pub transaction_results: Vec, +} + +#[derive(Clone)] +pub struct BundleTransactionSimulationResult { + pub result: Result<()>, + pub logs: TransactionLogMessages, + pub pre_execution_accounts: Option>, + pub post_execution_accounts: Option>, + pub units_consumed: u64, +} + pub struct TransactionSimulationResult { pub result: Result<()>, pub logs: TransactionLogMessages, @@ -1185,7 +1249,7 @@ pub struct Bank { inflation: Arc>, /// cache of vote_account and stake_account state for this fork - stakes_cache: StakesCache, + pub stakes_cache: StakesCache, /// staked nodes on epoch boundaries, saved off when a bank.slot() is at /// a leader schedule calculation boundary @@ -3576,12 +3640,33 @@ impl Bank { &'a self, transactions: &'b [SanitizedTransaction], transaction_results: impl Iterator>, + additional_read_locks: &HashSet, + additional_write_locks: &HashSet, ) -> TransactionBatch<'a, 'b> { - // this lock_results could be: Ok, AccountInUse, WouldExceedBlockMaxLimit or WouldExceedAccountMaxLimit let lock_results = self.rc.accounts.lock_accounts_with_results( transactions.iter(), transaction_results, self.get_transaction_account_lock_limit(), + additional_read_locks, + additional_write_locks, + ); + TransactionBatch::new(lock_results, self, Cow::Borrowed(transactions)) + } + + /// Prepare a locked transaction batch from a list of sanitized transactions, and their cost + /// limited packing status, where transactions will be locked sequentially until the first failure + pub fn prepare_sequential_sanitized_batch_with_results<'a, 'b>( + &'a self, + transactions: &'b [SanitizedTransaction], + // For use cases where you don't want to actually lock the accounts, for example when simulating. + account_locks_override: Option>, + ) -> TransactionBatch<'a, 'b> { + // this lock_results could be: Ok, AccountInUse, BundleNotContinuous, AccountLoadedTwice, or TooManyAccountLocks + let tx_account_lock_limit = self.get_transaction_account_lock_limit(); + let lock_results = self.rc.accounts.lock_accounts_sequential_with_results( + transactions.iter(), + tx_account_lock_limit, + account_locks_override, ); TransactionBatch::new(lock_results, self, Cow::Borrowed(transactions)) } @@ -3600,6 +3685,243 @@ impl Bank { batch } + /// Run bundles against a frozen bank without committing the results and return [BundleSimulationResult]. + /// Client has the option to request pre/post execution results on a per-transaction basis. + /// + /// For example given: + /// + /// Bundle: [T0{A, B, C}, T1{D}, T2{E, A, C}, T3{D, F}] + /// Requested Pre-Execution Accounts: [None, [A, D], [B], [A, C, F]] + /// Requested Post-Execution Accounts: [None, [D], None, [A, B, F]] + /// + /// It is expected that the following is returned: + /// Returned Pre-Execution Accounts: [None, [T0(A), D], [T0(B)], [T0(T2(A)), T0(T2(C)), F]] + /// Returned Post-Execution Accounts: [None, [T1(D)], None, [T0(T2(A), T0(B), T3(F)]] + pub fn simulate_bundle( + &self, + bundle: Vec, + pre_execution_accounts_requested: Vec>>, + post_execution_accounts_requested: Vec>>, + ) -> result::Result> { + assert!(self.is_frozen(), "simulation bank must be frozen"); + assert_eq!(pre_execution_accounts_requested.len(), bundle.len()); + assert_eq!(post_execution_accounts_requested.len(), bundle.len()); + + self.simulate_bundle_unchecked( + bundle, + pre_execution_accounts_requested, + post_execution_accounts_requested, + ) + } + + /// Run transactions against a bank without committing the results; does not check if the bank is frozen. + fn simulate_bundle_unchecked( + &self, + bundle: Vec, + pre_execution_accounts_requested: Vec>>, + post_execution_accounts_requested: Vec>>, + ) -> result::Result> { + // Used to cache account data in between batch execution iterations + let mut account_overrides = AccountOverrides::default(); + + let mut pre_execution_accounts_return_data = + Vec::with_capacity(pre_execution_accounts_requested.len()); + let mut post_execution_accounts_return_data = + Vec::with_capacity(post_execution_accounts_requested.len()); + let mut transaction_results = Vec::with_capacity(bundle.len()); + + let mut timings = ExecuteTimings::default(); + let mut chunk_start = 0; + while chunk_start != bundle.len() { + let chunk_end = min(bundle.len(), chunk_start + 128); + let chunk = &bundle[chunk_start..chunk_end]; + + let account_locks_override = Mutex::new(AccountLocks::default()); + let batch = self.prepare_sequential_sanitized_batch_with_results( + chunk, + Some(account_locks_override), + ); + + // check if any error + if let Some((error, failed_tx_idx)) = check_bundle_lock_results(batch.lock_results()) { + transaction_results.extend(vec![ + BundleTransactionSimulationResult { + result: Err(TransactionError::SkippedExecution), + logs: vec![], + pre_execution_accounts: None, + post_execution_accounts: None, + units_consumed: 0, + }; + bundle.len() - chunk_start + ]); + + let mut res = transaction_results + .get_mut(failed_tx_idx + chunk_start) + .unwrap(); + res.result = Err(error.clone()); + + let failed_tx = &batch.sanitized_transactions()[failed_tx_idx]; + return Ok(BundleSimulationResult { + summary: BundleSimulationSummary::Failed { + error: error.into(), + tx_signature: *failed_tx.signature(), + }, + transaction_results, + }); + } + + // Set chunk_end to its true value i.e. the first occurrence of an acceptable lock error. + let chunk_end = match batch.lock_results().iter().position(|res| res.is_err()) { + Some(err_idx) => chunk_start + err_idx, + None => chunk_end, + }; + // Load the accounts requested by caller for current chunk of transactions prior to executing. + let pre_execution_accounts = &pre_execution_accounts_requested[chunk_start..chunk_end]; + for maybe_accounts in pre_execution_accounts { + if let Some(accounts) = maybe_accounts { + let mut pre_accounts = Vec::with_capacity(accounts.len()); + + for pubkey in accounts { + let data = if let Some(data) = account_overrides.get(pubkey).cloned() { + Ok(data) + } else { + self.get_account(pubkey) + // TODO(seg): let's use a concrete error type + .ok_or(format!("pubkey {} does not exist", pubkey)) + }?; + pre_accounts.push((*pubkey, data)); + } + + pre_execution_accounts_return_data.push(Some(pre_accounts)) + } else { + pre_execution_accounts_return_data.push(None); + } + } + + // Execute the transaction! + let LoadAndExecuteTransactionsOutput { + mut loaded_transactions, + execution_results, + .. + } = self.load_and_execute_transactions( + &batch, + // After simulation, transactions will need to be forwarded to the leader + // for processing. During forwarding, the transaction could expire if the + // delay is not accounted for. + MAX_PROCESSING_AGE - MAX_TRANSACTION_FORWARDING_DELAY, + false, + true, + &mut timings, + Some(&account_overrides), + ); + + // Load account data for successful txs in current batch and store them to the overrides/cache. + let post_loaded_accounts = self + .collect_accounts_to_store( + batch.sanitized_transactions(), + &execution_results, + &mut loaded_transactions, + ) + .into_iter() + .map(|(pubkey, data)| { + account_overrides.set_account(pubkey, Some(data.clone())); + (pubkey, data) + }) + .collect::>(); + + // We know `transactions[chunk_start..chunk_end]` succeeded, so fetch the corresponding requested pubkeys. + // e.g. given Bundle: [T0{A, B}, T1{B, C}, T2{E, F}] and Post Execution Accounts: [None, [A, B], [E]] + // where current chunk is (1..3) then we load up [[A, B], [E]] + let post_execution_accounts = + &post_execution_accounts_requested[chunk_start..chunk_end]; + for maybe_accounts in post_execution_accounts { + if let Some(accounts) = maybe_accounts { + let mut post_accounts = Vec::with_capacity(accounts.len()); + for pubkey in accounts { + let maybe_data = + if let Some(data) = post_loaded_accounts.get(pubkey).cloned() { + Some(data.clone()) + } else { + account_overrides.get(pubkey).cloned() + }; + if let Some(data) = maybe_data { + post_accounts.push((*pubkey, data.clone())); + } + } + + post_execution_accounts_return_data.push(Some(post_accounts)) + } else { + post_execution_accounts_return_data.push(None); + } + } + + let simulation_results = loaded_transactions.iter().zip(&execution_results[..]).map( + |(loaded_tx_result, exec_result)| { + Self::build_transaction_simulation_result(loaded_tx_result, exec_result) + }, + ); + + // save the transaction results + for (offset, tx_result) in simulation_results.enumerate() { + let position = offset + chunk_start; + if position == chunk_end { + break; + } + + transaction_results.push(BundleTransactionSimulationResult { + result: tx_result.result, + logs: tx_result.logs, + pre_execution_accounts: pre_execution_accounts_return_data + .get(position) + .cloned() + .unwrap_or_default(), + post_execution_accounts: post_execution_accounts_return_data + .get(position) + .cloned() + .unwrap_or_default(), + units_consumed: tx_result.units_consumed, + }); + } + + if let Err((error, tx_signature)) = + TransactionExecutionResult::check_bundle_execution_results( + &execution_results[..], + batch.sanitized_transactions(), + ) + { + // fill the result of the vector with [SkippedExecution] if any txs left over + transaction_results.extend(vec![ + BundleTransactionSimulationResult { + result: Err(TransactionError::SkippedExecution), + logs: vec![], + pre_execution_accounts: None, + post_execution_accounts: None, + units_consumed: 0, + }; + bundle.len() - chunk_end + ]); + + return Ok(BundleSimulationResult { + summary: BundleSimulationSummary::Failed { + error, + tx_signature: *tx_signature, + }, + transaction_results, + }); + } + + // Welcome to Rust & Solana where we optimize for performance over readability! + // Remember chunk_end was updated above based on whether or not there was the + // batch was not continuous. + chunk_start = chunk_end; + } + + Ok(BundleSimulationResult { + summary: BundleSimulationSummary::Succeeded, + transaction_results, + }) + } + /// Run transactions against a frozen bank without committing the results pub fn simulate_transaction( &self, @@ -3617,14 +3939,13 @@ impl Bank { transaction: SanitizedTransaction, ) -> TransactionSimulationResult { let account_keys = transaction.message().account_keys(); - let number_of_accounts = account_keys.len(); let account_overrides = self.get_account_overrides_for_simulation(&account_keys); let batch = self.prepare_simulation_batch(transaction); let mut timings = ExecuteTimings::default(); let LoadAndExecuteTransactionsOutput { loaded_transactions, - mut execution_results, + execution_results, .. } = self.load_and_execute_transactions( &batch, @@ -3638,41 +3959,41 @@ impl Bank { Some(&account_overrides), ); - let post_simulation_accounts = loaded_transactions - .into_iter() - .next() - .unwrap() - .0 - .ok() - .map(|loaded_transaction| { - loaded_transaction - .accounts - .into_iter() - .take(number_of_accounts) - .collect::>() - }) - .unwrap_or_default(); + Self::build_transaction_simulation_result(&loaded_transactions[0], &execution_results[0]) + } - let units_consumed = timings - .details - .per_program_timings - .iter() - .fold(0, |acc: u64, (_, program_timing)| { - acc.saturating_add(program_timing.accumulated_units) - }); + fn build_transaction_simulation_result( + loaded_transaction_result: &TransactionLoadResult, + execution_result: &TransactionExecutionResult, + ) -> TransactionSimulationResult { + let (logs, units_consumed, result) = match execution_result { + TransactionExecutionResult::Executed { details, .. } => { + let log_messages = if let Some(ref log_messages) = details.log_messages { + log_messages.clone() + } else { + vec![] + }; - debug!("simulate_transaction: {:?}", timings); + ( + log_messages, + details.executed_units, + execution_result.flattened_result(), + ) + } + TransactionExecutionResult::NotExecuted(_) => { + (vec![], 0, execution_result.flattened_result()) + } + }; - let execution_result = execution_results.pop().unwrap(); - let flattened_result = execution_result.flattened_result(); - let logs = match execution_result { - TransactionExecutionResult::Executed { details, .. } => details.log_messages, - TransactionExecutionResult::NotExecuted(_) => None, - } - .unwrap_or_default(); + let post_simulation_accounts = loaded_transaction_result + .0 + .as_ref() + .ok() + .map(|tx| tx.accounts.clone()) + .unwrap_or_default(); TransactionSimulationResult { - result: flattened_result, + result, logs, post_simulation_accounts, units_consumed, @@ -3874,6 +4195,29 @@ impl Bank { balances } + pub fn collect_balances_with_cache( + &self, + batch: &TransactionBatch, + account_overrides: Option<&AccountOverrides>, + ) -> TransactionBalances { + let mut balances: TransactionBalances = vec![]; + for transaction in batch.sanitized_transactions() { + let mut transaction_balances: Vec = vec![]; + for account_key in transaction.message().account_keys().iter() { + let balance = match account_overrides { + None => self.get_balance(account_key), + Some(overrides) => match overrides.get(account_key) { + None => self.get_balance(account_key), + Some(account_data) => account_data.lamports(), + }, + }; + transaction_balances.push(balance); + } + balances.push(transaction_balances); + } + balances + } + /// Get any cached executors needed by the transaction fn get_executors(&self, accounts: &[TransactionAccount]) -> Rc> { let executable_keys: Vec<_> = accounts @@ -4676,6 +5020,30 @@ impl Bank { } } + pub fn collect_accounts_to_store<'a>( + &self, + txs: &'a [SanitizedTransaction], + res: &'a [TransactionExecutionResult], + loaded: &'a mut [TransactionLoadResult], + ) -> Vec<(&'a Pubkey, &'a AccountSharedData)> { + let durable_nonce = { + let separate_nonce_from_blockhash = self.separate_nonce_from_blockhash(); + let durable_nonce = + DurableNonce::from_blockhash(&self.last_blockhash(), separate_nonce_from_blockhash); + (durable_nonce, separate_nonce_from_blockhash) + }; + Accounts::collect_accounts_to_store( + txs, + res, + loaded, + &self.rent_collector, + &durable_nonce, + self.get_lamports_per_signature(), + self.leave_nonce_on_success(), + self.preserve_rent_epoch_for_rent_exempt_accounts(), + ) + } + // Distribute collected rent fees for this slot to staked validators (excluding stakers) // according to stake. // @@ -7071,6 +7439,127 @@ pub(crate) mod tests { } } + fn tx_factory( + readonly_accounts: Vec, + mut writeable_accounts: Vec, + signer_key_pair: Keypair, + ) -> Transaction { + if !writeable_accounts.contains(&signer_key_pair.pubkey()) { + writeable_accounts.insert(0, signer_key_pair.pubkey()); + } + let num_readonly_unsigned_accounts = readonly_accounts.len() as u8; + writeable_accounts.extend(readonly_accounts); + + let message = Message { + header: MessageHeader { + num_required_signatures: 1, + num_readonly_signed_accounts: 0, + num_readonly_unsigned_accounts, + }, + account_keys: writeable_accounts, + recent_blockhash: Hash::default(), + instructions: vec![], + }; + let signature = signer_key_pair.sign_message(&message.serialize()[..]); + + Transaction { + signatures: vec![signature], + message, + } + } + + #[test] + fn test_prepare_sequential_sanitized_batch_with_results_happy_path() { + let (genesis_config, _mint_keypair) = create_genesis_config(10); + let bank = Bank::new_for_tests(&genesis_config); + + // 1. create a bundle of self-conflicting account accesses + // e.g. T0{write-a, write-b}, T1{write-a, read-b, read-c}, T2{read-c, write-d, write-e}, T3{read-e, write-f} + let a = Keypair::new(); + let b = Keypair::new(); + let c = Keypair::new(); + let d = Keypair::new(); + let e = Keypair::new(); + let f = Keypair::new(); + + let tx_0 = tx_factory( + vec![], + vec![a.pubkey(), b.pubkey()], + Keypair::from_base58_string(&*a.to_base58_string()), + ); + let tx_0 = SanitizedTransaction::from_transaction_for_tests(tx_0); + + let tx_1 = tx_factory(vec![b.pubkey(), c.pubkey()], vec![a.pubkey()], a); + let tx_1 = SanitizedTransaction::from_transaction_for_tests(tx_1); + + let tx_2 = tx_factory(vec![c.pubkey()], vec![d.pubkey(), e.pubkey()], d); + let tx_2 = SanitizedTransaction::from_transaction_for_tests(tx_2); + + let tx_3 = tx_factory(vec![e.pubkey()], vec![f.pubkey()], f); + let tx_3 = SanitizedTransaction::from_transaction_for_tests(tx_3); + + // 2. test batches are chunked correctly + let sanitized_txs = vec![tx_0, tx_1, tx_2, tx_3]; + + let expected_next_start = 1; + _test_prepare_sequential_sanitized_batch_with_results( + &bank, + &sanitized_txs, + 0, + sanitized_txs.len(), + Some(expected_next_start), + 1, + ); + + let new_start = expected_next_start; + let expected_next_start = 3; + _test_prepare_sequential_sanitized_batch_with_results( + &bank, + &sanitized_txs, + new_start, + sanitized_txs.len(), + Some(expected_next_start), + 2, + ); + + let new_start = expected_next_start; + _test_prepare_sequential_sanitized_batch_with_results( + &bank, + &sanitized_txs, + new_start, + sanitized_txs.len(), + None, + 1, + ); + } + + fn _test_prepare_sequential_sanitized_batch_with_results( + bank: &Bank, + sanitized_txs: &[SanitizedTransaction], + chunk_start: usize, + chunk_end: usize, + expected_next_start: Option, + expected_okays: usize, + ) { + let account_locks_override = Mutex::new(AccountLocks::default()); + let chunk = &sanitized_txs[chunk_start..chunk_end]; + let batch = bank + .prepare_sequential_sanitized_batch_with_results(chunk, Some(account_locks_override)); + + assert_eq!( + batch + .lock_results() + .iter() + .filter(|res| res.is_ok()) + .count(), + expected_okays + ); + + let first_err_idx = batch.lock_results().iter().position(|res| res.is_err()); + let actual_next_start = first_err_idx.map(|first_err_idx| first_err_idx + chunk_start); + assert_eq!(actual_next_start, expected_next_start); + } + #[test] fn test_nonce_info() { let lamports_per_signature = 42; @@ -7649,6 +8138,593 @@ pub(crate) mod tests { assert_eq!(account, bank.get_account(&pubkey).unwrap()); } + #[test] + #[should_panic] + fn test_simulate_bundle_unfrozen_bank() { + let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000); + let bank = Bank::new_for_tests(&genesis_config); + let _ = bank.simulate_bundle(vec![], vec![], vec![]); + } + + #[test] + #[should_panic] + fn test_simulate_bundle_mismatched_lengths() { + let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000); + let bank = Bank::new_for_tests(&genesis_config); + bank.freeze(); + + let _ = bank.simulate_bundle(vec![], vec![None], vec![None]); + } + + fn setup_system_accounts( + pubkeys: Vec, + lamports: u64, + bank: &Bank, + ) -> Vec { + pubkeys + .iter() + .map(|pk| { + let data = AccountSharedData::new(lamports, 0, &system_program::id()); + bank.store_account(pk, &data); + data + }) + .collect::>() + } + + fn assert_transaction_results( + actual_results: Vec>, + expected_results: Vec>, + ) { + assert_eq!(actual_results.len(), expected_results.len()); + for (i, (actual, expected)) in actual_results.iter().zip(expected_results).enumerate() { + assert_eq!( + actual, + &expected, + "{}", + format_args!("result at index {} did not match", i) + ); + } + } + + fn assert_simulate_bundle_correct_lamports( + actual_account_data: Vec>>, + expected_lamports: Vec>>, + ) { + assert_eq!(actual_account_data.len(), expected_lamports.len()); + + for (i, maybe_actual) in actual_account_data.iter().enumerate() { + if let Some(expected) = expected_lamports[i].clone() { + assert!(maybe_actual.is_some()); + let actual = maybe_actual.clone().unwrap(); + assert_eq!(actual.len(), expected.keys().len()); + + for (pk, lamports) in expected { + let account = actual.iter().find(|acc| acc.0 == pk).unwrap(); + assert_eq!(account.1.lamports(), lamports) + } + } else { + assert!(maybe_actual.is_none()); + } + } + } + + /// Tests with a bundle expected to fail due to `check_bundle_lock_results`. None of the transactions + /// should execute due to bad locking behaviour! + /// + /// Bundle: [T0{Faucet, A, B}, T1{Z, C}, T2{Z, C}, T3{Faucet, A, A, B}, T4{Faucet, C}] + /// Requested Pre-Execution Accounts: [[A, B], None, None, [A, B], [C]] + /// Requested Post-Execution Accounts: [[A], [C], None, [A, B], [C]] + /// + /// Expect the following: + /// Returned Pre-Execution Accounts: [None, None, None, None, None] + /// Returned Post-Execution Accounts: [None, None, None, None, None] + #[test] + fn test_simulate_bundle_with_bad_locks() { + let (genesis_config, faucet_keypair) = create_genesis_config(1_000_000); + let bank = Bank::new_for_tests(&genesis_config); + let recent_blockhash = bank.confirmed_last_blockhash(); + + // Setup + let a = solana_sdk::pubkey::new_rand(); + let b = solana_sdk::pubkey::new_rand(); + let c = solana_sdk::pubkey::new_rand(); + let z = Keypair::new(); + let initial_lamports = 100_000; + let _ = setup_system_accounts(vec![a, b, c, z.pubkey()], initial_lamports, &bank); + + bank.freeze(); + + let mut expected_pre_lamports_returned = vec![]; + let mut expected_post_lamports_returned = vec![]; + + // Create the transactions + let to_lamports = &[(a, 100), (b, 1000)]; + let ixs = system_instruction::transfer_many(&faucet_keypair.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&faucet_keypair.pubkey())); + let tx_0 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + expected_pre_lamports_returned.push(None); + expected_post_lamports_returned.push(None); + + let to_lamports = &[(c, 1)]; + let ixs = system_instruction::transfer_many(&z.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&z.pubkey())); + let tx_1 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&z], + message, + recent_blockhash, + )) + .unwrap(); + expected_pre_lamports_returned.push(None); + expected_post_lamports_returned.push(None); + + let to_lamports = &[(c, 42069)]; + let ixs = system_instruction::transfer_many(&z.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&z.pubkey())); + let tx_2 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&z], + message, + recent_blockhash, + )) + .unwrap(); + expected_pre_lamports_returned.push(None); + expected_post_lamports_returned.push(None); + + let message = Message { + header: MessageHeader { + num_required_signatures: 1, + ..MessageHeader::default() + }, + account_keys: vec![faucet_keypair.pubkey(), a, a], + ..Message::default() + }; + let tx_3 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + expected_pre_lamports_returned.push(None); + expected_post_lamports_returned.push(None); + + let to_lamports = &[(c, 3433)]; + let ixs = system_instruction::transfer_many(&faucet_keypair.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&faucet_keypair.pubkey())); + let tx_4 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + expected_pre_lamports_returned.push(None); + expected_post_lamports_returned.push(None); + + // Create params + let pre_execution_accounts = vec![ + Some(vec![a, b]), + None, + None, + Some(vec![a, b]), + Some(vec![c]), + ]; + let post_execution_accounts = vec![ + Some(vec![a]), + Some(vec![c]), + None, + Some(vec![a, b]), + Some(vec![c]), + ]; + let bundle = vec![tx_0, tx_1, tx_2, tx_3.clone(), tx_4]; + + // Do it! + let result = bank + .simulate_bundle( + bundle.clone(), + pre_execution_accounts, + post_execution_accounts, + ) + .unwrap(); + + // Basic assertions + assert_eq!( + result.summary, + BundleSimulationSummary::Failed { + error: BundleExecutionError::TransactionFailure( + TransactionError::AccountLoadedTwice + ), + tx_signature: *tx_3.signature() + } + ); + assert_eq!(result.transaction_results.len(), bundle.len()); + + let expected_reults = vec![ + Err(TransactionError::SkippedExecution), + Err(TransactionError::SkippedExecution), + Err(TransactionError::SkippedExecution), + Err(TransactionError::AccountLoadedTwice), + Err(TransactionError::SkippedExecution), + ]; + let actual_results = result + .transaction_results + .clone() + .into_iter() + .map(|res| res.result) + .collect::>>(); + assert_transaction_results(actual_results, expected_reults); + + let actual_pre_lamports = result + .transaction_results + .clone() + .into_iter() + .map(|res| res.pre_execution_accounts) + .collect::>>>(); + assert_simulate_bundle_correct_lamports( + actual_pre_lamports, + expected_pre_lamports_returned, + ); + + let actual_post_lamports = result + .transaction_results + .into_iter() + .map(|res| res.post_execution_accounts) + .collect::>>>(); + assert_simulate_bundle_correct_lamports( + actual_post_lamports, + expected_post_lamports_returned, + ); + } + + /// Tests with a bundle expected to fail due to failing transaction execution. + /// The first two txs are parallelize and both succeed. T3 fails execution causing + /// all txs in its chunk (T2 & T4) to fail with [TransactionError::SkippedExecution]. + /// + /// Bundle: [T0{Faucet, A, B}, T1{Z, C}, T2{Faucet, C}, T3{Z, A, B}, T4{Faucet, C}] + /// Requested Pre-Execution Accounts: [[A, B], None, [C], [A, B], [C]] + /// Requested Post-Execution Accounts: [[A], [C], None, [A, B], [C]] + /// + /// Expect the following: + /// Returned Pre-Execution Accounts: [[A, B], None, [T1(C)], [T0(A), T0(B)], None] + /// Returned Post-Execution Accounts: [[T0(A)], [T1(C)], None, [T0(A), T0(B)], None] + #[test] + fn test_simulate_bundle_with_failing_tx() { + let (genesis_config, faucet_keypair) = create_genesis_config(1_000_000); + let bank = Bank::new_for_tests(&genesis_config); + let recent_blockhash = bank.confirmed_last_blockhash(); + + // Setup + let a = solana_sdk::pubkey::new_rand(); + let b = solana_sdk::pubkey::new_rand(); + let c = solana_sdk::pubkey::new_rand(); + let z = Keypair::new(); + let initial_lamports = 100_000; + let (pre_a_data, pre_b_data, pre_c_data, pre_z_data) = + match &setup_system_accounts(vec![a, b, c, z.pubkey()], initial_lamports, &bank)[..] { + [pre_a_data, pre_b_data, pre_c_data, pre_z_data] => ( + pre_a_data.clone(), + pre_b_data.clone(), + pre_c_data.clone(), + pre_z_data.clone(), + ), + _ => unreachable!(), + }; + + bank.freeze(); + + let mut expected_pre_lamports_returned = vec![]; + let mut expected_post_lamports_returned = vec![]; + + // Create the transactions + let to_lamports = &[(a, 100), (b, 1000)]; + let ixs = system_instruction::transfer_many(&faucet_keypair.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&faucet_keypair.pubkey())); + let tx_0 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + let mut m = HashMap::new(); + m.insert(a, pre_a_data.lamports()); + m.insert(b, pre_b_data.lamports()); + expected_pre_lamports_returned.push(Some(m)); + let mut m = HashMap::new(); + m.insert(a, pre_a_data.lamports() + 100); + expected_post_lamports_returned.push(Some(m)); + + let to_lamports = &[(c, 1)]; + let ixs = system_instruction::transfer_many(&z.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&z.pubkey())); + let tx_1 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&z], + message, + recent_blockhash, + )) + .unwrap(); + expected_pre_lamports_returned.push(None); + let mut m = HashMap::new(); + m.insert(c, pre_c_data.lamports() + 1); + expected_post_lamports_returned.push(Some(m)); + + let to_lamports = &[(c, 42069)]; + let ixs = system_instruction::transfer_many(&faucet_keypair.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&faucet_keypair.pubkey())); + let tx_2 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + let mut m = HashMap::new(); + m.insert(c, pre_c_data.lamports() + 1); + expected_pre_lamports_returned.push(Some(m)); + expected_post_lamports_returned.push(None); + + let to_lamports = &[(c, pre_z_data.lamports() + 1000)]; + let ixs = system_instruction::transfer_many(&z.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&z.pubkey())); + let tx_3 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&z], + message, + recent_blockhash, + )) + .unwrap(); + let mut m = HashMap::new(); + m.insert(a, pre_a_data.lamports() + 100); + m.insert(b, pre_b_data.lamports() + 1000); + expected_pre_lamports_returned.push(Some(m)); + let mut m = HashMap::new(); + m.insert(a, pre_a_data.lamports() + 100); + m.insert(b, pre_b_data.lamports() + 1000); + expected_post_lamports_returned.push(Some(m)); + + let to_lamports = &[(c, 3433)]; + let ixs = system_instruction::transfer_many(&faucet_keypair.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&faucet_keypair.pubkey())); + let tx_4 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + expected_pre_lamports_returned.push(None); + expected_post_lamports_returned.push(None); + + // Create params + let pre_execution_accounts = vec![ + Some(vec![a, b]), + None, + Some(vec![c]), + Some(vec![a, b]), + Some(vec![c]), + ]; + let post_execution_accounts = vec![ + Some(vec![a]), + Some(vec![c]), + None, + Some(vec![a, b]), + Some(vec![c]), + ]; + let bundle = vec![tx_0, tx_1, tx_2, tx_3.clone(), tx_4]; + + // Do it! + let result = bank + .simulate_bundle( + bundle.clone(), + pre_execution_accounts, + post_execution_accounts, + ) + .unwrap(); + + // Basic assertions + assert_eq!( + result.summary, + BundleSimulationSummary::Failed { + error: BundleExecutionError::TransactionFailure( + TransactionError::InstructionError(0, InstructionError::Custom(1)) + ), + tx_signature: *tx_3.signature() + } + ); + assert_eq!(result.transaction_results.len(), bundle.len()); + + let expected_reults = vec![ + Ok(()), + Ok(()), + Ok(()), + Err(TransactionError::InstructionError( + 0, + InstructionError::Custom(1), + )), + Err(TransactionError::SkippedExecution), + ]; + let actual_results = result + .transaction_results + .clone() + .into_iter() + .map(|res| res.result) + .collect::>>(); + assert_transaction_results(actual_results, expected_reults); + + let actual_pre_lamports = result + .transaction_results + .clone() + .into_iter() + .map(|res| res.pre_execution_accounts) + .collect::>>>(); + assert_simulate_bundle_correct_lamports( + actual_pre_lamports, + expected_pre_lamports_returned, + ); + + let actual_post_lamports = result + .transaction_results + .into_iter() + .map(|res| res.post_execution_accounts) + .collect::>>>(); + assert_simulate_bundle_correct_lamports( + actual_post_lamports, + expected_post_lamports_returned, + ); + } + + /// Tests with a bundle expected to succeed, containing no parallelize chunks + /// + /// Bundle: [T0{Faucet, A, B, C}, T1{Faucet, D}, T2{Faucet, E, A, C}, T3{Faucet, D, F}] + /// Requested Pre-Execution Accounts: [None, [A, D], [B], [A, C, F]] + /// Requested Post-Execution Accounts: [None, [D], None, [A, B, F]] + /// + /// Expect the following: + /// Returned Pre-Execution Accounts: [None, [T0(A), D], [T0(B)], [T0(T2(A)), T0(T2(C)), F]] + /// Returned Post-Execution Accounts: [None, [T1(D)], None, [T0(T2(A), T0(B), T3(F)]] + #[test] + fn test_simulate_bundle_happy_path() { + let (genesis_config, faucet_keypair) = create_genesis_config(1_000_000); + let bank = Bank::new_for_tests(&genesis_config); + let recent_blockhash = bank.confirmed_last_blockhash(); + + // Create some accounts and save them to the bank + let a = solana_sdk::pubkey::new_rand(); + let b = solana_sdk::pubkey::new_rand(); + let c = solana_sdk::pubkey::new_rand(); + let d = solana_sdk::pubkey::new_rand(); + let e = solana_sdk::pubkey::new_rand(); + let f = solana_sdk::pubkey::new_rand(); + let initial_lamports = 100_000; + let (pre_a_data, pre_b_data, pre_c_data, pre_d_data, pre_f_data) = + match &setup_system_accounts(vec![a, b, c, d, e, f], initial_lamports, &bank)[..] { + [pre_a_data, pre_b_data, pre_c_data, pre_d_data, _, pre_f_data] => ( + pre_a_data.clone(), + pre_b_data.clone(), + pre_c_data.clone(), + pre_d_data.clone(), + pre_f_data.clone(), + ), + _ => unreachable!(), + }; + + bank.freeze(); + + let mut expected_pre_lamports_returned = vec![]; + let mut expected_post_lamports_returned = vec![]; + + // Create the transactions + let to_lamports = &[(a, 100), (b, 1000), (c, 200)]; + let ixs = system_instruction::transfer_many(&faucet_keypair.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&faucet_keypair.pubkey())); + let tx_0 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + expected_pre_lamports_returned.push(None); + expected_post_lamports_returned.push(None); + + let to_lamports = &[(d, 343)]; + let ixs = system_instruction::transfer_many(&faucet_keypair.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&faucet_keypair.pubkey())); + let tx_1 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + let mut m = HashMap::new(); + m.insert(a, pre_a_data.lamports() + 100); + m.insert(d, pre_d_data.lamports()); + expected_pre_lamports_returned.push(Some(m)); + let mut m = HashMap::new(); + m.insert(d, pre_d_data.lamports() + 343); + expected_post_lamports_returned.push(Some(m)); + + let to_lamports = &[(e, 378), (a, 1002), (c, 200)]; + let ixs = system_instruction::transfer_many(&faucet_keypair.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&faucet_keypair.pubkey())); + let tx_2 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + let mut m = HashMap::new(); + m.insert(b, pre_b_data.lamports() + 1000); + expected_pre_lamports_returned.push(Some(m)); + expected_post_lamports_returned.push(None); + + let to_lamports = &[(d, 378), (f, 1002)]; + let ixs = system_instruction::transfer_many(&faucet_keypair.pubkey(), to_lamports); + let message = Message::new(&ixs[..], Some(&faucet_keypair.pubkey())); + let tx_3 = SanitizedTransaction::try_from_legacy_transaction(Transaction::new( + &[&faucet_keypair], + message, + recent_blockhash, + )) + .unwrap(); + let mut m = HashMap::new(); + m.insert(a, pre_a_data.lamports() + 100 + 1002); + m.insert(c, pre_c_data.lamports() + 200 + 200); + m.insert(f, pre_f_data.lamports()); + expected_pre_lamports_returned.push(Some(m)); + let mut m = HashMap::new(); + m.insert(a, pre_a_data.lamports() + 100 + 1002); + m.insert(b, pre_b_data.lamports() + 1000); + m.insert(f, pre_f_data.lamports() + 1002); + expected_post_lamports_returned.push(Some(m)); + + // Create params + let pre_execution_accounts = + vec![None, Some(vec![a, d]), Some(vec![b]), Some(vec![a, c, f])]; + let post_execution_accounts = vec![None, Some(vec![d]), None, Some(vec![a, b, f])]; + let bundle = vec![tx_0, tx_1, tx_2, tx_3]; + + // Do it! + let result = bank + .simulate_bundle( + bundle.clone(), + pre_execution_accounts, + post_execution_accounts, + ) + .unwrap(); + + // Basic assertions + assert_eq!(result.summary, BundleSimulationSummary::Succeeded); + assert_eq!(result.transaction_results.len(), bundle.len()); + + let expected_reults = vec![Ok(()), Ok(()), Ok(()), Ok(())]; + let actual_results = result + .transaction_results + .clone() + .into_iter() + .map(|res| res.result) + .collect::>>(); + assert_transaction_results(actual_results, expected_reults); + + let actual_pre_lamports = result + .transaction_results + .clone() + .into_iter() + .map(|res| res.pre_execution_accounts) + .collect::>>>(); + assert_simulate_bundle_correct_lamports( + actual_pre_lamports, + expected_pre_lamports_returned, + ); + + let actual_post_lamports = result + .transaction_results + .into_iter() + .map(|res| res.post_execution_accounts) + .collect::>>>(); + assert_simulate_bundle_correct_lamports( + actual_post_lamports, + expected_post_lamports_returned, + ); + } + #[test] fn test_store_account_and_update_capitalization_increased() { let old_lamports = 400; diff --git a/runtime/src/builtins.rs b/runtime/src/builtins.rs index 9071bc78e6..bb3e59427d 100644 --- a/runtime/src/builtins.rs +++ b/runtime/src/builtins.rs @@ -198,7 +198,7 @@ fn builtin_feature_transitions() -> Vec { ] } -pub(crate) fn get() -> Builtins { +pub fn get() -> Builtins { Builtins { genesis_builtins: genesis_builtins(), feature_transitions: builtin_feature_transitions(), diff --git a/runtime/src/snapshot_utils.rs b/runtime/src/snapshot_utils.rs index 4a3e74fdfd..fbd4a8f031 100644 --- a/runtime/src/snapshot_utils.rs +++ b/runtime/src/snapshot_utils.rs @@ -884,17 +884,20 @@ pub fn bank_from_latest_snapshot_archives( verify_index: bool, accounts_db_config: Option, accounts_update_notifier: Option, + halt_at_slot: Option, ) -> Result<( Bank, FullSnapshotArchiveInfo, Option, )> { - let full_snapshot_archive_info = get_highest_full_snapshot_archive_info(&snapshot_archives_dir) - .ok_or(SnapshotError::NoSnapshotArchives)?; + let full_snapshot_archive_info = + get_highest_full_snapshot_archive_info(&snapshot_archives_dir, halt_at_slot) + .ok_or(SnapshotError::NoSnapshotArchives)?; let incremental_snapshot_archive_info = get_highest_incremental_snapshot_archive_info( &snapshot_archives_dir, full_snapshot_archive_info.slot(), + halt_at_slot, ); info!( @@ -1253,11 +1256,14 @@ where } /// Get the highest slot of the full snapshot archives in a directory -pub fn get_highest_full_snapshot_archive_slot

(snapshot_archives_dir: P) -> Option +pub fn get_highest_full_snapshot_archive_slot

( + snapshot_archives_dir: P, + halt_at_slot: Option, +) -> Option where P: AsRef, { - get_highest_full_snapshot_archive_info(snapshot_archives_dir) + get_highest_full_snapshot_archive_info(snapshot_archives_dir, halt_at_slot) .map(|full_snapshot_archive_info| full_snapshot_archive_info.slot()) } @@ -1266,19 +1272,35 @@ where pub fn get_highest_incremental_snapshot_archive_slot>( snapshot_archives_dir: P, full_snapshot_slot: Slot, + halt_at_slot: Option, ) -> Option { - get_highest_incremental_snapshot_archive_info(snapshot_archives_dir, full_snapshot_slot) - .map(|incremental_snapshot_archive_info| incremental_snapshot_archive_info.slot()) + get_highest_incremental_snapshot_archive_info( + snapshot_archives_dir, + full_snapshot_slot, + halt_at_slot, + ) + .map(|incremental_snapshot_archive_info| incremental_snapshot_archive_info.slot()) } /// Get the path (and metadata) for the full snapshot archive with the highest slot in a directory pub fn get_highest_full_snapshot_archive_info

( snapshot_archives_dir: P, + halt_at_slot: Option, ) -> Option where P: AsRef, { let mut full_snapshot_archives = get_full_snapshot_archives(snapshot_archives_dir); + info!( + "halt_at_slot: {:?} full_snapshot_archives: {:?}", + halt_at_slot, full_snapshot_archives + ); + if let Some(halt_at_slot) = halt_at_slot { + info!("retaining slots for {}", halt_at_slot); + full_snapshot_archives + .retain(|archive| archive.snapshot_archive_info().slot <= halt_at_slot); + } + info!("full_snapshot_archives: {:?}", full_snapshot_archives); full_snapshot_archives.sort_unstable(); full_snapshot_archives.into_iter().rev().next() } @@ -1288,6 +1310,7 @@ where pub fn get_highest_incremental_snapshot_archive_info

( snapshot_archives_dir: P, full_snapshot_slot: Slot, + halt_at_slot: Option, ) -> Option where P: AsRef, @@ -1302,6 +1325,9 @@ where incremental_snapshot_archive_info.base_slot() == full_snapshot_slot }) .collect::>(); + if let Some(halt_at_slot) = halt_at_slot { + incremental_snapshot_archives.retain(|archive| archive.slot() <= halt_at_slot); + } incremental_snapshot_archives.sort_unstable(); incremental_snapshot_archives.into_iter().rev().next() } @@ -1353,7 +1379,8 @@ pub fn purge_old_snapshot_archives

( // `maximum_incremental_snapshot_archives_to_retain`. // // Purge all the rest. - let highest_full_snapshot_slot = get_highest_full_snapshot_archive_slot(&snapshot_archives_dir); + let highest_full_snapshot_slot = + get_highest_full_snapshot_archive_slot(&snapshot_archives_dir, None); let mut incremental_snapshot_archives_with_same_base_slot = vec![]; let mut incremental_snapshot_archives_with_different_base_slot = vec![]; get_incremental_snapshot_archives(&snapshot_archives_dir) @@ -2607,7 +2634,7 @@ mod tests { ); assert_eq!( - get_highest_full_snapshot_archive_slot(temp_snapshot_archives_dir.path()), + get_highest_full_snapshot_archive_slot(temp_snapshot_archives_dir.path(), None), Some(max_slot - 1) ); } @@ -2632,7 +2659,8 @@ mod tests { assert_eq!( get_highest_incremental_snapshot_archive_slot( temp_snapshot_archives_dir.path(), - full_snapshot_slot + full_snapshot_slot, + None ), Some(max_incremental_snapshot_slot - 1) ); @@ -2641,7 +2669,8 @@ mod tests { assert_eq!( get_highest_incremental_snapshot_archive_slot( temp_snapshot_archives_dir.path(), - max_full_snapshot_slot + max_full_snapshot_slot, + None, ), None ); @@ -3243,6 +3272,7 @@ mod tests { false, Some(ACCOUNTS_DB_CONFIG_FOR_TESTING), None, + None, ) .unwrap(); diff --git a/runtime/src/stakes.rs b/runtime/src/stakes.rs index 34b993a7d3..ac832bdb55 100644 --- a/runtime/src/stakes.rs +++ b/runtime/src/stakes.rs @@ -149,7 +149,7 @@ pub struct Stakes { vote_accounts: VoteAccounts, /// stake_delegations - stake_delegations: ImHashMap, + pub stake_delegations: ImHashMap, /// unused unused: u64, @@ -318,7 +318,7 @@ impl Stakes { &self.vote_accounts } - pub(crate) fn stake_delegations(&self) -> &ImHashMap { + pub fn stake_delegations(&self) -> &ImHashMap { &self.stake_delegations } diff --git a/rustfmt.toml b/rustfmt.toml index e26d07f0d8..c7ccd48750 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +1,7 @@ imports_granularity = "One" group_imports = "One" + +ignore = [ + "jito-programs", + "anchor" +] \ No newline at end of file diff --git a/s b/s new file mode 100755 index 0000000000..d6e0fd31b3 --- /dev/null +++ b/s @@ -0,0 +1,15 @@ +#!/usr/bin/env sh + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" + +if [ -f .env ]; then + export $(cat .env | grep -v '#' | awk '/=/ {print $1}') +else + echo "Missing .env file" + exit 0 +fi + +echo "Syncing to host: $HOST" + +# sync to build server, ignoring local builds and local/remote dev ledger +rsync -avh --delete --exclude target --exclude docker-output "$SCRIPT_DIR" "$HOST":~/ diff --git a/scripts/increment-cargo-version.sh b/scripts/increment-cargo-version.sh index faf91f36d6..ce2fcc86ad 100755 --- a/scripts/increment-cargo-version.sh +++ b/scripts/increment-cargo-version.sh @@ -25,6 +25,9 @@ ignores=( web3.js/examples web3.js/test node_modules + jito-programs + anchor + solana-accountsdb-connector ) not_paths=() diff --git a/scripts/run.sh b/scripts/run.sh index 86407d339d..48c9af6418 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -102,6 +102,11 @@ args=( --identity "$validator_identity" --vote-account "$validator_vote_account" --ledger "$ledgerDir" + --tip-payment-program-pubkey "DThZmRNNXh7kvTQW9hXeGoWGPKktK8pgVAyoTLjH7UrT" + --tip-distribution-program-pubkey "FjrdANjvo76aCYQ4kf9FM1R8aESUcEE6F8V7qyoVUQcM" + --tip-distribution-account-payer "$validator_identity" + --merkle-root-upload-authority "$validator_identity" + --commission-bps 0 --gossip-port 8001 --full-rpc-api --rpc-port 8899 diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index ddf9800b54..20546f2af9 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -34,9 +34,11 @@ full = [ "libsecp256k1", "sha3", "digest", + "uuid" ] [dependencies] +anchor-lang = { path = "../anchor/lang" } assert_matches = { version = "1.5.0", optional = true } base64 = "0.13" bincode = "1.3.3" @@ -78,6 +80,7 @@ solana-program = { path = "program", version = "=1.13.6" } solana-sdk-macro = { path = "macro", version = "=1.13.6" } thiserror = "1.0" uriparse = "0.6.3" +uuid = { version = "1.0.0", features = ["v4", "fast-rng"], optional = true } wasm-bindgen = "0.2" [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/sdk/src/bundle/error.rs b/sdk/src/bundle/error.rs new file mode 100644 index 0000000000..503446f97e --- /dev/null +++ b/sdk/src/bundle/error.rs @@ -0,0 +1,51 @@ +#![cfg(feature = "full")] + +use { + anchor_lang::error::Error, serde::Deserialize, solana_program::pubkey::Pubkey, + solana_sdk::transaction::TransactionError, std::time::Duration, thiserror::Error, +}; + +#[derive(Error, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum BundleExecutionError { + #[error("PoH max height reached in the middle of a bundle.")] + PohMaxHeightError, + + #[error("A transaction in the bundle failed")] + TransactionFailure(#[from] TransactionError), + + #[error("The bundle exceeds the cost model")] + ExceedsCostModel, + + #[error("Tip error {0}")] + TipError(#[from] TipPaymentError), + + #[error("Shutdown triggered")] + Shutdown, + + #[error("The time spent retrying bundles exceeded the allowed time {0:?}")] + MaxRetriesExceeded(Duration), + + #[error("Error locking bundle because the transaction is malformed")] + LockError, +} + +#[derive(Error, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum TipPaymentError { + #[error("account is missing from bank: {0}")] + AccountMissing(Pubkey), + + #[error("MEV program is non-existent")] + ProgramNonExistent(Pubkey), + + #[error("Anchor error: {0}")] + AnchorError(String), +} + +impl From for TipPaymentError { + fn from(anchor_err: Error) -> Self { + match anchor_err { + Error::AnchorError(e) => Self::AnchorError(e.error_msg), + Error::ProgramError(e) => Self::AnchorError(e.to_string()), + } + } +} diff --git a/sdk/src/bundle/mod.rs b/sdk/src/bundle/mod.rs new file mode 100644 index 0000000000..0ecbaf9e33 --- /dev/null +++ b/sdk/src/bundle/mod.rs @@ -0,0 +1,12 @@ +#![cfg(feature = "full")] + +use crate::transaction::VersionedTransaction; + +pub mod error; +pub mod sanitized; +pub mod utils; + +#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)] +pub struct VersionedBundle { + pub transactions: Vec, +} diff --git a/sdk/src/bundle/sanitized.rs b/sdk/src/bundle/sanitized.rs new file mode 100644 index 0000000000..e544e03c19 --- /dev/null +++ b/sdk/src/bundle/sanitized.rs @@ -0,0 +1,8 @@ +#![cfg(feature = "full")] + +use solana_sdk::transaction::SanitizedTransaction; + +#[derive(Clone, Debug)] +pub struct SanitizedBundle { + pub transactions: Vec, +} diff --git a/sdk/src/bundle/utils.rs b/sdk/src/bundle/utils.rs new file mode 100644 index 0000000000..04c7446eda --- /dev/null +++ b/sdk/src/bundle/utils.rs @@ -0,0 +1,20 @@ +use {crate::bundle::error::BundleExecutionError, solana_sdk::transaction::TransactionError}; + +type LockResult = Result<(), TransactionError>; + +/// Checks that preparing a bundle gives an acceptable batch back +pub fn check_bundle_lock_results(lock_results: &[LockResult]) -> Option<(TransactionError, usize)> { + for (i, res) in lock_results.iter().enumerate() { + match res { + Ok(()) + | Err(TransactionError::AccountInUse) + | Err(TransactionError::BundleNotContinuous) => {} + Err(e) => { + return Some((e.clone(), i)); + } + } + } + None +} + +pub type BundleExecutionResult = Result; diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 08da2ce824..3e4230a33d 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -12,6 +12,7 @@ pub use solana_program::*; pub mod account; pub mod account_utils; pub mod builtins; +pub mod bundle; pub mod client; pub mod commitment_config; pub mod compute_budget; diff --git a/sdk/src/transaction/error.rs b/sdk/src/transaction/error.rs index 3f25fa5a62..0d9fa6944c 100644 --- a/sdk/src/transaction/error.rs +++ b/sdk/src/transaction/error.rs @@ -149,6 +149,14 @@ pub enum TransactionError { "Transaction results in an account ({account_index}) without insufficient funds for rent" )] InsufficientFundsForRent { account_index: u8 }, + + /// Bundle is not continuous + #[error("Bundle is not continuous")] + BundleNotContinuous, + + /// This error type should be used when a transaction in a bundle is not executed due to an earlier tx error. + #[error("Transaction did not execute.")] + SkippedExecution, } impl From for TransactionError { diff --git a/send-transaction-service/Cargo.toml b/send-transaction-service/Cargo.toml index e7dc13bb0f..bc879c6cd4 100644 --- a/send-transaction-service/Cargo.toml +++ b/send-transaction-service/Cargo.toml @@ -13,14 +13,15 @@ edition = "2021" crossbeam-channel = "0.5" log = "0.4.14" solana-client = { path = "../client", version = "=1.13.6" } +solana-gossip = { path = "../gossip", version = "=1.13.6" } solana-measure = { path = "../measure", version = "=1.13.6" } solana-metrics = { path = "../metrics", version = "=1.13.6" } solana-runtime = { path = "../runtime", version = "=1.13.6" } solana-sdk = { path = "../sdk", version = "=1.13.6" } - [dev-dependencies] solana-logger = { path = "../logger", version = "=1.13.6" } +solana-streamer = { path = "../streamer", version = "=1.13.6" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/send-transaction-service/src/send_transaction_service.rs b/send-transaction-service/src/send_transaction_service.rs index e440968b9d..f0b68e2dc9 100644 --- a/send-transaction-service/src/send_transaction_service.rs +++ b/send-transaction-service/src/send_transaction_service.rs @@ -3,6 +3,7 @@ use { crossbeam_channel::{Receiver, RecvTimeoutError}, log::*, solana_client::{connection_cache::ConnectionCache, tpu_connection::TpuConnection}, + solana_gossip::cluster_info::ClusterInfo, solana_measure::measure::Measure, solana_metrics::datapoint_warn, solana_runtime::{bank::Bank, bank_forks::BankForks}, @@ -325,7 +326,7 @@ const SEND_TRANSACTION_METRICS_REPORT_RATE_MS: u64 = 5000; impl SendTransactionService { pub fn new( - tpu_address: SocketAddr, + cluster_info: Arc, bank_forks: &Arc>, leader_info: Option, receiver: Receiver, @@ -339,7 +340,7 @@ impl SendTransactionService { ..Config::default() }; Self::new_with_config( - tpu_address, + cluster_info, bank_forks, leader_info, receiver, @@ -349,7 +350,7 @@ impl SendTransactionService { } pub fn new_with_config( - tpu_address: SocketAddr, + cluster_info: Arc, bank_forks: &Arc>, leader_info: Option, receiver: Receiver, @@ -364,7 +365,7 @@ impl SendTransactionService { let exit = Arc::new(AtomicBool::new(false)); let receive_txn_thread = Self::receive_txn_thread( - tpu_address, + cluster_info.clone(), receiver, leader_info_provider.clone(), connection_cache.clone(), @@ -375,7 +376,7 @@ impl SendTransactionService { ); let retry_thread = Self::retry_thread( - tpu_address, + cluster_info, bank_forks.clone(), leader_info_provider, connection_cache.clone(), @@ -393,7 +394,7 @@ impl SendTransactionService { /// Thread responsible for receiving transactions from RPC clients. fn receive_txn_thread( - tpu_address: SocketAddr, + cluster_info: Arc, receiver: Receiver, leader_info_provider: Arc>>, connection_cache: Arc, @@ -454,6 +455,7 @@ impl SendTransactionService { stats .sent_transactions .fetch_add(transactions.len() as u64, Ordering::Relaxed); + let tpu_address = cluster_info.my_contact_info().tpu; let _result = Self::send_transactions_in_batch( &tpu_address, &mut transactions, @@ -500,7 +502,7 @@ impl SendTransactionService { /// Thread responsible for retrying transactions fn retry_thread( - tpu_address: SocketAddr, + cluster_info: Arc, bank_forks: Arc>, leader_info_provider: Arc>>, connection_cache: Arc, @@ -536,7 +538,7 @@ impl SendTransactionService { bank_forks.working_bank().clone(), ) }; - + let tpu_address = cluster_info.my_contact_info().tpu; let _result = Self::process_transactions( &working_bank, &root_bank, @@ -780,27 +782,40 @@ mod test { super::*, crate::tpu_info::NullTpuInfo, crossbeam_channel::unbounded, + solana_gossip::contact_info::ContactInfo, solana_sdk::{ account::AccountSharedData, genesis_config::create_genesis_config, nonce::{self, state::DurableNonce}, pubkey::Pubkey, - signature::Signer, + signature::{Keypair, Signer}, system_program, system_transaction, }, - std::ops::Sub, + solana_streamer::socket::SocketAddrSpace, + std::{ + net::{IpAddr, Ipv4Addr}, + ops::Sub, + }, }; #[test] fn service_exit() { - let tpu_address = "127.0.0.1:0".parse().unwrap(); let bank = Bank::default_for_tests(); let bank_forks = Arc::new(RwLock::new(BankForks::new(bank))); let (sender, receiver) = unbounded(); let connection_cache = Arc::new(ConnectionCache::default()); + let contact_info = ContactInfo { + tpu: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080), + ..ContactInfo::default() + }; + let cluster_info: Arc = Arc::new(ClusterInfo::new( + contact_info, + Arc::new(Keypair::new()), + SocketAddrSpace::new(false), + )); let send_tranaction_service = SendTransactionService::new::( - tpu_address, + cluster_info, &bank_forks, None, receiver, diff --git a/solana-accountsdb-connector b/solana-accountsdb-connector new file mode 160000 index 0000000000..45cab4114e --- /dev/null +++ b/solana-accountsdb-connector @@ -0,0 +1 @@ +Subproject commit 45cab4114e32ba408a7b9ad1174fcfa20a3e9748 diff --git a/start b/start new file mode 100755 index 0000000000..be2e1a9a7e --- /dev/null +++ b/start @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +solana_keygen=./target/release/solana-keygen +SOLANA_CONFIG_DIR=./config + +mkdir $SOLANA_CONFIG_DIR + +NDEBUG=1 ./multinode-demo/setup.sh +./target/release/solana-ledger-tool -l config/bootstrap-validator/ create-snapshot 0 +NDEBUG=1 ./multinode-demo/faucet.sh diff --git a/start_multi b/start_multi new file mode 100755 index 0000000000..0083cf363b --- /dev/null +++ b/start_multi @@ -0,0 +1,29 @@ +#!/usr/bin/env sh +solana_keygen=./target/release/solana-keygen +SOLANA_CONFIG_DIR=./config + +mkdir $SOLANA_CONFIG_DIR +if [ $? -eq 0 ] ; then + echo "New Config! Generating Identities" + $solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/a/identity.json + $solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/a/stake-account.json + $solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/a/vote-account.json + + $solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/b/identity.json + $solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/b/stake-account.json + $solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/b/vote-account.json +fi + + +NDEBUG=1 ./multinode-demo/setup.sh \ + --bootstrap-validator \ + "$SOLANA_CONFIG_DIR"/a/identity.json \ + "$SOLANA_CONFIG_DIR"/a/vote-account.json \ + "$SOLANA_CONFIG_DIR"/a/stake-account.json \ + --bootstrap-validator \ + "$SOLANA_CONFIG_DIR"/b/identity.json \ + "$SOLANA_CONFIG_DIR"/b/vote-account.json \ + "$SOLANA_CONFIG_DIR"/b/stake-account.json + +./target/release/solana-ledger-tool -l config/bootstrap-validator/ create-snapshot 0 +NDEBUG=1 ./multinode-demo/faucet.sh diff --git a/storage-bigtable/src/bigtable.rs b/storage-bigtable/src/bigtable.rs index d8440b3c95..5d410c8889 100644 --- a/storage-bigtable/src/bigtable.rs +++ b/storage-bigtable/src/bigtable.rs @@ -223,7 +223,7 @@ impl BigTableConnection { self.channel.clone(), move |mut req: Request<()>| { if let Some(access_token) = &access_token { - match MetadataValue::from_str(&access_token.get()) { + match MetadataValue::try_from(&access_token.get()) { Ok(authorization_header) => { req.metadata_mut() .insert("authorization", authorization_header); diff --git a/storage-proto/proto/transaction_by_addr.proto b/storage-proto/proto/transaction_by_addr.proto index 2d582ba524..aa619550f8 100644 --- a/storage-proto/proto/transaction_by_addr.proto +++ b/storage-proto/proto/transaction_by_addr.proto @@ -57,6 +57,8 @@ enum TransactionErrorType { WOULD_EXCEED_ACCOUNT_DATA_TOTAL_LIMIT = 29; DUPLICATE_INSTRUCTION = 30; INSUFFICIENT_FUNDS_FOR_RENT = 31; + BUNDLE_NOT_CONTINUOUS = 32; + SKIPPED_EXECUTION = 33; } message InstructionError { diff --git a/storage-proto/src/convert.rs b/storage-proto/src/convert.rs index cb6eaf06b7..2bbad7d394 100644 --- a/storage-proto/src/convert.rs +++ b/storage-proto/src/convert.rs @@ -730,6 +730,8 @@ impl TryFrom for TransactionError { 27 => TransactionError::InvalidRentPayingAccount, 28 => TransactionError::WouldExceedMaxVoteCostLimit, 29 => TransactionError::WouldExceedAccountDataTotalLimit, + 32 => TransactionError::BundleNotContinuous, + 33 => TransactionError::SkippedExecution, _ => return Err("Invalid TransactionError"), }) } @@ -833,6 +835,12 @@ impl From for tx_by_addr::TransactionError { TransactionError::InsufficientFundsForRent { .. } => { tx_by_addr::TransactionErrorType::InsufficientFundsForRent } + TransactionError::BundleNotContinuous => { + tx_by_addr::TransactionErrorType::BundleNotContinuous + } + TransactionError::SkippedExecution => { + tx_by_addr::TransactionErrorType::SkippedExecution + } } as i32, instruction_error: match transaction_error { TransactionError::InstructionError(index, ref instruction_error) => { diff --git a/tip-distributor/Cargo.toml b/tip-distributor/Cargo.toml new file mode 100644 index 0000000000..83e79a29f2 --- /dev/null +++ b/tip-distributor/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "solana-tip-distributor" +version = "1.13.6" +edition = "2021" +license = "Apache-2.0" +description = "Collection of binaries used to distribute MEV rewards to delegators and validators." + +[dependencies] +anchor-lang = { path = "../anchor/lang" } +bigdecimal = "0.3.0" +clap = { version = "3.2.5", features = ["derive", "env"] } +env_logger = "0.9.0" +futures = "0.3.21" +im = "15.1.0" +itertools = "0.10.3" +log = "0.4.17" +num-traits = "0.2.15" +serde = "1.0.137" +serde_json = "1.0.81" +solana-client = { path = "../client", version = "=1.13.6" } +solana-genesis-utils = { path = "../genesis-utils", version = "=1.13.6" } +solana-ledger = { path = "../ledger", version = "=1.13.6" } +solana-merkle-tree = { path = "../merkle-tree", version = "=1.13.6" } +solana-program = { path = "../sdk/program", version = "=1.13.6" } +solana-rpc = { path = "../rpc", version = "=1.13.6" } +solana-runtime = { path = "../runtime", version = "=1.13.6" } +solana-sdk = { path = "../sdk", version = "=1.13.6" } +solana-stake-program = { path = "../programs/stake", version = "=1.13.6" } +thiserror = "1.0.31" +tip-distribution = { path = "../jito-programs/tip-payment/programs/tip-distribution", features = ["no-entrypoint"] } +tip-payment = { path = "../jito-programs/tip-payment/programs/tip-payment", features = ["no-entrypoint"] } +tokio = { version = "1.12.0", features = ["rt-multi-thread", "macros", "sync", "time", "full"] } + +[[bin]] +name = "solana-stake-meta-generator" +path = "src/bin/stake-meta-generator.rs" + +[[bin]] +name = "solana-merkle-root-generator" +path = "src/bin/merkle-root-generator.rs" + +[[bin]] +name = "solana-merkle-root-uploader" +path = "src/bin/merkle-root-uploader.rs" + +[[bin]] +name = "solana-claim-mev-tips" +path = "src/bin/claim-mev-tips.rs" diff --git a/tip-distributor/README.md b/tip-distributor/README.md new file mode 100644 index 0000000000..018cef98ac --- /dev/null +++ b/tip-distributor/README.md @@ -0,0 +1,43 @@ +# Tip Distributor +This library and collection of binaries are responsible for generating and uploading merkle roots to the on-chain +tip-distribution program found [here](https://github.com/jito-labs/jito-programs/blob/a450ef006e60e10894c02269ec8a301b81a083a0/tip-payment/programs/tip-distribution/src/lib.rs). + +## Background +Each individual validator is assigned a new PDA per epoch where their share of tips, in lamports, will be stored. +At the end of the epoch it's expected that validators take a commission and then distribute the rest of the funds +to their delegators such that delegators receive rewards proportional to their respective delegations. The distribution +mechanism is via merkle proofs similar to how airdrops work. + +The merkle roots are calculated off-chain and uploaded to the validator's **TipDistributionAccount** PDA. Validators may +elect an account to upload the merkle roots on their behalf. Once uploaded, users can invoke the **claim** instruction +and receive the rewards they're entitled to. Once all funds are claimed by users the validator can close the account and +refunded the rent. + +## Scripts + +### stake-meta-generator + +This script generates a JSON file identifying individual stake delegations to a validator, along with amount of lamports +in each validator's **TipDistributionAccount**. All validators will be contained in the JSON list, regardless of whether +the validator is a participant in the system; participant being indicative of running the jito-solana client to accept tips +having initialized a **TipDistributionAccount** PDA account for the epoch. + +One edge case that we've taken into account is the last validator in an epoch N receives tips but those tips don't get transferred +out into the PDA until some slot in epoch N + 1. Due to this we cannot rely on the bank's state at epoch N for lamports amount +in the PDAs. We use the bank solely to take a snapshot of delegations, but an RPC node to fetch the PDA lamports for more up-to-date data. + +### merkle-root-generator +This script accepts a path to the above JSON file as one of its arguments, and generates a merkle-root. It'll optionally upload the root +on-chain if specified. Additionally, it'll spit the generated merkle trees out into a JSON file. + +## How it works? +In order to use this library as the merkle root creator one must follow the following steps: +1. Download a ledger snapshot containing the slot of interest, i.e. the last slot in an epoch. The Solana foundation has snapshots that can be found [here](https://console.cloud.google.com/storage/browser/mainnet-beta-ledger-us-ny5). +2. Download the snapshot onto your worker machine (where this script will run). +3. Run `solana-ledger-tool -l ${PATH_TO_LEDGER} create-snapshot ${YOUR_SLOT} ${WHERE_TO_CREATE_SNAPSHOT}` + 1. The snapshot created at `${WHERE_TO_CREATE_SNAPSHOT}` will have the highest slot of `${YOUR_SLOT}`, assuming you downloaded the correct snapshot. +4. Run `stake-meta-generator --ledger-path ${WHERE_TO_CREATE_SNAPSHOT} --tip-distribution-program-id ${PUBKEY} --out-path ${JSON_OUT_PATH} --snapshot-slot ${SLOT} --rpc-url ${URL}` + 1. Note: `${WHERE_TO_CREATE_SNAPSHOT}` must be the same in steps 3 & 4. +5. Run `merkle-root-generator --path-to-my-keypair ${KEYPAIR_PATH} --stake-meta-coll-path ${STAKE_META_COLLECTION_JSON} --rpc-url ${URL} --upload-roots ${BOOL} --force-upload-root ${BOOL}` + +Voila! diff --git a/tip-distributor/src/bin/claim-mev-tips.rs b/tip-distributor/src/bin/claim-mev-tips.rs new file mode 100644 index 0000000000..45b515dbd1 --- /dev/null +++ b/tip-distributor/src/bin/claim-mev-tips.rs @@ -0,0 +1,52 @@ +//! This binary claims MEV tips. + +use { + clap::Parser, + log::*, + solana_sdk::pubkey::Pubkey, + solana_tip_distributor::claim_mev_workflow::claim_mev_tips, + std::{path::PathBuf, str::FromStr}, +}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// Path to JSON file containing the [GeneratedMerkleTreeCollection] object. + #[clap(long, env)] + merkle_trees_path: PathBuf, + + /// RPC to send transactions through + #[clap(long, env)] + rpc_url: String, + + /// Tip distribution program ID + #[clap(long, env)] + tip_distribution_program_id: String, + + /// Path to keypair + #[clap(long, env)] + keypair_path: PathBuf, +} + +fn main() { + env_logger::init(); + info!("Starting to claim mev tips..."); + + let args: Args = Args::parse(); + + let tip_distribution_program_id = Pubkey::from_str(&args.tip_distribution_program_id) + .expect("valid tip_distribution_program_id"); + + if let Err(e) = claim_mev_tips( + &args.merkle_trees_path, + &args.rpc_url, + &tip_distribution_program_id, + &args.keypair_path, + ) { + panic!("error claiming mev tips: {:?}", e); + } + info!( + "done claiming mev tips from file {:?}", + args.merkle_trees_path + ); +} diff --git a/tip-distributor/src/bin/merkle-root-generator.rs b/tip-distributor/src/bin/merkle-root-generator.rs new file mode 100644 index 0000000000..f9e9072bed --- /dev/null +++ b/tip-distributor/src/bin/merkle-root-generator.rs @@ -0,0 +1,29 @@ +//! This binary generates a merkle tree for each [TipDistributionAccount]; they are derived +//! using a user provided [StakeMetaCollection] JSON file. + +use { + clap::Parser, log::*, + solana_tip_distributor::merkle_root_generator_workflow::generate_merkle_root, + std::path::PathBuf, +}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// Path to JSON file containing the [StakeMetaCollection] object. + #[clap(long, env)] + stake_meta_coll_path: PathBuf, + + /// Path to JSON file to get populated with tree node data. + #[clap(long, env)] + out_path: PathBuf, +} + +fn main() { + env_logger::init(); + info!("Starting merkle-root-generator workflow..."); + + let args: Args = Args::parse(); + generate_merkle_root(&args.stake_meta_coll_path, &args.out_path).expect("merkle tree produced"); + info!("saved merkle roots to {:?}", args.stake_meta_coll_path); +} diff --git a/tip-distributor/src/bin/merkle-root-uploader.rs b/tip-distributor/src/bin/merkle-root-uploader.rs new file mode 100644 index 0000000000..f23e8f74b2 --- /dev/null +++ b/tip-distributor/src/bin/merkle-root-uploader.rs @@ -0,0 +1,50 @@ +use { + clap::Parser, + log::info, + solana_sdk::pubkey::Pubkey, + solana_tip_distributor::merkle_root_upload_workflow::upload_merkle_root, + std::{path::PathBuf, str::FromStr}, +}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// Path to JSON file containing the [StakeMetaCollection] object. + #[clap(long, env)] + merkle_root_path: PathBuf, + + /// The path to the keypair used to sign and pay for the `upload_merkle_root` transactions. + #[clap(long, env)] + keypair_path: PathBuf, + + /// The RPC to send transactions to. + #[clap(long, env)] + rpc_url: String, + + /// Tip distribution program ID + #[clap(long, env)] + tip_distribution_program_id: String, +} + +fn main() { + env_logger::init(); + + let args: Args = Args::parse(); + + let tip_distribution_program_id = Pubkey::from_str(&args.tip_distribution_program_id) + .expect("valid tip_distribution_program_id"); + + info!("starting merkle root uploader..."); + if let Err(e) = upload_merkle_root( + &args.merkle_root_path, + &args.keypair_path, + &args.rpc_url, + &tip_distribution_program_id, + ) { + panic!("failed to upload merkle roots: {:?}", e); + } + info!( + "uploaded merkle roots from file {:?}", + args.merkle_root_path + ); +} diff --git a/tip-distributor/src/bin/stake-meta-generator.rs b/tip-distributor/src/bin/stake-meta-generator.rs new file mode 100644 index 0000000000..365f82290e --- /dev/null +++ b/tip-distributor/src/bin/stake-meta-generator.rs @@ -0,0 +1,67 @@ +//! This binary is responsible for generating a JSON file that contains meta-data about stake +//! & delegations given a ledger snapshot directory. The JSON file is structured as an array +//! of [StakeMeta] objects. + +use { + clap::Parser, + log::*, + solana_sdk::{clock::Slot, pubkey::Pubkey}, + solana_tip_distributor::{self, stake_meta_generator_workflow::generate_stake_meta}, + std::{ + fs::{self}, + path::PathBuf, + process::exit, + }, +}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// Ledger path, where you created the snapshot. + #[clap(long, env, parse(try_from_str = Args::ledger_path_parser))] + ledger_path: PathBuf, + + /// The tip-distribution program id. + #[clap(long, env)] + tip_distribution_program_id: Pubkey, + + /// The tip-payment program id. + #[clap(long, env)] + tip_payment_program_id: Pubkey, + + /// Path to JSON file populated with the [StakeMetaCollection] object. + #[clap(long, env)] + out_path: String, + + /// The expected snapshot slot. + #[clap(long, env)] + snapshot_slot: Slot, +} + +impl Args { + fn ledger_path_parser(ledger_path: &str) -> Result { + Ok(fs::canonicalize(ledger_path).unwrap_or_else(|err| { + error!("Unable to access ledger path '{}': {}", ledger_path, err); + exit(1); + })) + } +} + +fn main() { + env_logger::init(); + info!("Starting stake-meta-generator..."); + + let args: Args = Args::parse(); + + if let Err(e) = generate_stake_meta( + &args.ledger_path, + &args.snapshot_slot, + &args.tip_distribution_program_id, + &args.out_path, + &args.tip_payment_program_id, + ) { + error!("error producing stake-meta: {:?}", e); + } else { + info!("produced stake meta"); + } +} diff --git a/tip-distributor/src/claim_mev_workflow.rs b/tip-distributor/src/claim_mev_workflow.rs new file mode 100644 index 0000000000..3a2fd19bd8 --- /dev/null +++ b/tip-distributor/src/claim_mev_workflow.rs @@ -0,0 +1,143 @@ +use { + crate::{read_json_from_file, send_transactions_with_retry, GeneratedMerkleTreeCollection}, + anchor_lang::{AccountDeserialize, InstructionData, ToAccountMetas}, + log::{debug, info}, + solana_client::{ + client_error::ClientErrorKind, nonblocking::rpc_client::RpcClient, rpc_request::RpcError, + }, + solana_program::system_program, + solana_sdk::{ + commitment_config::CommitmentConfig, + instruction::Instruction, + pubkey::Pubkey, + signature::{read_keypair_file, Signer}, + transaction::Transaction, + }, + std::{path::PathBuf, time::Duration}, + thiserror::Error, + tip_distribution::state::*, + tokio::runtime::Builder, +}; + +#[derive(Error, Debug)] +pub enum ClaimMevError { + #[error(transparent)] + IoError(#[from] std::io::Error), + + #[error(transparent)] + JsonError(#[from] serde_json::Error), +} + +pub fn claim_mev_tips( + merkle_root_path: &PathBuf, + rpc_url: &str, + tip_distribution_program_id: &Pubkey, + keypair_path: &PathBuf, +) -> Result<(), ClaimMevError> { + // roughly how long before blockhash expires + const MAX_RETRY_DURATION: Duration = Duration::from_secs(60); + + let merkle_trees: GeneratedMerkleTreeCollection = + read_json_from_file(merkle_root_path).expect("read GeneratedMerkleTreeCollection"); + let keypair = read_keypair_file(keypair_path).expect("read keypair file"); + + let tip_distribution_config = + Pubkey::find_program_address(&[Config::SEED], tip_distribution_program_id).0; + + let rpc_client = + RpcClient::new_with_commitment(rpc_url.to_string(), CommitmentConfig::confirmed()); + + let runtime = Builder::new_multi_thread() + .worker_threads(16) + .enable_all() + .build() + .unwrap(); + + let mut transactions = Vec::new(); + + runtime.block_on(async move { + let blockhash = rpc_client + .get_latest_blockhash() + .await + .expect("read blockhash"); + + for tree in merkle_trees.generated_merkle_trees { + for node in tree.tree_nodes { + let (claim_status_pubkey, claim_status_bump) = Pubkey::find_program_address( + &[ + ClaimStatus::SEED, + node.claimant.as_ref(), // ordering matters here + tree.tip_distribution_account.as_ref(), + ], + tip_distribution_program_id, + ); + + // only claim for ones that have merkle root on-chain + let account = rpc_client + .get_account(&tree.tip_distribution_account) + .await + .expect("expected to fetch tip distribution account"); + + let mut data = account.data.as_slice(); + let fetched_tip_distribution_account = + TipDistributionAccount::try_deserialize(&mut data) + .expect("failed to deserialize tip_distribution_account state"); + + if fetched_tip_distribution_account.merkle_root.is_some() { + match rpc_client.get_account(&claim_status_pubkey).await { + Ok(_) => { + debug!( + "claim status account already exists: {:?}", + claim_status_pubkey + ); + } + Err(e) => { + if matches!(e.kind(), ClientErrorKind::RpcError(RpcError::ForUser(_))) { + info!("claiming for public key: {:?}", node.claimant); + + let ix = Instruction { + program_id: *tip_distribution_program_id, + data: tip_distribution::instruction::Claim { + proof: node.proof.unwrap(), + amount: node.amount, + bump: claim_status_bump, + } + .data(), + accounts: tip_distribution::accounts::Claim { + config: tip_distribution_config, + tip_distribution_account: tree.tip_distribution_account, + claimant: node.claimant, + claim_status: claim_status_pubkey, + payer: keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + }; + let transaction = Transaction::new_signed_with_payer( + &[ix], + Some(&keypair.pubkey()), + &[&keypair], + blockhash, + ); + info!("tx: {:?}", transaction); + transactions.push(transaction); + } else { + panic!("unexpected rpc error: {:?}", e); + } + } + } + } else { + info!( + "not claiming because merkle root isn't uploaded yet claimant: {:?} tda: {:?}", + node.claimant, + tree.tip_distribution_account + ); + } + } + } + + send_transactions_with_retry(&rpc_client, &transactions, MAX_RETRY_DURATION).await; + }); + + Ok(()) +} diff --git a/tip-distributor/src/lib.rs b/tip-distributor/src/lib.rs new file mode 100644 index 0000000000..4ccde97ff0 --- /dev/null +++ b/tip-distributor/src/lib.rs @@ -0,0 +1,779 @@ +pub mod claim_mev_workflow; +pub mod merkle_root_generator_workflow; +pub mod merkle_root_upload_workflow; +pub mod stake_meta_generator_workflow; + +use { + crate::{ + merkle_root_generator_workflow::MerkleRootGeneratorError, + stake_meta_generator_workflow::StakeMetaGeneratorError::CheckedMathError, + }, + bigdecimal::{num_bigint::BigUint, BigDecimal}, + log::{error, info}, + num_traits::{CheckedDiv, CheckedMul, ToPrimitive}, + serde::{de::DeserializeOwned, Deserialize, Serialize}, + solana_client::nonblocking::rpc_client::RpcClient, + solana_merkle_tree::MerkleTree, + solana_sdk::{ + account::{AccountSharedData, ReadableAccount}, + clock::Slot, + hash::{Hash, Hasher}, + pubkey::Pubkey, + signature::Signature, + stake_history::Epoch, + transaction::Transaction, + }, + std::{ + collections::HashMap, + fs::File, + io::BufReader, + ops::{Div, Mul}, + path::PathBuf, + time::{Duration, Instant}, + }, + tip_distribution::state::TipDistributionAccount, + tip_payment::{ + Config, CONFIG_ACCOUNT_SEED, TIP_ACCOUNT_SEED_0, TIP_ACCOUNT_SEED_1, TIP_ACCOUNT_SEED_2, + TIP_ACCOUNT_SEED_3, TIP_ACCOUNT_SEED_4, TIP_ACCOUNT_SEED_5, TIP_ACCOUNT_SEED_6, + TIP_ACCOUNT_SEED_7, + }, + tokio::time::sleep, +}; + +#[derive(Deserialize, Serialize, Debug)] +pub struct GeneratedMerkleTreeCollection { + pub generated_merkle_trees: Vec, + pub bank_hash: String, + pub epoch: Epoch, + pub slot: Slot, +} + +#[derive(Eq, Debug, Hash, PartialEq, Deserialize, Serialize)] +pub struct GeneratedMerkleTree { + #[serde(with = "pubkey_string_conversion")] + pub tip_distribution_account: Pubkey, + #[serde(with = "pubkey_string_conversion")] + pub merkle_root_upload_authority: Pubkey, + pub merkle_root: Hash, + pub tree_nodes: Vec, + pub max_total_claim: u64, + pub max_num_nodes: u64, +} + +pub struct TipPaymentPubkeys { + config_pda: Pubkey, + tip_pdas: Vec, +} + +impl GeneratedMerkleTreeCollection { + pub fn new_from_stake_meta_collection( + stake_meta_coll: StakeMetaCollection, + ) -> Result { + let generated_merkle_trees = stake_meta_coll + .stake_metas + .into_iter() + .filter(|stake_meta| stake_meta.maybe_tip_distribution_meta.is_some()) + .filter_map(|stake_meta| { + let mut tree_nodes = match TreeNode::vec_from_stake_meta(&stake_meta) { + Err(e) => return Some(Err(e)), + Ok(maybe_tree_nodes) => maybe_tree_nodes, + }?; + + let hashed_nodes: Vec<[u8; 32]> = + tree_nodes.iter().map(|n| n.hash().to_bytes()).collect(); + + let tip_distribution_meta = stake_meta.maybe_tip_distribution_meta.unwrap(); + + let merkle_tree = MerkleTree::new(&hashed_nodes[..], true); + let max_num_nodes = tree_nodes.len() as u64; + + for (i, tree_node) in tree_nodes.iter_mut().enumerate() { + tree_node.proof = Some(get_proof(&merkle_tree, i)); + } + + Some(Ok(GeneratedMerkleTree { + max_num_nodes, + tip_distribution_account: tip_distribution_meta.tip_distribution_pubkey, + merkle_root_upload_authority: tip_distribution_meta + .merkle_root_upload_authority, + merkle_root: *merkle_tree.get_root().unwrap(), + tree_nodes, + max_total_claim: tip_distribution_meta.total_tips, + })) + }) + .collect::, MerkleRootGeneratorError>>()?; + + Ok(GeneratedMerkleTreeCollection { + generated_merkle_trees, + bank_hash: stake_meta_coll.bank_hash, + epoch: stake_meta_coll.epoch, + slot: stake_meta_coll.slot, + }) + } +} + +pub fn get_proof(merkle_tree: &MerkleTree, i: usize) -> Vec<[u8; 32]> { + let mut proof = Vec::new(); + let path = merkle_tree.find_path(i).expect("path to index"); + for branch in path.get_proof_entries() { + if let Some(hash) = branch.get_left_sibling() { + proof.push(hash.to_bytes()); + } else if let Some(hash) = branch.get_right_sibling() { + proof.push(hash.to_bytes()); + } else { + panic!("expected some hash at each level of the tree"); + } + } + proof +} + +fn derive_tip_payment_pubkeys(program_id: &Pubkey) -> TipPaymentPubkeys { + let config_pda = Pubkey::find_program_address(&[CONFIG_ACCOUNT_SEED], program_id).0; + let tip_pda_0 = Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_0], program_id).0; + let tip_pda_1 = Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_1], program_id).0; + let tip_pda_2 = Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_2], program_id).0; + let tip_pda_3 = Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_3], program_id).0; + let tip_pda_4 = Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_4], program_id).0; + let tip_pda_5 = Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_5], program_id).0; + let tip_pda_6 = Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_6], program_id).0; + let tip_pda_7 = Pubkey::find_program_address(&[TIP_ACCOUNT_SEED_7], program_id).0; + + TipPaymentPubkeys { + config_pda, + tip_pdas: vec![ + tip_pda_0, tip_pda_1, tip_pda_2, tip_pda_3, tip_pda_4, tip_pda_5, tip_pda_6, tip_pda_7, + ], + } +} + +#[derive(Clone, Eq, Debug, Hash, PartialEq, Deserialize, Serialize)] +pub struct TreeNode { + /// The stake account entitled to redeem. + #[serde(with = "pubkey_string_conversion")] + pub claimant: Pubkey, + + #[serde(with = "pubkey_string_conversion")] + pub staker_pubkey: Pubkey, + + #[serde(with = "pubkey_string_conversion")] + pub withdrawer_pubkey: Pubkey, + + /// The amount this account is entitled to. + pub amount: u64, + + /// The proof associated with this TreeNode + pub proof: Option>, +} + +impl TreeNode { + fn vec_from_stake_meta( + stake_meta: &StakeMeta, + ) -> Result>, MerkleRootGeneratorError> { + if let Some(tip_distribution_meta) = stake_meta.maybe_tip_distribution_meta.as_ref() { + let validator_fee = calc_validator_fee( + tip_distribution_meta.total_tips, + tip_distribution_meta.validator_fee_bps, + ); + let mut tree_nodes = vec![TreeNode { + claimant: stake_meta.validator_vote_account, + staker_pubkey: Pubkey::default(), + withdrawer_pubkey: Pubkey::default(), + amount: validator_fee, + proof: None, + }]; + + let remaining_tips = tip_distribution_meta + .total_tips + .checked_sub(validator_fee) + .unwrap(); + + // The theoretically smallest weight an account can have is (1 / SOL_TOTAL_SUPPLY_IN_LAMPORTS) + // where we round SOL_TOTAL_SUPPLY is rounded to 500_000_000. We use u64::MAX. This gives a reasonable + // guarantee that everyone gets paid out regardless of weight, as long as some non-zero amount of + // lamports were delegated. + let uint_precision_multiplier = BigUint::from(u64::MAX); + let f64_precision_multiplier = BigDecimal::try_from(u64::MAX as f64).unwrap(); + + let total_delegated = BigDecimal::try_from(stake_meta.total_delegated as f64) + .expect("failed to convert total_delegated to BigDecimal"); + tree_nodes.extend(stake_meta + .delegations + .iter() + .map(|delegation| { + // TODO(seg): Check this math! + let amount_delegated = BigDecimal::try_from(delegation.lamports_delegated as f64) + .expect(&*format!( + "failed to convert amount_delegated to BigDecimal [stake_account={}, amount_delegated={}]", + delegation.stake_account_pubkey, + delegation.lamports_delegated, + )); + let mut weight = amount_delegated.div(&total_delegated); + + let use_multiplier = weight < f64_precision_multiplier; + + if use_multiplier { + weight = weight.mul(&f64_precision_multiplier); + } + + let truncated_weight = weight.to_u128() + .expect(&*format!("failed to convert weight to u128 [stake_account={}, weight={}]", delegation.stake_account_pubkey, weight)); + let truncated_weight = BigUint::from(truncated_weight); + + let mut amount = truncated_weight + .checked_mul(&BigUint::from(remaining_tips)) + .unwrap(); + + if use_multiplier { + amount = amount.checked_div(&uint_precision_multiplier).unwrap(); + } + + Ok(TreeNode { + claimant: delegation.stake_account_pubkey, + staker_pubkey: delegation.staker_pubkey, + withdrawer_pubkey: delegation.withdrawer_pubkey, + amount: amount.to_u64().unwrap(), + proof: None + }) + }) + .collect::, MerkleRootGeneratorError>>()?); + + let total_claim_amount = tree_nodes.iter().fold(0u64, |sum, tree_node| { + sum.checked_add(tree_node.amount).unwrap() + }); + assert!(total_claim_amount < stake_meta.total_delegated); + + Ok(Some(tree_nodes)) + } else { + Ok(None) + } + } + + fn hash(&self) -> Hash { + let mut hasher = Hasher::default(); + hasher.hash(self.claimant.as_ref()); + hasher.hash(self.amount.to_le_bytes().as_ref()); + hasher.result() + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct StakeMetaCollection { + /// List of [StakeMeta]. + pub stake_metas: Vec, + + /// base58 encoded tip-distribution program id. + #[serde(with = "pubkey_string_conversion")] + pub tip_distribution_program_id: Pubkey, + + /// Base58 encoded bank hash this object was generated at. + pub bank_hash: String, + + /// Epoch for which this object was generated for. + pub epoch: Epoch, + + /// Slot at which this object was generated. + pub slot: Slot, +} + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq)] +pub struct StakeMeta { + #[serde(with = "pubkey_string_conversion")] + pub validator_vote_account: Pubkey, + + /// The validator's tip-distribution meta if it exists. + pub maybe_tip_distribution_meta: Option, + + /// Delegations to this validator. + pub delegations: Vec, + + /// The total amount of delegations to the validator. + pub total_delegated: u64, + + /// The validator's delegation commission rate as a percentage between 0-100. + pub commission: u8, +} + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq)] +pub struct TipDistributionMeta { + #[serde(with = "pubkey_string_conversion")] + pub merkle_root_upload_authority: Pubkey, + + #[serde(with = "pubkey_string_conversion")] + pub tip_distribution_pubkey: Pubkey, + + /// The validator's total tips in the [TipDistributionAccount]. + pub total_tips: u64, + + /// The validator's cut of tips from [TipDistributionAccount], calculated from the on-chain + /// commission fee bps. + pub validator_fee_bps: u16, +} + +impl TipDistributionMeta { + fn from_tda_wrapper( + tda_wrapper: TipDistributionAccountWrapper, + // The amount that will be left remaining in the tda to maintain rent exemption status. + rent_exempt_amount: u64, + ) -> Result { + Ok(TipDistributionMeta { + tip_distribution_pubkey: tda_wrapper.tip_distribution_pubkey, + total_tips: tda_wrapper + .account_data + .lamports() + .checked_sub(rent_exempt_amount) + .ok_or(CheckedMathError)?, + validator_fee_bps: tda_wrapper + .tip_distribution_account + .validator_commission_bps, + merkle_root_upload_authority: tda_wrapper + .tip_distribution_account + .merkle_root_upload_authority, + }) + } +} + +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq)] +pub struct Delegation { + #[serde(with = "pubkey_string_conversion")] + pub stake_account_pubkey: Pubkey, + + #[serde(with = "pubkey_string_conversion")] + pub staker_pubkey: Pubkey, + + #[serde(with = "pubkey_string_conversion")] + pub withdrawer_pubkey: Pubkey, + + /// Lamports delegated by the stake account + pub lamports_delegated: u64, +} + +/// Convenience wrapper around [TipDistributionAccount] +pub struct TipDistributionAccountWrapper { + pub tip_distribution_account: TipDistributionAccount, + pub account_data: AccountSharedData, + pub tip_distribution_pubkey: Pubkey, +} + +// TODO: move to program's sdk +pub fn derive_tip_distribution_account_address( + tip_distribution_program_id: &Pubkey, + vote_pubkey: &Pubkey, + epoch: Epoch, +) -> (Pubkey, u8) { + Pubkey::find_program_address( + &[ + TipDistributionAccount::SEED, + vote_pubkey.to_bytes().as_ref(), + epoch.to_le_bytes().as_ref(), + ], + tip_distribution_program_id, + ) +} + +/// Calculate validator fee denominated in lamports +pub fn calc_validator_fee(total_tips: u64, validator_commission_bps: u16) -> u64 { + let validator_commission_rate = + math::fee_tenth_of_bps(((validator_commission_bps as u64).checked_mul(10).unwrap()) as u64); + let validator_fee: math::U64F64 = validator_commission_rate.mul_u64(total_tips); + + validator_fee + .floor() + .checked_add((validator_fee.frac_part() != 0) as u64) + .unwrap() +} + +pub async fn send_transactions_with_retry( + rpc_client: &RpcClient, + transactions: &[Transaction], + max_send_duration: Duration, +) { + let mut transactions_to_send: HashMap = transactions + .iter() + .map(|tx| (tx.signatures[0], tx.clone())) + .collect(); + + let start = Instant::now(); + while !transactions_to_send.is_empty() && start.elapsed() < max_send_duration { + info!("sending {} transactions", transactions_to_send.len()); + + for (signature, tx) in &transactions_to_send { + match rpc_client.send_transaction(tx).await { + Ok(send_tx_sig) => { + info!("send transaction: {:?}", send_tx_sig); + } + Err(e) => { + error!("error sending transaction {:?} error: {:?}", signature, e); + } + } + } + + sleep(Duration::from_secs(10)).await; + + let mut signatures_confirmed: Vec = Vec::new(); + for signature in transactions_to_send.keys() { + match rpc_client.confirm_transaction(signature).await { + Ok(true) => { + info!("confirmed signature: {:?}", signature); + signatures_confirmed.push(*signature); + } + Ok(false) => { + info!("didn't confirmed signature: {:?}", signature); + } + Err(e) => { + error!( + "error confirming signature: {:?}, signature: {:?}", + signature, e + ); + } + } + } + + info!("confirmed #{} signatures", signatures_confirmed.len()); + for sig in signatures_confirmed { + transactions_to_send.remove(&sig); + } + } + + assert!( + transactions_to_send.is_empty(), + "all transactions failed to send" + ); +} + +mod math { + /// copy-pasta from [here](https://github.com/project-serum/serum-dex/blob/e00bb9e6dac0a1fff295acb034722be9afc1eba3/dex/src/fees.rs#L43) + #[repr(transparent)] + #[derive(Copy, Clone)] + pub(crate) struct U64F64(u128); + + #[allow(dead_code)] + impl U64F64 { + const ONE: Self = U64F64(1 << 64); + + pub(crate) fn add(self, other: U64F64) -> U64F64 { + U64F64(self.0.checked_add(other.0).unwrap()) + } + + pub(crate) fn div(self, other: U64F64) -> u128 { + self.0.checked_div(other.0).unwrap() + } + + pub(crate) fn mul_u64(self, other: u64) -> U64F64 { + U64F64(self.0.checked_mul(other as u128).unwrap()) + } + + /// right shift 64 + pub(crate) fn floor(self) -> u64 { + (self.0.checked_div(2u128.checked_pow(64).unwrap()).unwrap()) as u64 + } + + pub(crate) fn frac_part(self) -> u64 { + self.0 as u64 + } + + /// left shift 64 + pub(crate) fn from_int(n: u64) -> Self { + U64F64( + (n as u128) + .checked_mul(2u128.checked_pow(64).unwrap()) + .unwrap(), + ) + } + } + + pub(crate) fn fee_tenth_of_bps(tenth_of_bps: u64) -> U64F64 { + U64F64( + ((tenth_of_bps as u128) + .checked_mul(2u128.checked_pow(64).unwrap()) + .unwrap()) + .checked_div(100_000) + .unwrap(), + ) + } +} + +mod pubkey_string_conversion { + use { + serde::{self, Deserialize, Deserializer, Serializer}, + solana_sdk::pubkey::Pubkey, + std::str::FromStr, + }; + + pub(crate) fn serialize(pubkey: &Pubkey, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&pubkey.to_string()) + } + + pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Pubkey::from_str(&s).map_err(serde::de::Error::custom) + } +} + +pub(crate) fn read_json_from_file(path: &PathBuf) -> serde_json::Result +where + T: DeserializeOwned, +{ + let file = File::open(path).unwrap(); + let reader = BufReader::new(file); + serde_json::from_reader(reader) +} + +#[cfg(test)] +mod tests { + use {super::*, solana_sdk::bs58, tip_distribution::merkle_proof}; + + #[test] + fn test_merkle_tree_verify() { + // Create the merkle tree and proofs + let acct_0 = bs58::encode(Pubkey::new_unique().as_ref()).into_string(); + let acct_1 = bs58::encode(Pubkey::new_unique().as_ref()).into_string(); + + let tree_nodes = vec![ + TreeNode { + claimant: acct_0.parse().unwrap(), + staker_pubkey: Pubkey::default(), + withdrawer_pubkey: Pubkey::default(), + amount: 151_507, + proof: None, + }, + TreeNode { + claimant: acct_1.parse().unwrap(), + staker_pubkey: Pubkey::default(), + withdrawer_pubkey: Pubkey::default(), + amount: 176_624, + proof: None, + }, + ]; + + // First the nodes are hashed and merkle tree constructed + let hashed_nodes: Vec<[u8; 32]> = tree_nodes.iter().map(|n| n.hash().to_bytes()).collect(); + let mk = MerkleTree::new(&hashed_nodes[..], true); + let root = mk.get_root().expect("to have valid root").to_bytes(); + + // verify first node + let node = solana_program::hash::hashv(&[&[0u8], &hashed_nodes[0]]); + let proof = get_proof(&mk, 0); + assert!(merkle_proof::verify(proof, root, node.to_bytes())); + + // verify second node + let node = solana_program::hash::hashv(&[&[0u8], &hashed_nodes[1]]); + let proof = get_proof(&mk, 1); + assert!(merkle_proof::verify(proof, root, node.to_bytes())); + } + + #[test] + fn test_new_from_stake_meta_collection_happy_path() { + let merkle_root_upload_authority = Pubkey::new_unique(); + + let (tda_0, tda_1) = (Pubkey::new_unique(), Pubkey::new_unique()); + + let stake_account_0 = Pubkey::new_unique(); + let stake_account_1 = Pubkey::new_unique(); + let stake_account_2 = Pubkey::new_unique(); + let stake_account_3 = Pubkey::new_unique(); + + let staker_account_0 = Pubkey::new_unique(); + let staker_account_1 = Pubkey::new_unique(); + let staker_account_2 = Pubkey::new_unique(); + let staker_account_3 = Pubkey::new_unique(); + + let validator_vote_account_0 = Pubkey::new_unique(); + let validator_vote_account_1 = Pubkey::new_unique(); + + println!("test stake_account {}", stake_account_0); + println!("test stake_account {}", stake_account_1); + println!("test stake_account {}", stake_account_2); + println!("test stake_account {}", stake_account_3); + + let stake_meta_collection = StakeMetaCollection { + stake_metas: vec![ + StakeMeta { + validator_vote_account: validator_vote_account_0, + maybe_tip_distribution_meta: Some(TipDistributionMeta { + merkle_root_upload_authority, + tip_distribution_pubkey: tda_0, + total_tips: 1_900_122_111_000, + validator_fee_bps: 100, + }), + delegations: vec![ + Delegation { + stake_account_pubkey: stake_account_0, + staker_pubkey: staker_account_0, + withdrawer_pubkey: staker_account_0, + lamports_delegated: 123_999_123_555, + }, + Delegation { + stake_account_pubkey: stake_account_1, + staker_pubkey: staker_account_1, + withdrawer_pubkey: staker_account_1, + lamports_delegated: 144_555_444_556, + }, + ], + total_delegated: 1_555_123_000_333_454_000, + commission: 100, + }, + StakeMeta { + validator_vote_account: validator_vote_account_1, + maybe_tip_distribution_meta: Some(TipDistributionMeta { + merkle_root_upload_authority, + tip_distribution_pubkey: tda_1, + total_tips: 1_900_122_111_333, + validator_fee_bps: 200, + }), + delegations: vec![ + Delegation { + stake_account_pubkey: stake_account_2, + staker_pubkey: staker_account_2, + withdrawer_pubkey: staker_account_2, + lamports_delegated: 224_555_444, + }, + Delegation { + stake_account_pubkey: stake_account_3, + staker_pubkey: staker_account_3, + withdrawer_pubkey: staker_account_3, + lamports_delegated: 700_888_944_555, + }, + ], + total_delegated: 2_565_318_909_444_123, + commission: 10, + }, + ], + tip_distribution_program_id: Pubkey::new_unique(), + bank_hash: solana_sdk::hash::Hash::new_unique().to_string(), + epoch: 100, + slot: 2_000_000, + }; + + let merkle_tree_collection = GeneratedMerkleTreeCollection::new_from_stake_meta_collection( + stake_meta_collection.clone(), + ) + .unwrap(); + + assert_eq!(stake_meta_collection.epoch, merkle_tree_collection.epoch); + assert_eq!( + stake_meta_collection.bank_hash, + merkle_tree_collection.bank_hash + ); + assert_eq!(stake_meta_collection.slot, merkle_tree_collection.slot); + assert_eq!( + stake_meta_collection.stake_metas.len(), + merkle_tree_collection.generated_merkle_trees.len() + ); + + let tree_nodes = vec![ + TreeNode { + claimant: validator_vote_account_0, + staker_pubkey: Pubkey::default(), + withdrawer_pubkey: Pubkey::default(), + amount: 19_001_221_110, + proof: None, + }, + TreeNode { + claimant: stake_account_0, + staker_pubkey: Pubkey::default(), + withdrawer_pubkey: Pubkey::default(), + amount: 149_992, + proof: None, + }, + TreeNode { + claimant: stake_account_1, + staker_pubkey: Pubkey::default(), + withdrawer_pubkey: Pubkey::default(), + amount: 174_858, + proof: None, + }, + ]; + let hashed_nodes: Vec<[u8; 32]> = tree_nodes.iter().map(|n| n.hash().to_bytes()).collect(); + let merkle_tree = MerkleTree::new(&hashed_nodes[..], true); + let gmt_0 = GeneratedMerkleTree { + tip_distribution_account: tda_0, + merkle_root_upload_authority, + merkle_root: *merkle_tree.get_root().unwrap(), + tree_nodes, + max_total_claim: stake_meta_collection.stake_metas[0] + .clone() + .maybe_tip_distribution_meta + .unwrap() + .total_tips, + max_num_nodes: 3, + }; + + let tree_nodes = vec![ + TreeNode { + claimant: validator_vote_account_1, + staker_pubkey: Pubkey::default(), + withdrawer_pubkey: Pubkey::default(), + amount: 38_002_442_227, + proof: None, + }, + TreeNode { + claimant: stake_account_2, + staker_pubkey: Pubkey::default(), + withdrawer_pubkey: Pubkey::default(), + amount: 163_000, + proof: None, + }, + TreeNode { + claimant: stake_account_3, + staker_pubkey: Pubkey::default(), + withdrawer_pubkey: Pubkey::default(), + amount: 508_762_900, + proof: None, + }, + ]; + let hashed_nodes: Vec<[u8; 32]> = tree_nodes.iter().map(|n| n.hash().to_bytes()).collect(); + let merkle_tree = MerkleTree::new(&hashed_nodes[..], true); + let gmt_1 = GeneratedMerkleTree { + tip_distribution_account: tda_1, + merkle_root_upload_authority, + merkle_root: *merkle_tree.get_root().unwrap(), + tree_nodes, + max_total_claim: stake_meta_collection.stake_metas[1] + .clone() + .maybe_tip_distribution_meta + .unwrap() + .total_tips, + max_num_nodes: 3, + }; + + let expected_generated_merkle_trees = vec![gmt_0, gmt_1]; + let actual_generated_merkle_trees = merkle_tree_collection.generated_merkle_trees; + + expected_generated_merkle_trees + .iter() + .for_each(|expected_gmt| { + let actual_gmt = actual_generated_merkle_trees + .iter() + .find(|gmt| { + gmt.tip_distribution_account == expected_gmt.tip_distribution_account + }) + .unwrap(); + + assert_eq!(expected_gmt.max_num_nodes, actual_gmt.max_num_nodes); + assert_eq!(expected_gmt.max_total_claim, actual_gmt.max_total_claim); + assert_eq!( + expected_gmt.tip_distribution_account, + actual_gmt.tip_distribution_account + ); + assert_eq!(expected_gmt.tree_nodes.len(), actual_gmt.tree_nodes.len()); + expected_gmt + .tree_nodes + .iter() + .for_each(|expected_tree_node| { + let actual_tree_node = actual_gmt + .tree_nodes + .iter() + .find(|tree_node| tree_node.claimant == expected_tree_node.claimant) + .unwrap(); + assert_eq!(expected_tree_node.amount, actual_tree_node.amount); + }); + assert_eq!(expected_gmt.merkle_root, actual_gmt.merkle_root); + }); + } +} diff --git a/tip-distributor/src/merkle_root_generator_workflow.rs b/tip-distributor/src/merkle_root_generator_workflow.rs new file mode 100644 index 0000000000..0da8c1fdb0 --- /dev/null +++ b/tip-distributor/src/merkle_root_generator_workflow.rs @@ -0,0 +1,49 @@ +use { + crate::{read_json_from_file, GeneratedMerkleTreeCollection, StakeMetaCollection}, + log::*, + std::{ + fmt::Debug, + fs::File, + io::{BufWriter, Write}, + path::PathBuf, + }, + thiserror::Error, +}; + +#[derive(Error, Debug)] +pub enum MerkleRootGeneratorError { + #[error(transparent)] + IoError(#[from] std::io::Error), + + #[error(transparent)] + RpcError(#[from] Box), + + #[error(transparent)] + SerdeJsonError(#[from] serde_json::Error), +} + +pub fn generate_merkle_root( + stake_meta_coll_path: &PathBuf, + out_path: &PathBuf, +) -> Result<(), MerkleRootGeneratorError> { + let stake_meta_coll: StakeMetaCollection = read_json_from_file(stake_meta_coll_path)?; + + let merkle_tree_coll = + GeneratedMerkleTreeCollection::new_from_stake_meta_collection(stake_meta_coll)?; + + write_to_json_file(&merkle_tree_coll, out_path)?; + Ok(()) +} + +fn write_to_json_file( + merkle_tree_coll: &GeneratedMerkleTreeCollection, + file_path: &PathBuf, +) -> Result<(), MerkleRootGeneratorError> { + let file = File::create(file_path)?; + let mut writer = BufWriter::new(file); + let json = serde_json::to_string_pretty(&merkle_tree_coll).unwrap(); + let _ = writer.write(json.as_bytes())?; + writer.flush()?; + + Ok(()) +} diff --git a/tip-distributor/src/merkle_root_upload_workflow.rs b/tip-distributor/src/merkle_root_upload_workflow.rs new file mode 100644 index 0000000000..4925087fae --- /dev/null +++ b/tip-distributor/src/merkle_root_upload_workflow.rs @@ -0,0 +1,126 @@ +use { + crate::{ + read_json_from_file, send_transactions_with_retry, GeneratedMerkleTree, + GeneratedMerkleTreeCollection, + }, + anchor_lang::AccountDeserialize, + log::{error, info}, + solana_client::nonblocking::rpc_client::RpcClient, + solana_sdk::{ + commitment_config::CommitmentConfig, + pubkey::Pubkey, + signature::{read_keypair_file, Signer}, + transaction::Transaction, + }, + std::{path::PathBuf, time::Duration}, + thiserror::Error, + tip_distribution::{ + sdk::instruction::{upload_merkle_root_ix, UploadMerkleRootAccounts, UploadMerkleRootArgs}, + state::{Config, TipDistributionAccount}, + }, + tokio::runtime::Builder, +}; + +#[derive(Error, Debug)] +pub enum MerkleRootUploadError { + #[error(transparent)] + IoError(#[from] std::io::Error), + + #[error(transparent)] + JsonError(#[from] serde_json::Error), +} + +pub fn upload_merkle_root( + merkle_root_path: &PathBuf, + keypair_path: &PathBuf, + rpc_url: &str, + tip_distribution_program_id: &Pubkey, +) -> Result<(), MerkleRootUploadError> { + // max amount of time before blockhash expires + const MAX_RETRY_DURATION: Duration = Duration::from_secs(60); + + let merkle_tree: GeneratedMerkleTreeCollection = + read_json_from_file(merkle_root_path).expect("read GeneratedMerkleTreeCollection"); + let keypair = read_keypair_file(keypair_path).expect("read keypair file"); + + let tip_distribution_config = + Pubkey::find_program_address(&[Config::SEED], tip_distribution_program_id).0; + + let runtime = Builder::new_multi_thread() + .worker_threads(16) + .enable_all() + .build() + .expect("build runtime"); + + runtime.block_on(async move { + let rpc_client = + RpcClient::new_with_commitment(rpc_url.to_string(), CommitmentConfig::confirmed()); + let recent_blockhash = rpc_client + .get_latest_blockhash() + .await + .expect("get blockhash"); + + let trees: Vec = merkle_tree + .generated_merkle_trees + .into_iter() + .filter(|tree| tree.merkle_root_upload_authority == keypair.pubkey()) + .collect(); + + info!("num trees to upload: {:?}", trees.len()); + + let mut trees_needing_update: Vec = vec![]; + for tree in trees { + let account = rpc_client + .get_account(&tree.tip_distribution_account) + .await + .expect("fetch expect"); + + let mut data = account.data.as_slice(); + let fetched_tip_distribution_account = + TipDistributionAccount::try_deserialize(&mut data) + .expect("failed to deserialize tip_distribution_account state"); + + let needs_upload = match fetched_tip_distribution_account.merkle_root { + Some(merkle_root) => { + merkle_root.total_funds_claimed == 0 + && merkle_root.root != tree.merkle_root.to_bytes() + } + None => true, + }; + + if needs_upload { + trees_needing_update.push(tree); + } + } + + info!("num trees need uploading: {:?}", trees_needing_update.len()); + + let transactions: Vec = trees_needing_update + .iter() + .map(|tree| { + let ix = upload_merkle_root_ix( + *tip_distribution_program_id, + UploadMerkleRootArgs { + root: tree.merkle_root.to_bytes(), + max_total_claim: tree.max_total_claim, + max_num_nodes: tree.max_num_nodes, + }, + UploadMerkleRootAccounts { + config: tip_distribution_config, + merkle_root_upload_authority: keypair.pubkey(), + tip_distribution_account: tree.tip_distribution_account, + }, + ); + Transaction::new_signed_with_payer( + &[ix], + Some(&keypair.pubkey()), + &[&keypair], + recent_blockhash, + ) + }) + .collect(); + send_transactions_with_retry(&rpc_client, &transactions, MAX_RETRY_DURATION).await; + }); + + Ok(()) +} diff --git a/tip-distributor/src/stake_meta_generator_workflow.rs b/tip-distributor/src/stake_meta_generator_workflow.rs new file mode 100644 index 0000000000..fde03fd47c --- /dev/null +++ b/tip-distributor/src/stake_meta_generator_workflow.rs @@ -0,0 +1,836 @@ +use { + crate::{ + derive_tip_distribution_account_address, derive_tip_payment_pubkeys, Config, StakeMeta, + StakeMetaCollection, TipDistributionAccount, TipDistributionAccountWrapper, + TipDistributionMeta, + }, + anchor_lang::AccountDeserialize, + itertools::Itertools, + log::*, + solana_client::client_error::ClientError, + solana_ledger::{ + bank_forks_utils, + blockstore::BlockstoreError, + blockstore_processor::{BlockstoreProcessorError, ProcessOptions}, + }, + solana_program::{ + borsh::try_from_slice_unchecked, + stake::state::{Delegation, StakeState}, + }, + solana_runtime::{ + bank::Bank, + hardened_unpack::{open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE}, + snapshot_config::SnapshotConfig, + stakes::StakesCache, + vote_account::VoteAccount, + }, + solana_sdk::{ + account::{ReadableAccount, WritableAccount}, + clock::Slot, + pubkey::Pubkey, + }, + std::{ + collections::HashMap, + fmt::{Debug, Display, Formatter}, + fs::File, + io::{BufWriter, Write}, + path::{Path, PathBuf}, + sync::Arc, + }, + thiserror::Error, +}; + +#[derive(Error, Debug)] +pub enum StakeMetaGeneratorError { + #[error(transparent)] + AnchorError(#[from] anchor_lang::error::Error), + + #[error(transparent)] + BlockstoreError(#[from] BlockstoreError), + + #[error(transparent)] + BlockstoreProcessorError(#[from] BlockstoreProcessorError), + + #[error(transparent)] + IoError(#[from] std::io::Error), + + CheckedMathError, + + #[error(transparent)] + RpcError(#[from] ClientError), + + #[error(transparent)] + SerdeJsonError(#[from] serde_json::Error), + + SnapshotSlotNotFound, +} + +impl Display for StakeMetaGeneratorError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + Debug::fmt(&self, f) + } +} + +/// Runs the entire workflow of creating a bank from a snapshot to writing stake meta-data +/// to a JSON file. +pub fn generate_stake_meta( + ledger_path: &Path, + snapshot_slot: &Slot, + tip_distribution_program_id: &Pubkey, + out_path: &str, + tip_payment_program_id: &Pubkey, +) -> Result<(), StakeMetaGeneratorError> { + info!("Creating bank from ledger path..."); + let bank = create_bank_from_snapshot(ledger_path, snapshot_slot)?; + + info!("Generating stake_meta_collection object..."); + let stake_meta_coll = + generate_stake_meta_collection(&bank, tip_distribution_program_id, tip_payment_program_id)?; + + info!("Writing stake_meta_collection to JSON {}...", out_path); + write_to_json_file(&stake_meta_coll, out_path)?; + + Ok(()) +} + +fn create_bank_from_snapshot( + ledger_path: &Path, + snapshot_slot: &Slot, +) -> Result, StakeMetaGeneratorError> { + let genesis_config = open_genesis_config(ledger_path, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE); + let snapshot_config = SnapshotConfig { + full_snapshot_archive_interval_slots: Slot::MAX, + incremental_snapshot_archive_interval_slots: Slot::MAX, + snapshot_archives_dir: PathBuf::from(ledger_path), + bank_snapshots_dir: PathBuf::from(ledger_path), + ..SnapshotConfig::default() + }; + let (bank_forks, _snapshot_hashes) = bank_forks_utils::bank_forks_from_snapshot( + &genesis_config, + vec![PathBuf::from(ledger_path).join(Path::new("stake-meta.accounts"))], + None, + &snapshot_config, + &ProcessOptions::default(), + None, + ); + + let working_bank = bank_forks.working_bank(); + assert_eq!( + working_bank.slot(), + *snapshot_slot, + "expected working bank slot {}, found {}", + snapshot_slot, + working_bank.slot() + ); + + Ok(working_bank) +} + +fn write_to_json_file( + stake_meta_coll: &StakeMetaCollection, + out_path: &str, +) -> Result<(), StakeMetaGeneratorError> { + let file = File::create(out_path)?; + let mut writer = BufWriter::new(file); + let json = serde_json::to_string_pretty(&stake_meta_coll).unwrap(); + let _ = writer.write(json.as_bytes())?; + writer.flush()?; + + Ok(()) +} + +/// Creates a collection of [StakeMeta]'s from the given bank. +pub fn generate_stake_meta_collection( + bank: &Arc, + tip_distribution_program_id: &Pubkey, + tip_payment_program_id: &Pubkey, +) -> Result { + assert!(bank.is_frozen()); + + let epoch_vote_accounts = bank.epoch_vote_accounts(bank.epoch()).expect(&*format!( + "No epoch_vote_accounts found for slot {} at epoch {}", + bank.slot(), + bank.epoch() + )); + + let l_stakes = bank.stakes_cache.stakes(); + let delegations = l_stakes.stake_delegations(); + + let voter_pubkey_to_delegations = group_delegations_by_voter_pubkey(delegations, bank); + + // the last leader in an epoch may not crank the tip program before the epoch is over, which + // would result in MEV rewards for epoch N not being cranked until epoch N + 1. This means that + // the account balance in the snapshot could be incorrect. + // We assume that the rewards sitting in the tip program PDAs are cranked out by the time all of + // the rewards are claimed. + let tip_accounts = derive_tip_payment_pubkeys(tip_payment_program_id); + let account = bank.get_account(&tip_accounts.config_pda); + let maybe_tip_receiver: Option = account + .and_then(|account| Config::try_deserialize(&mut account.data()).ok()) + .map(|config| config.tip_receiver); + + let excess_tip_balances: u64 = tip_accounts + .tip_pdas + .iter() + .map(|pubkey| { + bank.get_account(pubkey) + .map(|acc| { + acc.lamports() + .checked_sub(bank.get_minimum_balance_for_rent_exemption(acc.data().len())) + .expect("tip balance underflow") + }) + .unwrap_or_default() + }) + .sum(); + + let vote_pk_and_maybe_tdas: Vec<( + (Pubkey, &VoteAccount), + Option, + )> = epoch_vote_accounts + .iter() + .map(|(vote_pubkey, (_total_stake, vote_account))| { + let tip_distribution_pubkey = derive_tip_distribution_account_address( + tip_distribution_program_id, + vote_pubkey, + bank.epoch(), + ) + .0; + let tda = bank + .get_account(&tip_distribution_pubkey) + .map(|mut account_data| { + let tip_distribution_account = + TipDistributionAccount::try_deserialize(&mut account_data.data()) + .expect("deserialized TipDistributionAccount"); + // this snapshot might have tips that weren't claimed by the time the epoch is over + // assume that it will eventually be cranked and credit the excess to this account + if maybe_tip_receiver.is_some() + && tip_distribution_pubkey == maybe_tip_receiver.unwrap() + { + account_data.set_lamports( + account_data + .lamports() + .checked_add(excess_tip_balances) + .expect("tip overflow"), + ); + } + TipDistributionAccountWrapper { + tip_distribution_account, + account_data, + tip_distribution_pubkey, + } + }); + Ok(((*vote_pubkey, vote_account), tda)) + }) + .collect::>()?; + + let mut stake_metas = vec![]; + for ((vote_pubkey, vote_account), maybe_tda) in vote_pk_and_maybe_tdas { + if let Some(delegations) = voter_pubkey_to_delegations.get(&vote_pubkey).cloned() { + let total_delegated = delegations.iter().fold(0u64, |sum, delegation| { + sum.checked_add(delegation.lamports_delegated).unwrap() + }); + + let maybe_tip_distribution_meta = if let Some(tda) = maybe_tda { + let rent_exempt_amount = + bank.get_minimum_balance_for_rent_exemption(tda.account_data.data().len()); + + Some(TipDistributionMeta::from_tda_wrapper( + tda, + rent_exempt_amount, + )?) + } else { + None + }; + + stake_metas.push(StakeMeta { + maybe_tip_distribution_meta, + validator_vote_account: vote_pubkey, + delegations: delegations.clone(), + total_delegated, + commission: vote_account.vote_state().as_ref().unwrap().commission, + }); + } else { + warn!( + "voter_pubkey not found in voter_pubkey_to_delegations map [validator_vote_pubkey={}]", + vote_pubkey + ); + } + } + + Ok(StakeMetaCollection { + stake_metas, + tip_distribution_program_id: *tip_distribution_program_id, + bank_hash: bank.hash().to_string(), + epoch: bank.epoch(), + slot: bank.slot(), + }) +} + +/// Given an [EpochStakes] object, return delegations grouped by voter_pubkey (validator delegated to). +fn group_delegations_by_voter_pubkey( + delegations: &im::HashMap, + bank: &Bank, +) -> HashMap> { + delegations + .into_iter() + .filter(|(_stake_pubkey, delegation)| delegation.stake(bank.epoch(), None) > 0) + .into_group_map_by(|(_stake_pubkey, delegation)| delegation.voter_pubkey) + .into_iter() + .map(|(voter_pubkey, group)| { + ( + voter_pubkey, + group + .into_iter() + .map(|(stake_pubkey, delegation)| { + let account_data = bank.get_account(stake_pubkey).expect("account exists"); + assert!( + StakesCache::is_stake(&account_data), + "{} is not StakeState", + stake_pubkey + ); + let stake_state = + try_from_slice_unchecked::(account_data.data()) + .expect("StakeState deserializes"); + crate::Delegation { + stake_account_pubkey: *stake_pubkey, + staker_pubkey: stake_state + .authorized() + .map(|a| a.staker) + .unwrap_or_default(), + withdrawer_pubkey: stake_state + .authorized() + .map(|a| a.withdrawer) + .unwrap_or_default(), + lamports_delegated: delegation.stake, + } + }) + .collect::>(), + ) + }) + .collect() +} + +#[cfg(test)] +mod tests { + use { + super::*, + crate::derive_tip_distribution_account_address, + anchor_lang::AccountSerialize, + solana_runtime::genesis_utils::{ + create_genesis_config_with_vote_accounts, GenesisConfigInfo, ValidatorVoteKeypairs, + }, + solana_sdk::{ + self, + account::{from_account, AccountSharedData}, + message::Message, + signature::{Keypair, Signer}, + stake::{ + self, + state::{Authorized, Lockup}, + }, + stake_history::StakeHistory, + sysvar, + transaction::Transaction, + }, + solana_stake_program::stake_state, + tip_distribution::state::TipDistributionAccount, + }; + + #[test] + fn test_generate_stake_meta_collection_happy_path() { + /* 1. Create a Bank seeded with some validator stake accounts */ + let validator_keypairs_0 = ValidatorVoteKeypairs::new_rand(); + let validator_keypairs_1 = ValidatorVoteKeypairs::new_rand(); + let validator_keypairs_2 = ValidatorVoteKeypairs::new_rand(); + let validator_keypairs = vec![ + &validator_keypairs_0, + &validator_keypairs_1, + &validator_keypairs_2, + ]; + const INITIAL_VALIDATOR_STAKES: u64 = 10_000; + let GenesisConfigInfo { genesis_config, .. } = create_genesis_config_with_vote_accounts( + 1_000_000_000, + &validator_keypairs, + vec![INITIAL_VALIDATOR_STAKES; 3], + ); + + let bank = Bank::new_for_tests(&genesis_config); + + /* 2. Seed the Bank with [TipDistributionAccount]'s */ + let merkle_root_upload_authority = Pubkey::new_unique(); + let tip_distribution_program_id = Pubkey::new_unique(); + + let delegator_0 = Keypair::new(); + let delegator_1 = Keypair::new(); + let delegator_2 = Keypair::new(); + let delegator_3 = Keypair::new(); + let delegator_4 = Keypair::new(); + + let delegator_0_pk = delegator_0.pubkey(); + let delegator_1_pk = delegator_1.pubkey(); + let delegator_2_pk = delegator_2.pubkey(); + let delegator_3_pk = delegator_3.pubkey(); + let delegator_4_pk = delegator_4.pubkey(); + + let d_0_data = AccountSharedData::new( + 300_000_000_000_000 * 10, + 0, + &solana_sdk::system_program::id(), + ); + let d_1_data = AccountSharedData::new( + 100_000_203_000_000 * 10, + 0, + &solana_sdk::system_program::id(), + ); + let d_2_data = AccountSharedData::new( + 100_000_235_899_000 * 10, + 0, + &solana_sdk::system_program::id(), + ); + let d_3_data = AccountSharedData::new( + 200_000_000_000_000 * 10, + 0, + &solana_sdk::system_program::id(), + ); + let d_4_data = AccountSharedData::new( + 100_000_000_777_000 * 10, + 0, + &solana_sdk::system_program::id(), + ); + + bank.store_account(&delegator_0_pk, &d_0_data); + bank.store_account(&delegator_1_pk, &d_1_data); + bank.store_account(&delegator_2_pk, &d_2_data); + bank.store_account(&delegator_3_pk, &d_3_data); + bank.store_account(&delegator_4_pk, &d_4_data); + + /* 3. Delegate some stake to the initial set of validators */ + let mut validator_0_delegations = vec![crate::Delegation { + stake_account_pubkey: validator_keypairs_0.stake_keypair.pubkey(), + staker_pubkey: validator_keypairs_0.stake_keypair.pubkey(), + withdrawer_pubkey: validator_keypairs_0.stake_keypair.pubkey(), + lamports_delegated: INITIAL_VALIDATOR_STAKES, + }]; + let stake_account = delegate_stake_helper( + &bank, + &delegator_0, + &validator_keypairs_0.vote_keypair.pubkey(), + 30_000_000_000, + ); + validator_0_delegations.push(crate::Delegation { + stake_account_pubkey: stake_account, + staker_pubkey: delegator_0.pubkey(), + withdrawer_pubkey: delegator_0.pubkey(), + lamports_delegated: 30_000_000_000, + }); + let stake_account = delegate_stake_helper( + &bank, + &delegator_1, + &validator_keypairs_0.vote_keypair.pubkey(), + 3_000_000_000, + ); + validator_0_delegations.push(crate::Delegation { + stake_account_pubkey: stake_account, + staker_pubkey: delegator_1.pubkey(), + withdrawer_pubkey: delegator_1.pubkey(), + lamports_delegated: 3_000_000_000, + }); + let stake_account = delegate_stake_helper( + &bank, + &delegator_2, + &validator_keypairs_0.vote_keypair.pubkey(), + 33_000_000_000, + ); + validator_0_delegations.push(crate::Delegation { + stake_account_pubkey: stake_account, + staker_pubkey: delegator_2.pubkey(), + withdrawer_pubkey: delegator_2.pubkey(), + lamports_delegated: 33_000_000_000, + }); + + let mut validator_1_delegations = vec![crate::Delegation { + stake_account_pubkey: validator_keypairs_1.stake_keypair.pubkey(), + staker_pubkey: validator_keypairs_1.stake_keypair.pubkey(), + withdrawer_pubkey: validator_keypairs_1.stake_keypair.pubkey(), + lamports_delegated: INITIAL_VALIDATOR_STAKES, + }]; + let stake_account = delegate_stake_helper( + &bank, + &delegator_3, + &validator_keypairs_1.vote_keypair.pubkey(), + 4_222_364_000, + ); + validator_1_delegations.push(crate::Delegation { + stake_account_pubkey: stake_account, + staker_pubkey: delegator_3.pubkey(), + withdrawer_pubkey: delegator_3.pubkey(), + lamports_delegated: 4_222_364_000, + }); + let stake_account = delegate_stake_helper( + &bank, + &delegator_4, + &validator_keypairs_1.vote_keypair.pubkey(), + 6_000_000_527, + ); + validator_1_delegations.push(crate::Delegation { + stake_account_pubkey: stake_account, + staker_pubkey: delegator_4.pubkey(), + withdrawer_pubkey: delegator_4.pubkey(), + lamports_delegated: 6_000_000_527, + }); + + let mut validator_2_delegations = vec![crate::Delegation { + stake_account_pubkey: validator_keypairs_2.stake_keypair.pubkey(), + staker_pubkey: validator_keypairs_2.stake_keypair.pubkey(), + withdrawer_pubkey: validator_keypairs_2.stake_keypair.pubkey(), + lamports_delegated: INITIAL_VALIDATOR_STAKES, + }]; + let stake_account = delegate_stake_helper( + &bank, + &delegator_0, + &validator_keypairs_2.vote_keypair.pubkey(), + 1_300_123_156, + ); + validator_2_delegations.push(crate::Delegation { + stake_account_pubkey: stake_account, + staker_pubkey: delegator_0.pubkey(), + withdrawer_pubkey: delegator_0.pubkey(), + lamports_delegated: 1_300_123_156, + }); + let stake_account = delegate_stake_helper( + &bank, + &delegator_4, + &validator_keypairs_2.vote_keypair.pubkey(), + 1_610_565_420, + ); + validator_2_delegations.push(crate::Delegation { + stake_account_pubkey: stake_account, + staker_pubkey: delegator_4.pubkey(), + withdrawer_pubkey: delegator_4.pubkey(), + lamports_delegated: 1_610_565_420, + }); + + /* 4. Run assertions */ + fn warmed_up(bank: &Bank, stake_pubkeys: &[Pubkey]) -> bool { + for stake_pubkey in stake_pubkeys { + let stake = + stake_state::stake_from(&bank.get_account(stake_pubkey).unwrap()).unwrap(); + + if stake.delegation.stake + != stake.stake( + bank.epoch(), + Some( + &from_account::( + &bank.get_account(&sysvar::stake_history::id()).unwrap(), + ) + .unwrap(), + ), + ) + { + return false; + } + } + + true + } + fn next_epoch(bank: &Arc) -> Arc { + bank.squash(); + + Arc::new(Bank::new_from_parent( + bank, + &Pubkey::default(), + bank.get_slots_in_epoch(bank.epoch()) + bank.slot(), + )) + } + + let mut bank = Arc::new(bank); + let mut stake_pubkeys = validator_0_delegations + .iter() + .map(|v| v.stake_account_pubkey) + .collect::>(); + stake_pubkeys.extend( + validator_1_delegations + .iter() + .map(|v| v.stake_account_pubkey), + ); + stake_pubkeys.extend( + validator_2_delegations + .iter() + .map(|v| v.stake_account_pubkey), + ); + loop { + if warmed_up(&bank, &stake_pubkeys[..]) { + break; + } + + // Cycle thru banks until we're fully warmed up + bank = next_epoch(&bank); + } + + let tip_distribution_account_0 = derive_tip_distribution_account_address( + &tip_distribution_program_id, + &validator_keypairs_0.vote_keypair.pubkey(), + bank.epoch(), + ); + let tip_distribution_account_1 = derive_tip_distribution_account_address( + &tip_distribution_program_id, + &validator_keypairs_1.vote_keypair.pubkey(), + bank.epoch(), + ); + let tip_distribution_account_2 = derive_tip_distribution_account_address( + &tip_distribution_program_id, + &validator_keypairs_2.vote_keypair.pubkey(), + bank.epoch(), + ); + + let tda_0 = TipDistributionAccount { + validator_vote_account: validator_keypairs_0.vote_keypair.pubkey(), + merkle_root_upload_authority, + merkle_root: None, + epoch_created_at: bank.epoch(), + validator_commission_bps: 50, + bump: tip_distribution_account_0.1, + }; + let tda_1 = TipDistributionAccount { + validator_vote_account: validator_keypairs_1.vote_keypair.pubkey(), + merkle_root_upload_authority, + merkle_root: None, + epoch_created_at: bank.epoch(), + validator_commission_bps: 500, + bump: tip_distribution_account_1.1, + }; + let tda_2 = TipDistributionAccount { + validator_vote_account: validator_keypairs_2.vote_keypair.pubkey(), + merkle_root_upload_authority, + merkle_root: None, + epoch_created_at: bank.epoch(), + validator_commission_bps: 75, + bump: tip_distribution_account_2.1, + }; + + let tip_distro_0_tips = 1_000_000 * 10; + let tip_distro_1_tips = 69_000_420 * 10; + let tip_distro_2_tips = 789_000_111 * 10; + + let tda_0_fields = (tip_distribution_account_0.0, tda_0.validator_commission_bps); + let data_0 = + tda_to_account_shared_data(&tip_distribution_program_id, tip_distro_0_tips, tda_0); + let tda_1_fields = (tip_distribution_account_1.0, tda_1.validator_commission_bps); + let data_1 = + tda_to_account_shared_data(&tip_distribution_program_id, tip_distro_1_tips, tda_1); + let tda_2_fields = (tip_distribution_account_2.0, tda_2.validator_commission_bps); + let data_2 = + tda_to_account_shared_data(&tip_distribution_program_id, tip_distro_2_tips, tda_2); + + bank.store_account(&tip_distribution_account_0.0, &data_0); + bank.store_account(&tip_distribution_account_1.0, &data_1); + bank.store_account(&tip_distribution_account_2.0, &data_2); + + bank.freeze(); + let stake_meta_collection = generate_stake_meta_collection( + &bank, + &tip_distribution_program_id, + &Pubkey::new_unique(), + ) + .unwrap(); + assert_eq!( + stake_meta_collection.tip_distribution_program_id, + tip_distribution_program_id + ); + assert_eq!(stake_meta_collection.slot, bank.slot()); + assert_eq!(stake_meta_collection.epoch, bank.epoch()); + + let mut expected_stake_metas = HashMap::new(); + expected_stake_metas.insert( + validator_keypairs_0.vote_keypair.pubkey(), + StakeMeta { + validator_vote_account: validator_keypairs_0.vote_keypair.pubkey(), + delegations: validator_0_delegations.clone(), + total_delegated: validator_0_delegations + .iter() + .fold(0u64, |sum, delegation| { + sum.checked_add(delegation.lamports_delegated).unwrap() + }), + maybe_tip_distribution_meta: Some(TipDistributionMeta { + merkle_root_upload_authority, + tip_distribution_pubkey: tda_0_fields.0, + total_tips: tip_distro_0_tips + .checked_sub( + bank.get_minimum_balance_for_rent_exemption( + TipDistributionAccount::SIZE, + ), + ) + .unwrap(), + validator_fee_bps: tda_0_fields.1, + }), + commission: 0, + }, + ); + expected_stake_metas.insert( + validator_keypairs_1.vote_keypair.pubkey(), + StakeMeta { + validator_vote_account: validator_keypairs_1.vote_keypair.pubkey(), + delegations: validator_1_delegations.clone(), + total_delegated: validator_1_delegations + .iter() + .fold(0u64, |sum, delegation| { + sum.checked_add(delegation.lamports_delegated).unwrap() + }), + maybe_tip_distribution_meta: Some(TipDistributionMeta { + merkle_root_upload_authority, + tip_distribution_pubkey: tda_1_fields.0, + total_tips: tip_distro_1_tips + .checked_sub( + bank.get_minimum_balance_for_rent_exemption( + TipDistributionAccount::SIZE, + ), + ) + .unwrap(), + validator_fee_bps: tda_1_fields.1, + }), + commission: 0, + }, + ); + expected_stake_metas.insert( + validator_keypairs_2.vote_keypair.pubkey(), + StakeMeta { + validator_vote_account: validator_keypairs_2.vote_keypair.pubkey(), + delegations: validator_2_delegations.clone(), + total_delegated: validator_2_delegations + .iter() + .fold(0u64, |sum, delegation| { + sum.checked_add(delegation.lamports_delegated).unwrap() + }), + maybe_tip_distribution_meta: Some(TipDistributionMeta { + merkle_root_upload_authority, + tip_distribution_pubkey: tda_2_fields.0, + total_tips: tip_distro_2_tips + .checked_sub( + bank.get_minimum_balance_for_rent_exemption( + TipDistributionAccount::SIZE, + ), + ) + .unwrap(), + validator_fee_bps: tda_2_fields.1, + }), + commission: 0, + }, + ); + + println!( + "validator_0 [vote_account={}, stake_account={}]", + validator_keypairs_0.vote_keypair.pubkey(), + validator_keypairs_0.stake_keypair.pubkey() + ); + println!( + "validator_1 [vote_account={}, stake_account={}]", + validator_keypairs_1.vote_keypair.pubkey(), + validator_keypairs_1.stake_keypair.pubkey() + ); + println!( + "validator_2 [vote_account={}, stake_account={}]", + validator_keypairs_2.vote_keypair.pubkey(), + validator_keypairs_2.stake_keypair.pubkey(), + ); + + assert_eq!( + expected_stake_metas.len(), + stake_meta_collection.stake_metas.len() + ); + + for actual_stake_meta in stake_meta_collection.stake_metas { + let expected_stake_meta = expected_stake_metas + .get(&actual_stake_meta.validator_vote_account) + .unwrap(); + assert_eq!( + expected_stake_meta.maybe_tip_distribution_meta, + actual_stake_meta.maybe_tip_distribution_meta + ); + assert_eq!( + expected_stake_meta.total_delegated, + actual_stake_meta.total_delegated + ); + assert_eq!(expected_stake_meta.commission, actual_stake_meta.commission); + assert_eq!( + expected_stake_meta.validator_vote_account, + actual_stake_meta.validator_vote_account + ); + + assert_eq!( + expected_stake_meta.delegations.len(), + actual_stake_meta.delegations.len() + ); + + for expected_delegation in &expected_stake_meta.delegations { + let actual_delegation = actual_stake_meta + .delegations + .iter() + .find(|d| d.stake_account_pubkey == expected_delegation.stake_account_pubkey) + .unwrap(); + + assert_eq!(expected_delegation, actual_delegation); + } + } + } + + /// Helper function that sends a delegate stake instruction to the bank. + /// Returns the created stake account pubkey. + fn delegate_stake_helper( + bank: &Bank, + from_keypair: &Keypair, + vote_account: &Pubkey, + delegation_amount: u64, + ) -> Pubkey { + if let Some(from_account) = bank.get_account(&from_keypair.pubkey()) { + assert_eq!(from_account.owner(), &solana_sdk::system_program::id()); + } else { + panic!("from_account DNE"); + } + assert!(bank.get_account(vote_account).is_some()); + + let stake_keypair = Keypair::new(); + let instructions = stake::instruction::create_account_and_delegate_stake( + &from_keypair.pubkey(), + &stake_keypair.pubkey(), + vote_account, + &Authorized::auto(&from_keypair.pubkey()), + &Lockup::default(), + delegation_amount, + ); + + let message = Message::new(&instructions[..], Some(&from_keypair.pubkey())); + let transaction = Transaction::new( + &[from_keypair, &stake_keypair], + message, + bank.last_blockhash(), + ); + + bank.process_transaction(&transaction) + .map_err(|e| { + eprintln!("Error delegating stake [error={}]", e); + e + }) + .unwrap(); + + stake_keypair.pubkey() + } + + fn tda_to_account_shared_data( + tip_distribution_program_id: &Pubkey, + lamports: u64, + tda: TipDistributionAccount, + ) -> AccountSharedData { + let mut account_data = AccountSharedData::new( + lamports, + TipDistributionAccount::SIZE, + tip_distribution_program_id, + ); + + let mut data: [u8; TipDistributionAccount::SIZE] = [0u8; TipDistributionAccount::SIZE]; + let mut cursor = std::io::Cursor::new(&mut data[..]); + tda.try_serialize(&mut cursor).unwrap(); + + account_data.set_data(data.to_vec()); + account_data + } +} diff --git a/validator/Cargo.toml b/validator/Cargo.toml index fc355fc6f7..5248464aaa 100644 --- a/validator/Cargo.toml +++ b/validator/Cargo.toml @@ -54,6 +54,7 @@ solana-test-validator = { path = "../test-validator", version = "=1.13.6" } solana-version = { path = "../version", version = "=1.13.6" } solana-vote-program = { path = "../programs/vote", version = "=1.13.6" } symlink = "0.1.0" +tonic = { version = "0.5.2", features = ["tls", "tls-roots", "tls-webpki-roots"] } [target.'cfg(not(target_env = "msvc"))'.dependencies] jemallocator = { package = "tikv-jemallocator", version = "0.4.1", features = ["unprefixed_malloc_on_supported_platforms"] } diff --git a/validator/src/bootstrap.rs b/validator/src/bootstrap.rs index dd12f61cf6..bc873a8027 100644 --- a/validator/src/bootstrap.rs +++ b/validator/src/bootstrap.rs @@ -386,12 +386,13 @@ fn get_highest_local_snapshot_hash( snapshot_archives_dir: impl AsRef, ) -> Option<(Slot, Hash)> { if let Some(full_snapshot_info) = - snapshot_utils::get_highest_full_snapshot_archive_info(&snapshot_archives_dir) + snapshot_utils::get_highest_full_snapshot_archive_info(&snapshot_archives_dir, None) { if let Some(incremental_snapshot_info) = snapshot_utils::get_highest_incremental_snapshot_archive_info( &snapshot_archives_dir, full_snapshot_info.slot(), + None, ) { Some(( diff --git a/validator/src/dashboard.rs b/validator/src/dashboard.rs index ec94e0d5a7..684cc67008 100644 --- a/validator/src/dashboard.rs +++ b/validator/src/dashboard.rs @@ -275,6 +275,7 @@ fn get_validator_stats( Err(err) => { if let client_error::ClientErrorKind::RpcError( rpc_request::RpcError::RpcResponseError { + request_id: _, code: _, message: _, data: diff --git a/validator/src/main.rs b/validator/src/main.rs index 9aca6a830b..ba5e4ffe76 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -26,7 +26,9 @@ use { }, solana_core::{ ledger_cleanup_service::{DEFAULT_MAX_LEDGER_SHREDS, DEFAULT_MIN_MAX_LEDGER_SHREDS}, + proxy::{block_engine_stage::BlockEngineConfig, relayer_stage::RelayerConfig}, system_monitor_service::SystemMonitorService, + tip_manager::{TipDistributionAccountConfig, TipManagerConfig}, tower_storage, tpu::DEFAULT_TPU_COALESCE_MS, validator::{is_snapshot_config_valid, Validator, ValidatorConfig, ValidatorStartProgress}, @@ -89,6 +91,7 @@ use { sync::{Arc, RwLock}, time::{Duration, SystemTime}, }, + tonic::transport::Endpoint, }; #[cfg(not(target_env = "msvc"))] @@ -1725,6 +1728,100 @@ pub fn main() { .help("Allow contacting private ip addresses") .hidden(true), ) + .arg( + Arg::with_name("relayer_address") + .long("relayer-address") + .value_name("relayer_address") + .takes_value(true) + .help("Address of the relayer") + ) + .arg( + Arg::with_name("block_engine_address") + .long("block-engine-address") + .value_name("block_engine_address") + .takes_value(true) + .help("Address of the block engine") + ) + .arg( + Arg::with_name("block_engine_auth_service_address") + .long("block-engine-auth-service-address") + .value_name("block_engine_auth_service_address") + .takes_value(true) + .help("Address of the block engine's authentication service.") + ) + .arg( + Arg::with_name("relayer_auth_service_address") + .long("relayer-auth-service-address") + .value_name("relayer_auth_service_address") + .takes_value(true) + .help("Address of the block engine's authentication service.") + ) + .arg( + Arg::with_name("trust_relayer_packets") + .long("trust-relayer-packets") + .takes_value(false) + .help("Skip signature verification on relayer packets. Not recommended unless the relayer is trusted.") + ) + .arg( + Arg::with_name("relayer_expected_heartbeat_interval_ms") + .long("relayer-expected-heartbeat-interval-ms") + .takes_value(true) + .help("Interval at which the Relayer is expected to send heartbeat messages.") + ) + .arg( + Arg::with_name("relayer_max_failed_heartbeats") + .long("relayer-max-failed-heartbeats") + .takes_value(true) + .help("Maximum number of heartbeats the Relayer can miss before falling back to the normal TPU pipeline.") + ) + .arg( + Arg::with_name("trust_block_engine_packets") + .long("trust-block-engine-packets") + .takes_value(false) + .help("Skip signature verification on block engine packets. Not recommended unless the block engine is trusted.") + ) + .arg( + Arg::with_name("tip_payment_program_pubkey") + .long("tip-payment-program-pubkey") + .value_name("TIP_PAYMENT_PROGRAM_PUBKEY") + .takes_value(true) + .help("The public key of the tip-payment program") + ) + .arg( + Arg::with_name("tip_distribution_program_pubkey") + .long("tip-distribution-program-pubkey") + .value_name("TIP_DISTRIBUTION_PROGRAM_PUBKEY") + .takes_value(true) + .help("The public key of the tip-distribution program.") + ) + .arg( + Arg::with_name("tip_distribution_account_payer") + .long("tip-distribution-account-payer") + .value_name("TIP_DISTRIBUTION_ACCOUNT_PAYER") + .takes_value(true) + .help("The payer of my tip distribution accounts.") + ) + .arg( + Arg::with_name("merkle_root_upload_authority") + .long("merkle-root-upload-authority") + .value_name("MERKLE_ROOT_UPLOAD_AUTHORITY") + .takes_value(true) + .help("The public key of the authorized merkle-root uploader.") + ) + .arg( + Arg::with_name("commission_bps") + .long("commission-bps") + .value_name("COMMISSION_BPS") + .takes_value(true) + .help("The commission validator takes from tips expressed in basis points.") + ) + .arg( + Arg::with_name("shred_receiver_address") + .long("shred-receiver-address") + .value_name("SHRED_RECEIVER_ADDRESS") + .takes_value(true) + .help("Shred receiver listening address") + ) .after_help("The default subcommand is run") .subcommand( SubCommand::with_name("exit") @@ -2480,6 +2577,88 @@ pub fn main() { } let full_api = matches.is_present("full_rpc_api"); + let voting_disabled = matches.is_present("no_voting") || restricted_repair_only_mode; + let tip_manager_config = tip_manager_config_from_matches(&matches, voting_disabled); + + let is_block_engine_enabled = matches.is_present("block_engine_address") + || matches.is_present("block_engine_auth_service_address") + || matches.is_present("trust_block_engine_packets"); + let maybe_block_engine_config = is_block_engine_enabled.then(|| { + let addr: String = value_of(&matches, "block_engine_auth_service_address") + .expect("missing block-engine-auth-service-address"); + let mut auth_service_endpoint = Endpoint::from_shared(addr.clone()) + .expect("invalid block-engine-auth-service-address value"); + if addr.contains("https") { + auth_service_endpoint = auth_service_endpoint + .tls_config(tonic::transport::ClientTlsConfig::new()) + .expect("failed to set tls_config"); + } + + let addr: String = + value_of(&matches, "block_engine_address").expect("missing block-engine-address"); + let mut backend_endpoint = Endpoint::from_shared(addr.clone()) + .expect("invalid block-engine-address value") + .tcp_keepalive(Some(Duration::from_secs(60))); + if addr.contains("https") { + backend_endpoint = backend_endpoint + .tls_config(tonic::transport::ClientTlsConfig::new()) + .expect("failed to set tls_config"); + } + + BlockEngineConfig { + auth_service_endpoint, + backend_endpoint, + trust_packets: matches.is_present("trust_block_engine_packets"), + } + }); + + let is_relayer_enabled = matches.is_present("relayer_auth_service_address") + || matches.is_present("relayer_address") + || matches.is_present("trust_relayer_packets") + || matches.is_present("relayer_expected_heartbeat_interval_ms") + || matches.is_present("relayer_max_failed_heartbeats"); + let maybe_relayer_config = is_relayer_enabled.then(|| { + let addr: String = value_of(&matches, "relayer_auth_service_address") + .expect("missing relayer-auth-service-address"); + let mut auth_service_endpoint = Endpoint::from_shared(addr.clone()) + .expect("invalid relayer-auth-service-address value"); + if addr.contains("https") { + auth_service_endpoint = auth_service_endpoint + .tls_config(tonic::transport::ClientTlsConfig::new()) + .expect("failed to set tls_config"); + } + + let addr: String = value_of(&matches, "relayer_address").expect("missing relayer-address"); + let mut backend_endpoint = + Endpoint::from_shared(addr.clone()).expect("invalid relayer-address value"); + if addr.contains("https") { + backend_endpoint = backend_endpoint + .tls_config(tonic::transport::ClientTlsConfig::new()) + .expect("failed to set tls_config"); + } + + let expected_heartbeat_interval_ms = + value_of(&matches, "relayer_expected_heartbeat_interval_ms").unwrap_or(500); + let expected_heartbeat_interval = Duration::from_millis(expected_heartbeat_interval_ms); + + let max_failed_heartbeats = + value_of(&matches, "relayer_max_failed_heartbeats").unwrap_or(3); + assert!( + max_failed_heartbeats > 0, + "relayer-max-failed-heartbeats must be greater than zero" + ); + let oldest_allowed_heartbeat = + Duration::from_millis(max_failed_heartbeats * expected_heartbeat_interval_ms); + + RelayerConfig { + auth_service_endpoint, + backend_endpoint, + expected_heartbeat_interval, + oldest_allowed_heartbeat, + trust_packets: matches.is_present("trust_relayer_packets"), + } + }); + let mut validator_config = ValidatorConfig { require_tower: matches.is_present("require_tower"), tower_storage, @@ -2603,6 +2782,12 @@ pub fn main() { tpu_coalesce_ms, no_wait_for_vote_to_start_leader: matches.is_present("no_wait_for_vote_to_start_leader"), accounts_shrink_ratio, + maybe_relayer_config, + maybe_block_engine_config, + tip_manager_config, + shred_receiver_address: matches + .value_of("shred_receiver_address") + .map(|address| SocketAddr::from_str(address).expect("shred_receiver_address invalid")), ..ValidatorConfig::default() }; @@ -3058,3 +3243,58 @@ fn process_account_indexes(matches: &ArgMatches) -> AccountSecondaryIndexes { indexes: account_indexes, } } + +fn tip_manager_config_from_matches( + matches: &ArgMatches, + voting_disabled: bool, +) -> TipManagerConfig { + TipManagerConfig { + tip_payment_program_id: pubkey_of(matches, "tip_payment_program_pubkey").unwrap_or_else( + || { + if !voting_disabled { + panic!("--tip-payment-program-pubkey argument required when validator is voting"); + } + Pubkey::new_unique() + }, + ), + tip_distribution_program_id: pubkey_of(matches, "tip_distribution_program_pubkey") + .unwrap_or_else(|| { + if !voting_disabled { + panic!("--tip-distribution-program-pubkey argument required when validator is voting"); + } + Pubkey::new_unique() + }), + tip_distribution_account_config: TipDistributionAccountConfig { + payer: { + let keypair = + keypair_of(matches, "tip_distribution_account_payer").unwrap_or_else(|| { + if !voting_disabled { + panic!("--tip-distribution-account-payer argument required when validator is voting"); + } + Keypair::new() + }); + + Arc::new(keypair) + }, + merkle_root_upload_authority: pubkey_of(matches, "merkle_root_upload_authority") + .unwrap_or_else(|| { + if !voting_disabled { + panic!("--merkle-root-upload-authority argument required when validator is voting"); + } + Pubkey::new_unique() + }), + vote_account: pubkey_of(matches, "vote_account").unwrap_or_else(|| { + if !voting_disabled { + panic!("--vote-account argument required when validator is voting"); + } + Pubkey::new_unique() + }), + commission_bps: value_t!(matches, "commission_bps", u16).unwrap_or_else(|_| { + if !voting_disabled { + panic!("--commission-bps argument required when validator is voting"); + } + 0 + }), + }, + } +}