From 5b660ffc372749b4514e2f888b2b762a44175bd7 Mon Sep 17 00:00:00 2001 From: Godmode Galactus Date: Mon, 19 Dec 2022 18:35:25 +0100 Subject: [PATCH 1/6] Implementation of application fees (write account fees) by updating the account structure adding a new field `has_application_fee` and changing `rent_epoch` \ to `rent_epoch_or_application_fees`. Adding a new native program to manage application fees and implementing unit tests for the program and accounts. --- Cargo.lock | 2273 +++++++++-------- Cargo.toml | 2 + account-decoder/src/lib.rs | 15 +- banks-server/src/banks_server.rs | 10 +- bench-tps/tests/bench_tps.rs | 3 +- cli-output/src/cli_output.rs | 5 +- core/Cargo.toml | 1 + genesis/src/main.rs | 3 +- .../src/accounts_update_notifier.rs | 8 +- ledger-tool/src/main.rs | 2 + ledger/src/blockstore_processor.rs | 2 +- ledger/src/token_balances.rs | 30 +- program-runtime/src/invoke_context.rs | 52 +- program-runtime/src/pre_account.rs | 57 +- program-test/src/lib.rs | 9 +- program-test/src/programs.rs | 3 +- programs/application-fees-tests/Cargo.toml | 20 + .../tests/add_update_remove.rs | 254 ++ .../application-fees-tests/tests/common.rs | 57 + .../application-fees-tests/tests/rebate.rs | 544 ++++ .../tests/rebate_all.rs | 168 ++ programs/application-fees/Cargo.toml | 35 + programs/application-fees/build.rs | 27 + programs/application-fees/src/instruction.rs | 50 + programs/application-fees/src/lib.rs | 12 + programs/application-fees/src/processor.rs | 215 ++ programs/bpf_loader/benches/serialization.rs | 21 +- programs/bpf_loader/src/serialization.rs | 27 +- programs/bpf_loader/src/syscalls/cpi.rs | 13 +- programs/vote/benches/process_vote.rs | 3 +- rpc-client/src/mock_sender.rs | 3 +- rpc-client/src/nonblocking/rpc_client.rs | 3 +- rpc-client/src/rpc_client.rs | 6 +- rpc/Cargo.toml | 1 + rpc/src/rpc.rs | 8 +- rpc/src/transaction_status_service.rs | 2 + runtime/Cargo.toml | 1 + runtime/src/accounts.rs | 335 ++- runtime/src/accounts_db.rs | 81 +- runtime/src/accounts_index.rs | 34 +- runtime/src/ancient_append_vecs.rs | 3 +- runtime/src/append_vec.rs | 47 +- runtime/src/bank.rs | 274 +- runtime/src/builtins.rs | 8 + runtime/src/message_processor.rs | 19 +- runtime/src/read_only_accounts_cache.rs | 3 +- runtime/src/rent_collector.rs | 14 +- runtime/src/storable_accounts.rs | 15 +- sdk/program/src/instruction.rs | 10 + sdk/program/src/program_error.rs | 28 + sdk/src/account.rs | 352 ++- sdk/src/application_fees.rs | 10 + sdk/src/feature_set.rs | 3 + sdk/src/lib.rs | 1 + sdk/src/native_loader.rs | 11 +- sdk/src/recent_blockhashes_account.rs | 5 +- sdk/src/reward_type.rs | 2 + sdk/src/transaction_context.rs | 34 + storage-proto/src/convert.rs | 10 + test-validator/src/lib.rs | 9 +- 60 files changed, 3986 insertions(+), 1267 deletions(-) create mode 100644 programs/application-fees-tests/Cargo.toml create mode 100644 programs/application-fees-tests/tests/add_update_remove.rs create mode 100644 programs/application-fees-tests/tests/common.rs create mode 100644 programs/application-fees-tests/tests/rebate.rs create mode 100644 programs/application-fees-tests/tests/rebate_all.rs create mode 100644 programs/application-fees/Cargo.toml create mode 100644 programs/application-fees/build.rs create mode 100644 programs/application-fees/src/instruction.rs create mode 100644 programs/application-fees/src/lib.rs create mode 100644 programs/application-fees/src/processor.rs create mode 100644 sdk/src/application_fees.rs diff --git a/Cargo.lock b/Cargo.lock index acff94b2b40..9a87db6b6b9 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.6", + "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.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -82,48 +82,48 @@ 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 = "android_system_properties" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e" +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.58" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "arc-swap" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" [[package]] name = "ark-bn254" @@ -174,7 +174,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "quote 1.0.18", + "quote 1.0.23", "syn 1.0.107", ] @@ -186,7 +186,7 @@ checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ "num-bigint 0.4.3", "num-traits", - "quote 1.0.18", + "quote 1.0.23", "syn 1.0.107", ] @@ -247,7 +247,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.9", + "time 0.3.17", ] [[package]] @@ -256,8 +256,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", "synstructure", ] @@ -268,18 +268,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[package]] name = "assert_cmd" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e" +checksum = "9834fcc22e0874394a010230586367d4a3e9f11b560f469262678547e1d2575e" dependencies = [ - "bstr", + "bstr 1.2.0", "doc-comment", "predicates", "predicates-core", @@ -295,9 +295,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", @@ -318,9 +318,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", @@ -328,23 +328,23 @@ 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.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[package]] name = "async-trait" -version = "0.1.57" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -354,7 +354,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi 0.3.9", ] @@ -388,11 +388,11 @@ dependencies = [ "http", "http-body", "hyper", - "itoa 1.0.1", + "itoa 1.0.5", "matchit", "memchr", "mime", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project-lite", "rustversion", "serde", @@ -427,7 +427,7 @@ 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.5", @@ -442,15 +442,21 @@ 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 = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "base64ct" -version = "1.3.3" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874f8444adcb4952a8bc51305c8be95c8ec8237bb0d2e78d2e039f771f8828a0" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" [[package]] name = "bincode" @@ -473,8 +479,8 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "regex", "rustc-hash", "shlex", @@ -482,9 +488,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", ] @@ -512,28 +518,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.3.1" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" +checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" dependencies = [ "arrayref", "arrayvec", "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]] @@ -542,26 +536,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.6", + "block-padding", + "generic-array", ] [[package]] name = "block-buffer" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" -dependencies = [ - "generic-array 0.14.6", -] - -[[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]] @@ -589,7 +574,7 @@ dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "syn 1.0.107", ] @@ -599,8 +584,8 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -610,8 +595,8 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -628,9 +613,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.3.2" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -654,6 +639,18 @@ dependencies = [ "serde", ] +[[package]] +name = "bstr" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832" +dependencies = [ + "memchr", + "once_cell", + "regex-automata", + "serde", +] + [[package]] name = "bumpalo" version = "3.12.0" @@ -670,18 +667,13 @@ 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.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ebf10dda65f19ff0f42ea15572a359ed60d7fc74fdc984d90310937be0014b" +checksum = "3348673602e04848647fffaa8e9a861e7b5d5cae6570727b41bde0f722514484" dependencies = [ + "serde", "utf8-width", ] @@ -693,21 +685,21 @@ checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" [[package]] name = "bytemuck" -version = "1.11.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e" +checksum = "1aca418a974d83d40a0c1f0c5cba6ff4bc28d8df099109ca459a2118d40b6322" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -719,9 +711,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.2.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "bytesize" @@ -752,18 +744,18 @@ dependencies = [ [[package]] name = "camino" -version = "1.0.9" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412" +checksum = "c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055" dependencies = [ "serde", ] [[package]] name = "caps" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938c50180feacea622ef3b8f4a496057c868dcf8ac7a64d781dd8f3f51a9c143" +checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" dependencies = [ "libc", "thiserror", @@ -780,15 +772,16 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.0" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3abb7553d5b9b8421c6de7cb02606ff15e0c6eea7d8eadd75ef013fd636bec36" +checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07" dependencies = [ "camino", "cargo-platform", "semver 1.0.16", "serde", "serde_json", + "thiserror", ] [[package]] @@ -841,16 +834,16 @@ dependencies = [ "num-integer", "num-traits", "serde", - "time 0.1.43", + "time 0.1.45", "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", ] @@ -861,7 +854,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array 0.14.6", + "generic-array", ] [[package]] @@ -876,9 +869,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", @@ -887,9 +880,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", @@ -902,34 +895,53 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.8" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" +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.7" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ - "heck 0.4.0", + "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] +[[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 = "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" @@ -945,17 +957,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.0" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", - "regex", - "terminal_size", "unicode-width", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -986,29 +996,29 @@ checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "const_format" -version = "0.2.26" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939dc9e2eb9077e0679d2ce32de1ded8531779360b003b4a972a7a39ec263495" +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.50", - "quote 1.0.18", - "unicode-xid 0.2.2", + "proc-macro2 1.0.51", + "quote 1.0.23", + "unicode-xid 0.2.4", ] [[package]] name = "constant_time_eq" -version = "0.1.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" [[package]] name = "convert_case" @@ -1018,9 +1028,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", @@ -1046,18 +1056,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", ] @@ -1087,9 +1097,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", @@ -1104,18 +1114,17 @@ dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", "lazy_static", - "memoffset 0.6.4", + "memoffset 0.6.5", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", - "lazy_static", ] [[package]] @@ -1126,11 +1135,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.6", + "generic-array", "typenum", ] @@ -1140,7 +1149,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.6", + "generic-array", "subtle", ] @@ -1150,7 +1159,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", @@ -1177,12 +1186,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.2.3" +version = "3.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d91974fbbe88ec1df0c24a4f00f99583667a7e2e6272b2b92d294d81e462173" +checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639" dependencies = [ - "nix", - "winapi 0.3.9", + "nix 0.26.2", + "windows-sys 0.45.0", ] [[package]] @@ -1199,6 +1208,50 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cxx" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc831ee6a32dd495436e317595e639a587aa9907bef96fe6e6abc290ab6204e9" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94331d54f1b1a8895cd81049f7eaaaef9d05a7dcb4d1fd08bf3ff0806246789d" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2 1.0.51", + "quote 1.0.23", + "scratch", + "syn 1.0.107", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48dcd35ba14ca9b40d6e4b4b39961f23d835dbb8eed74565ded361d93e1feb8a" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.107", +] + [[package]] name = "darling" version = "0.14.2" @@ -1217,8 +1270,8 @@ checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "strsim 0.10.0", "syn 1.0.107", ] @@ -1230,7 +1283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" dependencies = [ "darling_core", - "quote 1.0.18", + "quote 1.0.23", "syn 1.0.107", ] @@ -1247,20 +1300,22 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.2.0" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ "cfg-if 1.0.0", - "num_cpus", - "parking_lot 0.12.1", + "hashbrown 0.12.3", + "lock_api", + "once_cell", + "parking_lot_core 0.9.7", ] [[package]] name = "data-encoding" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" [[package]] name = "der" @@ -1297,31 +1352,32 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[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.50", - "quote 1.0.18", - "rustc_version 0.3.3", + "proc-macro2 1.0.51", + "quote 1.0.23", + "rustc_version 0.4.0", "syn 1.0.107", ] [[package]] name = "dialoguer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92e7e37ecef6857fdc0c0c5d42fd5b0938e46590c2183cc92dd310a6d078eb1" +checksum = "af3c796f3b0b408d9fd581611b47fa850821fcb84aa640b83a3c1a5be2d691f2" dependencies = [ "console", + "shell-words", "tempfile", "zeroize", ] @@ -1332,31 +1388,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.6", + "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.2", + "block-buffer 0.10.3", "crypto-common", "subtle", ] @@ -1397,8 +1444,8 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -1439,9 +1486,9 @@ checksum = "abe71d579d1812060163dff96056261deb5bf6729b100fa2e36a68b9649ba3d3" [[package]] name = "ed25519" -version = "1.2.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ "signature", ] @@ -1469,26 +1516,26 @@ dependencies = [ "derivation-path", "ed25519-dalek", "hmac 0.12.1", - "sha2 0.10.5", + "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.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "encode_unicode" @@ -1498,9 +1545,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.29" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ "cfg-if 1.0.0", ] @@ -1520,33 +1567,34 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[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.3", "num-traits", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", + "rustc_version 0.4.0", "syn 1.0.107", ] [[package]] name = "enum_dispatch" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb359f1476bf611266ac1f5355bc14aeca37b299d0ebccc038ee7058891c9cb" +checksum = "11f36e95862220b211a6e2aa5eca09b4fa391b13cd52ceb8035a24bf65a79de2" dependencies = [ "once_cell", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -1601,15 +1649,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" @@ -1622,22 +1664,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.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517" +checksum = "28c0190ff0bd3b28bfdd4d0cf9f92faa12880fb0b8ae2054723dd6c76a4efd42" dependencies = [ "cfg-if 1.0.0", "rustix", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -1648,9 +1690,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", @@ -1659,27 +1701,27 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" 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.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "398ea4fabe40b9b0d885340a2a991a44c8a645624075ad966d21f88688e2b69e" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", @@ -1717,19 +1759,18 @@ 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]] name = "fs_extra" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "fuchsia-cprng" @@ -1745,9 +1786,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -1760,9 +1801,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1770,15 +1811,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -1788,38 +1829,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures 0.1.31", "futures-channel", @@ -1873,15 +1914,6 @@ dependencies = [ "regex", ] -[[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.6" @@ -1918,31 +1950,31 @@ 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]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", - "bstr", + "bstr 1.2.0", "fnv", "log", "regex", @@ -1955,7 +1987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8af59a261bcf42f45d1b261232847b9b850ba0a1419d6100698246fb66e9240" dependencies = [ "arc-swap", - "futures 0.3.24", + "futures 0.3.26", "log", "reqwest", "serde", @@ -1963,15 +1995,15 @@ dependencies = [ "serde_json", "simpl", "smpl_jwt", - "time 0.3.9", + "time 0.3.17", "tokio", ] [[package]] name = "goblin" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c955ab4e0ad8c843ea653a3d143048b87490d9be56bd7132a435c2407846ac8f" +checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143" dependencies = [ "log", "plain", @@ -1980,9 +2012,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", @@ -1993,7 +2025,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.6.9", + "tokio-util 0.7.2", "tracing", ] @@ -2026,18 +2058,18 @@ dependencies = [ [[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", ] [[package]] @@ -2060,9 +2092,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -2073,6 +2105,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -2081,13 +2122,14 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hidapi" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b1717343691998deb81766bfcd1dce6df0d5d6c37070b5a3de2bb6d39f7822" +checksum = "798154e4b6570af74899d71155fb0072d5b17e6aa12f39c8ef22c60fb8ec99e7" dependencies = [ "cc", "libc", "pkg-config", + "winapi 0.3.9", ] [[package]] @@ -2112,7 +2154,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]] @@ -2122,7 +2164,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array 0.14.6", + "generic-array", "hmac 0.8.1", ] @@ -2134,7 +2176,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa 1.0.5", ] [[package]] @@ -2162,9 +2204,9 @@ 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" @@ -2174,9 +2216,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.23" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", @@ -2187,7 +2229,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.1", + "itoa 1.0.5", "pin-project-lite", "socket2", "tokio", @@ -2203,7 +2245,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" dependencies = [ "bytes", - "futures 0.3.24", + "futures 0.3.26", "headers", "http", "hyper", @@ -2216,15 +2258,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" dependencies = [ "http", "hyper", - "rustls 0.20.6", + "rustls 0.20.8", "tokio", - "tokio-rustls 0.23.3", + "tokio-rustls 0.23.4", ] [[package]] @@ -2254,17 +2296,28 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.46" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501" +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 = "ident_case" version = "1.0.1" @@ -2284,11 +2337,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", ] @@ -2306,7 +2358,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", @@ -2323,9 +2375,9 @@ checksum = "5a9d968042a4902e08810946fc7cd5851eb75e80301342305af755ca06cb82ce" [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown 0.12.3", @@ -2334,22 +2386,23 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.1" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfddc9561e8baf264e0e45e197fd7696320026eb10a8180340debc27b18f535b" +checksum = "cef509aa9bc73864d6756f0d34d35504af3cf0844373afe9b8669a5b8005a729" dependencies = [ "console", "number_prefix", + "portable-atomic", "unicode-width", ] [[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.6", + "generic-array", ] [[package]] @@ -2363,15 +2416,19 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "0.7.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ea37f355c05dde75b84bba2d767906ad522e97cd9e2eef2be7a4ab7fb442c06" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +dependencies = [ + "libc", + "windows-sys 0.45.0", +] [[package]] name = "ipnet" -version = "2.3.1" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" [[package]] name = "itertools" @@ -2390,24 +2447,24 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[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.59" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -2430,7 +2487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.24", + "futures 0.3.26", "jsonrpc-core", "jsonrpc-pubsub", "jsonrpc-server-utils", @@ -2448,7 +2505,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.24", + "futures 0.3.26", "futures-executor", "futures-util", "log", @@ -2463,7 +2520,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.24", + "futures 0.3.26", "jsonrpc-client-transports", ] @@ -2474,8 +2531,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2" dependencies = [ "proc-macro-crate 0.1.5", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -2485,7 +2542,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.24", + "futures 0.3.26", "hyper", "jsonrpc-core", "jsonrpc-server-utils", @@ -2501,7 +2558,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845" dependencies = [ - "futures 0.3.24", + "futures 0.3.26", "jsonrpc-core", "jsonrpc-server-utils", "log", @@ -2516,7 +2573,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.24", + "futures 0.3.26", "jsonrpc-core", "lazy_static", "log", @@ -2532,22 +2589,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes", - "futures 0.3.24", + "futures 0.3.26", "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" @@ -2573,15 +2633,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.131" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[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", @@ -2589,9 +2649,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" @@ -2657,33 +2717,43 @@ 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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +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.46" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "lock_api" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ + "autocfg", "scopeguard", ] @@ -2731,17 +2801,11 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" -[[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" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matchit" @@ -2751,9 +2815,9 @@ checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" [[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" @@ -2766,9 +2830,9 @@ dependencies = [ [[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", ] @@ -2790,7 +2854,7 @@ checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder", "keccak", - "rand_core 0.6.3", + "rand_core 0.6.4", "zeroize", ] @@ -2808,15 +2872,15 @@ 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.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] @@ -2859,8 +2923,8 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -2872,9 +2936,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", @@ -2890,9 +2954,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", @@ -2901,27 +2965,47 @@ dependencies = [ [[package]] name = "nix" -version = "0.25.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ "autocfg", "bitflags", "cfg-if 1.0.0", "libc", - "memoffset 0.6.4", + "memoffset 0.6.5", "pin-utils", ] +[[package]] +name = "nix" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "libc", + "static_assertions", +] + [[package]] name = "nom" -version = "7.0.0" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", - "version_check", +] + +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", ] [[package]] @@ -2932,9 +3016,9 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[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", ] @@ -2991,16 +3075,16 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[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", @@ -3036,48 +3120,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] [[package]] name = "num_enum" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e" dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro-crate 1.3.0", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] -[[package]] -name = "num_threads" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15" -dependencies = [ - "libc", -] - [[package]] name = "number_prefix" version = "0.4.0" @@ -3086,24 +3162,18 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "oid-registry" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d4bda43fd1b844cbc6e6e54b5444e2b1bc7838bce59ad205902cccbb26d6761" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" dependencies = [ "asn1-rs", ] [[package]] name = "once_cell" -version = "1.13.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "opaque-debug" @@ -3113,9 +3183,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.41" +version = "0.10.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -3132,31 +3202,31 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[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.75" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg", "cc", @@ -3179,7 +3249,7 @@ dependencies = [ "futures-util", "js-sys", "lazy_static", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project", "rand 0.8.5", "thiserror", @@ -3187,34 +3257,30 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "ouroboros" -version = "0.15.0" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f31a3b678685b150cba82b702dcdc5e155893f63610cf388d30cd988d4ca2bf" +checksum = "dfbb50b356159620db6ac971c6d5c9ab788c9cc38a6f49619fca2a27acb062ca" dependencies = [ "aliasable", "ouroboros_macro", - "stable_deref_trait", ] [[package]] name = "ouroboros_macro" -version = "0.15.0" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084fd65d5dd8b3772edccb5ffd1e4b7eba43897ecd0f9401e330e8c542959408" +checksum = "4a0d9d1a6191c4f391f87219d1ea42b23f09ee84d64763cd05ee6ea88d9f384d" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -3224,7 +3290,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ - "futures 0.3.24", + "futures 0.3.26", "libc", "log", "rand 0.7.3", @@ -3240,7 +3306,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.5", + "parking_lot_core 0.8.6", ] [[package]] @@ -3250,14 +3316,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.1", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -3269,22 +3335,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.1" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys 0.32.0", + "windows-sys 0.45.0", ] [[package]] name = "paste" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "pbkdf2" @@ -3301,7 +3367,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.3", + "digest 0.10.6", ] [[package]] @@ -3316,7 +3382,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] @@ -3327,9 +3393,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" @@ -3342,18 +3408,19 @@ dependencies = [ [[package]] name = "pest" -version = "2.1.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f" dependencies = [ + "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "8bf026e2d0581559db66d837fe5242320f525d85c76283c61f4d51a1238d65ea" dependencies = [ "pest", "pest_generator", @@ -3361,33 +3428,33 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "2b27bd18aa01d91c8ed2b61ea23406a676b42d82609c6e2581fba42f0c15f17f" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "9f02b677c1859756359fc9983c2e56a0237f18624a3789528804406b7e915e5d" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1 0.8.2", + "sha2 0.10.6", ] [[package]] name = "petgraph" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ "fixedbitset", "indexmap", @@ -3418,16 +3485,16 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[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" @@ -3448,9 +3515,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" @@ -3466,21 +3533,27 @@ checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug", "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b" + [[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.1.1" +version = "2.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c" +checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" dependencies = [ "difflib", "float-cmp", @@ -3492,15 +3565,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", @@ -3514,11 +3587,11 @@ checksum = "c6fa0831dd7cc608c38a5e323422a0077678fa5744aa2be4ad91c4ece8eec8d5" [[package]] name = "prettyplease" -version = "0.1.9" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b83ec2d0af5c5c556257ff52c9f98934e243b9fd39604bfb2a9b75ec2e97f18" +checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "syn 1.0.107", ] @@ -3533,12 +3606,12 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ - "thiserror", - "toml", + "once_cell", + "toml_edit", ] [[package]] @@ -3548,8 +3621,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", "version_check", ] @@ -3560,8 +3633,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "version_check", ] @@ -3576,18 +3649,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" +checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" dependencies = [ "bit-set", "bitflags", @@ -3601,6 +3674,7 @@ dependencies = [ "regex-syntax", "rusty-fork", "tempfile", + "unarray", ] [[package]] @@ -3645,12 +3719,12 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276470f7f281b0ed53d2ae42dd52b4a8d08853a3c70e7fe95882acbb98a6ae94" +checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ "bytes", - "heck 0.4.0", + "heck 0.4.1", "itertools", "lazy_static", "log", @@ -3673,8 +3747,8 @@ checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -3686,8 +3760,8 @@ checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -3721,9 +3795,9 @@ dependencies = [ [[package]] name = "protobuf-src" -version = "1.0.5+3.19.3" +version = "1.1.0+21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe57f68bf9767f48f8cbcbceb5da21524e2b1330a821c1c2502c447d8043f078" +checksum = "c7ac8852baeb3cc6fb83b93646fb93c0ffe5d14bf138c945ceb4b9948ee0e3c1" dependencies = [ "autotools", ] @@ -3734,7 +3808,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]] @@ -3760,7 +3834,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.20.6", + "rustls 0.20.8", "thiserror", "tokio", "tracing", @@ -3777,7 +3851,7 @@ dependencies = [ "rand 0.8.5", "ring", "rustc-hash", - "rustls 0.20.6", + "rustls 0.20.8", "rustls-native-certs", "slab", "thiserror", @@ -3810,11 +3884,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", ] [[package]] @@ -3851,7 +3925,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -3871,7 +3945,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]] @@ -3900,11 +3974,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]] @@ -3922,7 +3996,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]] @@ -3931,7 +4005,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]] @@ -3942,21 +4016,19 @@ checksum = "655b020bbf5c89791160a30f0d4706d8ec7aa5718d6a198f6df19c400e4f4470" [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.2" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -3968,7 +4040,7 @@ dependencies = [ name = "rbpf-cli" version = "1.16.0" dependencies = [ - "clap 3.1.8", + "clap 3.2.23", "serde", "serde_json", "solana-bpf-loader-program", @@ -3986,7 +4058,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring", - "time 0.3.9", + "time 0.3.17", "yasna", ] @@ -4001,21 +4073,22 @@ 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]] @@ -4030,14 +4103,14 @@ dependencies = [ "lru", "parking_lot 0.11.2", "smallvec", - "spin 0.9.2", + "spin 0.9.4", ] [[package]] name = "regex" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -4052,9 +4125,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -4067,12 +4140,12 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.12" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ "async-compression", - "base64 0.13.0", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", @@ -4089,19 +4162,19 @@ dependencies = [ "mime", "native-tls", "once_cell", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project-lite", - "rustls 0.20.6", - "rustls-pemfile 1.0.0", + "rustls 0.20.8", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", - "tokio-rustls 0.23.3", - "tokio-util 0.7.1", + "tokio-rustls 0.23.4", + "tokio-util 0.7.2", "tower-service", - "url 2.2.2", + "url 2.3.1", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -4145,9 +4218,20 @@ dependencies = [ [[package]] name = "rpassword" -version = "7.0.0" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322" +dependencies = [ + "libc", + "rtoolbox", + "winapi 0.3.9", +] + +[[package]] +name = "rtoolbox" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b763cb66df1c928432cc35053f8bd4cec3335d8559fc16010017d16b3c1680" +checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a" dependencies = [ "libc", "winapi 0.3.9", @@ -4194,16 +4278,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.35.9" +version = "0.36.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c825b8aa8010eb9ee99b75f05e10180b9278d161583034d7574c9d617aeada" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.36.1", + "windows-sys 0.45.0", ] [[package]] @@ -4212,7 +4296,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", @@ -4221,9 +4305,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.6" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" dependencies = [ "log", "ring", @@ -4233,32 +4317,23 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" -dependencies = [ - "openssl-probe", - "rustls-pemfile 0.2.1", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "0.2.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" dependencies = [ - "base64 0.13.0", + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", ] [[package]] name = "rustls-pemfile" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64 0.13.0", + "base64 0.21.0", ] [[package]] @@ -4281,9 +4356,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "same-file" @@ -4296,12 +4371,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -4310,6 +4384,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "scroll" version = "0.11.0" @@ -4325,8 +4405,8 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -4352,9 +4432,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.4.2" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -4365,9 +4445,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.4.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -4411,9 +4491,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718dc5fff5b36f99093fc49b280cfc96ce6fc824317783bff5a1fed0c7a64819" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" dependencies = [ "serde", ] @@ -4424,18 +4504,18 @@ version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "7434af0dc1cbd59268aa98b4c22c131c0584d2232f6fb166efb993e2832e896a" dependencies = [ - "itoa 1.0.1", + "itoa 1.0.5", "ryu", "serde", ] @@ -4447,7 +4527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.1", + "itoa 1.0.5", "ryu", "serde", ] @@ -4469,8 +4549,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1966009f3c05f095697c537312f5415d1e3ed31ce0a56942bac4c771c5c335e" dependencies = [ "darling", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -4488,12 +4568,12 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.13" +version = "0.9.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8613d593412a0deb7bbd8de9d908efff5a0cb9ccd8f62c641e7b2ed2f57291d1" +checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567" dependencies = [ "indexmap", - "itoa 1.0.1", + "itoa 1.0.5", "ryu", "serde", "unsafe-libyaml", @@ -4505,12 +4585,26 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92761393ee4dc3ff8f4af487bd58f4307c9329bbedea02cac0089ad9c411e153" dependencies = [ - "dashmap 5.2.0", - "futures 0.3.24", + "dashmap 5.4.0", + "futures 0.3.26", "lazy_static", "log", "parking_lot 0.12.1", - "serial_test_derive", + "serial_test_derive 0.9.0", +] + +[[package]] +name = "serial_test" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "538c30747ae860d6fb88330addbbd3e0ddbe46d662d032855596d8a8ca260611" +dependencies = [ + "dashmap 5.4.0", + "futures 0.3.26", + "lazy_static", + "log", + "parking_lot 0.12.1", + "serial_test_derive 1.0.0", ] [[package]] @@ -4520,21 +4614,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b6f5d1c3087fb119617cff2966fe3808a80e5eb59a8c1601d5994d66f4346a5" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[package]] -name = "sha-1" -version = "0.8.2" +name = "serial_test_derive" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -4547,18 +4640,29 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] name = "sha-1" -version = "0.10.0" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.6", +] + +[[package]] +name = "sha1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.10.6", ] [[package]] @@ -4571,18 +4675,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.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9db03534dff993187064c4e0c05a5708d2a9728ace9a8959b77bedf415dac5" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.10.6", ] [[package]] @@ -4594,16 +4698,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.4" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaedf34ed289ea47c2b741bb72e5357a209512d67bcd4bda44359e5bf0470f56" +checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" dependencies = [ - "digest 0.10.3", + "digest 0.10.6", "keccak", ] @@ -4616,6 +4720,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "shlex" version = "1.1.0" @@ -4643,9 +4753,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" @@ -4665,15 +4775,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" @@ -4681,14 +4794,14 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95b6ff8c21c74ce7744643a7cddbb02579a44f1f77e4316bff1ddb741aca8ac9" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "log", "openssl", "serde", "serde_derive", "serde_json", "simpl", - "time 0.3.9", + "time 0.3.17", ] [[package]] @@ -4707,9 +4820,9 @@ 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.24", + "futures 0.3.26", "httparse", "log", "rand 0.8.5", @@ -4721,7 +4834,7 @@ name = "solana-account-decoder" version = "1.16.0" dependencies = [ "Inflector", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bs58", "bv", @@ -4742,7 +4855,7 @@ dependencies = [ name = "solana-accounts-bench" version = "1.16.0" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "log", "rayon", "solana-logger 1.16.0", @@ -4756,7 +4869,7 @@ dependencies = [ name = "solana-accounts-cluster-bench" version = "1.16.0" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "log", "rand 0.7.3", "rayon", @@ -4810,11 +4923,40 @@ dependencies = [ "solana-sdk 1.16.0", ] +[[package]] +name = "solana-application-fees-program" +version = "1.16.0" +dependencies = [ + "bincode", + "bytemuck", + "log", + "num-derive", + "num-traits", + "rustc_version 0.4.0", + "serde", + "solana-frozen-abi 1.16.0", + "solana-frozen-abi-macro 1.16.0", + "solana-program 1.16.0", + "solana-program-runtime", + "solana-sdk 1.16.0", +] + +[[package]] +name = "solana-application-fees-program-tests" +version = "1.16.0" +dependencies = [ + "assert_matches", + "bincode", + "solana-application-fees-program", + "solana-program-test", + "solana-sdk 1.16.0", +] + [[package]] name = "solana-banking-bench" version = "1.16.0" dependencies = [ - "clap 3.1.8", + "clap 3.2.23", "crossbeam-channel", "log", "rand 0.7.3", @@ -4839,7 +4981,7 @@ name = "solana-banks-client" version = "1.16.0" dependencies = [ "borsh", - "futures 0.3.24", + "futures 0.3.26", "solana-banks-interface", "solana-banks-server", "solana-program 1.16.0", @@ -4866,7 +5008,7 @@ version = "1.16.0" dependencies = [ "bincode", "crossbeam-channel", - "futures 0.3.24", + "futures 0.3.26", "solana-banks-interface", "solana-client", "solana-runtime", @@ -4882,7 +5024,7 @@ dependencies = [ name = "solana-bench-streamer" version = "1.16.0" dependencies = [ - "clap 3.1.8", + "clap 3.2.23", "crossbeam-channel", "solana-net-utils", "solana-streamer", @@ -4893,14 +5035,14 @@ dependencies = [ name = "solana-bench-tps" version = "1.16.0" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "log", "rand 0.7.3", "rayon", "serde_json", - "serde_yaml 0.9.13", - "serial_test", + "serde_yaml 0.9.17", + "serial_test 0.9.0", "solana-clap-utils", "solana-cli-config", "solana-client", @@ -4994,7 +5136,7 @@ name = "solana-cargo-build-bpf" version = "1.16.0" dependencies = [ "cargo_metadata", - "clap 3.1.8", + "clap 3.2.23", "log", "solana-logger 1.16.0", "solana-sdk 1.16.0", @@ -5007,13 +5149,13 @@ dependencies = [ "assert_cmd", "bzip2", "cargo_metadata", - "clap 3.1.8", + "clap 3.2.23", "log", "predicates", "regex", "reqwest", "semver 1.0.16", - "serial_test", + "serial_test 1.0.0", "solana-download-utils", "solana-logger 1.16.0", "solana-sdk 1.16.0", @@ -5025,7 +5167,7 @@ name = "solana-cargo-test-bpf" version = "1.16.0" dependencies = [ "cargo_metadata", - "clap 3.1.8", + "clap 3.2.23", ] [[package]] @@ -5033,7 +5175,7 @@ name = "solana-cargo-test-sbf" version = "1.16.0" dependencies = [ "cargo_metadata", - "clap 3.1.8", + "clap 3.2.23", "log", "solana-logger 1.16.0", ] @@ -5043,7 +5185,7 @@ name = "solana-clap-utils" version = "1.16.0" dependencies = [ "chrono", - "clap 2.33.3", + "clap 2.34.0", "rpassword", "solana-perf", "solana-remote-wallet", @@ -5052,7 +5194,7 @@ dependencies = [ "thiserror", "tiny-bip39", "uriparse", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -5060,7 +5202,7 @@ name = "solana-clap-v3-utils" version = "1.16.0" dependencies = [ "chrono", - "clap 3.1.8", + "clap 3.2.23", "rpassword", "solana-perf", "solana-remote-wallet", @@ -5069,7 +5211,7 @@ dependencies = [ "thiserror", "tiny-bip39", "uriparse", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -5078,7 +5220,7 @@ version = "1.16.0" dependencies = [ "bincode", "bs58", - "clap 2.33.3", + "clap 2.34.0", "console", "const_format", "criterion-stats", @@ -5132,10 +5274,10 @@ dependencies = [ "lazy_static", "serde", "serde_derive", - "serde_yaml 0.9.13", + "serde_yaml 0.9.17", "solana-clap-utils", "solana-sdk 1.16.0", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -5143,9 +5285,9 @@ name = "solana-cli-output" version = "1.16.0" dependencies = [ "Inflector", - "base64 0.13.0", + "base64 0.13.1", "chrono", - "clap 2.33.3", + "clap 2.34.0", "console", "ed25519-dalek", "humantime", @@ -5172,7 +5314,7 @@ dependencies = [ "bincode", "crossbeam-channel", "enum_dispatch", - "futures 0.3.24", + "futures 0.3.26", "futures-util", "indexmap", "indicatif", @@ -5276,7 +5418,7 @@ name = "solana-core" version = "1.16.0" dependencies = [ "ahash", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bs58", "chrono", @@ -5302,8 +5444,9 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serial_test", + "serial_test 0.9.0", "solana-address-lookup-table-program", + "solana-application-fees-program", "solana-bloom", "solana-client", "solana-entry", @@ -5347,13 +5490,13 @@ name = "solana-dos" version = "1.16.0" dependencies = [ "bincode", - "clap 3.1.8", + "clap 3.2.23", "crossbeam-channel", "itertools", "log", "rand 0.7.3", "serde", - "serial_test", + "serial_test 0.9.0", "solana-bench-tps", "solana-client", "solana-core", @@ -5425,7 +5568,7 @@ version = "1.16.0" dependencies = [ "bincode", "byteorder", - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "log", "serde", @@ -5443,9 +5586,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi" -version = "1.14.8" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "341bba362c91aedad2ad9fc0c28c2e39aaa606e6b9c049e8fbcc9f60675163ff" +checksum = "ffc55e72b77452b4469a7f46c3526cbddb4a43382370d5c1112dc108569cfe16" dependencies = [ "ahash", "blake3", @@ -5455,7 +5598,7 @@ dependencies = [ "byteorder", "cc", "either", - "generic-array 0.14.6", + "generic-array", "getrandom 0.1.16", "hashbrown 0.12.3", "im", @@ -5463,14 +5606,14 @@ dependencies = [ "log", "memmap2", "once_cell", - "rand_core 0.6.3", + "rand_core 0.6.4", "rustc_version 0.4.0", "serde", "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.5", - "solana-frozen-abi-macro 1.14.8", + "sha2 0.10.6", + "solana-frozen-abi-macro 1.15.0", "subtle", "thiserror", ] @@ -5487,7 +5630,7 @@ dependencies = [ "byteorder", "cc", "either", - "generic-array 0.14.6", + "generic-array", "getrandom 0.1.16", "hashbrown 0.12.3", "im", @@ -5495,13 +5638,13 @@ dependencies = [ "log", "memmap2", "once_cell", - "rand_core 0.6.3", + "rand_core 0.6.4", "rustc_version 0.4.0", "serde", "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.5", + "sha2 0.10.6", "solana-frozen-abi-macro 1.16.0", "solana-logger 1.16.0", "subtle", @@ -5510,12 +5653,12 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "1.14.8" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fae474ab37e2ccc4dfd33edd36a05d7df02b8531fa9870cb244f9491b64fe3" +checksum = "a7084605b674cf344312c3a2a9c0de05126c2ff4d3d77cc6746f236ca3c4cb53" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "rustc_version 0.4.0", "syn 1.0.107", ] @@ -5524,8 +5667,8 @@ dependencies = [ name = "solana-frozen-abi-macro" version = "1.16.0" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "rustc_version 0.4.0", "syn 1.0.107", ] @@ -5534,12 +5677,12 @@ dependencies = [ name = "solana-genesis" version = "1.16.0" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bincode", - "clap 2.33.3", + "clap 2.34.0", "serde", "serde_json", - "serde_yaml 0.9.13", + "serde_yaml 0.9.17", "solana-clap-utils", "solana-cli-config", "solana-entry", @@ -5598,7 +5741,7 @@ version = "1.16.0" dependencies = [ "bincode", "bv", - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "flate2", "indexmap", @@ -5616,7 +5759,7 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "serial_test", + "serial_test 0.9.0", "solana-bloom", "solana-clap-utils", "solana-client", @@ -5649,19 +5792,19 @@ dependencies = [ "bincode", "bzip2", "chrono", - "clap 2.33.3", + "clap 2.34.0", "console", "crossbeam-channel", "ctrlc", "dirs-next", "indicatif", "lazy_static", - "nix", + "nix 0.25.1", "reqwest", "scopeguard", "semver 1.0.16", "serde", - "serde_yaml 0.9.13", + "serde_yaml 0.9.17", "solana-clap-utils", "solana-config-program", "solana-logger 1.16.0", @@ -5670,7 +5813,7 @@ dependencies = [ "solana-version", "tar", "tempfile", - "url 2.2.2", + "url 2.3.1", "winapi 0.3.9", "winreg", ] @@ -5680,7 +5823,7 @@ name = "solana-keygen" version = "1.16.0" dependencies = [ "bs58", - "clap 3.1.8", + "clap 3.2.23", "dirs-next", "num_cpus", "solana-clap-v3-utils", @@ -5705,7 +5848,7 @@ dependencies = [ "crossbeam-channel", "dashmap 4.0.2", "fs_extra", - "futures 0.3.24", + "futures 0.3.26", "itertools", "lazy_static", "libc", @@ -5723,7 +5866,7 @@ dependencies = [ "rustc_version 0.4.0", "serde", "serde_bytes", - "sha2 0.10.5", + "sha2 0.10.6", "solana-account-decoder", "solana-bpf-loader-program", "solana-entry", @@ -5761,11 +5904,11 @@ dependencies = [ "bs58", "bytecount", "chrono", - "clap 2.33.3", + "clap 2.34.0", "crossbeam-channel", "csv", "dashmap 4.0.2", - "futures 0.3.24", + "futures 0.3.26", "histogram", "itertools", "log", @@ -5806,7 +5949,7 @@ dependencies = [ "log", "rand 0.7.3", "rayon", - "serial_test", + "serial_test 0.9.0", "solana-client", "solana-config-program", "solana-core", @@ -5833,7 +5976,7 @@ name = "solana-log-analyzer" version = "1.16.0" dependencies = [ "byte-unit", - "clap 3.1.8", + "clap 3.2.23", "serde", "serde_json", "solana-logger 1.16.0", @@ -5842,9 +5985,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.14.8" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec82f7dedfee58ff2ac102b20a033a195950e7355fb29f1713f46cee629ffda" +checksum = "dae1169570b4f086a42f340b86b698b8b64dfa0f931f2a4f0f3c5b18195d6711" dependencies = [ "env_logger", "lazy_static", @@ -5876,7 +6019,7 @@ version = "1.16.0" name = "solana-merkle-root-bench" version = "1.16.0" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "log", "solana-logger 1.16.0", "solana-measure", @@ -5906,7 +6049,7 @@ dependencies = [ "log", "rand 0.7.3", "reqwest", - "serial_test", + "serial_test 0.9.0", "solana-sdk 1.16.0", ] @@ -5914,7 +6057,7 @@ dependencies = [ name = "solana-net-shaper" version = "1.16.0" dependencies = [ - "clap 3.1.8", + "clap 3.2.23", "rand 0.7.3", "serde", "serde_json", @@ -5926,10 +6069,10 @@ name = "solana-net-utils" version = "1.16.0" dependencies = [ "bincode", - "clap 3.1.8", + "clap 3.2.23", "crossbeam-channel", "log", - "nix", + "nix 0.25.1", "rand 0.7.3", "serde", "serde_derive", @@ -5938,7 +6081,7 @@ dependencies = [ "solana-sdk 1.16.0", "solana-version", "tokio", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -5967,7 +6110,7 @@ dependencies = [ "libc", "log", "matches", - "nix", + "nix 0.25.1", "rand 0.7.3", "rayon", "serde", @@ -6004,7 +6147,7 @@ dependencies = [ name = "solana-poh-bench" version = "1.16.0" dependencies = [ - "clap 3.1.8", + "clap 3.2.23", "log", "rand 0.7.3", "rayon", @@ -6018,11 +6161,15 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.14.8" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f480a0a440ea15d8436de1c9ac01501cb15979dae4a0a5fc8e33198949b38681" +checksum = "3442ab665ded18fd8526213027a2c05035164b7696e7bf535b7c2d7fa75536fe" dependencies = [ - "base64 0.13.0", + "ark-bn254", + "ark-ec", + "ark-ff", + "array-bytes", + "base64 0.13.1", "bincode", "bitflags", "blake3", @@ -6035,14 +6182,15 @@ dependencies = [ "console_error_panic_hook", "console_log", "curve25519-dalek", - "getrandom 0.2.3", + "getrandom 0.2.8", "itertools", "js-sys", "lazy_static", "libc", "libsecp256k1", "log", - "memoffset 0.6.4", + "memoffset 0.8.0", + "num-bigint 0.4.3", "num-derive", "num-traits", "parking_lot 0.12.1", @@ -6054,11 +6202,11 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.5", - "sha3 0.10.4", - "solana-frozen-abi 1.14.8", - "solana-frozen-abi-macro 1.14.8", - "solana-sdk-macro 1.14.8", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.15.0", + "solana-frozen-abi-macro 1.15.0", + "solana-sdk-macro 1.15.0", "thiserror", "tiny-bip39", "wasm-bindgen", @@ -6075,7 +6223,7 @@ dependencies = [ "ark-ff", "array-bytes", "assert_matches", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "blake3", @@ -6088,7 +6236,7 @@ dependencies = [ "console_error_panic_hook", "console_log", "curve25519-dalek", - "getrandom 0.2.3", + "getrandom 0.2.8", "itertools", "js-sys", "lazy_static", @@ -6108,8 +6256,8 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.5", - "sha3 0.10.4", + "sha2 0.10.6", + "sha3 0.10.6", "solana-frozen-abi 1.16.0", "solana-frozen-abi-macro 1.16.0", "solana-logger 1.16.0", @@ -6125,7 +6273,7 @@ dependencies = [ name = "solana-program-runtime" version = "1.16.0" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bincode", "eager", "enum-iterator", @@ -6154,7 +6302,7 @@ version = "1.16.0" dependencies = [ "assert_matches", "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bincode", "chrono-humanize", "crossbeam-channel", @@ -6195,7 +6343,7 @@ dependencies = [ "tokio-stream", "tokio-tungstenite", "tungstenite", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -6205,14 +6353,14 @@ dependencies = [ "async-mutex", "async-trait", "crossbeam-channel", - "futures 0.3.24", + "futures 0.3.26", "itertools", "lazy_static", "log", "quinn", "quinn-proto", "quinn-udp", - "rustls 0.20.6", + "rustls 0.20.8", "solana-connection-cache", "solana-logger 1.16.0", "solana-measure", @@ -6257,7 +6405,7 @@ dependencies = [ name = "solana-rpc" version = "1.16.0" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bincode", "bs58", "crossbeam-channel", @@ -6275,7 +6423,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serial_test", + "serial_test 0.9.0", "soketto", "solana-account-decoder", "solana-address-lookup-table-program", @@ -6289,6 +6437,7 @@ dependencies = [ "solana-net-utils", "solana-perf", "solana-poh", + "solana-program-runtime", "solana-rayon-threadlimit", "solana-rpc-client-api", "solana-runtime", @@ -6307,7 +6456,7 @@ dependencies = [ "symlink", "thiserror", "tokio", - "tokio-util 0.6.9", + "tokio-util 0.6.10", ] [[package]] @@ -6316,11 +6465,11 @@ version = "1.16.0" dependencies = [ "assert_matches", "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bs58", "crossbeam-channel", - "futures 0.3.24", + "futures 0.3.26", "indicatif", "jsonrpc-core", "jsonrpc-http-server", @@ -6343,7 +6492,7 @@ dependencies = [ name = "solana-rpc-client-api" version = "1.16.0" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bs58", "jsonrpc-core", "reqwest", @@ -6364,8 +6513,8 @@ name = "solana-rpc-client-nonce-utils" version = "1.16.0" dependencies = [ "anyhow", - "clap 2.33.3", - "futures 0.3.24", + "clap 2.34.0", + "futures 0.3.26", "serde_json", "solana-account-decoder", "solana-clap-utils", @@ -6444,6 +6593,7 @@ dependencies = [ "serde", "serde_derive", "solana-address-lookup-table-program", + "solana-application-fees-program", "solana-bpf-loader-program", "solana-bucket-map", "solana-compute-budget-program", @@ -6474,12 +6624,12 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.14.8" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65641c3c87a81fbbf7663360a2d8d5e145280021c444220257f9975ff6cddc80" +checksum = "73788ea1793a23a3d24d1d9ed81a64dbbdd02dac058e0e363a604135e351e670" dependencies = [ "assert_matches", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "borsh", @@ -6488,10 +6638,10 @@ dependencies = [ "byteorder", "chrono", "derivation-path", - "digest 0.10.3", + "digest 0.10.6", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array 0.14.6", + "generic-array", "hmac 0.12.1", "itertools", "js-sys", @@ -6501,6 +6651,7 @@ dependencies = [ "memmap2", "num-derive", "num-traits", + "num_enum", "pbkdf2 0.11.0", "qstring", "rand 0.7.3", @@ -6511,13 +6662,14 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.5", - "sha3 0.10.4", - "solana-frozen-abi 1.14.8", - "solana-frozen-abi-macro 1.14.8", - "solana-logger 1.14.8", - "solana-program 1.14.8", - "solana-sdk-macro 1.14.8", + "serde_with", + "sha2 0.10.6", + "sha3 0.10.6", + "solana-frozen-abi 1.15.0", + "solana-frozen-abi-macro 1.15.0", + "solana-logger 1.15.0", + "solana-program 1.15.0", + "solana-sdk-macro 1.15.0", "thiserror", "uriparse", "wasm-bindgen", @@ -6529,7 +6681,7 @@ version = "1.16.0" dependencies = [ "anyhow", "assert_matches", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bitflags", "borsh", @@ -6539,10 +6691,10 @@ dependencies = [ "chrono", "curve25519-dalek", "derivation-path", - "digest 0.10.3", + "digest 0.10.6", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array 0.14.6", + "generic-array", "hex", "hmac 0.12.1", "itertools", @@ -6565,8 +6717,8 @@ dependencies = [ "serde_derive", "serde_json", "serde_with", - "sha2 0.10.5", - "sha3 0.10.4", + "sha2 0.10.6", + "sha3 0.10.6", "solana-frozen-abi 1.16.0", "solana-frozen-abi-macro 1.16.0", "solana-logger 1.16.0", @@ -6581,13 +6733,13 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.14.8" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "768f16d1a7315fc66ba835eebf9e95a83365ac94222551bc5cdcc6a74cb4a137" +checksum = "e9e216372c12c4bd820afd02ab90564472e14e1ff609b6737e9d832749370656" dependencies = [ "bs58", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "rustversion", "syn 1.0.107", ] @@ -6597,8 +6749,8 @@ name = "solana-sdk-macro" version = "1.16.0" dependencies = [ "bs58", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "rustversion", "syn 1.0.107", ] @@ -6622,7 +6774,7 @@ dependencies = [ name = "solana-stake-accounts" version = "1.16.0" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "solana-clap-utils", "solana-cli-config", "solana-remote-wallet", @@ -6661,7 +6813,7 @@ dependencies = [ "bzip2", "enum-iterator", "flate2", - "futures 0.3.24", + "futures 0.3.26", "goauth", "http", "hyper", @@ -6703,7 +6855,7 @@ dependencies = [ name = "solana-store-tool" version = "1.16.0" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "log", "solana-logger 1.16.0", "solana-runtime", @@ -6722,7 +6874,7 @@ dependencies = [ "itertools", "libc", "log", - "nix", + "nix 0.25.1", "pem", "percentage", "pkcs8", @@ -6731,7 +6883,7 @@ dependencies = [ "quinn-udp", "rand 0.7.3", "rcgen", - "rustls 0.20.6", + "rustls 0.20.8", "solana-logger 1.16.0", "solana-metrics", "solana-perf", @@ -6745,10 +6897,10 @@ dependencies = [ name = "solana-sys-tuner" version = "1.16.0" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "libc", "log", - "nix", + "nix 0.25.1", "solana-logger 1.16.0", "solana-version", "sysctl", @@ -6760,7 +6912,7 @@ dependencies = [ name = "solana-test-validator" version = "1.16.0" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "log", "serde_derive", "serde_json", @@ -6803,7 +6955,7 @@ version = "1.16.0" dependencies = [ "bincode", "chrono", - "clap 2.33.3", + "clap 2.34.0", "console", "csv", "ctrlc", @@ -6860,7 +7012,7 @@ name = "solana-transaction-dos" version = "1.16.0" dependencies = [ "bincode", - "clap 2.33.3", + "clap 2.34.0", "log", "rand 0.7.3", "rayon", @@ -6887,7 +7039,7 @@ name = "solana-transaction-status" version = "1.16.0" dependencies = [ "Inflector", - "base64 0.13.0", + "base64 0.13.1", "bincode", "borsh", "bs58", @@ -6933,7 +7085,7 @@ name = "solana-validator" version = "1.16.0" dependencies = [ "chrono", - "clap 2.33.3", + "clap 2.34.0", "console", "core_affinity", "crossbeam-channel", @@ -6952,7 +7104,7 @@ dependencies = [ "rayon", "serde", "serde_json", - "serde_yaml 0.9.13", + "serde_yaml 0.9.17", "signal-hook", "solana-account-decoder", "solana-clap-utils", @@ -7026,7 +7178,7 @@ dependencies = [ name = "solana-watchtower" version = "1.16.0" dependencies = [ - "clap 2.33.3", + "clap 2.34.0", "humantime", "log", "solana-clap-utils", @@ -7056,13 +7208,13 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "1.14.8" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5982ab9d8771b3d9bbef11ece78348c496a9f70a90a96225aee0a70bd13b9d" +checksum = "ffa4276fd41317c7367f665684410430c8ddae065af6e997b98a26a201ca2c1e" dependencies = [ "aes-gcm-siv", "arrayref", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bytemuck", "byteorder", @@ -7078,8 +7230,8 @@ dependencies = [ "serde", "serde_json", "sha3 0.9.1", - "solana-program 1.14.8", - "solana-sdk 1.14.8", + "solana-program 1.15.0", + "solana-sdk 1.15.0", "subtle", "thiserror", "zeroize", @@ -7091,7 +7243,7 @@ version = "1.16.0" dependencies = [ "aes-gcm-siv", "arrayref", - "base64 0.13.0", + "base64 0.13.1", "bincode", "bytemuck", "byteorder", @@ -7142,9 +7294,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" @@ -7166,7 +7318,7 @@ dependencies = [ "borsh", "num-derive", "num-traits", - "solana-program 1.14.8", + "solana-program 1.15.0", "spl-token", "spl-token-2022", "thiserror", @@ -7179,7 +7331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c5557ec281a34f7f9053feb6e0d795162ba0c6a52898b21c3d1e899481191d5" dependencies = [ "num_enum", - "solana-program 1.14.8", + "solana-program 1.15.0", ] [[package]] @@ -7188,7 +7340,7 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" dependencies = [ - "solana-program 1.14.8", + "solana-program 1.15.0", ] [[package]] @@ -7202,7 +7354,7 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-program 1.14.8", + "solana-program 1.15.0", "thiserror", ] @@ -7217,19 +7369,13 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-program 1.14.8", - "solana-zk-token-sdk 1.14.8", + "solana-program 1.15.0", + "solana-zk-token-sdk 1.15.0", "spl-memo", "spl-token", "thiserror", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "static_assertions" version = "1.1.0" @@ -7261,22 +7407,22 @@ 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.50", - "quote 1.0.18", + "heck 0.4.1", + "proc-macro2 1.0.51", + "quote 1.0.23", "rustversion", "syn 1.0.107", ] @@ -7310,16 +7456,16 @@ version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "unicode-ident", ] [[package]] name = "sync_wrapper" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "synstructure" @@ -7327,10 +7473,10 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", - "unicode-xid 0.2.2", + "unicode-xid 0.2.4", ] [[package]] @@ -7345,9 +7491,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", @@ -7358,15 +7504,15 @@ dependencies = [ [[package]] name = "systemstat" -version = "0.2.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ef8054a60d76603befaecaf7efe08d32d1a05a1e5df70c547b07507e9e262d" +checksum = "a24aec24a9312c83999a28e3ef9db7e2afd5c64bf47725b758cdc1cafd5b0bd2" dependencies = [ "bytesize", "lazy_static", "libc", "nom", - "time 0.3.9", + "time 0.3.17", "winapi 0.3.9", ] @@ -7389,7 +7535,7 @@ checksum = "1c38a012bed6fb9681d3bf71ffaa4f88f3b4b9ed3198cda6e4c8462d24d4bb80" dependencies = [ "anyhow", "fnv", - "futures 0.3.24", + "futures 0.3.26", "humantime", "opentelemetry", "pin-project", @@ -7400,7 +7546,7 @@ dependencies = [ "thiserror", "tokio", "tokio-serde", - "tokio-util 0.6.9", + "tokio-util 0.6.10", "tracing", "tracing-opentelemetry", ] @@ -7411,8 +7557,8 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee42b4e559f17bce0385ebf511a7beb67d5cc33c12c96b7f4e9789919d9c10f" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -7432,28 +7578,18 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi 0.3.9", -] - [[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 = "test-case" @@ -7472,8 +7608,8 @@ checksum = "e45b7bf6e19353ddd832745c8fcf77a17a93171df7151187f26623f2b75b5b26" dependencies = [ "cfg-if 1.0.0", "proc-macro-error", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -7488,27 +7624,27 @@ 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.31" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -7529,9 +7665,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", @@ -7540,9 +7676,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", @@ -7550,31 +7686,41 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi 0.3.9", ] [[package]] name = "time" -version = "0.3.9" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ - "itoa 1.0.1", - "libc", - "num_threads", + "itoa 1.0.5", + "serde", + "time-core", "time-macros", ] +[[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.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] [[package]] name = "tiny-bip39" @@ -7597,18 +7743,18 @@ 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", ] [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" @@ -7632,9 +7778,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", @@ -7642,12 +7788,12 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] @@ -7674,11 +7820,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4151fda0cf2798550ad0b34bcfc9b9dcc2a9d2471c895c68f3a8818e54f2389e" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "rustls 0.20.6", + "rustls 0.20.8", "tokio", "webpki 0.22.0", ] @@ -7701,9 +7847,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite", @@ -7718,9 +7864,9 @@ checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" dependencies = [ "futures-util", "log", - "rustls 0.20.6", + "rustls 0.20.8", "tokio", - "tokio-rustls 0.23.3", + "tokio-rustls 0.23.4", "tungstenite", "webpki 0.22.0", "webpki-roots", @@ -7728,9 +7874,9 @@ dependencies = [ [[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", @@ -7744,9 +7890,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", @@ -7758,13 +7904,30 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + [[package]] name = "tonic" version = "0.6.2" @@ -7773,7 +7936,7 @@ checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a" dependencies = [ "async-stream", "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bytes", "futures-core", "futures-util", @@ -7782,14 +7945,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", @@ -7806,7 +7969,7 @@ dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.13.0", + "base64 0.13.1", "bytes", "futures-core", "futures-util", @@ -7815,15 +7978,15 @@ dependencies = [ "http-body", "hyper", "hyper-timeout", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "pin-project", "prost 0.11.6", "prost-derive 0.11.6", - "rustls-pemfile 1.0.0", + "rustls-pemfile", "tokio", - "tokio-rustls 0.23.3", + "tokio-rustls 0.23.4", "tokio-stream", - "tokio-util 0.7.1", + "tokio-util 0.7.2", "tower", "tower-layer", "tower-service", @@ -7837,9 +8000,9 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2 1.0.51", "prost-build 0.9.0", - "quote 1.0.18", + "quote 1.0.23", "syn 1.0.107", ] @@ -7850,9 +8013,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4" dependencies = [ "prettyplease", - "proc-macro2 1.0.50", - "prost-build 0.11.4", - "quote 1.0.18", + "proc-macro2 1.0.51", + "prost-build 0.11.6", + "quote 1.0.23", "syn 1.0.107", ] @@ -7870,7 +8033,7 @@ dependencies = [ "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.1", + "tokio-util 0.7.2", "tower-layer", "tower-service", "tracing", @@ -7903,15 +8066,15 @@ 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", @@ -7922,22 +8085,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.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", ] [[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]] @@ -7952,10 +8116,11 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.17.2" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f9378e96a9361190ae297e7f3a8ff644aacd2897f244b1ff81f381669196fa6" +checksum = "fbbe89715c1dbbb790059e2565353978564924ee85017b5fff365c872ff6721f" dependencies = [ + "once_cell", "opentelemetry", "tracing", "tracing-core", @@ -7964,9 +8129,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.7" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5312f325fe3588e277415f5a6cca1f4ccad0f248c4cd5a4bd33032d7286abc22" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" dependencies = [ "sharded-slab", "thread_local", @@ -7981,9 +8146,9 @@ checksum = "0de5f738ceab88e2491a94ddc33c3feeadfa95fedc60363ef110845df12f3878" [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" @@ -7991,17 +8156,17 @@ version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "byteorder", "bytes", "http", "httparse", "log", "rand 0.8.5", - "rustls 0.20.6", - "sha-1 0.10.0", + "rustls 0.20.8", + "sha-1 0.10.1", "thiserror", - "url 2.2.2", + "url 2.3.1", "utf-8", "webpki 0.22.0", "webpki-roots", @@ -8009,15 +8174,21 @@ dependencies = [ [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + +[[package]] +name = "unarray" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicase" @@ -8030,36 +8201,36 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" -version = "1.0.2" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[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.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[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" @@ -8069,9 +8240,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" @@ -8079,7 +8250,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" dependencies = [ - "generic-array 0.14.6", + "generic-array", "subtle", ] @@ -8103,9 +8274,9 @@ dependencies = [ [[package]] name = "unsafe-libyaml" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68" +checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2" [[package]] name = "untrusted" @@ -8136,14 +8307,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]] @@ -8164,9 +8334,15 @@ 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 = "7cf7d77f457ef8dfa11e4cd5933c5ddb5dc52a94664071951219a97710f0a32b" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vcpkg" @@ -8182,9 +8358,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" @@ -8230,15 +8406,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.82" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -8246,24 +8428,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.28" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -8273,22 +8455,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ - "quote 1.0.18", + "quote 1.0.23", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -8296,15 +8478,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -8332,22 +8514,22 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.1" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c475786c6f47219345717a043a37ec04cb4bc185e28853adcc4fa0a947eba630" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" dependencies = [ "webpki 0.22.0", ] [[package]] name = "which" -version = "4.2.2" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", - "lazy_static", "libc", + "once_cell", ] [[package]] @@ -8395,146 +8577,84 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[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", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "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", + "windows-targets", ] [[package]] -name = "windows-sys" -version = "0.42.0" +name = "windows-targets" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "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_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc", ] [[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.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" - -[[package]] -name = "windows_i686_gnu" -version = "0.32.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" - -[[package]] -name = "windows_i686_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" - -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.32.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "winreg" @@ -8552,7 +8672,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", @@ -8560,14 +8680,14 @@ dependencies = [ "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.9", + "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", ] @@ -8583,11 +8703,11 @@ dependencies = [ [[package]] name = "yasna" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346d34a236c9d3e5f3b9b74563f238f955bbd05fa0b8b4efa53c130c43982f4c" +checksum = "aed2e7a52e3744ab4d0c05c20aa065258e84c49fd4226f5191b2ed29712710b4" dependencies = [ - "time 0.3.9", + "time 0.3.17", ] [[package]] @@ -8601,12 +8721,12 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.2.0" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.18", + "proc-macro2 1.0.51", + "quote 1.0.23", "syn 1.0.107", "synstructure", ] @@ -8622,9 +8742,9 @@ dependencies = [ [[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", @@ -8632,10 +8752,11 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.6+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "68a3f9792c0c3dc6c165840a75f47ae1f4da402c2d006881129579f6597e801b" dependencies = [ "cc", "libc", + "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index 16b5dbb6e31..2e2246afa11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,8 @@ members = [ "programs/stake", "programs/vote", "programs/zk-token-proof", + "programs/application-fees", + "programs/application-fees-tests", "pubsub-client", "quic-client", "rayon-threadlimit", diff --git a/account-decoder/src/lib.rs b/account-decoder/src/lib.rs index 0fb64d947a1..28e2a041c4a 100644 --- a/account-decoder/src/lib.rs +++ b/account-decoder/src/lib.rs @@ -20,7 +20,6 @@ use { crate::parse_account_data::{parse_account_data, AccountAdditionalData, ParsedAccount}, solana_sdk::{ account::{ReadableAccount, WritableAccount}, - clock::Epoch, fee_calculator::FeeCalculator, pubkey::Pubkey, }, @@ -42,8 +41,9 @@ pub struct UiAccount { pub data: UiAccountData, pub owner: String, pub executable: bool, - pub rent_epoch: Epoch, + pub rent_epoch: u64, pub space: Option, + pub application_fees: Option, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -131,6 +131,11 @@ impl UiAccount { executable: account.executable(), rent_epoch: account.rent_epoch(), space: Some(space as u64), + application_fees: if account.has_application_fees() { + Some(account.application_fees()) + } else { + None + }, } } @@ -151,12 +156,16 @@ impl UiAccount { UiAccountEncoding::Binary | UiAccountEncoding::JsonParsed => None, }, }?; + let has_app_fees: bool = self.application_fees.is_some(); Some(T::create( self.lamports, data, Pubkey::from_str(&self.owner).ok()?, self.executable, - self.rent_epoch, + if has_app_fees { 0 } else { self.rent_epoch }, + // TODO APPLICATION_FEES + has_app_fees, + self.application_fees.map_or(0, |x| x), )) } } diff --git a/banks-server/src/banks_server.rs b/banks-server/src/banks_server.rs index 049353647c5..a5452a2c1d4 100644 --- a/banks-server/src/banks_server.rs +++ b/banks-server/src/banks_server.rs @@ -356,10 +356,12 @@ impl Banks for BanksServer { ) -> BanksTransactionResultWithMetadata { let bank = self.bank_forks.read().unwrap().working_bank(); match bank.process_transaction_with_metadata(transaction) { - TransactionExecutionResult::NotExecuted(error) => BanksTransactionResultWithMetadata { - result: Err(error), - metadata: None, - }, + TransactionExecutionResult::NotExecuted { error, .. } => { + BanksTransactionResultWithMetadata { + result: Err(error), + metadata: None, + } + } TransactionExecutionResult::Executed { details, .. } => { BanksTransactionResultWithMetadata { result: details.status, diff --git a/bench-tps/tests/bench_tps.rs b/bench-tps/tests/bench_tps.rs index c33300608a5..4ea5d23668d 100644 --- a/bench-tps/tests/bench_tps.rs +++ b/bench-tps/tests/bench_tps.rs @@ -39,7 +39,8 @@ fn program_account(program_data: &[u8]) -> AccountSharedData { data: program_data.to_vec(), owner: solana_sdk::bpf_loader::id(), executable: true, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }) } diff --git a/cli-output/src/cli_output.rs b/cli-output/src/cli_output.rs index 142816bf119..fdfcaf750e0 100644 --- a/cli-output/src/cli_output.rs +++ b/cli-output/src/cli_output.rs @@ -192,9 +192,12 @@ impl fmt::Display for CliAccount { )?; writeln_name_value( f, - "Rent Epoch:", + "rent_epoch", &self.keyed_account.account.rent_epoch.to_string(), )?; + if let Some(application_fees) = self.keyed_account.account.application_fees { + writeln_name_value(f, "application_fees", &application_fees.to_string())?; + } Ok(()) } } diff --git a/core/Cargo.toml b/core/Cargo.toml index 1c54ba8e826..a0e615e6aee 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -38,6 +38,7 @@ rolling-file = "0.2.0" serde = "1.0.152" serde_derive = "1.0.103" solana-address-lookup-table-program = { path = "../programs/address-lookup-table", version = "=1.16.0" } +solana-application-fees-program = { path = "../programs/application-fees", version = "=1.16.0" } solana-bloom = { path = "../bloom", version = "=1.16.0" } solana-client = { path = "../client", version = "=1.16.0" } solana-entry = { path = "../entry", version = "=1.16.0" } diff --git a/genesis/src/main.rs b/genesis/src/main.rs index 80bd168cd1e..b03ae216e19 100644 --- a/genesis/src/main.rs +++ b/genesis/src/main.rs @@ -629,7 +629,8 @@ fn main() -> Result<(), Box> { data: program_data, executable: true, owner: loader, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), ); } diff --git a/geyser-plugin-manager/src/accounts_update_notifier.rs b/geyser-plugin-manager/src/accounts_update_notifier.rs index 34a43d8958f..5ac5c671941 100644 --- a/geyser-plugin-manager/src/accounts_update_notifier.rs +++ b/geyser-plugin-manager/src/accounts_update_notifier.rs @@ -132,7 +132,13 @@ impl AccountsUpdateNotifierImpl { lamports: stored_account_meta.account_meta.lamports, owner: stored_account_meta.account_meta.owner.as_ref(), executable: stored_account_meta.account_meta.executable, - rent_epoch: stored_account_meta.account_meta.rent_epoch, + rent_epoch: if stored_account_meta.account_meta.has_application_fees { + 0 + } else { + stored_account_meta + .account_meta + .rent_epoch_or_application_fees + }, data: stored_account_meta.data, write_version: stored_account_meta.meta.write_version_obsolete, txn_signature: None, diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index b1ce07b4895..51170aa0727 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -390,6 +390,8 @@ fn output_account( } println!(" rent_epoch: {}", account.rent_epoch()); println!(" data_len: {}", account.data().len()); + println!(" has_application_fees: {}", account.has_application_fees()); + println!(" application_fees: {}", account.application_fees()); if print_account_data { let account_data = UiAccount::encode(pubkey, account, encoding, None, None).data; match account_data { diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index 01dbc7ac4ff..4bafb10400f 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -1675,7 +1675,7 @@ impl TransactionStatusSender { .into_iter() .map(|result| match result { TransactionExecutionResult::Executed { details, .. } => Some(details), - TransactionExecutionResult::NotExecuted(_) => None, + TransactionExecutionResult::NotExecuted { .. } => None, }) .collect(), balances, diff --git a/ledger/src/token_balances.rs b/ledger/src/token_balances.rs index 673cc5556b1..a15755ea57a 100644 --- a/ledger/src/token_balances.rs +++ b/ledger/src/token_balances.rs @@ -156,7 +156,8 @@ mod test { data: data.to_vec(), owner: pubkey_from_spl_token(&spl_token::id()), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let other_mint_pubkey = Pubkey::new_unique(); let other_mint = Account { @@ -164,7 +165,8 @@ mod test { data: data.to_vec(), owner: Pubkey::new_unique(), // !is_known_spl_token_id executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let token_owner = Pubkey::new_unique(); @@ -186,14 +188,16 @@ mod test { data: data.to_vec(), owner: pubkey_from_spl_token(&spl_token::id()), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let other_account = Account { lamports: 100, data: data.to_vec(), owner: Pubkey::new_unique(), // !is_known_spl_token_id executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let other_mint_data = TokenAccount { @@ -214,7 +218,8 @@ mod test { data: data.to_vec(), owner: pubkey_from_spl_token(&spl_token::id()), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let mut accounts = BTreeMap::new(); @@ -319,7 +324,8 @@ mod test { data: mint_data.to_vec(), owner: pubkey_from_spl_token(&spl_token_2022::id()), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let other_mint_pubkey = Pubkey::new_unique(); let other_mint = Account { @@ -327,7 +333,8 @@ mod test { data: mint_data.to_vec(), owner: Pubkey::new_unique(), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let token_owner = Pubkey::new_unique(); @@ -363,14 +370,16 @@ mod test { data: account_data.to_vec(), owner: pubkey_from_spl_token(&spl_token_2022::id()), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let other_account = Account { lamports: 100, data: account_data.to_vec(), owner: Pubkey::new_unique(), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let other_mint_token_base = TokenAccount { @@ -405,7 +414,8 @@ mod test { data: account_data.to_vec(), owner: pubkey_from_spl_token(&spl_token_2022::id()), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let mut accounts = BTreeMap::new(); diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 11e9c6b0932..b7ed9471f17 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -30,6 +30,7 @@ use { alloc::Layout, borrow::Cow, cell::RefCell, + collections::HashMap, fmt::{self, Debug}, rc::Rc, sync::Arc, @@ -101,6 +102,29 @@ struct SyscallContext { allocator: Rc>, } +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ApplicationFeeChanges { + pub application_fees: HashMap, + pub rebated: HashMap, + pub updated: Vec<(Pubkey, u64)>, +} + +impl ApplicationFeeChanges { + pub fn new() -> Self { + Self { + application_fees: HashMap::new(), + rebated: HashMap::new(), + updated: Vec::new(), + } + } +} + +impl Default for ApplicationFeeChanges { + fn default() -> Self { + Self::new() + } +} + pub struct InvokeContext<'a> { pub transaction_context: &'a mut TransactionContext, rent: Rent, @@ -119,6 +143,7 @@ pub struct InvokeContext<'a> { pub blockhash: Hash, pub lamports_per_signature: u64, syscall_context: Vec>, + pub application_fee_changes: ApplicationFeeChanges, } impl<'a> InvokeContext<'a> { @@ -135,6 +160,7 @@ impl<'a> InvokeContext<'a> { blockhash: Hash, lamports_per_signature: u64, prev_accounts_data_len: u64, + application_fees: HashMap, ) -> Self { Self { transaction_context, @@ -154,6 +180,11 @@ impl<'a> InvokeContext<'a> { blockhash, lamports_per_signature, syscall_context: Vec::new(), + application_fee_changes: ApplicationFeeChanges { + application_fees, + rebated: HashMap::new(), + updated: Vec::new(), + }, } } @@ -191,6 +222,7 @@ impl<'a> InvokeContext<'a> { Hash::default(), 0, 0, + HashMap::new(), ) } @@ -369,6 +401,24 @@ impl<'a> InvokeContext<'a> { .checked_add(u128::from(account.lamports())) .ok_or(InstructionError::UnbalancedInstruction)?; + // additional check on application fees if they are balanced / ie if account has application fees then they should be either in application fees or in rebates + if pre_account.has_application_fees() { + let key = pre_account.key(); + let app_fees = self + .application_fee_changes + .application_fees + .get(key) + .map_or(0, |x| *x); + let rebates = self + .application_fee_changes + .rebated + .get(key) + .map_or(0, |x| *x); + if pre_account.application_fees() != app_fees + rebates { + return Err(InstructionError::UnbalancedInstruction); + } + } + let pre_data_len = pre_account.data().len() as i64; let post_data_len = account.data().len() as i64; let data_len_delta = post_data_len.saturating_sub(pre_data_len); @@ -454,7 +504,7 @@ impl<'a> InvokeContext<'a> { .checked_add(u128::from(account.lamports())) .ok_or(InstructionError::UnbalancedInstruction)?; if is_writable && !pre_account.executable() { - pre_account.update(account.clone()); + pre_account.update(account.clone())?; } let pre_data_len = pre_account.data().len() as i64; diff --git a/program-runtime/src/pre_account.rs b/program-runtime/src/pre_account.rs index 2ca91ba0904..4cc04545bcd 100644 --- a/program-runtime/src/pre_account.rs +++ b/program-runtime/src/pre_account.rs @@ -118,6 +118,13 @@ impl PreAccount { return Err(InstructionError::RentEpochModified); } + // no one modifies application fees (yet) + let application_fees_changed = pre.has_application_fees() != post.has_application_fees() + || pre.application_fees() != post.application_fees(); + if application_fees_changed { + return Err(InstructionError::CannotChangeApplicationFees); + } + if outermost_call { timings.total_account_count = timings.total_account_count.saturating_add(1); if owner_changed @@ -134,12 +141,13 @@ impl PreAccount { Ok(()) } - pub fn update(&mut self, account: AccountSharedData) { + pub fn update(&mut self, account: AccountSharedData) -> Result<(), InstructionError> { let rent_epoch = self.account.rent_epoch(); self.account = account; - self.account.set_rent_epoch(rent_epoch); + self.account.set_rent_epoch(rent_epoch)?; self.changed = true; + Ok(()) } pub fn key(&self) -> &Pubkey { @@ -158,6 +166,14 @@ impl PreAccount { self.account.executable() } + pub fn has_application_fees(&self) -> bool { + self.account.has_application_fees() + } + + pub fn application_fees(&self) -> u64 { + self.account.application_fees() + } + pub fn is_zeroed(buf: &[u8]) -> bool { const ZEROS_LEN: usize = 1024; static ZEROS: [u8; ZEROS_LEN] = [0; ZEROS_LEN]; @@ -251,10 +267,19 @@ mod tests { self.post.set_data(post); self } - pub fn rent_epoch(mut self, pre: u64, post: u64) -> Self { - self.pre.account.set_rent_epoch(pre); - self.post.set_rent_epoch(post); - self + pub fn rent_epoch(mut self, pre: u64, post: u64) -> Result { + self.pre.account.set_rent_epoch(pre)?; + self.post.set_rent_epoch(post)?; + Ok(self) + } + pub fn change_application_fees( + mut self, + pre: u64, + post: u64, + ) -> Result { + self.pre.account.set_application_fees(pre)?; + self.post.set_application_fees(post)?; + Ok(self) } pub fn verify(&self) -> Result<(), InstructionError> { self.pre.verify( @@ -498,12 +523,32 @@ mod tests { assert_eq!( Change::new(&alice_program_id, &system_program::id()) .rent_epoch(0, 1) + .unwrap() .verify(), Err(InstructionError::RentEpochModified), "no one touches rent_epoch" ); } + #[test] + fn test_verify_account_changes_application_fees() { + let alice_program_id = solana_sdk::pubkey::new_rand(); + + assert_eq!( + Change::new(&alice_program_id, &system_program::id()).verify(), + Ok(()), + "nothing changed!" + ); + assert_eq!( + Change::new(&alice_program_id, &system_program::id()) + .change_application_fees(0, 1) + .unwrap() + .verify(), + Err(InstructionError::CannotChangeApplicationFees), + "no one touches application fees" + ); + } + #[test] fn test_verify_account_changes_deduct_lamports_and_reassign_account() { let alice_program_id = solana_sdk::pubkey::new_rand(); diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index 105cba8a44c..4ba3d171a1b 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -549,7 +549,8 @@ impl ProgramTest { })), owner, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }, ); } @@ -571,7 +572,8 @@ impl ProgramTest { .unwrap_or_else(|err| panic!("Failed to base64 decode: {err}")), owner, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }, ); } @@ -620,7 +622,8 @@ impl ProgramTest { data, owner: solana_sdk::bpf_loader::id(), executable: true, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }, ); }; diff --git a/program-test/src/programs.rs b/program-test/src/programs.rs index 78d67453da2..abfb4af9795 100644 --- a/program-test/src/programs.rs +++ b/program-test/src/programs.rs @@ -87,7 +87,8 @@ pub fn spl_programs(rent: &Rent) -> Vec<(Pubkey, AccountSharedData)> { data, owner: *loader_id, executable: true, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), )); accounts.into_iter() diff --git a/programs/application-fees-tests/Cargo.toml b/programs/application-fees-tests/Cargo.toml new file mode 100644 index 00000000000..2723b780f0f --- /dev/null +++ b/programs/application-fees-tests/Cargo.toml @@ -0,0 +1,20 @@ + +[package] +name = "solana-application-fees-program-tests" +version = "1.16.0" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" +edition = "2021" +publish = false + +[dev-dependencies] +assert_matches = "1.5.0" +bincode = "1.3.3" +solana-application-fees-program = { path = "../application-fees", version = "=1.16.0" } +solana-program-test = { path = "../../program-test", version = "=1.16.0" } +solana-sdk = { path = "../../sdk", version = "=1.16.0" } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/application-fees-tests/tests/add_update_remove.rs b/programs/application-fees-tests/tests/add_update_remove.rs new file mode 100644 index 00000000000..dbe781d5ead --- /dev/null +++ b/programs/application-fees-tests/tests/add_update_remove.rs @@ -0,0 +1,254 @@ +use solana_application_fees_program::instruction::update_fees; +use solana_sdk::native_token::LAMPORTS_PER_SOL; + +use { + assert_matches::assert_matches, + solana_program_test::tokio, + solana_sdk::{ + signature::{Keypair, Signer}, + transaction::Transaction, + }, +}; + +mod common; +use { + crate::common::{ + advance_slot, assert_error, create_owner_and_dummy_account, setup_test_context, + }, + solana_sdk::instruction::InstructionError, +}; + +#[tokio::test] +async fn test_add_update_remove_write_lock_fees() { + let mut context = setup_test_context().await; + + let (owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + + { + let client = &mut context.banks_client; + + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(100, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&context.payer.pubkey()), + &[&context.payer, &owner], + recent_blockhash, + ); + + let account = client.get_account(writable_account).await.unwrap().unwrap(); + assert_eq!(account.has_application_fees, false); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + } + + advance_slot(&mut context).await; + + let account = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, 100); + + { + let client = &mut context.banks_client; + let recent_blockhash = context.last_blockhash; + // test update + let update_ix = update_fees(10000, writable_account, owner.pubkey()); + + let update_transaction = Transaction::new_signed_with_payer( + &[update_ix.clone()], + Some(&context.payer.pubkey()), + &[&context.payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(update_transaction).await, Ok(())); + } + advance_slot(&mut context).await; + + let account2 = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account2.rent_epoch_or_application_fees, 10000); + assert_eq!(account2.has_application_fees, true); + + { + let client = &mut context.banks_client; + let recent_blockhash = context.last_blockhash; + // test remove + let remove_ix = update_fees(0, writable_account, owner.pubkey()); + + let remove_transaction = Transaction::new_signed_with_payer( + &[remove_ix.clone()], + Some(&context.payer.pubkey()), + &[&context.payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(remove_transaction).await, Ok(())); + } + + advance_slot(&mut context).await; + + let account3 = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account3.rent_epoch_or_application_fees, 0); + assert_eq!(account3.has_application_fees, false); +} + +#[tokio::test] +async fn test_adding_write_lock_fees_with_wrong_owner() { + let mut context = setup_test_context().await; + + let (_owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + let (owner2, _writable_account2) = create_owner_and_dummy_account(&mut context).await; + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(100, writable_account, owner2.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner2], + recent_blockhash, + ); + + assert_error( + client.process_transaction(transaction).await, + InstructionError::IllegalOwner, + ) + .await; + } +} + +#[tokio::test] +#[should_panic] +async fn test_adding_write_lock_fees_without_signature_owner() { + let mut context = setup_test_context().await; + + let (owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(100, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer], + recent_blockhash, + ); + + assert_error( + client.process_transaction(transaction).await, + InstructionError::MissingRequiredSignature, + ) + .await; + } +} + +#[tokio::test] +#[should_panic] +async fn test_adding_write_lock_fees_without_signature_payer() { + let mut context = setup_test_context().await; + + let (owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(100, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[&owner], + recent_blockhash, + ); + + assert_error( + client.process_transaction(transaction).await, + InstructionError::MissingRequiredSignature, + ) + .await; + } +} + +#[tokio::test] +async fn test_add_update_remove_owner_same_as_writable_account() { + let mut context = setup_test_context().await; + + let owner = Keypair::new(); + let writable_account = owner.pubkey(); + + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(LAMPORTS_PER_SOL, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + } + advance_slot(&mut context).await; + + // test update + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + + let update_ix = update_fees(2 * LAMPORTS_PER_SOL, writable_account, owner.pubkey()); + + let update_transaction = Transaction::new_signed_with_payer( + &[update_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(update_transaction).await, Ok(())); + } + advance_slot(&mut context).await; + + // test remove + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + + let remove_ix = update_fees(0, writable_account, owner.pubkey()); + + let remove_transaction = Transaction::new_signed_with_payer( + &[remove_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(remove_transaction).await, Ok(())); + } +} diff --git a/programs/application-fees-tests/tests/common.rs b/programs/application-fees-tests/tests/common.rs new file mode 100644 index 00000000000..7622cc1ce00 --- /dev/null +++ b/programs/application-fees-tests/tests/common.rs @@ -0,0 +1,57 @@ +use { + assert_matches::assert_matches, + solana_application_fees_program::{id, processor::process_instruction}, + solana_program_test::{ + BanksClientError, ProgramTest, ProgramTestBanksClientExt, ProgramTestContext, + }, + solana_sdk::{ + instruction::InstructionError, + pubkey::Pubkey, + signer::{keypair::Keypair, Signer}, + system_instruction::create_account, + transaction::{Transaction, TransactionError}, + }, +}; +pub async fn setup_test_context() -> ProgramTestContext { + let program_test = ProgramTest::new("", id(), Some(process_instruction)); + program_test.start_with_context().await +} + +pub async fn create_owner_and_dummy_account(context: &mut ProgramTestContext) -> (Keypair, Pubkey) { + let owner = Keypair::new(); + let account = create_a_dummy_account(context, &owner.pubkey()).await; + (owner, account) +} + +pub async fn create_a_dummy_account(context: &mut ProgramTestContext, owner: &Pubkey) -> Pubkey { + let account = Keypair::new(); + let payer = &context.payer; + let client = &mut context.banks_client; + let recent_blockhash = context.last_blockhash; + let ix = create_account(&payer.pubkey(), &account.pubkey(), 100_000_000, 1, owner); + let tx = Transaction::new_signed_with_payer( + &[ix.clone()], + Some(&payer.pubkey()), + &[payer, &account], + recent_blockhash, + ); + assert_matches!(client.process_transaction(tx).await, Ok(())); + account.pubkey() +} + +pub async fn advance_slot(context: &mut ProgramTestContext) { + let client = &mut context.banks_client; + context.last_blockhash = client + .get_new_latest_blockhash(&context.last_blockhash) + .await + .unwrap(); + let slot = context.banks_client.get_root_slot().await.unwrap(); + context.warp_to_slot(slot + 1).unwrap(); +} + +pub async fn assert_error(res: Result<(), BanksClientError>, expected_err: InstructionError) { + assert_eq!( + res.unwrap_err().unwrap(), + TransactionError::InstructionError(0, expected_err), + ); +} diff --git a/programs/application-fees-tests/tests/rebate.rs b/programs/application-fees-tests/tests/rebate.rs new file mode 100644 index 00000000000..f5e74bd34ee --- /dev/null +++ b/programs/application-fees-tests/tests/rebate.rs @@ -0,0 +1,544 @@ +mod common; +use { + crate::common::{ + advance_slot, assert_error, create_owner_and_dummy_account, setup_test_context, + }, + assert_matches::assert_matches, + solana_application_fees_program::instruction::{rebate, update_fees}, + solana_program_test::tokio, + solana_sdk::{ + instruction::InstructionError, native_token::LAMPORTS_PER_SOL, signature::Keypair, + system_instruction, system_transaction, + }, + solana_sdk::{signature::Signer, transaction::Transaction}, +}; + +#[tokio::test] +async fn test_application_fees_are_applied_without_rebate() { + let mut context = setup_test_context().await; + + let (owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(LAMPORTS_PER_SOL, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + let account = client.get_account(writable_account).await.unwrap().unwrap(); + assert_eq!(account.has_application_fees, false); + assert_eq!(account.rent_epoch_or_application_fees, 0); + } + advance_slot(&mut context).await; + let account = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, LAMPORTS_PER_SOL); + + // check if the application fees are correcly dispatched to the correct account + let balance_writable_account_before = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + + // transfer 1 lamport to the writable account / but payer has to pay 1SOL as application fee + { + let client = &mut context.banks_client; + let payer = &context.payer; + let balance_before_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + + let blockhash = client.get_latest_blockhash().await.unwrap(); + let transfer_ix = system_transaction::transfer(payer, &writable_account, 1, blockhash); + assert_matches!(client.process_transaction(transfer_ix).await, Ok(())); + + let balance_after_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + assert!(balance_before_transaction - balance_after_transaction > LAMPORTS_PER_SOL); + } + + advance_slot(&mut context).await; + let balance_writable_account_after = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + assert_eq!( + balance_writable_account_after - balance_writable_account_before, + LAMPORTS_PER_SOL + 1 + ); +} + +#[tokio::test] +async fn test_application_fees_are_applied_on_multiple_accounts() { + let mut context = setup_test_context().await; + + let (owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + let (owner2, writable_account2) = create_owner_and_dummy_account(&mut context).await; + + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(LAMPORTS_PER_SOL, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + let add_ix = update_fees(LAMPORTS_PER_SOL * 2, writable_account2, owner2.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner2], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + } + advance_slot(&mut context).await; + + let account = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, LAMPORTS_PER_SOL); + + let account = context + .banks_client + .get_account(writable_account2) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, 2 * LAMPORTS_PER_SOL); + + let account = context + .banks_client + .get_account(writable_account2) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, 2 * LAMPORTS_PER_SOL); + + let balance_writable_account_before = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + let balance_writable_account_2_before = context + .banks_client + .get_balance(writable_account2) + .await + .unwrap(); + + // transfer 1 lamport to the writable account / but payer has to pay 1SOL as application fee + { + let client = &mut context.banks_client; + let payer = &context.payer; + let balance_before_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + + let blockhash = client.get_latest_blockhash().await.unwrap(); + let transfer_ix1 = system_instruction::transfer(&payer.pubkey(), &writable_account, 1); + let transfer_ix2 = system_instruction::transfer(&payer.pubkey(), &writable_account2, 1); + let transaction = Transaction::new_signed_with_payer( + &[transfer_ix1.clone(), transfer_ix2.clone()], + Some(&payer.pubkey()), + &[payer], + blockhash, + ); + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + let balance_after_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + assert!(balance_before_transaction - balance_after_transaction > 3 * LAMPORTS_PER_SOL); + } + + // check if the application fees are correcly dispatched to the correct account + advance_slot(&mut context).await; + let balance_writable_account_after = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + let balance_writable_account_2_after = context + .banks_client + .get_balance(writable_account2) + .await + .unwrap(); + assert_eq!( + balance_writable_account_after - balance_writable_account_before, + 1 * LAMPORTS_PER_SOL + 1 + ); + assert_eq!( + balance_writable_account_2_after - balance_writable_account_2_before, + 2 * LAMPORTS_PER_SOL + 1 + ); +} + +#[tokio::test] +async fn test_application_fees_are_applied_without_rebate_for_failed_transactions() { + let mut context = setup_test_context().await; + + let (owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + + let payer2 = { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(LAMPORTS_PER_SOL, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + let payer2 = Keypair::new(); + let transfer_ix = system_transaction::transfer( + payer, + &payer2.pubkey(), + 10 * LAMPORTS_PER_SOL, + recent_blockhash, + ); + assert_matches!(client.process_transaction(transfer_ix).await, Ok(())); + payer2 + }; + + advance_slot(&mut context).await; + let account = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, LAMPORTS_PER_SOL); + + // transfer 11 SOLs to the writable account which the payer clearly does not have / but payer has to pay 1SOL as application fee + { + let client = &mut context.banks_client; + let payer = &payer2; + let balance_before_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + + let blockhash = client.get_latest_blockhash().await.unwrap(); + let transfer_ix = system_transaction::transfer( + payer, + &writable_account, + 11 * LAMPORTS_PER_SOL, + blockhash, + ); + assert_error( + client.process_transaction(transfer_ix).await, + InstructionError::Custom(1), + ) + .await; + + let balance_after_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + assert!(balance_before_transaction - balance_after_transaction > LAMPORTS_PER_SOL); + } + + // check if the application fees are correcly dispatched to the correct account + let balance_writable_account_before = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + + advance_slot(&mut context).await; + + let balance_writable_account_after = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + assert_eq!( + balance_writable_account_after - balance_writable_account_before, + LAMPORTS_PER_SOL + ); +} + +#[tokio::test] +async fn test_application_fees_are_not_applied_if_rebated() { + let mut context = setup_test_context().await; + + let (owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(LAMPORTS_PER_SOL, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + } + advance_slot(&mut context).await; + + let account = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, LAMPORTS_PER_SOL); + + // transfer 1 lamport to the writable account / but payer has to pay 1SOL as application fee + { + let client = &mut context.banks_client; + let payer = &context.payer; + let balance_before_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + + let blockhash = client.get_latest_blockhash().await.unwrap(); + let transfer_ix = system_instruction::transfer(&payer.pubkey(), &writable_account, 1); + let rebate_ix = rebate(writable_account, owner.pubkey(), u64::MAX); + let transaction = Transaction::new_signed_with_payer( + &[transfer_ix.clone(), rebate_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + blockhash, + ); + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + let balance_after_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + assert!(balance_before_transaction - balance_after_transaction < LAMPORTS_PER_SOL); + } + + // check if the application fees are correcly dispatched to the correct account + let balance_writable_account_before = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + + advance_slot(&mut context).await; + + let balance_writable_account_after = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + assert_eq!( + balance_writable_account_after - balance_writable_account_before, + 0 + ); +} + +#[tokio::test] +async fn test_application_fees_are_not_applied_on_single_rebated_account() { + let mut context = setup_test_context().await; + + let (owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + let (owner2, writable_account2) = create_owner_and_dummy_account(&mut context).await; + + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(LAMPORTS_PER_SOL, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + let add_ix = update_fees(LAMPORTS_PER_SOL * 2, writable_account2, owner2.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner2], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + } + + advance_slot(&mut context).await; + let account = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, LAMPORTS_PER_SOL); + + let account = context + .banks_client + .get_account(writable_account2) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, 2 * LAMPORTS_PER_SOL); + + // transfer 1 lamport to the writable account / but payer has to pay 1SOL as application fee + { + let client = &mut context.banks_client; + let payer = &context.payer; + let balance_before_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + + let blockhash = client.get_latest_blockhash().await.unwrap(); + let transfer_ix1 = system_instruction::transfer(&payer.pubkey(), &writable_account, 1); + let transfer_ix2 = system_instruction::transfer(&payer.pubkey(), &writable_account2, 1); + let rebate_ix = rebate(writable_account, owner.pubkey(), u64::MAX); + let transaction = Transaction::new_signed_with_payer( + &[ + transfer_ix1.clone(), + transfer_ix2.clone(), + rebate_ix.clone(), + ], + Some(&payer.pubkey()), + &[payer, &owner], + blockhash, + ); + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + let balance_after_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + assert!(balance_before_transaction - balance_after_transaction > 2 * LAMPORTS_PER_SOL); + assert!(balance_before_transaction - balance_after_transaction < 3 * LAMPORTS_PER_SOL); + } + + // check if the application fees are correcly dispatched to the correct account + let balance_writable_account_before = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + let balance_writable_account_2_before = context + .banks_client + .get_balance(writable_account2) + .await + .unwrap(); + + advance_slot(&mut context).await; + + let balance_writable_account_after = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + let balance_writable_account_2_after = context + .banks_client + .get_balance(writable_account2) + .await + .unwrap(); + assert_eq!( + balance_writable_account_after - balance_writable_account_before, + 0 + ); + assert_eq!( + balance_writable_account_2_after - balance_writable_account_2_before, + 2 * LAMPORTS_PER_SOL + ); +} + +#[tokio::test] +async fn test_application_fees_are_not_applied_if_rebated_owner_same_as_writable_account() { + let mut context = setup_test_context().await; + + let owner = Keypair::new(); + let writable_account = owner.pubkey(); + + { + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let transfer_ix = + system_instruction::transfer(&payer.pubkey(), &writable_account, LAMPORTS_PER_SOL); + let add_ix = update_fees(LAMPORTS_PER_SOL, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[transfer_ix.clone(), add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + } + advance_slot(&mut context).await; + + let account = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, LAMPORTS_PER_SOL); + + // transfer 1 lamport to the writable account / but payer has to pay 1SOL as application fee + { + let client = &mut context.banks_client; + let payer = &context.payer; + let balance_before_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + + let blockhash = client.get_latest_blockhash().await.unwrap(); + let transfer_ix = system_instruction::transfer(&payer.pubkey(), &writable_account, 1); + let rebate_ix = rebate(writable_account, owner.pubkey(), u64::MAX); + let transaction = Transaction::new_signed_with_payer( + &[transfer_ix.clone(), rebate_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + blockhash, + ); + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + let balance_after_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + assert!(balance_before_transaction - balance_after_transaction < LAMPORTS_PER_SOL); + } + + // check if the application fees are correcly dispatched to the correct account + let balance_writable_account_before = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + advance_slot(&mut context).await; + + let balance_writable_account_after = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + assert_eq!( + balance_writable_account_after - balance_writable_account_before, + 0 + ); +} diff --git a/programs/application-fees-tests/tests/rebate_all.rs b/programs/application-fees-tests/tests/rebate_all.rs new file mode 100644 index 00000000000..d9112404e83 --- /dev/null +++ b/programs/application-fees-tests/tests/rebate_all.rs @@ -0,0 +1,168 @@ +use solana_application_fees_program::instruction::{rebate_all, update_fees}; + +use { + assert_matches::assert_matches, + solana_program_test::tokio, + solana_sdk::{signature::Signer, transaction::Transaction}, +}; + +mod common; +use { + crate::common::{ + advance_slot, create_a_dummy_account, create_owner_and_dummy_account, setup_test_context, + }, + solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction}, +}; + +#[tokio::test] +async fn test_application_fees_are_not_applied_on_rebate_all() { + let mut context = setup_test_context().await; + + let (owner, writable_account) = create_owner_and_dummy_account(&mut context).await; + let (owner2, writable_account2) = create_owner_and_dummy_account(&mut context).await; + let writable_account3 = create_a_dummy_account(&mut context, &owner.pubkey()).await; + + { + // update fees for account 1 + let client = &mut context.banks_client; + let payer = &context.payer; + let recent_blockhash = context.last_blockhash; + let add_ix = update_fees(LAMPORTS_PER_SOL, writable_account, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + // update fees for account 2 + let add_ix = update_fees(LAMPORTS_PER_SOL * 2, writable_account2, owner2.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner2], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + // update fees for account 3 + let add_ix = update_fees(LAMPORTS_PER_SOL * 3, writable_account3, owner.pubkey()); + + let transaction = Transaction::new_signed_with_payer( + &[add_ix.clone()], + Some(&payer.pubkey()), + &[payer, &owner], + recent_blockhash, + ); + + assert_matches!(client.process_transaction(transaction).await, Ok(())); + } + + advance_slot(&mut context).await; + + let account = context + .banks_client + .get_account(writable_account) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, LAMPORTS_PER_SOL); + + let account = context + .banks_client + .get_account(writable_account2) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, 2 * LAMPORTS_PER_SOL); + + let account = context + .banks_client + .get_account(writable_account3) + .await + .unwrap() + .unwrap(); + assert_eq!(account.has_application_fees, true); + assert_eq!(account.rent_epoch_or_application_fees, 3 * LAMPORTS_PER_SOL); + + // check if the application fees are correcly dispatched to the correct account + let balance_writable_account_before = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + let balance_writable_account_2_before = context + .banks_client + .get_balance(writable_account2) + .await + .unwrap(); + let balance_writable_account_3_before = context + .banks_client + .get_balance(writable_account3) + .await + .unwrap(); + + // transfer 1 lamport to the writable accounts / rebate_all for owner (rebates 3+1 SOLs) / but payer has to pay 2SOL as application fee + { + let client = &mut context.banks_client; + let payer = &context.payer; + let balance_before_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + + let blockhash = client.get_latest_blockhash().await.unwrap(); + let transfer_ix1 = system_instruction::transfer(&payer.pubkey(), &writable_account, 1); + let transfer_ix2 = system_instruction::transfer(&payer.pubkey(), &writable_account2, 1); + let transfer_ix3 = system_instruction::transfer(&payer.pubkey(), &writable_account3, 1); + let rebate_all = rebate_all(owner.pubkey()); + let transaction = Transaction::new_signed_with_payer( + &[ + transfer_ix1.clone(), + transfer_ix2.clone(), + transfer_ix3.clone(), + rebate_all.clone(), + ], + Some(&payer.pubkey()), + &[payer, &owner], + blockhash, + ); + assert_matches!(client.process_transaction(transaction).await, Ok(())); + + let balance_after_transaction = client.get_balance(payer.pubkey()).await.unwrap(); + assert!(balance_before_transaction - balance_after_transaction < 3 * LAMPORTS_PER_SOL); + } + + advance_slot(&mut context).await; + let balance_writable_account_after = context + .banks_client + .get_balance(writable_account) + .await + .unwrap(); + let balance_writable_account_2_after = context + .banks_client + .get_balance(writable_account2) + .await + .unwrap(); + let balance_writable_account_3_after = context + .banks_client + .get_balance(writable_account3) + .await + .unwrap(); + assert_eq!( + balance_writable_account_after - balance_writable_account_before, + 1 + ); + assert_eq!( + balance_writable_account_2_after - balance_writable_account_2_before, + 2 * LAMPORTS_PER_SOL + 1 + ); + assert_eq!( + balance_writable_account_3_after - balance_writable_account_3_before, + 1 + ); +} diff --git a/programs/application-fees/Cargo.toml b/programs/application-fees/Cargo.toml new file mode 100644 index 00000000000..a81ab316ec1 --- /dev/null +++ b/programs/application-fees/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "solana-application-fees-program" +version = "1.16.0" +description = "Solana Application Fee program" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" +documentation = "https://docs.rs/solana-application-fees" +edition = "2021" + +[dependencies] +bincode = "1.3.3" +log = "0.4.17" +bytemuck = "1.11.0" +num-derive = "0.3" +num-traits = "0.2" +serde = { version = "1.0.152", features = ["derive"] } +solana-frozen-abi = { path = "../../frozen-abi", version = "=1.16.0" } +solana-frozen-abi-macro = { path = "../../frozen-abi/macro", version = "=1.16.0" } +solana-program = { path = "../../sdk/program", version = "=1.16.0" } + +[target.'cfg(not(target_os = "solana"))'.dependencies] +solana-program-runtime = { path = "../../program-runtime", version = "=1.16.0" } +solana-sdk = { path = "../../sdk", version = "=1.16.0" } + +[build-dependencies] +rustc_version = "0.4" + +[lib] +crate-type = ["lib"] +name = "solana_application_fees_program" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/application-fees/build.rs b/programs/application-fees/build.rs new file mode 100644 index 00000000000..c9550c1c5c4 --- /dev/null +++ b/programs/application-fees/build.rs @@ -0,0 +1,27 @@ +extern crate rustc_version; +use rustc_version::{version_meta, Channel}; + +fn main() { + // Copied and adapted from + // https://github.com/Kimundi/rustc-version-rs/blob/1d692a965f4e48a8cb72e82cda953107c0d22f47/README.md#example + // Licensed under Apache-2.0 + MIT + match version_meta().unwrap().channel { + Channel::Stable => { + println!("cargo:rustc-cfg=RUSTC_WITHOUT_SPECIALIZATION"); + } + Channel::Beta => { + println!("cargo:rustc-cfg=RUSTC_WITHOUT_SPECIALIZATION"); + } + Channel::Nightly => { + println!("cargo:rustc-cfg=RUSTC_WITH_SPECIALIZATION"); + } + Channel::Dev => { + println!("cargo:rustc-cfg=RUSTC_WITH_SPECIALIZATION"); + // See https://github.com/solana-labs/solana/issues/11055 + // We may be running the custom `rust-bpf-builder` toolchain, + // which currently needs `#![feature(proc_macro_hygiene)]` to + // be applied. + println!("cargo:rustc-cfg=RUSTC_NEEDS_PROC_MACRO_HYGIENE"); + } + } +} diff --git a/programs/application-fees/src/instruction.rs b/programs/application-fees/src/instruction.rs new file mode 100644 index 00000000000..91cf1073d54 --- /dev/null +++ b/programs/application-fees/src/instruction.rs @@ -0,0 +1,50 @@ +use serde::{Deserialize, Serialize}; +use solana_frozen_abi_macro::{AbiEnumVisitor, AbiExample}; + +use solana_program::{ + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, +}; + +// application fees instructions +#[derive(AbiExample, AbiEnumVisitor, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] +pub enum ApplicationFeesInstuctions { + // Add, Remove or change fees for a writable account + // Set fees=0 to remove the fees + UpdateFees { fees: u64 }, + // The write account owner i.e program usually can CPI this instruction to rebate the fees to good actors + // Rebate take fee amount to be rebated + Rebate { rebate_fees: u64 }, + // Rebase all fees beloning to the owner + RebateAll, +} + +pub fn update_fees(fees: u64, writable_account: Pubkey, owner: Pubkey) -> Instruction { + Instruction::new_with_bincode( + crate::id(), + &ApplicationFeesInstuctions::UpdateFees { fees: fees }, + vec![ + AccountMeta::new_readonly(owner, true), + AccountMeta::new(writable_account, false), + ], + ) +} + +pub fn rebate(writable_account: Pubkey, owner: Pubkey, rebate_fees: u64) -> Instruction { + Instruction::new_with_bincode( + crate::id(), + &ApplicationFeesInstuctions::Rebate { rebate_fees }, + vec![ + AccountMeta::new_readonly(owner, true), + AccountMeta::new_readonly(writable_account, false), + ], + ) +} + +pub fn rebate_all(owner: Pubkey) -> Instruction { + Instruction::new_with_bincode( + crate::id(), + &ApplicationFeesInstuctions::RebateAll, + vec![AccountMeta::new_readonly(owner, true)], + ) +} diff --git a/programs/application-fees/src/lib.rs b/programs/application-fees/src/lib.rs new file mode 100644 index 00000000000..4340a69bd9e --- /dev/null +++ b/programs/application-fees/src/lib.rs @@ -0,0 +1,12 @@ +#![allow(incomplete_features)] +#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))] +#![cfg_attr(RUSTC_NEEDS_PROC_MACRO_HYGIENE, feature(proc_macro_hygiene))] + +use solana_program::declare_id; + +#[cfg(not(target_os = "solana"))] +pub mod processor; + +pub mod instruction; + +declare_id!("App1icationFees1111111111111111111111111111"); diff --git a/programs/application-fees/src/processor.rs b/programs/application-fees/src/processor.rs new file mode 100644 index 00000000000..842b87ba14c --- /dev/null +++ b/programs/application-fees/src/processor.rs @@ -0,0 +1,215 @@ +use std::cmp::min; + +use crate::instruction::ApplicationFeesInstuctions; + +use { + solana_program_runtime::{ic_msg, invoke_context::InvokeContext}, + solana_sdk::{ + account::ReadableAccount, instruction::InstructionError, + program_utils::limited_deserialize, transaction_context::IndexOfAccount, + }, +}; + +pub fn process_instruction( + _first_instruction_account: IndexOfAccount, + invoke_context: &mut InvokeContext, +) -> Result<(), InstructionError> { + let transaction_context = &invoke_context.transaction_context; + let instruction_context = transaction_context.get_current_instruction_context()?; + let instruction_data = instruction_context.get_instruction_data(); + + match limited_deserialize(instruction_data)? { + ApplicationFeesInstuctions::UpdateFees { fees } => { + Processor::add_or_update_fees(invoke_context, fees) + } + ApplicationFeesInstuctions::Rebate { rebate_fees } => { + Processor::rebate(invoke_context, rebate_fees) + } + ApplicationFeesInstuctions::RebateAll => Processor::rebate_all(invoke_context), + } +} + +pub struct Processor; + +impl Processor { + fn add_or_update_fees( + invoke_context: &mut InvokeContext, + fees: u64, + ) -> Result<(), InstructionError> { + let transaction_context = &invoke_context.transaction_context; + let instruction_context = transaction_context.get_current_instruction_context()?; + + let owner = instruction_context.try_borrow_instruction_account(transaction_context, 0)?; + + if !owner.is_signer() { + ic_msg!(invoke_context, "Authority account must be a signer"); + return Err(InstructionError::MissingRequiredSignature); + } + + let writable_account = { + let index_in_transaction = + instruction_context.get_index_of_instruction_account_in_transaction(1)?; + let writable_account_key = + transaction_context.get_key_of_account_at_index(index_in_transaction)?; + if writable_account_key.eq(owner.get_key()) { + owner + } else { + let writable_account = + instruction_context.try_borrow_instruction_account(transaction_context, 1)?; + + if !writable_account.get_owner().eq(owner.get_key()) { + ic_msg!( + invoke_context, + "Invalid account owner {} instead of {}", + writable_account.get_owner().to_string(), + owner.get_key().to_string() + ); + return Err(InstructionError::IllegalOwner); + } + + drop(owner); + writable_account + } + }; + + if writable_account.get_rent_epoch() != 0 { + return Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch); + } + + let writable_account_key = *writable_account.get_key(); + ic_msg!( + invoke_context, + "ApplicationFeesInstuctions::Update called for {} to change fees to {}", + writable_account_key.to_string(), + fees + ); + drop(writable_account); + + invoke_context + .application_fee_changes + .updated + .push((writable_account_key, fees)); + Ok(()) + } + + fn rebate( + invoke_context: &mut InvokeContext, + rebate_fees: u64, + ) -> Result<(), InstructionError> { + let transaction_context = &invoke_context.transaction_context; + let instruction_context = transaction_context.get_current_instruction_context()?; + + let owner = instruction_context.try_borrow_instruction_account(transaction_context, 0)?; + if !owner.is_signer() { + ic_msg!(invoke_context, "Authority account must be a signer"); + return Err(InstructionError::MissingRequiredSignature); + } + + let index_in_transaction = + instruction_context.get_index_of_instruction_account_in_transaction(1)?; + let writable_account_key = + transaction_context.get_key_of_account_at_index(index_in_transaction)?; + let writable_account = { + if writable_account_key.eq(owner.get_key()) { + owner + } else { + let writable_account = + instruction_context.try_borrow_instruction_account(transaction_context, 1)?; + + if !writable_account.get_owner().eq(owner.get_key()) { + ic_msg!( + invoke_context, + "Invalid account owner {} instead of {}", + writable_account.get_owner().to_string(), + owner.get_key().to_string() + ); + return Err(InstructionError::IllegalOwner); + } + + drop(owner); + writable_account + } + }; + drop(writable_account); + // do rebate / update the application fees and add the rest into rebate + let lamports_rebated = { + let lamports = invoke_context + .application_fee_changes + .application_fees + .get_mut(&writable_account_key); + if let Some(lamports) = lamports { + let lamports_rebated = min(*lamports, rebate_fees); + // update app fees + *lamports = lamports.saturating_sub(lamports_rebated); + lamports_rebated + } else { + 0 + } + }; + // log message + if lamports_rebated > 0 { + invoke_context + .application_fee_changes + .rebated + .insert(*writable_account_key, lamports_rebated); + ic_msg!( + invoke_context, + "application fees rebated for writable account {} lamports {}", + writable_account_key.to_string(), + lamports_rebated + ); + } + Ok(()) + } + + fn rebate_all(invoke_context: &mut InvokeContext) -> Result<(), InstructionError> { + let transaction_context = &invoke_context.transaction_context; + let instruction_context = transaction_context.get_current_instruction_context()?; + let owner = instruction_context.try_borrow_instruction_account(transaction_context, 0)?; + let owner_key = *owner.get_key(); + if !owner.is_signer() { + ic_msg!(invoke_context, "Authority account must be a signer"); + return Err(InstructionError::MissingRequiredSignature); + } + drop(owner); + + let number_of_accounts = transaction_context.get_number_of_accounts(); + for i in 0..number_of_accounts { + let account = transaction_context.get_account_at_index(i)?; + let key = transaction_context.get_key_of_account_at_index(i)?; + let borrowed_account = account.try_borrow(); + if let Ok(borrowed_account) = borrowed_account { + let account_owner = borrowed_account.owner(); + if owner_key.eq(account_owner) && borrowed_account.has_application_fees() { + let lamports_rebated = invoke_context + .application_fee_changes + .application_fees + .get_mut(key); + // we have to do this because we have already borrowed invoke context as a mut + let mut rebated_amount = None; + if let Some(lamports_rebated) = lamports_rebated { + rebated_amount = Some(*lamports_rebated); + // add these in rabates map + invoke_context + .application_fee_changes + .rebated + .insert(*key, *lamports_rebated); + // update the application fee charged to 0 + *lamports_rebated = 0; + } + + // log message + if let Some(rebated_amount) = rebated_amount { + ic_msg!( + invoke_context, + "application fees rebated for writable account {} lamports {}", + key.to_string(), + rebated_amount, + ); + } + } + } + } + Ok(()) + } +} diff --git a/programs/bpf_loader/benches/serialization.rs b/programs/bpf_loader/benches/serialization.rs index e14f55476ca..f842b7aa7f2 100644 --- a/programs/bpf_loader/benches/serialization.rs +++ b/programs/bpf_loader/benches/serialization.rs @@ -24,7 +24,8 @@ fn create_inputs(owner: Pubkey, num_instruction_accounts: usize) -> TransactionC data: vec![], owner, executable: true, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), ), ( @@ -34,7 +35,8 @@ fn create_inputs(owner: Pubkey, num_instruction_accounts: usize) -> TransactionC data: vec![1u8; 100000], owner, executable: false, - rent_epoch: 100, + has_application_fees: false, + rent_epoch_or_application_fees: 100, }), ), ( @@ -44,7 +46,8 @@ fn create_inputs(owner: Pubkey, num_instruction_accounts: usize) -> TransactionC data: vec![11u8; 100000], owner, executable: true, - rent_epoch: 200, + has_application_fees: false, + rent_epoch_or_application_fees: 200, }), ), ( @@ -54,7 +57,8 @@ fn create_inputs(owner: Pubkey, num_instruction_accounts: usize) -> TransactionC data: vec![], owner, executable: false, - rent_epoch: 3100, + has_application_fees: false, + rent_epoch_or_application_fees: 3100, }), ), ( @@ -64,7 +68,8 @@ fn create_inputs(owner: Pubkey, num_instruction_accounts: usize) -> TransactionC data: vec![1u8; 100000], owner, executable: false, - rent_epoch: 100, + has_application_fees: false, + rent_epoch_or_application_fees: 100, }), ), ( @@ -74,7 +79,8 @@ fn create_inputs(owner: Pubkey, num_instruction_accounts: usize) -> TransactionC data: vec![11u8; 10000], owner, executable: true, - rent_epoch: 200, + has_application_fees: false, + rent_epoch_or_application_fees: 200, }), ), ( @@ -84,7 +90,8 @@ fn create_inputs(owner: Pubkey, num_instruction_accounts: usize) -> TransactionC data: vec![], owner, executable: false, - rent_epoch: 3100, + has_application_fees: false, + rent_epoch_or_application_fees: 3100, }), ), ]; diff --git a/programs/bpf_loader/src/serialization.rs b/programs/bpf_loader/src/serialization.rs index 46cf2a3914e..241ded123fc 100644 --- a/programs/bpf_loader/src/serialization.rs +++ b/programs/bpf_loader/src/serialization.rs @@ -534,7 +534,8 @@ mod tests { data: vec![], owner: bpf_loader::id(), executable: true, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), )]; @@ -549,7 +550,8 @@ mod tests { data: vec![], owner: program_id, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), )); } @@ -629,7 +631,8 @@ mod tests { data: vec![], owner: bpf_loader::id(), executable: true, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), ), ( @@ -639,7 +642,8 @@ mod tests { data: vec![1u8, 2, 3, 4, 5], owner: bpf_loader::id(), executable: false, - rent_epoch: 100, + has_application_fees: false, + rent_epoch_or_application_fees: 100, }), ), ( @@ -649,7 +653,8 @@ mod tests { data: vec![11u8, 12, 13, 14, 15, 16, 17, 18, 19], owner: bpf_loader::id(), executable: true, - rent_epoch: 200, + has_application_fees: false, + rent_epoch_or_application_fees: 200, }), ), ( @@ -659,7 +664,8 @@ mod tests { data: vec![], owner: bpf_loader::id(), executable: false, - rent_epoch: 3100, + has_application_fees: false, + rent_epoch_or_application_fees: 3100, }), ), ( @@ -669,7 +675,8 @@ mod tests { data: vec![1u8, 2, 3, 4, 5], owner: bpf_loader::id(), executable: false, - rent_epoch: 100, + has_application_fees: false, + rent_epoch_or_application_fees: 100, }), ), ( @@ -679,7 +686,8 @@ mod tests { data: vec![11u8, 12, 13, 14, 15, 16, 17, 18, 19], owner: bpf_loader::id(), executable: true, - rent_epoch: 200, + has_application_fees: false, + rent_epoch_or_application_fees: 200, }), ), ( @@ -689,7 +697,8 @@ mod tests { data: vec![], owner: bpf_loader::id(), executable: false, - rent_epoch: 3100, + has_application_fees: false, + rent_epoch_or_application_fees: 3100, }), ), ]; diff --git a/programs/bpf_loader/src/syscalls/cpi.rs b/programs/bpf_loader/src/syscalls/cpi.rs index a8baa383303..8e1af738e4c 100644 --- a/programs/bpf_loader/src/syscalls/cpi.rs +++ b/programs/bpf_loader/src/syscalls/cpi.rs @@ -1024,9 +1024,12 @@ fn update_callee_account( { return Err(SyscallError::InstructionError(InstructionError::RentEpochModified).into()); } else { - callee_account + if let Err(e) = callee_account .borrow_mut() - .set_rent_epoch(caller_account.rent_epoch); + .set_rent_epoch(caller_account.rent_epoch) + { + return Err(SyscallError::InstructionError(e).into()); + } } } @@ -1665,7 +1668,8 @@ mod tests { data, owner: program_id, executable: false, - rent_epoch: 100, + has_application_fees: false, + rent_epoch_or_application_fees: 100, }); vec![ ( @@ -1675,7 +1679,8 @@ mod tests { data: vec![], owner: bpf_loader::id(), executable: true, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), false, ), diff --git a/programs/vote/benches/process_vote.rs b/programs/vote/benches/process_vote.rs index 604d8b6107c..232faaadce8 100644 --- a/programs/vote/benches/process_vote.rs +++ b/programs/vote/benches/process_vote.rs @@ -65,7 +65,8 @@ fn create_accounts() -> ( data: vote_account_data, owner: solana_vote_program::id(), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, } }; diff --git a/rpc-client/src/mock_sender.rs b/rpc-client/src/mock_sender.rs index ca9cd45691f..7da20e8ef93 100644 --- a/rpc-client/src/mock_sender.rs +++ b/rpc-client/src/mock_sender.rs @@ -464,7 +464,8 @@ impl RpcSender for MockSender { data: vec![], owner: pubkey, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; serde_json::to_value(vec![ RpcKeyedAccount { diff --git a/rpc-client/src/nonblocking/rpc_client.rs b/rpc-client/src/nonblocking/rpc_client.rs index 4a55d1b69ac..f5f412f001e 100644 --- a/rpc-client/src/nonblocking/rpc_client.rs +++ b/rpc-client/src/nonblocking/rpc_client.rs @@ -5448,7 +5448,8 @@ pub fn create_rpc_client_mocks() -> crate::mock_sender::Mocks { data: vec![], owner: pubkey, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; UiAccount::encode(&pubkey, &account, UiAccountEncoding::Base64, None, None) }, diff --git a/rpc-client/src/rpc_client.rs b/rpc-client/src/rpc_client.rs index ce6d012e69d..910ce71eca0 100644 --- a/rpc-client/src/rpc_client.rs +++ b/rpc-client/src/rpc_client.rs @@ -4061,7 +4061,8 @@ pub fn create_rpc_client_mocks() -> crate::mock_sender::Mocks { data: vec![], owner: pubkey, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; UiAccount::encode(&pubkey, &account, UiAccountEncoding::Base64, None, None) }, @@ -4336,7 +4337,8 @@ mod tests { data: vec![], owner: program_id, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let keyed_account = RpcKeyedAccount { pubkey: pubkey.to_string(), diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 58a2cc8576d..02c03976b0f 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -64,6 +64,7 @@ solana-address-lookup-table-program = { path = "../programs/address-lookup-table solana-net-utils = { path = "../net-utils", version = "=1.16.0" } solana-stake-program = { path = "../programs/stake", version = "=1.16.0" } symlink = "0.1.0" +solana-program-runtime = { path = "../program-runtime", version = "=1.16.0" } [lib] crate-type = ["lib"] diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index d624621b6af..a16b488b795 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -4923,6 +4923,8 @@ pub mod tests { solana_address_lookup_table_program::id(), false, 0, + false, + 0, ) }; bank.store_account(&address_table_pubkey, &address_table_account); @@ -5499,7 +5501,8 @@ pub mod tests { let pubkey = Pubkey::new_unique(); let address = pubkey.to_string(); let data = vec![1, 2, 3, 4, 5]; - let account = AccountSharedData::create(42, data.clone(), Pubkey::default(), false, 0); + let account = + AccountSharedData::create(42, data.clone(), Pubkey::default(), false, 0, false, 0); bank.store_account(&pubkey, &account); let request = create_test_request( @@ -5552,7 +5555,8 @@ pub mod tests { let pubkey = Pubkey::new_unique(); let address = pubkey.to_string(); let data = vec![1, 2, 3, 4, 5]; - let account = AccountSharedData::create(42, data.clone(), Pubkey::default(), false, 0); + let account = + AccountSharedData::create(42, data.clone(), Pubkey::default(), false, 0, false, 0); bank.store_account(&pubkey, &account); // Test 3 accounts, one empty, one non-existent, and one with data diff --git a/rpc/src/transaction_status_service.rs b/rpc/src/transaction_status_service.rs index 9fbfe879e27..83efb711c77 100644 --- a/rpc/src/transaction_status_service.rs +++ b/rpc/src/transaction_status_service.rs @@ -228,6 +228,7 @@ pub(crate) mod tests { dashmap::DashMap, solana_account_decoder::parse_token::token_amount_to_ui_amount, solana_ledger::{genesis_utils::create_genesis_config, get_tmp_ledger_path}, + solana_program_runtime::invoke_context::ApplicationFeeChanges, solana_runtime::bank::{Bank, NonceFull, NoncePartial, RentDebits, TransactionBalancesSet}, solana_sdk::{ account_utils::StateMut, @@ -387,6 +388,7 @@ pub(crate) mod tests { return_data: None, executed_units: 0, accounts_data_len_delta: 0, + application_fees_changes: ApplicationFeeChanges::new(), }); let balances = TransactionBalancesSet { diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index a1068d4277c..252eecf8f6b 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -41,6 +41,7 @@ regex = "1.6.0" serde = { version = "1.0.152", features = ["rc"] } serde_derive = "1.0.103" solana-address-lookup-table-program = { path = "../programs/address-lookup-table", version = "=1.16.0" } +solana-application-fees-program = { path = "../programs/application-fees", version = "=1.16.0" } solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.16.0" } solana-bucket-map = { path = "../bucket_map", version = "=1.16.0" } solana-compute-budget-program = { path = "../programs/compute-budget", version = "=1.16.0" } diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index c5a8c3a0e02..5b44d84eaa9 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -123,6 +123,8 @@ pub struct Accounts { pub(crate) account_locks: Mutex, } +pub type ApplicationFees = HashMap; + // for the load instructions pub type TransactionRent = u64; pub type TransactionProgramIndices = Vec>; @@ -132,6 +134,7 @@ pub struct LoadedTransaction { pub program_indices: TransactionProgramIndices, pub rent: TransactionRent, pub rent_debits: RentDebits, + pub application_fees: ApplicationFees, } pub type TransactionLoadResult = (Result, Option); @@ -309,7 +312,11 @@ impl Accounts { let requested_loaded_accounts_data_size_limit = Self::get_requested_loaded_accounts_data_size_limit(feature_set); let mut accumulated_accounts_data_size: usize = 0; + let mut account_application_fees: HashMap = HashMap::new(); + let mut payer_index = 0; + // we reverse the iteration over keys so that we collect all the application fees + // and then validate fees at the last let mut accounts = account_keys .iter() .enumerate() @@ -365,21 +372,16 @@ impl Accounts { error_counters, )?; + if account.has_application_fees { + // if account has application fees insert the fees in the map + account_application_fees.insert(*key, account.rent_epoch_or_application_fees); + } + if !validated_fee_payer && message.is_non_loader_key(i) { if i != 0 { warn!("Payer index should be 0! {:?}", tx); } - - Self::validate_fee_payer( - key, - &mut account, - i as IndexOfAccount, - error_counters, - rent_collector, - feature_set, - fee, - )?; - + payer_index = i; validated_fee_payer = true; } @@ -431,10 +433,22 @@ impl Accounts { account_found_and_dep_index.push((account_found, account_dep_index)); Ok((*key, account)) - }) - .collect::>>()?; - - if !validated_fee_payer { + }).collect::>>()?; + + if validated_fee_payer { + let key_and_account = &mut accounts[payer_index]; + let application_fees_sum = account_application_fees.iter().map(|x| *x.1).sum::(); + + Self::validate_fee_payer( + &key_and_account.0, + &mut key_and_account.1, + payer_index as IndexOfAccount, + error_counters, + rent_collector, + feature_set, + fee.saturating_add(application_fees_sum), + )?; + } else { error_counters.account_not_found += 1; return Err(TransactionError::AccountNotFound); } @@ -521,6 +535,7 @@ impl Accounts { program_indices, rent: tx_rent, rent_debits, + application_fees, }) } @@ -1253,7 +1268,7 @@ impl Accounts { let execution_status = match &execution_results[i] { TransactionExecutionResult::Executed { details, .. } => &details.status, // Don't store any accounts if tx wasn't executed - TransactionExecutionResult::NotExecuted(_) => continue, + TransactionExecutionResult::NotExecuted { .. } => continue, }; let maybe_nonce = match (execution_status, &*nonce) { @@ -1357,6 +1372,8 @@ fn prepare_if_nonce_account( #[cfg(test)] mod tests { + use std::str::FromStr; + use { super::*, crate::{ @@ -1364,8 +1381,12 @@ mod tests { rent_collector::RentCollector, }, assert_matches::assert_matches, + itertools::Itertools, solana_address_lookup_table_program::state::LookupTableMeta, - solana_program_runtime::executor_cache::TransactionExecutorCache, + solana_program_runtime::{ + compute_budget, executor_cache::TransactionExecutorCache, + invoke_context::ApplicationFeeChanges, + }, solana_sdk::{ account::{AccountSharedData, WritableAccount}, epoch_schedule::EpochSchedule, @@ -1414,6 +1435,7 @@ mod tests { return_data: None, executed_units: 0, accounts_data_len_delta: 0, + application_fees_changes: ApplicationFeeChanges::new(), }, tx_executor_cache: Rc::new(RefCell::new(TransactionExecutorCache::default())), } @@ -1783,11 +1805,11 @@ mod tests { let key1 = Pubkey::from([5u8; 32]); let mut account = AccountSharedData::new(1, 0, &Pubkey::default()); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key0, account)); let mut account = AccountSharedData::new(2, 1, &Pubkey::default()); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key1, account)); let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])]; @@ -1895,18 +1917,18 @@ mod tests { let key2 = Pubkey::from([6u8; 32]); let mut account = AccountSharedData::new(1, 0, &Pubkey::default()); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key0, account)); let mut account = AccountSharedData::new(40, 1, &Pubkey::default()); account.set_executable(true); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); account.set_owner(native_loader::id()); accounts.push((key1, account)); let mut account = AccountSharedData::new(41, 1, &Pubkey::default()); account.set_executable(true); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); account.set_owner(key1); accounts.push((key2, account)); @@ -2064,6 +2086,8 @@ mod tests { solana_address_lookup_table_program::id(), false, 0, + false, + 0, ) }; accounts.store_slow_uncached(0, &table_key, &table_account); @@ -2126,17 +2150,17 @@ mod tests { let key2 = Pubkey::from([6u8; 32]); let mut account = AccountSharedData::new(1, 0, &Pubkey::default()); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key0, account)); let mut account = AccountSharedData::new(40, 1, &native_loader::id()); account.set_executable(true); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key1, account)); let mut account = AccountSharedData::new(40, 1, &native_loader::id()); account.set_executable(true); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key2, account)); let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])]; @@ -2189,7 +2213,7 @@ mod tests { let programdata_key2 = Pubkey::from([8u8; 32]); let mut account = AccountSharedData::new(1, 0, &Pubkey::default()); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key0, account)); let program_data = UpgradeableLoaderState::ProgramData { @@ -2203,11 +2227,11 @@ mod tests { let mut account = AccountSharedData::new_data(40, &program, &bpf_loader_upgradeable::id()).unwrap(); account.set_executable(true); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key1, account)); let mut account = AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap(); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((programdata_key1, account)); let program = UpgradeableLoaderState::Program { @@ -2216,16 +2240,16 @@ mod tests { let mut account = AccountSharedData::new_data(40, &program, &bpf_loader_upgradeable::id()).unwrap(); account.set_executable(true); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key2, account)); let mut account = AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap(); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((programdata_key2, account)); let mut account = AccountSharedData::new(40, 1, &native_loader::id()); // create mock bpf_loader_upgradeable account.set_executable(true); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((bpf_loader_upgradeable::id(), account)); let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])]; @@ -2299,7 +2323,7 @@ mod tests { let key2 = Pubkey::from([6u8; 32]); let mut account = AccountSharedData::new(1, 0, &Pubkey::default()); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key0, account)); let program_data = UpgradeableLoaderState::ProgramData { @@ -2308,12 +2332,12 @@ mod tests { }; let mut account = AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap(); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key1, account)); let mut account = AccountSharedData::new(40, 1, &native_loader::id()); account.set_executable(true); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); accounts.push((key2, account)); let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])]; @@ -2339,7 +2363,7 @@ mod tests { // Solution 1: include bpf_loader_upgradeable account let mut account = AccountSharedData::new(40, 1, &native_loader::id()); // create mock bpf_loader_upgradeable account.set_executable(true); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); let accounts_with_upgradeable_loader = vec![ accounts[0].clone(), accounts[1].clone(), @@ -2898,6 +2922,7 @@ mod tests { program_indices: vec![], rent: 0, rent_debits: RentDebits::default(), + application_fees: ApplicationFees::new(), }), None, ); @@ -2908,6 +2933,7 @@ mod tests { program_indices: vec![], rent: 0, rent_debits: RentDebits::default(), + application_fees: ApplicationFees::new(), }), None, ); @@ -3387,6 +3413,7 @@ mod tests { program_indices: vec![], rent: 0, rent_debits: RentDebits::default(), + application_fees: ApplicationFees::new(), }), nonce.clone(), ); @@ -3500,6 +3527,7 @@ mod tests { program_indices: vec![], rent: 0, rent_debits: RentDebits::default(), + application_fees: ApplicationFees::new(), }), nonce.clone(), ); @@ -3852,4 +3880,241 @@ mod tests { ); } } + + #[test] + fn test_cannot_set_application_fees_for_account_with_rentepoch() { + let mut account = AccountSharedData::new(1000, 0, &Pubkey::default()); + account.set_rent_epoch(100).unwrap(); + assert_eq!( + account.set_application_fees(100), + Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch) + ); + } + + #[test] + fn test_cannot_set_rent_epoch_for_with_application_fees() { + let mut account = AccountSharedData::new(1000, 0, &Pubkey::default()); + account.set_application_fees(100).unwrap(); + assert_eq!( + account.set_rent_epoch(100), + Err(InstructionError::CannotSetRentEpochForAccountWithAppFees) + ); + } + + fn load_accounts_with_app_fees( + accounts: &Accounts, + txs: &[SanitizedTransaction], + ) -> Vec { + let rent_collector = RentCollector::default(); + let mut hash_queue = BlockhashQueue::new(100); + hash_queue.register_hash(txs[0].message().recent_blockhash(), 10); + + let ancestors = vec![(0, 0)].into_iter().collect(); + let mut error_counters = TransactionErrorMetrics::default(); + accounts.load_accounts( + &ancestors, + &txs, + txs.iter().map(|_| (Ok(()), None)).collect_vec(), + &hash_queue, + &mut error_counters, + &rent_collector, + &FeatureSet::all_enabled(), + &FeeStructure::default(), + None, + ) + } + + fn create_transfer_transaction( + from: &Keypair, + to: &Pubkey, + blockhash: Hash, + ) -> SanitizedTransaction { + let ix = system_instruction::transfer(&from.pubkey(), &to, 42); + let instructions = vec![ix]; + let message = Message::new(&instructions, Some(&from.pubkey())); + new_sanitized_tx(&[from], message, blockhash) + } + + fn create_transfer_transaction_with_multiple_instructions( + to: &[Pubkey], + from: &Keypair, + ) -> SanitizedTransaction { + let instructions = to + .iter() + .map(|x| system_instruction::transfer(&from.pubkey(), &x, 42)) + .collect_vec(); + let message = Message::new(&instructions, Some(&from.pubkey())); + let blockhash = Hash::new_unique(); + new_sanitized_tx(&[from], message, blockhash) + } + + fn hashmap_with_elements(elements: &[(Pubkey, u64)]) -> HashMap { + let mut map: HashMap = HashMap::new(); + elements.iter().for_each(|x| { + map.insert(x.0, x.1); + }); + map + } + + #[test] + fn test_application_fees_are_applied() { + solana_logger::setup(); + let accounts = Accounts::new_with_config_for_tests( + Vec::new(), + &ClusterType::Development, + AccountSecondaryIndexes::default(), + AccountShrinkThreshold::default(), + ); + + // call chain: native_loader -> key0 -> upgradeable bpf loader -> program_key (that has programdata_key) + let payer = Keypair::new(); + let owner = Keypair::new(); + let native_loader = + Pubkey::from_str("NativeLoader1111111111111111111111111111111").unwrap(); + let key1 = Pubkey::new_unique(); + let key2 = Pubkey::new_unique(); + let key3 = Pubkey::new_unique(); + + let mut dummy_program = + AccountSharedData::new_data(1, &[1, 2, 3, 4], &native_loader).unwrap(); + dummy_program.set_executable(true); + accounts.store_slow_uncached(0, &system_program::id(), &dummy_program); + + let mut payer_acc = AccountSharedData::new(10000000, 0, &system_program::id()); + payer_acc.set_lamports(1000000000); + accounts.store_slow_uncached(0, &payer.pubkey(), &payer_acc); + + let mut key1_acc = AccountSharedData::new(100, 0, &owner.pubkey()); + key1_acc.has_application_fees = true; + key1_acc.rent_epoch_or_application_fees = 100; + accounts.store_slow_uncached(0, &key1, &key1_acc); + + let mut key2_acc = AccountSharedData::new(100, 0, &owner.pubkey()); + key2_acc.has_application_fees = true; + key2_acc.rent_epoch_or_application_fees = 1000; + accounts.store_slow_uncached(0, &key2, &key2_acc); + + let mut key3_acc = AccountSharedData::new(100, 0, &owner.pubkey()); + key3_acc.has_application_fees = true; + key3_acc.rent_epoch_or_application_fees = 10000; + accounts.store_slow_uncached(0, &key3, &key3_acc); + + let blockhash = Hash::new_unique(); + let tx1 = create_transfer_transaction(&payer, &key1, blockhash); + let tx2 = create_transfer_transaction(&payer, &key2, blockhash); + let tx3 = create_transfer_transaction(&payer, &key3, blockhash); + + let result = load_accounts_with_app_fees(&accounts, &[tx1.clone()]); + assert_eq!(result.len(), 1); + // testing application fees for tx1 + let result = result[0].0.clone(); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!( + result.application_fees, + hashmap_with_elements(&[(key1, 100)]) + ); + + // testing application fees for t1,tx2 + let load_result = load_accounts_with_app_fees(&accounts, &[tx1.clone(), tx2.clone()]); + assert_eq!(load_result.len(), 2); + // testing application fees for tx1 + let result = load_result[0].0.clone(); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!( + result.application_fees, + hashmap_with_elements(&[(key1, 100)]) + ); + // testing application fees for tx2 + let result = load_result[1].0.clone(); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!( + result.application_fees, + hashmap_with_elements(&[(key2, 1000)]) + ); + + // testing application fees for tx1,tx2,tx3 + let load_result = load_accounts_with_app_fees(&accounts, &[tx1, tx2, tx3]); + assert_eq!(load_result.len(), 3); + // testing application fees for tx1 + let result = load_result[0].0.clone(); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!( + result.application_fees, + hashmap_with_elements(&[(key1, 100)]) + ); + // testing application fees for tx2 + let result = load_result[1].0.clone(); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!( + result.application_fees, + hashmap_with_elements(&[(key2, 1000)]) + ); + let result = load_result[2].0.clone(); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!( + result.application_fees, + hashmap_with_elements(&[(key3, 10000)]) + ); + + // all 3 in one instruction + let tx_multi = + create_transfer_transaction_with_multiple_instructions(&[key1, key2, key3], &payer); + let result = load_accounts_with_app_fees(&accounts, &[tx_multi]); + assert_eq!(result.len(), 1); + // testing application fees for tx1 + let result = result[0].0.clone(); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!( + result.application_fees, + hashmap_with_elements(&[(key1, 100), (key2, 1000), (key3, 10000)]) + ); + } + + #[test] + fn test_application_fees_fails_if_payer_does_not_have_enough_balance() { + solana_logger::setup(); + let accounts = Accounts::new_with_config_for_tests( + Vec::new(), + &ClusterType::Development, + AccountSecondaryIndexes::default(), + AccountShrinkThreshold::default(), + ); + + // call chain: native_loader -> key0 -> upgradeable bpf loader -> program_key (that has programdata_key) + let payer = Keypair::new(); + let owner = Keypair::new(); + let native_loader = + Pubkey::from_str("NativeLoader1111111111111111111111111111111").unwrap(); + let key1 = Pubkey::new_unique(); + + let mut dummy_program = + AccountSharedData::new_data(1, &[1, 2, 3, 4], &native_loader).unwrap(); + dummy_program.set_executable(true); + accounts.store_slow_uncached(0, &system_program::id(), &dummy_program); + + let mut payer_acc = AccountSharedData::new(10000000, 0, &system_program::id()); + payer_acc.set_lamports(10000); + accounts.store_slow_uncached(0, &payer.pubkey(), &payer_acc); + + let mut key1_acc = AccountSharedData::new(100, 0, &owner.pubkey()); + key1_acc.has_application_fees = true; + key1_acc.rent_epoch_or_application_fees = 10001; + accounts.store_slow_uncached(0, &key1, &key1_acc); + let blockhash = Hash::new_unique(); + let tx1 = create_transfer_transaction(&payer, &key1, blockhash); + let result = load_accounts_with_app_fees(&accounts, &[tx1]); + + // testing application fees for tx1 + assert_eq!(result.len(), 1); + let result = result[0].0.clone(); + assert!(result.is_err()); + assert_eq!(result, Err(TransactionError::InsufficientFundsForFee)); + } } diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index dd0527fb660..fad5f050350 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -899,11 +899,39 @@ impl<'a> ReadableAccount for LoadedAccount<'a> { fn rent_epoch(&self) -> Epoch { match self { LoadedAccount::Stored(stored_account_meta) => { - stored_account_meta.account_meta.rent_epoch + if stored_account_meta.account_meta.has_application_fees { + 0 + } else { + stored_account_meta + .account_meta + .rent_epoch_or_application_fees + } } LoadedAccount::Cached(cached_account) => cached_account.account.rent_epoch(), } } + fn has_application_fees(&self) -> bool { + match self { + LoadedAccount::Stored(stored_account_meta) => { + stored_account_meta.account_meta.has_application_fees + } + LoadedAccount::Cached(cached_account) => cached_account.account.has_application_fees(), + } + } + fn application_fees(&self) -> u64 { + match self { + LoadedAccount::Stored(stored_account_meta) => { + if stored_account_meta.account_meta.has_application_fees { + stored_account_meta + .account_meta + .rent_epoch_or_application_fees + } else { + 0 + } + } + LoadedAccount::Cached(cached_account) => cached_account.account.application_fees(), + } + } fn to_account_shared_data(&self) -> AccountSharedData { match self { LoadedAccount::Stored(_stored_account_meta) => AccountSharedData::create( @@ -912,6 +940,8 @@ impl<'a> ReadableAccount for LoadedAccount<'a> { *self.owner(), self.executable(), self.rent_epoch(), + self.has_application_fees(), + self.application_fees(), ), // clone here to prevent data copy LoadedAccount::Cached(cached_account) => cached_account.account.clone(), @@ -2211,7 +2241,21 @@ impl<'a> ReadableAccount for StoredAccountMeta<'a> { self.account_meta.executable } fn rent_epoch(&self) -> Epoch { - self.account_meta.rent_epoch + if self.account_meta.has_application_fees { + 0 + } else { + self.account_meta.rent_epoch_or_application_fees + } + } + fn has_application_fees(&self) -> bool { + self.account_meta.has_application_fees + } + fn application_fees(&self) -> u64 { + if self.account_meta.has_application_fees { + self.account_meta.rent_epoch_or_application_fees + } else { + 0 + } } } @@ -5973,12 +6017,18 @@ impl AccountsDb { pubkey: &Pubkey, include_slot: IncludeSlotInHash, ) -> Hash { + let rent_epoch_or_application_fees = if account.has_application_fees() { + account.application_fees() + } else { + account.rent_epoch() + }; Self::hash_account_data( slot, account.lamports(), account.owner(), account.executable(), - account.rent_epoch(), + rent_epoch_or_application_fees, + account.has_application_fees(), account.data(), pubkey, include_slot, @@ -5990,7 +6040,8 @@ impl AccountsDb { lamports: u64, owner: &Pubkey, executable: bool, - rent_epoch: Epoch, + rent_epoch_or_application_fees: u64, + has_application_fees: bool, data: &[u8], pubkey: &Pubkey, include_slot: IncludeSlotInHash, @@ -6013,7 +6064,7 @@ impl AccountsDb { } } - hasher.update(&rent_epoch.to_le_bytes()); + hasher.update(&rent_epoch_or_application_fees.to_le_bytes()); hasher.update(data); @@ -6023,6 +6074,12 @@ impl AccountsDb { hasher.update(&[0u8; 1]); } + if has_application_fees { + hasher.update(&[1u8; 1]); + } else { + hasher.update(&[0u8; 1]); + } + hasher.update(owner.as_ref()); hasher.update(pubkey.as_ref()); @@ -8700,7 +8757,7 @@ impl AccountsDb { let mut account = AccountSharedData::new(lamports, space, &owner); // just non-zero rent epoch. filler accounts are rent-exempt let dummy_rent_epoch = 2; - account.set_rent_epoch(dummy_rent_epoch); + account.set_rent_epoch(dummy_rent_epoch).unwrap(); (account, hash) } @@ -9528,7 +9585,8 @@ pub mod tests { lamports: 1, owner: Pubkey::from([2; 32]), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let offset = 3; let hash = Hash::new(&[2; 32]); @@ -9630,7 +9688,8 @@ pub mod tests { lamports, owner, executable, - rent_epoch, + has_application_fees: false, + rent_epoch_or_application_fees: rent_epoch, }; let offset = 99; let stored_size = 101; @@ -12195,14 +12254,16 @@ pub mod tests { lamports, owner, executable, - rent_epoch, + has_application_fees: false, + rent_epoch_or_application_fees: rent_epoch, }; let data = Vec::new(); let account = Account { lamports, owner, executable, - rent_epoch, + has_application_fees: false, + rent_epoch_or_application_fees: rent_epoch, data: data.clone(), }; let offset = 99; diff --git a/runtime/src/accounts_index.rs b/runtime/src/accounts_index.rs index 3e7f719e6ea..097fb14c667 100644 --- a/runtime/src/accounts_index.rs +++ b/runtime/src/accounts_index.rs @@ -3509,6 +3509,8 @@ pub mod tests { inline_spl_token::id(), false, 0, + false, + 0, ), secondary_indexes, true, @@ -3683,7 +3685,15 @@ pub mod tests { 0, 0, &account_key, - &AccountSharedData::create(0, account_data.to_vec(), Pubkey::default(), false, 0), + &AccountSharedData::create( + 0, + account_data.to_vec(), + Pubkey::default(), + false, + 0, + false, + 0, + ), &secondary_indexes, true, &mut vec![], @@ -3697,7 +3707,15 @@ pub mod tests { 0, 0, &account_key, - &AccountSharedData::create(0, account_data[1..].to_vec(), *token_id, false, 0), + &AccountSharedData::create( + 0, + account_data[1..].to_vec(), + *token_id, + false, + 0, + false, + 0, + ), &secondary_indexes, true, &mut vec![], @@ -3712,7 +3730,7 @@ pub mod tests { for _ in 0..2 { index.update_secondary_indexes( &account_key, - &AccountSharedData::create(0, account_data.to_vec(), *token_id, false, 0), + &AccountSharedData::create(0, account_data.to_vec(), *token_id, false, 0, false, 0), &secondary_indexes, ); check_secondary_index_mapping_correct(secondary_index, &[index_key], &account_key); @@ -3730,7 +3748,7 @@ pub mod tests { secondary_index.reverse_index.clear(); index.update_secondary_indexes( &account_key, - &AccountSharedData::create(0, account_data.to_vec(), *token_id, false, 0), + &AccountSharedData::create(0, account_data.to_vec(), *token_id, false, 0, false, 0), &secondary_indexes, ); assert!(!secondary_index.index.is_empty()); @@ -3746,7 +3764,7 @@ pub mod tests { secondary_index.reverse_index.clear(); index.update_secondary_indexes( &account_key, - &AccountSharedData::create(0, account_data.to_vec(), *token_id, false, 0), + &AccountSharedData::create(0, account_data.to_vec(), *token_id, false, 0, false, 0), &secondary_indexes, ); assert!(!secondary_index.index.is_empty()); @@ -3821,7 +3839,7 @@ pub mod tests { slot, slot, &account_key, - &AccountSharedData::create(0, account_data1.to_vec(), *token_id, false, 0), + &AccountSharedData::create(0, account_data1.to_vec(), *token_id, false, 0, false, 0), secondary_indexes, true, &mut vec![], @@ -3833,7 +3851,7 @@ pub mod tests { slot, slot, &account_key, - &AccountSharedData::create(0, account_data2.to_vec(), *token_id, false, 0), + &AccountSharedData::create(0, account_data2.to_vec(), *token_id, false, 0, false, 0), secondary_indexes, true, &mut vec![], @@ -3853,7 +3871,7 @@ pub mod tests { later_slot, later_slot, &account_key, - &AccountSharedData::create(0, account_data1.to_vec(), *token_id, false, 0), + &AccountSharedData::create(0, account_data1.to_vec(), *token_id, false, 0, false, 0), secondary_indexes, true, &mut vec![], diff --git a/runtime/src/ancient_append_vecs.rs b/runtime/src/ancient_append_vecs.rs index ff4ddcdedd8..9071dc2eac1 100644 --- a/runtime/src/ancient_append_vecs.rs +++ b/runtime/src/ancient_append_vecs.rs @@ -230,7 +230,8 @@ pub mod tests { lamports: 1, owner: Pubkey::from([2; 32]), executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }; let offset = 3; let hash = Hash::new(&[2; 32]); diff --git a/runtime/src/append_vec.rs b/runtime/src/append_vec.rs index 311297972cb..ee10a925077 100644 --- a/runtime/src/append_vec.rs +++ b/runtime/src/append_vec.rs @@ -11,7 +11,7 @@ use { serde::{Deserialize, Serialize}, solana_sdk::{ account::{Account, AccountSharedData, ReadableAccount}, - clock::{Epoch, Slot}, + clock::Slot, hash::Hash, pubkey::Pubkey, }, @@ -168,6 +168,9 @@ pub struct AccountMeta { pub owner: Pubkey, /// this account's data contains a loaded program (and is now read-only) pub executable: bool, + /// the epoch at which this account will next owe rent or application fees for the account + /// switched by the boolean above + pub application_fees: u64, } impl<'a, T: ReadableAccount> From<&'a T> for AccountMeta { @@ -176,7 +179,12 @@ impl<'a, T: ReadableAccount> From<&'a T> for AccountMeta { lamports: account.lamports(), owner: *account.owner(), executable: account.executable(), - rent_epoch: account.rent_epoch(), + has_application_fees: account.has_application_fees(), + application_fees: if account.has_application_fees() { + account.application_fees() + } else { + 0 + }, } } } @@ -210,7 +218,8 @@ impl<'a> StoredAccountMeta<'a> { lamports: self.account_meta.lamports, owner: self.account_meta.owner, executable: self.account_meta.executable, - rent_epoch: self.account_meta.rent_epoch, + has_application_fees: self.account_meta.has_application_fees, + rent_epoch_or_application_fees: self.account_meta.rent_epoch_or_application_fees, data: self.data.to_vec(), }) } @@ -220,7 +229,9 @@ impl<'a> StoredAccountMeta<'a> { } fn sanitize(&self) -> bool { - self.sanitize_executable() && self.sanitize_lamports() + self.sanitize_executable() + && self.sanitize_lamports() + && self.sanitize_has_application_fees() } fn sanitize_executable(&self) -> bool { @@ -228,6 +239,11 @@ impl<'a> StoredAccountMeta<'a> { self.ref_executable_byte() & !1 == 0 } + fn sanitize_has_application_fees(&self) -> bool { + // Sanitize executable to ensure higher 7-bits are cleared correctly. + self.ref_has_application_fees_byte() & !1 == 0 + } + fn sanitize_lamports(&self) -> bool { // Sanitize 0 lamports to ensure to be same as AccountSharedData::default() self.account_meta.lamports != 0 || self.clone_account() == AccountSharedData::default() @@ -241,6 +257,16 @@ impl<'a> StoredAccountMeta<'a> { let executable_byte: &u8 = unsafe { &*(executable_bool as *const bool as *const u8) }; executable_byte } + + fn ref_has_application_fees_byte(&self) -> &u8 { + // Use extra references to avoid value silently clamped to 1 (=true) and 0 (=false) + // Yes, this really happens; see test_new_from_file_crafted_executable + let has_application_fees: &bool = &self.account_meta.has_application_fees; + // UNSAFE: Force to interpret mmap-backed bool as u8 to really read the actual memory content + let has_application_fees_byte: &u8 = + unsafe { &*(has_application_fees as *const bool as *const u8) }; + has_application_fees_byte + } } pub struct AppendVecAccountsIter<'a> { @@ -649,8 +675,13 @@ impl AppendVec { .map(|account| AccountMeta { lamports: account.lamports(), owner: *account.owner(), - rent_epoch: account.rent_epoch(), executable: account.executable(), + has_application_fees: account.has_application_fees(), + rent_epoch_or_application_fees: if account.has_application_fees() { + account.application_fees() + } else { + account.rent_epoch() + }, }) .unwrap_or_default(); @@ -931,13 +962,15 @@ pub mod tests { lamports: 1, owner: Pubkey::new_unique(), executable: true, - rent_epoch: 3, + has_application_fees: false, + rent_epoch_or_application_fees: 3, }; let def2_account = Account { lamports: def1.lamports, owner: def1.owner, executable: def1.executable, - rent_epoch: def1.rent_epoch, + has_application_fees: def1.has_application_fees, + rent_epoch_or_application_fees: def1.rent_epoch_or_application_fees, data: Vec::new(), }; let def2 = AccountMeta::from(&def2_account); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 740e7890e2d..b943038bee2 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -33,6 +33,8 @@ //! It offers a high-level API that signs transactions //! on behalf of the caller, and a low-level API for when they have //! already been signed and verified. +use solana_program_runtime::invoke_context::ApplicationFeeChanges; +use solana_sdk::instruction::InstructionError; #[allow(deprecated)] use solana_sdk::recent_blockhashes_account; pub use solana_sdk::reward_type::RewardType; @@ -371,6 +373,7 @@ pub struct TransactionExecutionDetails { /// The change in accounts data len for this transaction. /// NOTE: This value is valid IFF `status` is `Ok`. pub accounts_data_len_delta: i64, + pub application_fees_changes: ApplicationFeeChanges, } /// Type safe representation of a transaction execution attempt which @@ -389,7 +392,10 @@ pub enum TransactionExecutionResult { details: TransactionExecutionDetails, tx_executor_cache: Rc>, }, - NotExecuted(TransactionError), + NotExecuted { + error: TransactionError, + application_fees: HashMap, + }, } impl TransactionExecutionResult { @@ -403,21 +409,58 @@ impl TransactionExecutionResult { pub fn was_executed(&self) -> bool { match self { Self::Executed { .. } => true, - Self::NotExecuted(_) => false, + Self::NotExecuted { .. } => false, } } pub fn details(&self) -> Option<&TransactionExecutionDetails> { match self { Self::Executed { details, .. } => Some(details), - Self::NotExecuted(_) => None, + Self::NotExecuted { .. } => None, } } pub fn flattened_result(&self) -> Result<()> { match self { Self::Executed { details, .. } => details.status.clone(), - Self::NotExecuted(err) => Err(err.clone()), + Self::NotExecuted { error, .. } => Err(error.clone()), + } + } + + pub fn get_application_fees(&self) -> HashMap { + match self { + Self::Executed { details, .. } => { + details.application_fees_changes.application_fees.clone() + } + Self::NotExecuted { + application_fees, .. + } => application_fees.clone(), + } + } + + pub fn get_application_fees_rebated(&self) -> u64 { + match self { + Self::Executed { details, .. } => details + .application_fees_changes + .rebated + .iter() + .map(|x| *x.1) + .reduce(|sum, x| sum.saturating_add(x)) + .unwrap_or_default(), + Self::NotExecuted { .. } => 0, + } + } + + pub fn get_updated_application_fees(&self) -> Option> { + match self { + Self::Executed { details, .. } => { + if details.application_fees_changes.updated.len() > 0 { + Some(details.application_fees_changes.updated.clone()) + } else { + None + } + } + Self::NotExecuted { .. } => None, } } } @@ -829,6 +872,7 @@ impl PartialEq for Bank { block_height, collector_id, collector_fees, + application_fees_collected, fee_calculator, fee_rate_governor, collected_rent, @@ -886,6 +930,14 @@ impl PartialEq for Bank { && block_height == &other.block_height && collector_id == &other.collector_id && collector_fees.load(Relaxed) == other.collector_fees.load(Relaxed) + && other.application_fees_collected.len() == application_fees_collected.len() + && other + .application_fees_collected + .iter() + .all(|iter| match application_fees_collected.get(iter.key()) { + Some(x) => *x.value() == *iter.value(), + None => false, + }) && fee_calculator == &other.fee_calculator && fee_rate_governor == &other.fee_rate_governor && collected_rent.load(Relaxed) == other.collected_rent.load(Relaxed) @@ -942,6 +994,13 @@ impl AbiExample for BuiltinPrograms { } } +#[repr(u8)] +#[derive(Eq, PartialEq, Hash, Debug, Clone)] +pub enum ApplicationFeesOperation { + Collected, + Updated, +} + /// Manager for the state of all accounts and programs after processing its entries. /// AbiExample is needed even without Serialize/Deserialize; actual (de-)serialization /// are implemented elsewhere for versioning @@ -1032,6 +1091,9 @@ pub struct Bank { /// Fees that have been collected collector_fees: AtomicU64, + /// Fees by applications + application_fees_collected: dashmap::DashMap<(Pubkey, ApplicationFeesOperation), u64>, + /// Deprecated, do not use /// Latest transaction fees for transactions processed by this bank pub(crate) fee_calculator: FeeCalculator, @@ -1286,6 +1348,7 @@ impl Bank { block_height: u64::default(), collector_id: Pubkey::default(), collector_fees: AtomicU64::default(), + application_fees_collected: dashmap::DashMap::new(), fee_calculator: FeeCalculator::default(), fee_rate_governor: FeeRateGovernor::default(), collected_rent: AtomicU64::default(), @@ -1569,6 +1632,7 @@ impl Bank { parent_slot: parent.slot(), collector_id: *collector_id, collector_fees: AtomicU64::new(0), + application_fees_collected: dashmap::DashMap::new(), ancestors: Ancestors::default(), hash: RwLock::new(Hash::default()), is_delta: AtomicBool::new(false), @@ -1844,6 +1908,7 @@ impl Bank { T::default() } let feature_set = new(); + let mut bank = Self { incremental_snapshot_persistence: fields.incremental_snapshot_persistence, rc: bank_rc, @@ -1874,6 +1939,7 @@ impl Bank { block_height: fields.block_height, collector_id: fields.collector_id, collector_fees: AtomicU64::new(fields.collector_fees), + application_fees_collected: dashmap::DashMap::new(), fee_calculator: fields.fee_calculator, fee_rate_governor: fields.fee_rate_governor, collected_rent: AtomicU64::new(fields.collected_rent), @@ -2099,6 +2165,14 @@ impl Bank { .as_ref() .map(|a| a.rent_epoch()) .unwrap_or(INITIAL_RENT_EPOCH), + old_account + .as_ref() + .map(|a| a.has_application_fees()) + .unwrap_or(false), + old_account + .as_ref() + .map(|a| a.application_fees()) + .unwrap_or(0), ) } @@ -3112,6 +3186,44 @@ impl Bank { burn += deposit; } } + + // apply application fees + let application_fees_collected = &self.application_fees_collected; + if application_fees_collected.len() > 0 { + application_fees_collected.iter().for_each(|iter| { + let (pubkey, operation) = iter.key(); + let amount = *iter.value(); + match operation { + ApplicationFeesOperation::Collected => match self.deposit(pubkey, amount) { + Ok(post_balance) => { + self.rewards.write().unwrap().push(( + *pubkey, + RewardInfo { + reward_type: RewardType::ApplicationFee, + lamports: amount as i64, + post_balance, + commission: None, + }, + )); + } + Err(_) => { + error!("Burning {} fee instead of crediting {}", pubkey, amount); + inc_new_counter_error!("bank-burned_fee_lamports", amount as usize); + burn += amount; + } + }, + ApplicationFeesOperation::Updated => { + if let Err(err) = self.update_application_fees(pubkey, amount) { + error!( + "Failed to update application fees for {} to {} error {}", + pubkey, amount, err + ); + } + } + } + }); + } + self.capitalization.fetch_sub(burn, Relaxed); } } @@ -3367,13 +3479,19 @@ impl Bank { ); // Add a bogus executable account, which will be loaded and ignored. - let (lamports, rent_epoch) = self.inherit_specially_retained_account_fields(&None); + let (lamports, rent_epoch, has_application_fees, application_fees) = + self.inherit_specially_retained_account_fields(&None); let account = AccountSharedData::from(Account { lamports, owner, data: vec![], executable: true, - rent_epoch, + has_application_fees: has_application_fees, + rent_epoch_or_application_fees: if has_application_fees { + application_fees + } else { + rent_epoch + }, }); self.store_account_and_update_capitalization(program_id, &account); } @@ -3795,7 +3913,7 @@ impl Bank { TransactionExecutionResult::Executed { details, .. } => { (details.log_messages, details.return_data) } - TransactionExecutionResult::NotExecuted(_) => (None, None), + TransactionExecutionResult::NotExecuted { .. } => (None, None), }; let logs = logs.unwrap_or_default(); @@ -4192,6 +4310,7 @@ impl Bank { lamports_per_signature, prev_accounts_data_len, &mut executed_units, + loaded_transaction.application_fees.clone(), ); process_message_time.stop(); @@ -4208,6 +4327,14 @@ impl Bank { store_missing_executors_time.as_us() ); + let final_application_fee_changes = match &process_result { + Ok(x) => x.application_fee_changes.clone(), + Err(_) => ApplicationFeeChanges { + application_fees: loaded_transaction.application_fees.clone(), + rebated: HashMap::new(), + updated: Vec::new(), + }, + }; let status = process_result .and_then(|info| { let post_account_state_info = @@ -4294,6 +4421,7 @@ impl Bank { return_data, executed_units, accounts_data_len_delta, + application_fees_changes: final_application_fee_changes, }, tx_executor_cache, } @@ -4391,7 +4519,7 @@ impl Bank { .iter_mut() .zip(sanitized_txs.iter()) .map(|(accs, tx)| match accs { - (Err(e), _nonce) => TransactionExecutionResult::NotExecuted(e.clone()), + (Err(e), _nonce) => TransactionExecutionResult::NotExecuted{ error : e.clone(), application_fees : HashMap::new() /* Ideally should lock accounts for which write lock was taken */}, (Ok(loaded_transaction), nonce) => { let compute_budget = if let Some(compute_budget) = self.runtime_config.compute_budget { @@ -4418,7 +4546,10 @@ impl Bank { compute_budget_process_transaction_time.as_us() ); if let Err(err) = process_transaction_result { - return TransactionExecutionResult::NotExecuted(err); + return TransactionExecutionResult::NotExecuted{ + error: err, + application_fees : loaded_transaction.application_fees.clone(), + }; } compute_budget }; @@ -4736,6 +4867,45 @@ impl Bank { .round() as u64 } + fn merge_application_fees<'a, I>( + result: &dashmap::DashMap<(Pubkey, ApplicationFeesOperation), u64>, + application_fees_collected: I, + application_fees_updated: I, + ) where + I: Iterator, + { + // add application fees collected by the accounts + for (pubkey, amount) in application_fees_collected { + match result.entry((*pubkey, ApplicationFeesOperation::Collected)) { + dashmap::mapref::entry::Entry::Occupied(mut x) => { + let v = x.get_mut(); + *v = *v + *amount; + } + dashmap::mapref::entry::Entry::Vacant(x) => { + x.insert(*amount); + } + } + } + + // process change in application fees for the next slot + for (pubkey, updated_fees) in application_fees_updated { + match result.entry((*pubkey, ApplicationFeesOperation::Updated)) { + dashmap::mapref::entry::Entry::Occupied(x) => { + // continue if the fees are the same + if x.get().eq(updated_fees) { + continue; + } + // should not process update application fees for an account multiple times a slot + warn!("Updated application fees for {} multiple times in same slot, so the fees won't be updated", pubkey); + x.remove_entry(); + } + dashmap::mapref::entry::Entry::Vacant(x) => { + x.insert(*updated_fees); + } + } + } + } + fn filter_program_errors_and_collect_fee( &self, txs: &[SanitizedTransaction], @@ -4743,6 +4913,8 @@ impl Bank { ) -> Vec> { let hash_queue = self.blockhash_queue.read().unwrap(); let mut fees = 0; + let mut application_fees_for_bank: HashMap = HashMap::new(); + let mut application_fees_to_update: HashMap = HashMap::new(); let results = txs .iter() @@ -4752,7 +4924,7 @@ impl Bank { TransactionExecutionResult::Executed { details, .. } => { Ok((&details.status, details.durable_nonce_fee.as_ref())) } - TransactionExecutionResult::NotExecuted(err) => Err(err.clone()), + TransactionExecutionResult::NotExecuted { error, .. } => Err(error.clone()), }?; let (lamports_per_signature, is_nonce) = durable_nonce_fee @@ -4793,11 +4965,61 @@ impl Bank { } fees += fee; + // treat application fees + let mut application_fee_sum: u64 = 0; + let application_fees_for_transaction = execution_result.get_application_fees(); + for (pubkey, fees) in application_fees_for_transaction.iter() { + match application_fees_for_bank.get_mut(pubkey) { + Some(v) => *v = *v + *fees, + None => { + application_fees_for_bank.insert(*pubkey, *fees); + } + } + application_fee_sum += *fees; + } + // treat updated application fees + let updated_application_fees = execution_result.get_updated_application_fees(); + if let Some(updated_application_fees) = updated_application_fees { + for (pubkey, updated_fees) in updated_application_fees.iter() { + match application_fees_to_update.get(pubkey) { + Some(value) => { + // ignore if the value is the same + if updated_fees.eq(value) { + continue; + } + // remove the application fees as we do not multiple updates of application fees in same slot + application_fees_to_update.remove(pubkey); + self.application_fees_collected + .remove(&(*pubkey, ApplicationFeesOperation::Updated)); + } + None => { + application_fees_to_update.insert(*pubkey, *updated_fees); + } + } + } + } + + // In similar way above we charge the application fee to the payer + if execution_status.is_err() && application_fee_sum > 0 { + self.withdraw(tx.message().fee_payer(), application_fee_sum)?; + } else { + // check for rebates + let rebates = execution_result.get_application_fees_rebated(); + if rebates > 0 { + let _ = self.deposit(tx.message().fee_payer(), rebates); + } + } Ok(()) }) .collect(); self.collector_fees.fetch_add(fees, Relaxed); + // treat application fees + Self::merge_application_fees( + &self.application_fees_collected, + application_fees_for_bank.iter(), + application_fees_to_update.iter(), + ); results } @@ -5303,6 +5525,14 @@ impl Bank { )); time_collecting_rent_us += measure.as_us(); + let rent_collected_info = match rent_collected_info { + Ok(info) => info, + Err(_) => { + error!("Trying to collect rent on account with application fees(should not happen)"); + CollectedInfo::default() + } + }; + // only store accounts where we collected rent // but get the hash for all these accounts even if collected rent is 0 (= not updated). // Also, there's another subtle side-effect from rewrites: this @@ -6058,7 +6288,13 @@ impl Bank { let txs = vec![tx.into()]; let batch = match self.prepare_entry_batch(txs) { Ok(batch) => batch, - Err(err) => return TransactionExecutionResult::NotExecuted(err), + // Normally we not able to prepare batch so no accounts were locked, so not application fees + Err(err) => { + return TransactionExecutionResult::NotExecuted { + error: err, + application_fees: HashMap::new(), + } + } }; let ( @@ -6326,6 +6562,19 @@ impl Bank { Ok(account.lamports()) } + pub fn update_application_fees( + &self, + pubkey: &Pubkey, + application_fees: u64, + ) -> std::result::Result<(), InstructionError> { + // This doesn't collect rents intentionally. + // Rents should only be applied to actual TXes + let mut account = self.get_account_with_fixed_root(pubkey).unwrap_or_default(); + account.set_application_fees(application_fees)?; + self.store_account(pubkey, &account); + Ok(()) + } + pub fn accounts(&self) -> Arc { self.rc.accounts.clone() } @@ -7628,7 +7877,8 @@ impl Bank { data: inline_spl_token::native_mint::ACCOUNT_DATA.to_vec(), lamports: sol_to_lamports(1.), executable: false, - rent_epoch: self.epoch() + 1, + has_application_fees: false, + rent_epoch_or_application_fees: self.epoch() + 1, }); // As a workaround for diff --git a/runtime/src/builtins.rs b/runtime/src/builtins.rs index d7ec37aed33..7ae462229c8 100644 --- a/runtime/src/builtins.rs +++ b/runtime/src/builtins.rs @@ -166,6 +166,14 @@ fn builtin_feature_transitions() -> Vec { ), feature_id: feature_set::zk_token_sdk_enabled::id(), }, + BuiltinFeatureTransition::Add { + builtin: Builtin::new( + "application_fees_program", + solana_application_fees_program::id(), + solana_application_fees_program::processor::process_instruction, + ), + feature_id: feature_set::add_application_fees_program::id(), + }, ] } diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 36e5b15cd92..aee47ee961a 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -1,3 +1,5 @@ +use solana_program_runtime::invoke_context::ApplicationFeeChanges; + use { serde::{Deserialize, Serialize}, solana_measure::measure::Measure, @@ -15,13 +17,14 @@ use { hash::Hash, message::SanitizedMessage, precompiles::is_precompile, + pubkey::Pubkey, rent::Rent, saturating_add_assign, sysvar::instructions, transaction::TransactionError, transaction_context::{IndexOfAccount, InstructionAccount, TransactionContext}, }, - std::{borrow::Cow, cell::RefCell, rc::Rc, sync::Arc}, + std::{borrow::Cow, cell::RefCell, collections::HashMap, rc::Rc, sync::Arc}, }; #[derive(Debug, Default, Clone, Deserialize, Serialize)] @@ -37,10 +40,11 @@ impl ::solana_frozen_abi::abi_example::AbiExample for MessageProcessor { } /// Resultant information gathered from calling process_message() -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct ProcessedMessageInfo { /// The change in accounts data len pub accounts_data_len_delta: i64, + pub application_fee_changes: ApplicationFeeChanges, } impl MessageProcessor { @@ -66,6 +70,7 @@ impl MessageProcessor { lamports_per_signature: u64, current_accounts_data_len: u64, accumulated_consumed_units: &mut u64, + application_fees: HashMap, ) -> Result { let mut invoke_context = InvokeContext::new( transaction_context, @@ -79,6 +84,7 @@ impl MessageProcessor { blockhash, lamports_per_signature, current_accounts_data_len, + application_fees, ); debug_assert_eq!(program_indices.len(), message.instructions().len()); @@ -179,6 +185,7 @@ impl MessageProcessor { } Ok(ProcessedMessageInfo { accounts_data_len_delta: invoke_context.get_accounts_data_meter().delta(), + application_fee_changes: invoke_context.application_fee_changes, }) } } @@ -197,6 +204,7 @@ mod tests { secp256k1_instruction::new_secp256k1_instruction, secp256k1_program, }, + std::collections::HashMap, }; #[derive(Debug, Serialize, Deserialize)] @@ -320,6 +328,7 @@ mod tests { 0, 0, &mut 0, + HashMap::new(), ); assert!(result.is_ok()); assert_eq!( @@ -370,6 +379,7 @@ mod tests { 0, 0, &mut 0, + HashMap::new(), ); assert_eq!( result, @@ -410,6 +420,7 @@ mod tests { 0, 0, &mut 0, + HashMap::new(), ); assert_eq!( result, @@ -547,6 +558,7 @@ mod tests { 0, 0, &mut 0, + HashMap::new(), ); assert_eq!( result, @@ -581,6 +593,7 @@ mod tests { 0, 0, &mut 0, + HashMap::new(), ); assert!(result.is_ok()); @@ -612,6 +625,7 @@ mod tests { 0, 0, &mut 0, + HashMap::new(), ); assert!(result.is_ok()); assert_eq!( @@ -692,6 +706,7 @@ mod tests { 0, 0, &mut 0, + HashMap::new(), ); assert_eq!( diff --git a/runtime/src/read_only_accounts_cache.rs b/runtime/src/read_only_accounts_cache.rs index 9956af64bb8..4ebe8662ceb 100644 --- a/runtime/src/read_only_accounts_cache.rs +++ b/runtime/src/read_only_accounts_cache.rs @@ -274,7 +274,8 @@ mod tests { lamports: rng.gen(), data, executable: rng.gen(), - rent_epoch: rng.gen(), + has_application_fees: rng.gen(), + rent_epoch_or_application_fees: rng.gen(), owner: Pubkey::default(), }); let slot = *slots.choose(&mut rng).unwrap(); diff --git a/runtime/src/rent_collector.rs b/runtime/src/rent_collector.rs index ea0bea42b20..b3e38962440 100644 --- a/runtime/src/rent_collector.rs +++ b/runtime/src/rent_collector.rs @@ -5,6 +5,7 @@ use solana_sdk::{ epoch_schedule::EpochSchedule, genesis_config::GenesisConfig, incinerator, + instruction::InstructionError, pubkey::Pubkey, rent::{Rent, RentDue}, }; @@ -132,18 +133,18 @@ impl RentCollector { } => match account.lamports().checked_sub(rent_due) { None | Some(0) => { let account = std::mem::take(account); - CollectedInfo { + Ok(CollectedInfo { rent_amount: account.lamports(), account_data_len_reclaimed: account.data().len() as u64, - } + }) } Some(lamports) => { account.set_lamports(lamports); - account.set_rent_epoch(new_rent_epoch); - CollectedInfo { + account.set_rent_epoch(new_rent_epoch)?; + Ok(CollectedInfo { rent_amount: rent_due, account_data_len_reclaimed: 0u64, - } + }) } }, } @@ -232,13 +233,14 @@ mod tests { set_exempt_rent_epoch_max: bool, ) -> CollectedInfo { // initialize rent_epoch as created at this epoch - account.set_rent_epoch(self.epoch); + account.set_rent_epoch(self.epoch).unwrap(); self.collect_from_existing_account( address, account, /*filler_account_suffix:*/ None, set_exempt_rent_epoch_max, ) + .unwrap() } } diff --git a/runtime/src/storable_accounts.rs b/runtime/src/storable_accounts.rs index 7250eca11f5..a7ff217ad09 100644 --- a/runtime/src/storable_accounts.rs +++ b/runtime/src/storable_accounts.rs @@ -337,7 +337,8 @@ pub mod tests { let lamports = 1; let owner = Pubkey::default(); let executable = false; - let rent_epoch = 0; + let has_application_fees = false; + let rent_epoch_or_application_fees = 0; let meta = StoredMeta { write_version_obsolete: 5, pubkey: pk, @@ -347,7 +348,8 @@ pub mod tests { lamports, owner, executable, - rent_epoch, + has_application_fees, + rent_epoch_or_application_fees, }; let data = Vec::default(); let offset = 99; @@ -389,6 +391,8 @@ pub mod tests { Pubkey::default(), false, 0, + false, + 0, ); raw.push(( @@ -404,7 +408,12 @@ pub mod tests { lamports: account.lamports(), owner: *account.owner(), executable: account.executable(), - rent_epoch: account.rent_epoch(), + has_application_fees: account.has_application_fees(), + rent_epoch_or_application_fees: if account.has_application_fees() { + account.application_fees() + } else { + account.rent_epoch() + }, }, )); } diff --git a/sdk/program/src/instruction.rs b/sdk/program/src/instruction.rs index 6ec1e218b77..be7be14e0be 100644 --- a/sdk/program/src/instruction.rs +++ b/sdk/program/src/instruction.rs @@ -260,8 +260,18 @@ pub enum InstructionError { /// Max instruction trace length exceeded #[error("Max instruction trace length exceeded")] MaxInstructionTraceLengthExceeded, + + // Setting rent epoch for account which has an application fees + #[error("Cannot set rent epoch for account which has application fees")] + CannotSetRentEpochForAccountWithAppFees, + + // Setting application fees for an account which is not rent free + #[error("Cannot set application fees for account which has rent epoch")] + CannotSetAppFeesForAccountWithRentEpoch, // Note: For any new error added here an equivalent ProgramError and its // conversions must also be added + #[error("Cannot change application fees")] + CannotChangeApplicationFees, } /// A directive for a single invocation of a Solana program. diff --git a/sdk/program/src/program_error.rs b/sdk/program/src/program_error.rs index a3b3febf30f..6174e9cb81c 100644 --- a/sdk/program/src/program_error.rs +++ b/sdk/program/src/program_error.rs @@ -57,6 +57,10 @@ pub enum ProgramError { InvalidRealloc, #[error("Instruction trace length exceeded the maximum allowed per transaction")] MaxInstructionTraceLengthExceeded, + #[error("Cannot set rent epoch for account which has application fees")] + CannotSetRentEpochForAccountWithAppFees, + #[error("Cannot set application fees for account which has rent epoch")] + CannotSetAppFeesForAccountWithRentEpoch, } pub trait PrintProgramError { @@ -102,6 +106,12 @@ impl PrintProgramError for ProgramError { Self::MaxInstructionTraceLengthExceeded => { msg!("Error: MaxInstructionTraceLengthExceeded") } + Self::CannotSetAppFeesForAccountWithRentEpoch => { + msg!("Error: CannotSetAppFeesForAccountWithRentEpoch") + } + Self::CannotSetRentEpochForAccountWithAppFees => { + msg!("Error: CannotSetRentEpochForAccountWithAppFees") + } } } } @@ -135,6 +145,8 @@ pub const ILLEGAL_OWNER: u64 = to_builtin!(18); pub const MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED: u64 = to_builtin!(19); pub const INVALID_ACCOUNT_DATA_REALLOC: u64 = to_builtin!(20); pub const MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED: u64 = to_builtin!(21); +pub const SETTING_RENT_EPOCH_FOR_APP_FEES: u64 = to_builtin!(22); +pub const SETTING_APP_FEES_FOR_RENT_EPOCH: u64 = to_builtin!(23); // Warning: Any new program errors added here must also be: // - Added to the below conversions // - Added as an equivalent to InstructionError @@ -175,6 +187,12 @@ impl From for u64 { error as u64 } } + ProgramError::CannotSetAppFeesForAccountWithRentEpoch => { + SETTING_APP_FEES_FOR_RENT_EPOCH + } + ProgramError::CannotSetRentEpochForAccountWithAppFees => { + SETTING_RENT_EPOCH_FOR_APP_FEES + } } } } @@ -203,6 +221,8 @@ impl From for ProgramError { MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED => Self::MaxAccountsDataAllocationsExceeded, INVALID_ACCOUNT_DATA_REALLOC => Self::InvalidRealloc, MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED => Self::MaxInstructionTraceLengthExceeded, + SETTING_APP_FEES_FOR_RENT_EPOCH => Self::CannotSetAppFeesForAccountWithRentEpoch, + SETTING_RENT_EPOCH_FOR_APP_FEES => Self::CannotSetRentEpochForAccountWithAppFees, _ => Self::Custom(error as u32), } } @@ -238,6 +258,12 @@ impl TryFrom for ProgramError { Self::Error::MaxInstructionTraceLengthExceeded => { Ok(Self::MaxInstructionTraceLengthExceeded) } + Self::Error::CannotSetAppFeesForAccountWithRentEpoch => { + Ok(Self::CannotSetAppFeesForAccountWithRentEpoch) + } + Self::Error::CannotSetRentEpochForAccountWithAppFees => { + Ok(Self::CannotSetRentEpochForAccountWithAppFees) + } _ => Err(error), } } @@ -271,6 +297,8 @@ where MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED => Self::MaxAccountsDataAllocationsExceeded, INVALID_ACCOUNT_DATA_REALLOC => Self::InvalidRealloc, MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED => Self::MaxInstructionTraceLengthExceeded, + SETTING_APP_FEES_FOR_RENT_EPOCH => Self::CannotSetAppFeesForAccountWithRentEpoch, + SETTING_RENT_EPOCH_FOR_APP_FEES => Self::CannotSetRentEpochForAccountWithAppFees, _ => { // A valid custom error has no bits set in the upper 32 if error >> BUILTIN_BIT_SHIFT == 0 { diff --git a/sdk/src/account.rs b/sdk/src/account.rs index fca8f8b71f5..d69cea88510 100644 --- a/sdk/src/account.rs +++ b/sdk/src/account.rs @@ -10,7 +10,10 @@ use { ser::{Serialize, Serializer}, Deserialize, }, - solana_program::{account_info::AccountInfo, debug_account_data::*, sysvar::Sysvar}, + solana_program::{ + account_info::AccountInfo, debug_account_data::*, instruction::InstructionError, + sysvar::Sysvar, + }, std::{ cell::{Ref, RefCell}, fmt, ptr, @@ -34,8 +37,11 @@ pub struct Account { pub owner: Pubkey, /// this account's data contains a loaded program (and is now read-only) pub executable: bool, - /// the epoch at which this account will next owe rent - pub rent_epoch: Epoch, + // has application fees + pub has_application_fees: bool, + /// the epoch at which this account will next owe rent or application fees for the account + /// switched by the boolean above + pub rent_epoch_or_application_fees: u64, } // mod because we need 'Account' below to have the name 'Account' to match expected serialization @@ -56,7 +62,8 @@ mod account_serialize { // can't be &pubkey because abi example doesn't support it owner: Pubkey, executable: bool, - rent_epoch: Epoch, + has_application_fees: bool, + rent_epoch_or_application_fees: Epoch, } /// allows us to implement serialize on AccountSharedData that is equivalent to Account::serialize without making a copy of the Vec @@ -67,12 +74,18 @@ mod account_serialize { where S: Serializer, { + let has_application_fees = account.has_application_fees(); let temp = Account { lamports: account.lamports(), data: account.data(), owner: *account.owner(), executable: account.executable(), - rent_epoch: account.rent_epoch(), + has_application_fees, + rent_epoch_or_application_fees: if has_application_fees { + account.application_fees() + } else { + account.rent_epoch() + }, }; temp.serialize(serializer) } @@ -110,8 +123,10 @@ pub struct AccountSharedData { owner: Pubkey, /// this account's data contains a loaded program (and is now read-only) executable: bool, + // has application fees + pub has_application_fees: bool, /// the epoch at which this account will next owe rent - rent_epoch: Epoch, + pub rent_epoch_or_application_fees: u64, } /// Compares two ReadableAccounts @@ -121,6 +136,8 @@ pub fn accounts_equal(me: &T, other: &U) me.lamports() == other.lamports() && me.executable() == other.executable() && me.rent_epoch() == other.rent_epoch() + && me.has_application_fees() == other.has_application_fees() + && me.application_fees() == other.application_fees() && me.owner() == other.owner() && me.data() == other.data() } @@ -133,7 +150,8 @@ impl From for Account { data: std::mem::take(account_data), owner: other.owner, executable: other.executable, - rent_epoch: other.rent_epoch, + has_application_fees: other.has_application_fees, + rent_epoch_or_application_fees: other.rent_epoch_or_application_fees, } } } @@ -145,7 +163,8 @@ impl From for AccountSharedData { data: Arc::new(other.data), owner: other.owner, executable: other.executable, - rent_epoch: other.rent_epoch, + has_application_fees: other.has_application_fees, + rent_epoch_or_application_fees: other.rent_epoch_or_application_fees, } } } @@ -179,13 +198,16 @@ pub trait WritableAccount: ReadableAccount { fn set_owner(&mut self, owner: Pubkey); fn copy_into_owner_from_slice(&mut self, source: &[u8]); fn set_executable(&mut self, executable: bool); - fn set_rent_epoch(&mut self, epoch: Epoch); + fn set_rent_epoch(&mut self, epoch: Epoch) -> Result<(), InstructionError>; + fn set_application_fees(&mut self, fees: u64) -> Result<(), InstructionError>; fn create( lamports: u64, data: Vec, owner: Pubkey, executable: bool, rent_epoch: Epoch, + has_application_fees: bool, + application_fees: u64, ) -> Self; } @@ -195,6 +217,8 @@ pub trait ReadableAccount: Sized { fn owner(&self) -> &Pubkey; fn executable(&self) -> bool; fn rent_epoch(&self) -> Epoch; + fn has_application_fees(&self) -> bool; + fn application_fees(&self) -> u64; fn to_account_shared_data(&self) -> AccountSharedData { AccountSharedData::create( self.lamports(), @@ -202,6 +226,8 @@ pub trait ReadableAccount: Sized { *self.owner(), self.executable(), self.rent_epoch(), + self.has_application_fees(), + self.application_fees(), ) } } @@ -220,7 +246,23 @@ impl ReadableAccount for Account { self.executable } fn rent_epoch(&self) -> Epoch { - self.rent_epoch + if self.has_application_fees { + 0 + } else { + self.rent_epoch_or_application_fees + } + } + + fn has_application_fees(&self) -> bool { + self.has_application_fees + } + + fn application_fees(&self) -> u64 { + if self.has_application_fees { + self.rent_epoch_or_application_fees + } else { + 0 + } } } @@ -243,8 +285,30 @@ impl WritableAccount for Account { fn set_executable(&mut self, executable: bool) { self.executable = executable; } - fn set_rent_epoch(&mut self, epoch: Epoch) { - self.rent_epoch = epoch; + fn set_rent_epoch(&mut self, epoch: Epoch) -> Result<(), InstructionError> { + if self.has_application_fees && epoch != 0 { + // cannot set epoch because application fees are present + Err(InstructionError::CannotSetRentEpochForAccountWithAppFees.into()) + } else { + self.rent_epoch_or_application_fees = epoch; + Ok(()) + } + } + fn set_application_fees(&mut self, fees: u64) -> Result<(), InstructionError> { + if self.has_application_fees { + self.rent_epoch_or_application_fees = fees; + if fees == 0 { + self.has_application_fees = false; + } + Ok(()) + } else { + if self.rent_epoch_or_application_fees != 0 { + return Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch.into()); + } + self.has_application_fees = true; + self.rent_epoch_or_application_fees = fees; + Ok(()) + } } fn create( lamports: u64, @@ -252,13 +316,20 @@ impl WritableAccount for Account { owner: Pubkey, executable: bool, rent_epoch: Epoch, + has_application_fees: bool, + application_fees: u64, ) -> Self { Account { lamports, data, owner, executable, - rent_epoch, + has_application_fees: has_application_fees, + rent_epoch_or_application_fees: if has_application_fees { + application_fees + } else { + rent_epoch + }, } } } @@ -282,8 +353,30 @@ impl WritableAccount for AccountSharedData { fn set_executable(&mut self, executable: bool) { self.executable = executable; } - fn set_rent_epoch(&mut self, epoch: Epoch) { - self.rent_epoch = epoch; + fn set_rent_epoch(&mut self, epoch: Epoch) -> Result<(), InstructionError> { + if self.has_application_fees && epoch != 0 { + // cannot set epoch because application fees are present + Err(InstructionError::CannotSetRentEpochForAccountWithAppFees.into()) + } else { + self.rent_epoch_or_application_fees = epoch; + Ok(()) + } + } + fn set_application_fees(&mut self, fees: u64) -> Result<(), InstructionError> { + if self.has_application_fees { + self.rent_epoch_or_application_fees = fees; + if fees == 0 { + self.has_application_fees = false; + } + Ok(()) + } else { + if self.rent_epoch_or_application_fees != 0 { + return Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch.into()); + } + self.has_application_fees = true; + self.rent_epoch_or_application_fees = fees; + Ok(()) + } } fn create( lamports: u64, @@ -291,13 +384,20 @@ impl WritableAccount for AccountSharedData { owner: Pubkey, executable: bool, rent_epoch: Epoch, + has_application_fees: bool, + application_fees: u64, ) -> Self { AccountSharedData { lamports, data: Arc::new(data), owner, executable, - rent_epoch, + has_application_fees: has_application_fees, + rent_epoch_or_application_fees: if has_application_fees { + application_fees + } else { + rent_epoch + }, } } } @@ -316,12 +416,28 @@ impl ReadableAccount for AccountSharedData { self.executable } fn rent_epoch(&self) -> Epoch { - self.rent_epoch + if self.has_application_fees { + 0 + } else { + self.rent_epoch_or_application_fees + } } fn to_account_shared_data(&self) -> AccountSharedData { // avoid data copy here self.clone() } + + fn has_application_fees(&self) -> bool { + self.has_application_fees + } + + fn application_fees(&self) -> u64 { + if self.has_application_fees { + self.rent_epoch_or_application_fees + } else { + 0 + } + } } impl ReadableAccount for Ref<'_, AccountSharedData> { @@ -338,7 +454,11 @@ impl ReadableAccount for Ref<'_, AccountSharedData> { self.executable } fn rent_epoch(&self) -> Epoch { - self.rent_epoch + if self.has_application_fees { + 0 + } else { + self.rent_epoch_or_application_fees + } } fn to_account_shared_data(&self) -> AccountSharedData { AccountSharedData { @@ -347,7 +467,20 @@ impl ReadableAccount for Ref<'_, AccountSharedData> { data: Arc::clone(&self.data), owner: *self.owner(), executable: self.executable(), - rent_epoch: self.rent_epoch(), + has_application_fees: self.has_application_fees(), + rent_epoch_or_application_fees: self.rent_epoch_or_application_fees, + } + } + + fn has_application_fees(&self) -> bool { + self.has_application_fees + } + + fn application_fees(&self) -> u64 { + if self.has_application_fees { + self.rent_epoch_or_application_fees + } else { + 0 } } } @@ -366,7 +499,23 @@ impl ReadableAccount for Ref<'_, Account> { self.executable } fn rent_epoch(&self) -> Epoch { - self.rent_epoch + if self.has_application_fees { + 0 + } else { + self.rent_epoch_or_application_fees + } + } + + fn has_application_fees(&self) -> bool { + self.has_application_fees + } + + fn application_fees(&self) -> u64 { + if self.has_application_fees { + self.rent_epoch_or_application_fees + } else { + 0 + } } } @@ -377,7 +526,9 @@ fn debug_fmt(item: &T, f: &mut fmt::Formatter<'_>) -> fmt::R .field("data.len", &item.data().len()) .field("owner", &item.owner()) .field("executable", &item.executable()) - .field("rent_epoch", &item.rent_epoch()); + .field("rent_epoch", &item.rent_epoch()) + .field("has_application_fees", &item.has_application_fees()) + .field("application_fees", &item.application_fees()); debug_account_data(item.data(), &mut f); f.finish() @@ -402,6 +553,8 @@ fn shared_new(lamports: u64, space: usize, owner: &Pubkey) - *owner, bool::default(), Epoch::default(), + false, + 0, ) } @@ -417,6 +570,8 @@ fn shared_new_rent_epoch( *owner, bool::default(), rent_epoch, + false, + 0, ) } @@ -440,6 +595,8 @@ fn shared_new_data( *owner, bool::default(), Epoch::default(), + false, + 0, )) } fn shared_new_ref_data( @@ -631,8 +788,9 @@ impl AccountSharedData { } } -pub type InheritableAccountFields = (u64, Epoch); -pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITIAL_RENT_EPOCH); +pub type InheritableAccountFields = (u64, Epoch, bool, u64); +pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = + (1, INITIAL_RENT_EPOCH, false, 0); /// Create an `Account` from a `Sysvar`. #[deprecated( @@ -640,17 +798,22 @@ pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITI note = "Please use `create_account_for_test` instead" )] pub fn create_account(sysvar: &S, lamports: u64) -> Account { - create_account_with_fields(sysvar, (lamports, INITIAL_RENT_EPOCH)) + create_account_with_fields(sysvar, (lamports, INITIAL_RENT_EPOCH, false, 0)) } pub fn create_account_with_fields( sysvar: &S, - (lamports, rent_epoch): InheritableAccountFields, + (lamports, rent_epoch, has_application_fees, application_fees): InheritableAccountFields, ) -> Account { let data_len = S::size_of().max(bincode::serialized_size(sysvar).unwrap() as usize); let mut account = Account::new(lamports, data_len, &solana_program::sysvar::id()); to_account::(sysvar, &mut account).unwrap(); - account.rent_epoch = rent_epoch; + account.rent_epoch_or_application_fees = if has_application_fees { + application_fees + } else { + rent_epoch + }; + account.has_application_fees = has_application_fees; account } @@ -666,7 +829,7 @@ pub fn create_account_for_test(sysvar: &S) -> Account { pub fn create_account_shared_data(sysvar: &S, lamports: u64) -> AccountSharedData { AccountSharedData::from(create_account_with_fields( sysvar, - (lamports, INITIAL_RENT_EPOCH), + (lamports, INITIAL_RENT_EPOCH, false, 0), )) } @@ -703,7 +866,7 @@ impl solana_program::account_info::Account for Account { &mut self.data, &self.owner, self.executable, - self.rent_epoch, + self.rent_epoch_or_application_fees, ) } } @@ -723,7 +886,7 @@ pub fn create_is_signer_account_infos<'a>( &mut account.data, &account.owner, account.executable, - account.rent_epoch, + account.rent_epoch_or_application_fees, ) }) .collect() @@ -731,15 +894,17 @@ pub fn create_is_signer_account_infos<'a>( #[cfg(test)] pub mod tests { + use crate::signer::{keypair::Keypair, Signer}; + use super::*; fn make_two_accounts(key: &Pubkey) -> (Account, AccountSharedData) { let mut account1 = Account::new(1, 2, key); account1.executable = true; - account1.rent_epoch = 4; + account1.rent_epoch_or_application_fees = 4; let mut account2 = AccountSharedData::new(1, 2, key); account2.executable = true; - account2.rent_epoch = 4; + account2.rent_epoch_or_application_fees = 4; assert!(accounts_equal(&account1, &account2)); (account1, account2) } @@ -848,7 +1013,7 @@ pub mod tests { assert_eq!(account.owner(), &key); assert!(account.executable); assert!(account.executable()); - assert_eq!(account.rent_epoch, 4); + assert_eq!(account.rent_epoch_or_application_fees, 4); assert_eq!(account.rent_epoch(), 4); let account = account2; assert_eq!(account.lamports, 1); @@ -859,7 +1024,7 @@ pub mod tests { assert_eq!(account.owner(), &key); assert!(account.executable); assert!(account.executable()); - assert_eq!(account.rent_epoch, 4); + assert_eq!(account.rent_epoch_or_application_fees, 4); assert_eq!(account.rent_epoch(), 4); } @@ -1026,15 +1191,19 @@ pub mod tests { } } else if field_index == 4 { if pass == 0 { - account1.rent_epoch += 1; + account1.rent_epoch_or_application_fees += 1; } else if pass == 1 { - account_expected.rent_epoch += 1; - account2.set_rent_epoch(account2.rent_epoch + 1); + account_expected.rent_epoch_or_application_fees += 1; + account2 + .set_rent_epoch(account2.rent_epoch_or_application_fees + 1) + .unwrap(); } else if pass == 2 { - account1.set_rent_epoch(account1.rent_epoch + 1); + account1 + .set_rent_epoch(account1.rent_epoch_or_application_fees + 1) + .unwrap(); } else if pass == 3 { - account_expected.rent_epoch += 1; - account2.rent_epoch += 1; + account_expected.rent_epoch_or_application_fees += 1; + account2.rent_epoch_or_application_fees += 1; } } @@ -1139,4 +1308,109 @@ pub mod tests { } } } + + #[repr(C)] + #[derive(Deserialize, PartialEq, Eq, Clone, Default)] + #[serde(rename_all = "camelCase")] + pub struct AccountWithApplicationFees { + /// lamports in the account + pub lamports: u64, + /// data held in this account + #[serde(with = "serde_bytes")] + pub data: Vec, + /// the program that owns this account. If executable, the program that loads this account. + pub owner: Pubkey, + /// this account's data contains a loaded program (and is now read-only) + pub executable: bool, + // has application fees + pub has_application_fees: bool, + /// the epoch at which this account will next owe rent + pub rent_epoch: Epoch, + } + + #[repr(C)] + #[derive(Deserialize, PartialEq, Eq, Clone, Default)] + #[serde(rename_all = "camelCase")] + pub struct AccountWithoutApplicationFees { + /// lamports in the account + pub lamports: u64, + /// data held in this account + #[serde(with = "serde_bytes")] + pub data: Vec, + /// the program that owns this account. If executable, the program that loads this account. + pub owner: Pubkey, + /// this account's data contains a loaded program (and is now read-only) + pub executable: bool, + /// the epoch at which this account will next owe rent + pub rent_epoch: Epoch, + } + + impl Serialize for AccountWithoutApplicationFees { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + crate::account::account_serialize::serialize_account(self, serializer) + } + } + + impl ReadableAccount for AccountWithoutApplicationFees { + fn lamports(&self) -> u64 { + self.lamports + } + fn data(&self) -> &[u8] { + &self.data + } + fn owner(&self) -> &Pubkey { + &self.owner + } + fn executable(&self) -> bool { + self.executable + } + fn rent_epoch(&self) -> Epoch { + self.rent_epoch + } + fn has_application_fees(&self) -> bool { + false + } + fn application_fees(&self) -> u64 { + 0 + } + } + + #[test] + fn serialize_account_without_app_fees_and_deserialize_as_account_with_app_fees() { + let kp = Keypair::new(); + let account1 = AccountWithoutApplicationFees { + lamports: rand::random(), + data: vec![0, 1, 2, 3], + owner: kp.pubkey(), + executable: true, + rent_epoch: 8273947, + }; + let serialize_acc1 = bincode::serialize(&account1).unwrap(); + let deserialized_acc1 = + bincode::deserialize::(serialize_acc1.as_slice()).unwrap(); + assert_eq!(account1.lamports, deserialized_acc1.lamports); + assert_eq!(deserialized_acc1.data, vec![0, 1, 2, 3]); + assert_eq!(account1.owner, deserialized_acc1.owner); + assert_eq!(account1.executable, deserialized_acc1.executable); + assert_eq!(account1.rent_epoch, deserialized_acc1.rent_epoch); + + let account2 = AccountWithoutApplicationFees { + lamports: rand::random(), + data: vec![4, 5, 7, 8], + owner: kp.pubkey(), + executable: false, + rent_epoch: 72839483726, + }; + let serialize_acc2 = bincode::serialize(&account2).unwrap(); + let deserialized_acc2 = + bincode::deserialize::(serialize_acc2.as_slice()).unwrap(); + assert_eq!(account2.lamports, deserialized_acc2.lamports); + assert_eq!(deserialized_acc2.data, vec![4, 5, 7, 8]); + assert_eq!(account2.owner, deserialized_acc2.owner); + assert_eq!(account2.executable, deserialized_acc2.executable); + assert_eq!(account2.rent_epoch, deserialized_acc2.rent_epoch); + } } diff --git a/sdk/src/application_fees.rs b/sdk/src/application_fees.rs new file mode 100644 index 00000000000..e463fab6c12 --- /dev/null +++ b/sdk/src/application_fees.rs @@ -0,0 +1,10 @@ +// This program is used to set an extra fee for a writable account +// The owner of an account or PDA can change the write account fee for the account, +// and this fee is only taken when you lock that account in write mode in a transaction. +// The fee will be charged even if eventually the transaction fails +// The fee will be charged only once per transaction even if there are multiple instructions locking the same account in write mode +// The owner of account will be reponsible to rebate the fees eventually or ( in the same instruction to not penalize good actors +roadmap ) + +#![cfg(feature = "full")] + +crate::declare_id!("App1icationFees1111111111111111111111111111"); diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index d0669965390..90ca5347658 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -604,6 +604,8 @@ pub mod remove_congestion_multiplier_from_fee_calculation { pub mod enable_request_heap_frame_ix { solana_sdk::declare_id!("Hr1nUA9b7NJ6eChS26o7Vi8gYYDDwWD3YeBfzJkTbU86"); +pub mod add_application_fees_program { + solana_sdk::declare_id!("7hwmoguW2KEXkznQEsGfqGA9XTpGvScVae5MroWX5A9o"); } lazy_static! { @@ -752,6 +754,7 @@ lazy_static! { (cap_transaction_accounts_data_size::id(), "cap transaction accounts data size up to a limit #27839"), (remove_congestion_multiplier_from_fee_calculation::id(), "Remove congestion multiplier from transaction fee calculation #29881"), (enable_request_heap_frame_ix::id(), "Enable transaction to request heap frame using compute budget instruction #30076"), + (add_application_fees_program::id(), "Add application fees program"), /*************** ADD NEW FEATURES HERE ***************/ ] .iter() diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index f6c312664bc..45746639ccb 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -56,6 +56,7 @@ pub use solana_program::{ pub mod account; pub mod account_utils; +pub mod application_fees; pub mod builtins; pub mod client; pub mod commitment_config; diff --git a/sdk/src/native_loader.rs b/sdk/src/native_loader.rs index 3f10fc527ad..c1f2f63671a 100644 --- a/sdk/src/native_loader.rs +++ b/sdk/src/native_loader.rs @@ -15,19 +15,24 @@ crate::declare_id!("NativeLoader1111111111111111111111111111111"); note = "Please use `create_loadable_account_for_test` instead" )] pub fn create_loadable_account(name: &str, lamports: u64) -> AccountSharedData { - create_loadable_account_with_fields(name, (lamports, INITIAL_RENT_EPOCH)) + create_loadable_account_with_fields(name, (lamports, INITIAL_RENT_EPOCH, false, 0)) } pub fn create_loadable_account_with_fields( name: &str, - (lamports, rent_epoch): InheritableAccountFields, + (lamports, rent_epoch, has_application_fees, application_fees): InheritableAccountFields, ) -> AccountSharedData { AccountSharedData::from(Account { lamports, owner: id(), data: name.as_bytes().to_vec(), executable: true, - rent_epoch, + has_application_fees: has_application_fees, + rent_epoch_or_application_fees: if has_application_fees { + application_fees + } else { + rent_epoch + }, }) } diff --git a/sdk/src/recent_blockhashes_account.rs b/sdk/src/recent_blockhashes_account.rs index a57b500c2b2..3a293622639 100644 --- a/sdk/src/recent_blockhashes_account.rs +++ b/sdk/src/recent_blockhashes_account.rs @@ -47,7 +47,10 @@ where I: IntoIterator>, { #[allow(deprecated)] - create_account_with_data_and_fields(recent_blockhash_iter, (lamports, INITIAL_RENT_EPOCH)) + create_account_with_data_and_fields( + recent_blockhash_iter, + (lamports, INITIAL_RENT_EPOCH, false, 0), + ) } #[deprecated( diff --git a/sdk/src/reward_type.rs b/sdk/src/reward_type.rs index 84bddfcfb97..0d8102658f2 100644 --- a/sdk/src/reward_type.rs +++ b/sdk/src/reward_type.rs @@ -8,6 +8,7 @@ pub enum RewardType { Rent, Staking, Voting, + ApplicationFee, } impl fmt::Display for RewardType { @@ -20,6 +21,7 @@ impl fmt::Display for RewardType { RewardType::Rent => "rent", RewardType::Staking => "staking", RewardType::Voting => "voting", + RewardType::ApplicationFee => "application_fee", } ) } diff --git a/sdk/src/transaction_context.rs b/sdk/src/transaction_context.rs index bf91b2a74c6..c60d1430382 100644 --- a/sdk/src/transaction_context.rs +++ b/sdk/src/transaction_context.rs @@ -716,12 +716,46 @@ impl<'a> BorrowedAccount<'a> { Ok(()) } + #[cfg(not(target_os = "solana"))] + pub fn set_application_fees(&mut self, application_fees: u64) -> Result<(), InstructionError> { + if self + .transaction_context + .is_early_verification_of_account_modifications_enabled() + { + // The application fees may not be applied for read only account + if !self.is_writable() { + return Err(InstructionError::ReadonlyLamportChange); + } + if !self.has_application_fees() && self.get_rent_epoch() != 0 { + return Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch); + } + // don't touch the account if the lamports do not change + if self.has_application_fees() && self.get_application_fees() == application_fees { + return Ok(()); + } + self.touch()?; + } + + // and only if the account is writable + self.account.set_application_fees(application_fees) + } + /// Returns the number of lamports of this account (transaction wide) #[inline] pub fn get_lamports(&self) -> u64 { self.account.lamports() } + #[inline] + pub fn has_application_fees(&self) -> bool { + self.account.has_application_fees() + } + + #[inline] + pub fn get_application_fees(&self) -> u64 { + self.account.application_fees() + } + /// Overwrites the number of lamports of this account (transaction wide) #[cfg(not(target_os = "solana"))] pub fn set_lamports(&mut self, lamports: u64) -> Result<(), InstructionError> { diff --git a/storage-proto/src/convert.rs b/storage-proto/src/convert.rs index 9e4926b194e..acb2d9cfe2c 100644 --- a/storage-proto/src/convert.rs +++ b/storage-proto/src/convert.rs @@ -94,6 +94,7 @@ impl From for generated::Reward { Some(RewardType::Rent) => generated::RewardType::Rent, Some(RewardType::Staking) => generated::RewardType::Staking, Some(RewardType::Voting) => generated::RewardType::Voting, + Some(RewardType::ApplicationFee) => generated::RewardType::Fee, } as i32, commission: reward.commission.map(|c| c.to_string()).unwrap_or_default(), } @@ -1071,6 +1072,15 @@ impl From for tx_by_addr::TransactionError { InstructionError::MaxInstructionTraceLengthExceeded => { tx_by_addr::InstructionErrorType::MaxInstructionTraceLengthExceeded } + InstructionError::CannotSetAppFeesForAccountWithRentEpoch => { + tx_by_addr::InstructionErrorType::InvalidAccountData + } + InstructionError::CannotSetRentEpochForAccountWithAppFees => { + tx_by_addr::InstructionErrorType::InvalidAccountData + } + InstructionError::CannotChangeApplicationFees => { + tx_by_addr::InstructionErrorType::InvalidAccountData + } } as i32, custom: match instruction_error { InstructionError::Custom(custom) => { diff --git a/test-validator/src/lib.rs b/test-validator/src/lib.rs index 700f4469b01..eb4609e412a 100644 --- a/test-validator/src/lib.rs +++ b/test-validator/src/lib.rs @@ -404,7 +404,8 @@ impl TestValidatorGenesis { ), owner, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), ) } @@ -426,7 +427,8 @@ impl TestValidatorGenesis { .unwrap_or_else(|err| panic!("Failed to base64 decode: {err}")), owner, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), ) } @@ -636,7 +638,8 @@ impl TestValidator { data, owner: program.loader, executable: true, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), ); } From e3f712816a913b8fcf8ff199f46cc64c1fbb324c Mon Sep 17 00:00:00 2001 From: Godmode Galactus Date: Mon, 6 Feb 2023 09:32:37 +0100 Subject: [PATCH 2/6] application fees resolving merge conflicts --- genesis/src/main.rs | 6 +++-- program-test/src/programs.rs | 3 ++- runtime/src/accounts.rs | 28 ++++++++++++++------- runtime/src/append_vec.rs | 11 ++++---- runtime/src/bank/tests.rs | 3 +-- runtime/src/rent_collector.rs | 39 +++++++++++++---------------- sdk/src/account.rs | 47 +++++++++++++++++++++++------------ sdk/src/feature_set.rs | 2 ++ 8 files changed, 82 insertions(+), 57 deletions(-) diff --git a/genesis/src/main.rs b/genesis/src/main.rs index b03ae216e19..30bb4b8a4ef 100644 --- a/genesis/src/main.rs +++ b/genesis/src/main.rs @@ -674,7 +674,8 @@ fn main() -> Result<(), Box> { data: program_data, owner: loader, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), ); @@ -689,7 +690,8 @@ fn main() -> Result<(), Box> { data: program_data, owner: loader, executable: true, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), ); } diff --git a/program-test/src/programs.rs b/program-test/src/programs.rs index abfb4af9795..27387cb4c96 100644 --- a/program-test/src/programs.rs +++ b/program-test/src/programs.rs @@ -70,7 +70,8 @@ pub fn spl_programs(rent: &Rent) -> Vec<(Pubkey, AccountSharedData)> { data: program_data, owner: *loader_id, executable: false, - rent_epoch: 0, + has_application_fees: false, + rent_epoch_or_application_fees: 0, }), )); bincode::serialize(&UpgradeableLoaderState::Program { diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index 5b44d84eaa9..16116890e63 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -312,7 +312,7 @@ impl Accounts { let requested_loaded_accounts_data_size_limit = Self::get_requested_loaded_accounts_data_size_limit(feature_set); let mut accumulated_accounts_data_size: usize = 0; - let mut account_application_fees: HashMap = HashMap::new(); + let mut application_fees: HashMap = HashMap::new(); let mut payer_index = 0; // we reverse the iteration over keys so that we collect all the application fees @@ -331,7 +331,7 @@ impl Accounts { .is_active(&feature_set::instructions_sysvar_owned_by_sysvar::id()), ) } else { - let (mut account, rent) = if let Some(account_override) = + let (account, rent) = if let Some(account_override) = account_overrides.and_then(|overrides| overrides.get(key)) { (account_override.clone(), 0) @@ -340,15 +340,24 @@ impl Accounts { .load_with_fixed_root(ancestors, key) .map(|(mut account, _)| { if message.is_writable(i) { - let rent_due = rent_collector + let rent_due_result = rent_collector .collect_from_existing_account( key, &mut account, self.accounts_db.filler_account_suffix.as_ref(), set_exempt_rent_epoch_max, - ) - .rent_amount; - (account, rent_due) + ); + match rent_due_result { + Ok(rent_due) => { + (account, rent_due.rent_amount) + }, + Err(_) => { + // should never happen + error!("trying to set rent epoch for the account with application fees {}", key); + (account, 0) + } + + } } else { (account, 0) } @@ -360,7 +369,8 @@ impl Accounts { // All new accounts must be rent-exempt (enforced in Bank::execute_loaded_transaction). // Currently, rent collection sets rent_epoch to u64::MAX, but initializing the account // with this field already set would allow us to skip rent collection for these accounts. - default_account.set_rent_epoch(u64::MAX); + // ignore error because error should never happen + let _ = default_account.set_rent_epoch(u64::MAX); } (default_account, 0) }) @@ -374,7 +384,7 @@ impl Accounts { if account.has_application_fees { // if account has application fees insert the fees in the map - account_application_fees.insert(*key, account.rent_epoch_or_application_fees); + application_fees.insert(*key, account.rent_epoch_or_application_fees); } if !validated_fee_payer && message.is_non_loader_key(i) { @@ -437,7 +447,7 @@ impl Accounts { if validated_fee_payer { let key_and_account = &mut accounts[payer_index]; - let application_fees_sum = account_application_fees.iter().map(|x| *x.1).sum::(); + let application_fees_sum = application_fees.iter().map(|x| *x.1).sum::(); Self::validate_fee_payer( &key_and_account.0, diff --git a/runtime/src/append_vec.rs b/runtime/src/append_vec.rs index ee10a925077..cfd9e0f1caa 100644 --- a/runtime/src/append_vec.rs +++ b/runtime/src/append_vec.rs @@ -163,27 +163,28 @@ pub struct AccountMeta { /// lamports in the account pub lamports: u64, /// the epoch at which this account will next owe rent - pub rent_epoch: Epoch, + pub rent_epoch_or_application_fees: u64, /// the program that owns this account. If executable, the program that loads this account. pub owner: Pubkey, /// this account's data contains a loaded program (and is now read-only) pub executable: bool, /// the epoch at which this account will next owe rent or application fees for the account /// switched by the boolean above - pub application_fees: u64, + pub has_application_fees: bool, } impl<'a, T: ReadableAccount> From<&'a T> for AccountMeta { fn from(account: &'a T) -> Self { + let has_application_fees = account.has_application_fees(); Self { lamports: account.lamports(), owner: *account.owner(), executable: account.executable(), - has_application_fees: account.has_application_fees(), - application_fees: if account.has_application_fees() { + has_application_fees, + rent_epoch_or_application_fees: if has_application_fees { account.application_fees() } else { - 0 + account.rent_epoch() }, } } diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 9e16c434538..e162981f8d4 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -21,7 +21,6 @@ use { genesis_sysvar_and_builtin_program_lamports, GenesisConfigInfo, ValidatorVoteKeypairs, }, inline_spl_token, - rent_collector::RENT_EXEMPT_RENT_EPOCH, rent_paying_accounts_by_partition::RentPayingAccountsByPartition, status_cache::MAX_CACHE_ENTRIES, transaction_error_metrics::TransactionErrorMetrics, @@ -42,7 +41,7 @@ use { solana_sdk::{ account::{ create_account_shared_data_with_fields as create_account, from_account, Account, - AccountSharedData, ReadableAccount, WritableAccount, + AccountSharedData, ReadableAccount, WritableAccount, RENT_EXEMPT_RENT_EPOCH, }, account_utils::StateMut, bpf_loader, bpf_loader_deprecated, diff --git a/runtime/src/rent_collector.rs b/runtime/src/rent_collector.rs index b3e38962440..897071f2557 100644 --- a/runtime/src/rent_collector.rs +++ b/runtime/src/rent_collector.rs @@ -1,6 +1,6 @@ //! calculate and collect rent from Accounts use solana_sdk::{ - account::{AccountSharedData, ReadableAccount, WritableAccount}, + account::{AccountSharedData, ReadableAccount, WritableAccount, RENT_EXEMPT_RENT_EPOCH}, clock::Epoch, epoch_schedule::EpochSchedule, genesis_config::GenesisConfig, @@ -30,11 +30,6 @@ impl Default for RentCollector { } } -/// When rent is collected from an exempt account, rent_epoch is set to this -/// value. The idea is to have a fixed, consistent value for rent_epoch for all accounts that do not collect rent. -/// This enables us to get rid of the field completely. -pub const RENT_EXEMPT_RENT_EPOCH: Epoch = Epoch::MAX; - /// when rent is collected for this account, this is the action to apply to the account #[derive(Debug)] enum RentResult { @@ -118,15 +113,15 @@ impl RentCollector { account: &mut AccountSharedData, filler_account_suffix: Option<&Pubkey>, set_exempt_rent_epoch_max: bool, - ) -> CollectedInfo { + ) -> Result { match self.calculate_rent_result(address, account, filler_account_suffix) { RentResult::Exempt => { if set_exempt_rent_epoch_max { - account.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH); + account.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH)?; } - CollectedInfo::default() + Ok(CollectedInfo::default()) } - RentResult::NoRentCollectionNow => CollectedInfo::default(), + RentResult::NoRentCollectionNow => Ok(CollectedInfo::default()), RentResult::CollectRent { new_rent_epoch, rent_due, @@ -263,7 +258,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - CollectedInfo::default() + Ok(CollectedInfo::default()) ); assert_eq!(account_clone, account); } @@ -286,7 +281,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - CollectedInfo::default() + Ok(CollectedInfo::default()) ); assert_eq!(account_clone, account_expected); } @@ -309,7 +304,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - CollectedInfo::default() + Ok(CollectedInfo::default()) ); assert_eq!(account_clone, account_expected); } @@ -341,10 +336,10 @@ mod tests { filler_accounts, set_exempt_rent_epoch_max ), - CollectedInfo { + Ok(CollectedInfo { rent_amount: rent_due_expected, account_data_len_reclaimed: 0 - } + }) ); let mut account_expected = account.clone(); account_expected.set_lamports(account.lamports() - rent_due_expected); @@ -374,7 +369,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - CollectedInfo::default() + Ok(CollectedInfo::default()) ); assert_eq!(account_clone, account_expected); } @@ -396,7 +391,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - CollectedInfo::default() + Ok(CollectedInfo::default()) ); assert_eq!(account_clone, account); } @@ -425,7 +420,7 @@ mod tests { Some(&filler_account), set_exempt_rent_epoch_max ), - CollectedInfo::default() + Ok(CollectedInfo::default()) ); assert_eq!(account_clone, account_expected); } @@ -442,7 +437,7 @@ mod tests { let (mut created_account, mut existing_account) = { let account = AccountSharedData::from(Account { lamports: old_lamports, - rent_epoch: old_epoch, + rent_epoch_or_application_fees: old_epoch, ..Account::default() }); @@ -511,7 +506,7 @@ mod tests { set_exempt_rent_epoch_max, ); assert_eq!(account.lamports(), huge_lamports); - assert_eq!(collected, CollectedInfo::default()); + assert_eq!(collected, Ok(CollectedInfo::default())); continue; } @@ -528,7 +523,7 @@ mod tests { set_exempt_rent_epoch_max, ); assert_eq!(account.lamports(), tiny_lamports - collected.rent_amount); - assert_ne!(collected, CollectedInfo::default()); + assert_ne!(collected, Ok(CollectedInfo::default())); } } } @@ -570,7 +565,7 @@ mod tests { let mut account = AccountSharedData::from(Account { lamports: account_lamports, // <-- must be below rent-exempt amount data: vec![u8::default(); account_data_len], - rent_epoch: account_rent_epoch, + rent_epoch_or_application_fees: account_rent_epoch, ..Account::default() }); let rent_collector = default_rent_collector_clone_with_epoch(account_rent_epoch + 1); diff --git a/sdk/src/account.rs b/sdk/src/account.rs index d69cea88510..f571659e95c 100644 --- a/sdk/src/account.rs +++ b/sdk/src/account.rs @@ -22,6 +22,11 @@ use { }, }; +/// When rent is collected from an exempt account, rent_epoch is set to this +/// value. The idea is to have a fixed, consistent value for rent_epoch for all accounts that do not collect rent. +/// This enables us to get rid of the field completely. +pub const RENT_EXEMPT_RENT_EPOCH: Epoch = Epoch::MAX; + /// An Account with data that is stored on chain #[repr(C)] #[frozen_abi(digest = "HawRVHh7t4d3H3bitWHFt25WhhoDmbJMCfWdESQQoYEy")] @@ -286,9 +291,13 @@ impl WritableAccount for Account { self.executable = executable; } fn set_rent_epoch(&mut self, epoch: Epoch) -> Result<(), InstructionError> { - if self.has_application_fees && epoch != 0 { - // cannot set epoch because application fees are present - Err(InstructionError::CannotSetRentEpochForAccountWithAppFees.into()) + if self.has_application_fees { + if epoch != RENT_EXEMPT_RENT_EPOCH { + // cannot set epoch because application fees are present + Err(InstructionError::CannotSetRentEpochForAccountWithAppFees.into()) + } else { + Ok(()) + } } else { self.rent_epoch_or_application_fees = epoch; Ok(()) @@ -302,12 +311,13 @@ impl WritableAccount for Account { } Ok(()) } else { - if self.rent_epoch_or_application_fees != 0 { - return Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch.into()); + if self.rent_epoch_or_application_fees != RENT_EXEMPT_RENT_EPOCH { + Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch.into()) + } else { + self.has_application_fees = true; + self.rent_epoch_or_application_fees = fees; + Ok(()) } - self.has_application_fees = true; - self.rent_epoch_or_application_fees = fees; - Ok(()) } } fn create( @@ -354,9 +364,13 @@ impl WritableAccount for AccountSharedData { self.executable = executable; } fn set_rent_epoch(&mut self, epoch: Epoch) -> Result<(), InstructionError> { - if self.has_application_fees && epoch != 0 { - // cannot set epoch because application fees are present - Err(InstructionError::CannotSetRentEpochForAccountWithAppFees.into()) + if self.has_application_fees { + if epoch != RENT_EXEMPT_RENT_EPOCH { + // cannot set epoch because application fees are present + Err(InstructionError::CannotSetRentEpochForAccountWithAppFees.into()) + } else { + Ok(()) + } } else { self.rent_epoch_or_application_fees = epoch; Ok(()) @@ -370,12 +384,13 @@ impl WritableAccount for AccountSharedData { } Ok(()) } else { - if self.rent_epoch_or_application_fees != 0 { - return Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch.into()); + if self.rent_epoch_or_application_fees != RENT_EXEMPT_RENT_EPOCH { + Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch.into()) + } else { + self.has_application_fees = true; + self.rent_epoch_or_application_fees = fees; + Ok(()) } - self.has_application_fees = true; - self.rent_epoch_or_application_fees = fees; - Ok(()) } } fn create( diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index 90ca5347658..37ff8c1e970 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -604,6 +604,8 @@ pub mod remove_congestion_multiplier_from_fee_calculation { pub mod enable_request_heap_frame_ix { solana_sdk::declare_id!("Hr1nUA9b7NJ6eChS26o7Vi8gYYDDwWD3YeBfzJkTbU86"); +} + pub mod add_application_fees_program { solana_sdk::declare_id!("7hwmoguW2KEXkznQEsGfqGA9XTpGvScVae5MroWX5A9o"); } From 852982ed7d70cd3c7de2663bd055f32164d48b46 Mon Sep 17 00:00:00 2001 From: Godmode Galactus Date: Mon, 6 Feb 2023 13:40:22 +0100 Subject: [PATCH 3/6] application fees merge conflicts for tests --- .../application-fees-tests/tests/rebate.rs | 2 +- programs/application-fees/src/processor.rs | 4 - runtime/src/append_vec.rs | 8 +- runtime/src/bank/tests.rs | 48 ++++++----- runtime/src/rent_collector.rs | 84 +++++++++++-------- runtime/src/storable_accounts.rs | 9 +- 6 files changed, 95 insertions(+), 60 deletions(-) diff --git a/programs/application-fees-tests/tests/rebate.rs b/programs/application-fees-tests/tests/rebate.rs index f5e74bd34ee..38d8612b05a 100644 --- a/programs/application-fees-tests/tests/rebate.rs +++ b/programs/application-fees-tests/tests/rebate.rs @@ -35,7 +35,7 @@ async fn test_application_fees_are_applied_without_rebate() { assert_matches!(client.process_transaction(transaction).await, Ok(())); let account = client.get_account(writable_account).await.unwrap().unwrap(); assert_eq!(account.has_application_fees, false); - assert_eq!(account.rent_epoch_or_application_fees, 0); + assert_eq!(account.rent_epoch_or_application_fees, u64::MAX); } advance_slot(&mut context).await; let account = context diff --git a/programs/application-fees/src/processor.rs b/programs/application-fees/src/processor.rs index 842b87ba14c..f42d76941ae 100644 --- a/programs/application-fees/src/processor.rs +++ b/programs/application-fees/src/processor.rs @@ -72,10 +72,6 @@ impl Processor { } }; - if writable_account.get_rent_epoch() != 0 { - return Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch); - } - let writable_account_key = *writable_account.get_key(); ic_msg!( invoke_context, diff --git a/runtime/src/append_vec.rs b/runtime/src/append_vec.rs index cfd9e0f1caa..1ee1d19fba4 100644 --- a/runtime/src/append_vec.rs +++ b/runtime/src/append_vec.rs @@ -1316,9 +1316,13 @@ pub mod tests { assert_eq!(mem::size_of::(), 0x30); assert_eq!(offset_of!(AccountMeta, lamports), 0x00); - assert_eq!(offset_of!(AccountMeta, rent_epoch), 0x08); + assert_eq!( + offset_of!(AccountMeta, rent_epoch_or_application_fees), + 0x08 + ); assert_eq!(offset_of!(AccountMeta, owner), 0x10); assert_eq!(offset_of!(AccountMeta, executable), 0x30); - assert_eq!(mem::size_of::(), 0x38); + assert_eq!(offset_of!(AccountMeta, executable), 0x38); + assert_eq!(mem::size_of::(), 0x46); } } diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index e162981f8d4..7ec87c7c1f5 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -172,6 +172,7 @@ fn new_execution_result( return_data: None, executed_units: 0, accounts_data_len_delta: 0, + application_fees_changes: ApplicationFeeChanges::new(), }, tx_executor_cache: Rc::new(RefCell::new(TransactionExecutorCache::default())), } @@ -548,12 +549,15 @@ fn test_credit_debit_rent_no_side_effect_on_hash() { { // make sure rent and epoch change are such that we collect all lamports in accounts 4 & 5 let mut account_copy = accounts[4].clone(); - let expected_rent = bank.rent_collector().collect_from_existing_account( - &keypairs[4].pubkey(), - &mut account_copy, - None, - set_exempt_rent_epoch_max, - ); + let expected_rent = bank + .rent_collector() + .collect_from_existing_account( + &keypairs[4].pubkey(), + &mut account_copy, + None, + set_exempt_rent_epoch_max, + ) + .unwrap(); assert_eq!(expected_rent.rent_amount, too_few_lamports); assert_eq!(account_copy.lamports(), 0); } @@ -2136,7 +2140,7 @@ fn test_collect_rent_from_accounts() { let data_size = 0; // make sure we're rent exempt let lamports = later_bank.get_minimum_balance_for_rent_exemption(data_size); // cannot be 0 or we zero out rent_epoch in rent collection and we need to be rent exempt let mut account = AccountSharedData::new(lamports, data_size, &Pubkey::default()); - account.set_rent_epoch(later_bank.epoch() - 1); // non-zero, but less than later_bank's epoch + account.set_rent_epoch(later_bank.epoch() - 1).unwrap(); // non-zero, but less than later_bank's epoch // loaded from previous slot, so we skip rent collection on it let _result = later_bank.collect_rent_from_accounts( @@ -4136,7 +4140,7 @@ fn test_bank_update_sysvar_account() { }, bank1.inherit_specially_retained_account_fields(optional_account), ); - account.set_rent_epoch(dummy_rent_epoch); + account.set_rent_epoch(dummy_rent_epoch).unwrap(); account }); let current_account = bank1.get_account(&dummy_clock_id).unwrap(); @@ -6242,7 +6246,10 @@ fn test_pre_post_transaction_balances() { // This is a TransactionError - not possible to charge fees assert!(matches!( transaction_results.execution_results[1], - TransactionExecutionResult::NotExecuted(TransactionError::AccountNotFound), + TransactionExecutionResult::NotExecuted { + error: TransactionError::AccountNotFound, + .. + } )); assert_eq!(transaction_balances_set.pre_balances[1], vec![0, 0, 1]); assert_eq!(transaction_balances_set.post_balances[1], vec![0, 0, 1]); @@ -7575,7 +7582,7 @@ fn test_bank_executor_cache() { ) .unwrap(); program_account.set_executable(true); - program_account.set_rent_epoch(1); + program_account.set_rent_epoch(1).unwrap(); let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata(); let mut programdata_account = AccountSharedData::new( 40, @@ -7589,7 +7596,7 @@ fn test_bank_executor_cache() { }) .unwrap(); programdata_account.data_mut()[programdata_data_offset..].copy_from_slice(&elf); - programdata_account.set_rent_epoch(1); + programdata_account.set_rent_epoch(1).unwrap(); bank.store_account_and_update_capitalization(&key1, &program_account); bank.store_account_and_update_capitalization(&programdata_key, &programdata_account); bank.create_executor(&key1).unwrap(); @@ -11503,7 +11510,7 @@ fn test_skip_rewrite() { let mut account = AccountSharedData::default(); let bank_slot = 10; for account_rent_epoch in 0..3 { - account.set_rent_epoch(account_rent_epoch); + account.set_rent_epoch(account_rent_epoch).unwrap(); for rent_amount in [0, 1] { for loaded_slot in (bank_slot - 1)..=bank_slot { for old_rent_epoch in account_rent_epoch.saturating_sub(1)..=account_rent_epoch { @@ -11686,7 +11693,7 @@ fn test_resize_and_rent() { account_data_size_small, &mock_program_id, ); - rent_paying_account.set_rent_epoch(1); + rent_paying_account.set_rent_epoch(1).unwrap(); // restore program-owned account bank.store_account(&rent_paying_pubkey, &rent_paying_account); @@ -12114,12 +12121,15 @@ fn test_accounts_data_size_and_rent_collection() { // Ensure if we collect rent from the account that it will be reclaimed { - let info = bank.rent_collector.collect_from_existing_account( - &keypair.pubkey(), - &mut account, - None, - set_exempt_rent_epoch_max, - ); + let info = bank + .rent_collector + .collect_from_existing_account( + &keypair.pubkey(), + &mut account, + None, + set_exempt_rent_epoch_max, + ) + .unwrap(); assert_eq!(info.account_data_len_reclaimed, data_size as u64); } diff --git a/runtime/src/rent_collector.rs b/runtime/src/rent_collector.rs index 897071f2557..2c4a157e259 100644 --- a/runtime/src/rent_collector.rs +++ b/runtime/src/rent_collector.rs @@ -272,7 +272,9 @@ mod tests { let mut account_clone = account.clone(); let mut account_expected = account.clone(); if set_exempt_rent_epoch_max { - account_expected.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH); + account_expected + .set_rent_epoch(RENT_EXEMPT_RENT_EPOCH) + .unwrap(); } assert_eq!( rent_collector.collect_from_existing_account( @@ -295,7 +297,9 @@ mod tests { let mut account_clone = account.clone(); let mut account_expected = account.clone(); if set_exempt_rent_epoch_max { - account_expected.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH); + account_expected + .set_rent_epoch(RENT_EXEMPT_RENT_EPOCH) + .unwrap(); } assert_eq!( rent_collector.collect_from_existing_account( @@ -316,7 +320,7 @@ mod tests { for (rent_epoch, rent_due_expected) in [(2, 2), (3, 5)] { rent_collector.epoch = rent_epoch; account.set_lamports(10); - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); let new_rent_epoch_expected = rent_collector.epoch + 1; assert!( matches!( @@ -343,7 +347,9 @@ mod tests { ); let mut account_expected = account.clone(); account_expected.set_lamports(account.lamports() - rent_due_expected); - account_expected.set_rent_epoch(new_rent_epoch_expected); + account_expected + .set_rent_epoch(new_rent_epoch_expected) + .unwrap(); assert_eq!(account_clone, account_expected); } } @@ -360,7 +366,9 @@ mod tests { let mut account_clone = account.clone(); let mut account_expected = account.clone(); if set_exempt_rent_epoch_max { - account_expected.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH); + account_expected + .set_rent_epoch(RENT_EXEMPT_RENT_EPOCH) + .unwrap(); } assert_eq!( rent_collector.collect_from_existing_account( @@ -377,7 +385,7 @@ mod tests { // enough lamports to make us exempt // but, our rent_epoch is set in the future, so we can't know if we are exempt yet or not. // We don't calculate rent amount vs data if the rent_epoch is already in the future. - account.set_rent_epoch(1_000_000); + account.set_rent_epoch(1_000_000).unwrap(); assert!(matches!( rent_collector.calculate_rent_result(&Pubkey::default(), &account, None,), RentResult::NoRentCollectionNow, @@ -397,7 +405,7 @@ mod tests { } // filler accounts are exempt - account.set_rent_epoch(1); + account.set_rent_epoch(1).unwrap(); account.set_lamports(10); assert!(matches!( rent_collector.calculate_rent_result( @@ -411,7 +419,9 @@ mod tests { let mut account_clone = account.clone(); let mut account_expected = account.clone(); if set_exempt_rent_epoch_max { - account_expected.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH); + account_expected + .set_rent_epoch(RENT_EXEMPT_RENT_EPOCH) + .unwrap(); } assert_eq!( rent_collector.collect_from_existing_account( @@ -461,12 +471,14 @@ mod tests { assert_eq!(collected.account_data_len_reclaimed, 0); // collect rent on a already-existing account - let collected = rent_collector.collect_from_existing_account( - &solana_sdk::pubkey::new_rand(), - &mut existing_account, - None, // filler_account_suffix - set_exempt_rent_epoch_max, - ); + let collected = rent_collector + .collect_from_existing_account( + &solana_sdk::pubkey::new_rand(), + &mut existing_account, + None, // filler_account_suffix + set_exempt_rent_epoch_max, + ) + .unwrap(); assert!(existing_account.lamports() < old_lamports); assert_eq!( existing_account.lamports() + collected.rent_amount, @@ -516,14 +528,16 @@ mod tests { account.set_lamports(tiny_lamports); // ... and trigger another rent collection on the same epoch and check that rent is working - let collected = rent_collector.collect_from_existing_account( - &pubkey, - &mut account, - None, // filler_account_suffix - set_exempt_rent_epoch_max, - ); + let collected = rent_collector + .collect_from_existing_account( + &pubkey, + &mut account, + None, // filler_account_suffix + set_exempt_rent_epoch_max, + ) + .unwrap(); assert_eq!(account.lamports(), tiny_lamports - collected.rent_amount); - assert_ne!(collected, Ok(CollectedInfo::default())); + assert_ne!(collected, CollectedInfo::default()); } } } @@ -543,12 +557,14 @@ mod tests { let epoch = 3; let rent_collector = default_rent_collector_clone_with_epoch(epoch); - let collected = rent_collector.collect_from_existing_account( - &pubkey, - &mut account, - None, // filler_account_suffix - set_exempt_rent_epoch_max, - ); + let collected = rent_collector + .collect_from_existing_account( + &pubkey, + &mut account, + None, // filler_account_suffix + set_exempt_rent_epoch_max, + ) + .unwrap(); assert_eq!(account.lamports(), 0); assert_eq!(collected.rent_amount, 1); } @@ -570,12 +586,14 @@ mod tests { }); let rent_collector = default_rent_collector_clone_with_epoch(account_rent_epoch + 1); - let collected = rent_collector.collect_from_existing_account( - &Pubkey::new_unique(), - &mut account, - None, // filler_account_suffix - set_exempt_rent_epoch_max, - ); + let collected = rent_collector + .collect_from_existing_account( + &Pubkey::new_unique(), + &mut account, + None, // filler_account_suffix + set_exempt_rent_epoch_max, + ) + .unwrap(); assert_eq!(collected.rent_amount, account_lamports); assert_eq!( diff --git a/runtime/src/storable_accounts.rs b/runtime/src/storable_accounts.rs index a7ff217ad09..3596af2774d 100644 --- a/runtime/src/storable_accounts.rs +++ b/runtime/src/storable_accounts.rs @@ -497,6 +497,8 @@ pub mod tests { Pubkey::default(), false, 0, + false, + 0, ); raw.push(( pk, @@ -510,7 +512,12 @@ pub mod tests { lamports: account.lamports(), owner: *account.owner(), executable: account.executable(), - rent_epoch: account.rent_epoch(), + has_application_fees: account.has_application_fees(), + rent_epoch_or_application_fees: if account.has_application_fees() { + account.application_fees() + } else { + account.rent_epoch() + }, }, )); } From 98b2abd826ec4be446eae177ed15b26a650cb842 Mon Sep 17 00:00:00 2001 From: Godmode Galactus Date: Mon, 6 Feb 2023 14:43:03 +0100 Subject: [PATCH 4/6] application fees adding more tests, return RENT_EXEMPT_EPOCH instead of 0 in case of application fees --- runtime/src/accounts_db.rs | 6 ++-- sdk/src/account.rs | 51 +++++++++++++++++++++++++++++++--- sdk/src/transaction_context.rs | 4 ++- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index fad5f050350..a44e2064b8e 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -18,6 +18,8 @@ //! tracks the number of commits to the entire data store. So the latest //! commit for each slot entry would be indexed. +use solana_sdk::account::RENT_EXEMPT_RENT_EPOCH; + use { crate::{ account_info::{AccountInfo, Offset, StorageLocation, StoredSize}, @@ -900,7 +902,7 @@ impl<'a> ReadableAccount for LoadedAccount<'a> { match self { LoadedAccount::Stored(stored_account_meta) => { if stored_account_meta.account_meta.has_application_fees { - 0 + RENT_EXEMPT_RENT_EPOCH } else { stored_account_meta .account_meta @@ -2242,7 +2244,7 @@ impl<'a> ReadableAccount for StoredAccountMeta<'a> { } fn rent_epoch(&self) -> Epoch { if self.account_meta.has_application_fees { - 0 + RENT_EXEMPT_RENT_EPOCH } else { self.account_meta.rent_epoch_or_application_fees } diff --git a/sdk/src/account.rs b/sdk/src/account.rs index f571659e95c..29766f7222e 100644 --- a/sdk/src/account.rs +++ b/sdk/src/account.rs @@ -252,7 +252,7 @@ impl ReadableAccount for Account { } fn rent_epoch(&self) -> Epoch { if self.has_application_fees { - 0 + RENT_EXEMPT_RENT_EPOCH } else { self.rent_epoch_or_application_fees } @@ -432,7 +432,7 @@ impl ReadableAccount for AccountSharedData { } fn rent_epoch(&self) -> Epoch { if self.has_application_fees { - 0 + RENT_EXEMPT_RENT_EPOCH } else { self.rent_epoch_or_application_fees } @@ -470,7 +470,7 @@ impl ReadableAccount for Ref<'_, AccountSharedData> { } fn rent_epoch(&self) -> Epoch { if self.has_application_fees { - 0 + RENT_EXEMPT_RENT_EPOCH } else { self.rent_epoch_or_application_fees } @@ -515,7 +515,7 @@ impl ReadableAccount for Ref<'_, Account> { } fn rent_epoch(&self) -> Epoch { if self.has_application_fees { - 0 + RENT_EXEMPT_RENT_EPOCH } else { self.rent_epoch_or_application_fees } @@ -1428,4 +1428,47 @@ pub mod tests { assert_eq!(account2.executable, deserialized_acc2.executable); assert_eq!(account2.rent_epoch, deserialized_acc2.rent_epoch); } + + + #[test] + fn test_updating_application_fees_for_account_with_rent_epoch_fails() { + let key = Pubkey::new_unique(); + let ( mut account1, mut account2) = make_two_accounts(&key); + assert_eq!(account1.set_application_fees(100), Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch)); + assert_eq!(account2.set_application_fees(100), Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch)); + + account1.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + account2.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + assert_eq!(account1.set_application_fees(100), Ok(())); + assert_eq!(account2.set_application_fees(100), Ok(())); + assert_eq!(account1.has_application_fees(), true); + assert_eq!(account2.has_application_fees(), true); + assert_eq!(account1.application_fees(), 100); + assert_eq!(account2.application_fees(), 100); + assert_eq!(account1.rent_epoch(), RENT_EXEMPT_RENT_EPOCH); + assert_eq!(account2.rent_epoch(), RENT_EXEMPT_RENT_EPOCH); + + // further setting rent_epoch to rent_exempt does not trigger error + account1.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + account2.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + } + + #[test] + fn test_updating_rent_epoch_for_account_with_application_fee_fails() { + let key = Pubkey::new_unique(); + let ( mut account1, mut account2) = make_two_accounts(&key); + account1.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + account2.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + assert_eq!(account1.set_application_fees(100), Ok(())); + assert_eq!(account2.set_application_fees(100), Ok(())); + assert_eq!(account1.has_application_fees(), true); + assert_eq!(account2.has_application_fees(), true); + assert_eq!(account1.application_fees(), 100); + assert_eq!(account2.application_fees(), 100); + assert_eq!(account1.rent_epoch(), RENT_EXEMPT_RENT_EPOCH); + assert_eq!(account2.rent_epoch(), RENT_EXEMPT_RENT_EPOCH); + + assert_eq!(account1.set_rent_epoch(12),Err(InstructionError::CannotSetRentEpochForAccountWithAppFees)); + assert_eq!(account2.set_rent_epoch(12),Err(InstructionError::CannotSetRentEpochForAccountWithAppFees)); + } } diff --git a/sdk/src/transaction_context.rs b/sdk/src/transaction_context.rs index c60d1430382..f81ba4703ec 100644 --- a/sdk/src/transaction_context.rs +++ b/sdk/src/transaction_context.rs @@ -718,6 +718,8 @@ impl<'a> BorrowedAccount<'a> { #[cfg(not(target_os = "solana"))] pub fn set_application_fees(&mut self, application_fees: u64) -> Result<(), InstructionError> { + use crate::account::RENT_EXEMPT_RENT_EPOCH; + if self .transaction_context .is_early_verification_of_account_modifications_enabled() @@ -726,7 +728,7 @@ impl<'a> BorrowedAccount<'a> { if !self.is_writable() { return Err(InstructionError::ReadonlyLamportChange); } - if !self.has_application_fees() && self.get_rent_epoch() != 0 { + if !self.has_application_fees() && self.get_rent_epoch() != RENT_EXEMPT_RENT_EPOCH { return Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch); } // don't touch the account if the lamports do not change From cf5c9126274f1cace165289a328dd7263c72f449 Mon Sep 17 00:00:00 2001 From: Godmode Galactus Date: Tue, 7 Feb 2023 17:19:28 +0100 Subject: [PATCH 5/6] application fees, making executable as account_flags and saving has_application_fees on same byte as exectuable to have same size for AccountMeta in append_vec --- Cargo.lock | 1 + .../src/accounts_update_notifier.rs | 8 +- program-runtime/src/pre_account.rs | 39 ++- runtime/Cargo.toml | 1 + runtime/src/accounts.rs | 28 +-- runtime/src/accounts_db.rs | 27 +- runtime/src/ancient_append_vecs.rs | 5 +- runtime/src/append_vec.rs | 233 ++++++++++++------ runtime/src/storable_accounts.rs | 17 +- sdk/src/account.rs | 29 ++- 10 files changed, 259 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a87db6b6b9..74f142df5dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6559,6 +6559,7 @@ dependencies = [ "arrayref", "assert_matches", "bincode", + "bitflags", "blake3", "bv", "bytemuck", diff --git a/geyser-plugin-manager/src/accounts_update_notifier.rs b/geyser-plugin-manager/src/accounts_update_notifier.rs index 5ac5c671941..89e4ede34cd 100644 --- a/geyser-plugin-manager/src/accounts_update_notifier.rs +++ b/geyser-plugin-manager/src/accounts_update_notifier.rs @@ -12,7 +12,7 @@ use { append_vec::StoredAccountMeta, }, solana_sdk::{ - account::{AccountSharedData, ReadableAccount}, + account::{AccountSharedData, ReadableAccount, RENT_EXEMPT_RENT_EPOCH}, clock::Slot, pubkey::Pubkey, signature::Signature, @@ -131,9 +131,9 @@ impl AccountsUpdateNotifierImpl { pubkey: stored_account_meta.pubkey().as_ref(), lamports: stored_account_meta.account_meta.lamports, owner: stored_account_meta.account_meta.owner.as_ref(), - executable: stored_account_meta.account_meta.executable, - rent_epoch: if stored_account_meta.account_meta.has_application_fees { - 0 + executable: stored_account_meta.account_meta.executable(), + rent_epoch: if stored_account_meta.account_meta.has_application_fees() { + RENT_EXEMPT_RENT_EPOCH } else { stored_account_meta .account_meta diff --git a/program-runtime/src/pre_account.rs b/program-runtime/src/pre_account.rs index 4cc04545bcd..ae43ae6537a 100644 --- a/program-runtime/src/pre_account.rs +++ b/program-runtime/src/pre_account.rs @@ -191,7 +191,11 @@ impl PreAccount { mod tests { use { super::*, - solana_sdk::{account::Account, instruction::InstructionError, system_program}, + solana_sdk::{ + account::{Account, RENT_EXEMPT_RENT_EPOCH}, + instruction::InstructionError, + system_program, + }, }; #[test] @@ -244,6 +248,30 @@ mod tests { }), } } + pub fn new_rent_free(owner: &Pubkey, program_id: &Pubkey) -> Self { + Self { + program_id: *program_id, + rent: Rent::default(), + is_writable: true, + pre: PreAccount::new( + &solana_sdk::pubkey::new_rand(), + AccountSharedData::from(Account { + owner: *owner, + lamports: std::u64::MAX, + has_application_fees: false, + rent_epoch_or_application_fees: RENT_EXEMPT_RENT_EPOCH, + ..Account::default() + }), + ), + post: AccountSharedData::from(Account { + owner: *owner, + lamports: std::u64::MAX, + has_application_fees: false, + rent_epoch_or_application_fees: RENT_EXEMPT_RENT_EPOCH, + ..Account::default() + }), + } + } pub fn read_only(mut self) -> Self { self.is_writable = false; self @@ -531,16 +559,11 @@ mod tests { } #[test] - fn test_verify_account_changes_application_fees() { + fn test_verify_account_cannot_change_application_fees() { let alice_program_id = solana_sdk::pubkey::new_rand(); assert_eq!( - Change::new(&alice_program_id, &system_program::id()).verify(), - Ok(()), - "nothing changed!" - ); - assert_eq!( - Change::new(&alice_program_id, &system_program::id()) + Change::new_rent_free(&alice_program_id, &system_program::id()) .change_application_fees(0, 1) .unwrap() .verify(), diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 252eecf8f6b..9f97bb748e6 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -65,6 +65,7 @@ tar = "0.4.38" tempfile = "3.3.0" thiserror = "1.0" zstd = "0.11.2" +bitflags = "1.3.2" [lib] crate-type = ["lib"] diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index 16116890e63..bdcb37ef6e5 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -382,9 +382,9 @@ impl Accounts { error_counters, )?; - if account.has_application_fees { + if account.has_application_fees() { // if account has application fees insert the fees in the map - application_fees.insert(*key, account.rent_epoch_or_application_fees); + application_fees.insert(*key, account.application_fees()); } if !validated_fee_payer && message.is_non_loader_key(i) { @@ -1382,8 +1382,6 @@ fn prepare_if_nonce_account( #[cfg(test)] mod tests { - use std::str::FromStr; - use { super::*, crate::{ @@ -1394,11 +1392,10 @@ mod tests { itertools::Itertools, solana_address_lookup_table_program::state::LookupTableMeta, solana_program_runtime::{ - compute_budget, executor_cache::TransactionExecutorCache, - invoke_context::ApplicationFeeChanges, + executor_cache::TransactionExecutorCache, invoke_context::ApplicationFeeChanges, }, solana_sdk::{ - account::{AccountSharedData, WritableAccount}, + account::{AccountSharedData, WritableAccount, RENT_EXEMPT_RENT_EPOCH}, epoch_schedule::EpochSchedule, genesis_config::ClusterType, hash::Hash, @@ -1415,6 +1412,7 @@ mod tests { cell::RefCell, convert::TryFrom, rc::Rc, + str::FromStr, sync::atomic::{AtomicBool, AtomicU64, Ordering}, thread, time, }, @@ -3995,18 +3993,18 @@ mod tests { accounts.store_slow_uncached(0, &payer.pubkey(), &payer_acc); let mut key1_acc = AccountSharedData::new(100, 0, &owner.pubkey()); - key1_acc.has_application_fees = true; - key1_acc.rent_epoch_or_application_fees = 100; + key1_acc.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + key1_acc.set_application_fees(100).unwrap(); accounts.store_slow_uncached(0, &key1, &key1_acc); let mut key2_acc = AccountSharedData::new(100, 0, &owner.pubkey()); - key2_acc.has_application_fees = true; - key2_acc.rent_epoch_or_application_fees = 1000; + key2_acc.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + key2_acc.set_application_fees(1000).unwrap(); accounts.store_slow_uncached(0, &key2, &key2_acc); let mut key3_acc = AccountSharedData::new(100, 0, &owner.pubkey()); - key3_acc.has_application_fees = true; - key3_acc.rent_epoch_or_application_fees = 10000; + key3_acc.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + key3_acc.set_application_fees(10000).unwrap(); accounts.store_slow_uncached(0, &key3, &key3_acc); let blockhash = Hash::new_unique(); @@ -4114,8 +4112,8 @@ mod tests { accounts.store_slow_uncached(0, &payer.pubkey(), &payer_acc); let mut key1_acc = AccountSharedData::new(100, 0, &owner.pubkey()); - key1_acc.has_application_fees = true; - key1_acc.rent_epoch_or_application_fees = 10001; + key1_acc.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + key1_acc.set_application_fees(10001).unwrap(); accounts.store_slow_uncached(0, &key1, &key1_acc); let blockhash = Hash::new_unique(); let tx1 = create_transfer_transaction(&payer, &key1, blockhash); diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index a44e2064b8e..11943edd889 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -893,7 +893,7 @@ impl<'a> ReadableAccount for LoadedAccount<'a> { fn executable(&self) -> bool { match self { LoadedAccount::Stored(stored_account_meta) => { - stored_account_meta.account_meta.executable + stored_account_meta.account_meta.executable() } LoadedAccount::Cached(cached_account) => cached_account.account.executable(), } @@ -901,7 +901,7 @@ impl<'a> ReadableAccount for LoadedAccount<'a> { fn rent_epoch(&self) -> Epoch { match self { LoadedAccount::Stored(stored_account_meta) => { - if stored_account_meta.account_meta.has_application_fees { + if stored_account_meta.account_meta.has_application_fees() { RENT_EXEMPT_RENT_EPOCH } else { stored_account_meta @@ -915,7 +915,7 @@ impl<'a> ReadableAccount for LoadedAccount<'a> { fn has_application_fees(&self) -> bool { match self { LoadedAccount::Stored(stored_account_meta) => { - stored_account_meta.account_meta.has_application_fees + stored_account_meta.account_meta.has_application_fees() } LoadedAccount::Cached(cached_account) => cached_account.account.has_application_fees(), } @@ -923,7 +923,7 @@ impl<'a> ReadableAccount for LoadedAccount<'a> { fn application_fees(&self) -> u64 { match self { LoadedAccount::Stored(stored_account_meta) => { - if stored_account_meta.account_meta.has_application_fees { + if stored_account_meta.account_meta.has_application_fees() { stored_account_meta .account_meta .rent_epoch_or_application_fees @@ -2240,20 +2240,20 @@ impl<'a> ReadableAccount for StoredAccountMeta<'a> { &self.account_meta.owner } fn executable(&self) -> bool { - self.account_meta.executable + self.account_meta.executable() } fn rent_epoch(&self) -> Epoch { - if self.account_meta.has_application_fees { + if self.account_meta.has_application_fees() { RENT_EXEMPT_RENT_EPOCH } else { self.account_meta.rent_epoch_or_application_fees } } fn has_application_fees(&self) -> bool { - self.account_meta.has_application_fees + self.account_meta.has_application_fees() } fn application_fees(&self) -> u64 { - if self.account_meta.has_application_fees { + if self.account_meta.has_application_fees() { self.account_meta.rent_epoch_or_application_fees } else { 0 @@ -9415,7 +9415,7 @@ pub mod tests { tests::*, AccountIndex, AccountSecondaryIndexes, AccountSecondaryIndexesIncludeExclude, ReadAccountMapEntry, RefCount, }, - append_vec::{test_utils::TempFile, AccountMeta, StoredMeta}, + append_vec::{test_utils::TempFile, AccountFlags, AccountMeta, StoredMeta}, cache_hash_data_stats::CacheHashDataStats, inline_spl_token, secondary_index::MAX_NUM_LARGEST_INDEX_KEYS_RETURNED, @@ -9586,8 +9586,7 @@ pub mod tests { let account_meta = AccountMeta { lamports: 1, owner: Pubkey::from([2; 32]), - executable: false, - has_application_fees: false, + account_flags: AccountFlags::NONE, rent_epoch_or_application_fees: 0, }; let offset = 3; @@ -9689,8 +9688,7 @@ pub mod tests { let account_meta = AccountMeta { lamports, owner, - executable, - has_application_fees: false, + account_flags: AccountFlags::new(executable, false), rent_epoch_or_application_fees: rent_epoch, }; let offset = 99; @@ -12255,8 +12253,7 @@ pub mod tests { let account_meta = AccountMeta { lamports, owner, - executable, - has_application_fees: false, + account_flags: AccountFlags::new(executable, false), rent_epoch_or_application_fees: rent_epoch, }; let data = Vec::new(); diff --git a/runtime/src/ancient_append_vecs.rs b/runtime/src/ancient_append_vecs.rs index 9071dc2eac1..86a2b85354d 100644 --- a/runtime/src/ancient_append_vecs.rs +++ b/runtime/src/ancient_append_vecs.rs @@ -198,7 +198,7 @@ pub mod tests { remove_account_for_tests, }, }, - append_vec::{AccountMeta, StoredAccountMeta, StoredMeta}, + append_vec::{AccountFlags, AccountMeta, StoredAccountMeta, StoredMeta}, }, solana_sdk::{ account::{AccountSharedData, ReadableAccount}, @@ -229,8 +229,7 @@ pub mod tests { let account_meta = AccountMeta { lamports: 1, owner: Pubkey::from([2; 32]), - executable: false, - has_application_fees: false, + account_flags: AccountFlags::new(false, false), rent_epoch_or_application_fees: 0, }; let offset = 3; diff --git a/runtime/src/append_vec.rs b/runtime/src/append_vec.rs index 1ee1d19fba4..217949db990 100644 --- a/runtime/src/append_vec.rs +++ b/runtime/src/append_vec.rs @@ -6,6 +6,7 @@ use { crate::storable_accounts::StorableAccounts, + bitflags::bitflags, log::*, memmap2::MmapMut, serde::{Deserialize, Serialize}, @@ -155,6 +156,28 @@ pub struct StoredMeta { pub pubkey: Pubkey, } +bitflags! { + #[derive(Serialize, Deserialize, Default)] + pub struct AccountFlags: u8 { + const NONE = 0b00000000; + const EXECUTABLE = 0b00000001; + const HAS_APPLICATION_FEES = 0b00000010; + } +} + +impl AccountFlags { + pub fn new(executable: bool, has_application_fees: bool) -> Self { + let mut flags = AccountFlags::NONE; + if executable { + flags |= AccountFlags::EXECUTABLE; + } + if has_application_fees { + flags |= AccountFlags::HAS_APPLICATION_FEES; + } + flags + } +} + /// This struct will be backed by mmaped and snapshotted data files. /// So the data layout must be stable and consistent across the entire cluster! #[derive(Serialize, Deserialize, Clone, Debug, Default, Eq, PartialEq)] @@ -162,15 +185,24 @@ pub struct StoredMeta { pub struct AccountMeta { /// lamports in the account pub lamports: u64, - /// the epoch at which this account will next owe rent + /// the epoch at which this account will next owe rent or application fees depending on the account flags pub rent_epoch_or_application_fees: u64, /// the program that owns this account. If executable, the program that loads this account. pub owner: Pubkey, /// this account's data contains a loaded program (and is now read-only) - pub executable: bool, - /// the epoch at which this account will next owe rent or application fees for the account - /// switched by the boolean above - pub has_application_fees: bool, + /// 1st bit executable + /// 2nd bit has_application_fees + pub account_flags: AccountFlags, +} + +impl AccountMeta { + pub fn executable(&self) -> bool { + self.account_flags & AccountFlags::EXECUTABLE == AccountFlags::EXECUTABLE + } + + pub fn has_application_fees(&self) -> bool { + self.account_flags & AccountFlags::HAS_APPLICATION_FEES == AccountFlags::HAS_APPLICATION_FEES + } } impl<'a, T: ReadableAccount> From<&'a T> for AccountMeta { @@ -179,8 +211,7 @@ impl<'a, T: ReadableAccount> From<&'a T> for AccountMeta { Self { lamports: account.lamports(), owner: *account.owner(), - executable: account.executable(), - has_application_fees, + account_flags: AccountFlags::new(account.executable(), account.has_application_fees()), rent_epoch_or_application_fees: if has_application_fees { account.application_fees() } else { @@ -218,8 +249,8 @@ impl<'a> StoredAccountMeta<'a> { AccountSharedData::from(Account { lamports: self.account_meta.lamports, owner: self.account_meta.owner, - executable: self.account_meta.executable, - has_application_fees: self.account_meta.has_application_fees, + executable: self.account_meta.executable(), + has_application_fees: self.account_meta.has_application_fees(), rent_epoch_or_application_fees: self.account_meta.rent_epoch_or_application_fees, data: self.data.to_vec(), }) @@ -230,19 +261,14 @@ impl<'a> StoredAccountMeta<'a> { } fn sanitize(&self) -> bool { - self.sanitize_executable() + self.sanitize_executable_and_application_fees() && self.sanitize_lamports() - && self.sanitize_has_application_fees() - } - - fn sanitize_executable(&self) -> bool { - // Sanitize executable to ensure higher 7-bits are cleared correctly. - self.ref_executable_byte() & !1 == 0 + && self.sanitize_executable_and_application_fees() } - fn sanitize_has_application_fees(&self) -> bool { + fn sanitize_executable_and_application_fees(&self) -> bool { // Sanitize executable to ensure higher 7-bits are cleared correctly. - self.ref_has_application_fees_byte() & !1 == 0 + self.ref_account_flags_byte() & !3 == 0 } fn sanitize_lamports(&self) -> bool { @@ -250,23 +276,14 @@ impl<'a> StoredAccountMeta<'a> { self.account_meta.lamports != 0 || self.clone_account() == AccountSharedData::default() } - fn ref_executable_byte(&self) -> &u8 { - // Use extra references to avoid value silently clamped to 1 (=true) and 0 (=false) - // Yes, this really happens; see test_new_from_file_crafted_executable - let executable_bool: &bool = &self.account_meta.executable; - // UNSAFE: Force to interpret mmap-backed bool as u8 to really read the actual memory content - let executable_byte: &u8 = unsafe { &*(executable_bool as *const bool as *const u8) }; - executable_byte - } - - fn ref_has_application_fees_byte(&self) -> &u8 { + fn ref_account_flags_byte(&self) -> &u8 { // Use extra references to avoid value silently clamped to 1 (=true) and 0 (=false) // Yes, this really happens; see test_new_from_file_crafted_executable - let has_application_fees: &bool = &self.account_meta.has_application_fees; - // UNSAFE: Force to interpret mmap-backed bool as u8 to really read the actual memory content - let has_application_fees_byte: &u8 = - unsafe { &*(has_application_fees as *const bool as *const u8) }; - has_application_fees_byte + let account_flags: &AccountFlags = &self.account_meta.account_flags; + // UNSAFE: Force to interpret mmap-backed account_flags as u8 to really read the actual memory content + let account_flags_byte: &u8 = + unsafe { &*(account_flags as *const AccountFlags as *const u8) }; + account_flags_byte } } @@ -676,8 +693,10 @@ impl AppendVec { .map(|account| AccountMeta { lamports: account.lamports(), owner: *account.owner(), - executable: account.executable(), - has_application_fees: account.has_application_fees(), + account_flags: AccountFlags::new( + account.executable(), + account.has_application_fees(), + ), rent_epoch_or_application_fees: if account.has_application_fees() { account.application_fees() } else { @@ -728,6 +747,8 @@ impl AppendVec { #[cfg(test)] pub mod tests { + use solana_sdk::account::RENT_EXEMPT_RENT_EPOCH; + use { super::{test_utils::*, *}, crate::accounts_db::INCLUDE_SLOT_IN_HASH_TESTS, @@ -773,18 +794,12 @@ pub mod tests { } } - fn get_executable_byte(&self) -> u8 { - let executable_bool: bool = self.account_meta.executable; - // UNSAFE: Force to interpret mmap-backed bool as u8 to really read the actual memory content - let executable_byte: u8 = unsafe { std::mem::transmute::(executable_bool) }; - executable_byte - } - #[allow(clippy::cast_ref_to_mut)] - fn set_executable_as_byte(&self, new_executable_byte: u8) { + fn set_account_flags_as_byte(&self, new_executable_byte: u8) { // UNSAFE: Force to interpret mmap-backed &bool as &u8 to write some crafted value; unsafe { - *(&self.account_meta.executable as *const bool as *mut u8) = new_executable_byte; + *(&self.account_meta.account_flags as *const AccountFlags as *mut u8) = + new_executable_byte; } } } @@ -962,15 +977,14 @@ pub mod tests { let def1 = AccountMeta { lamports: 1, owner: Pubkey::new_unique(), - executable: true, - has_application_fees: false, + account_flags: AccountFlags { bits: 0x1 }, rent_epoch_or_application_fees: 3, }; let def2_account = Account { lamports: def1.lamports, owner: def1.owner, - executable: def1.executable, - has_application_fees: def1.has_application_fees, + executable: def1.executable(), + has_application_fees: def1.has_application_fees(), rent_epoch_or_application_fees: def1.rent_epoch_or_application_fees, data: Vec::new(), }; @@ -1263,42 +1277,35 @@ pub mod tests { let accounts = av.accounts(0); // ensure false is 0u8 and true is 1u8 actually - assert_eq!(*accounts[0].ref_executable_byte(), 0); - assert_eq!(*accounts[1].ref_executable_byte(), 1); + assert_eq!(*accounts[0].ref_account_flags_byte(), 0); + assert_eq!(*accounts[1].ref_account_flags_byte(), 1); let account = &accounts[0]; - let crafted_executable = u8::max_value() - 1; + let crafted_executable = !3; - account.set_executable_as_byte(crafted_executable); + account.set_account_flags_as_byte(crafted_executable); // reload crafted accounts let accounts = av.accounts(0); let account = accounts.first().unwrap(); - // upper 7-bits are not 0, so sanitization should fail - assert!(!account.sanitize_executable()); + // upper 6-bits are not 0, so sanitization should fail + assert!(!account.sanitize_executable_and_application_fees()); // we can observe crafted value by ref { - let executable_bool: &bool = &account.account_meta.executable; + let account_flags = &account.account_meta.account_flags.bits; // Depending on use, *executable_bool can be truthy or falsy due to direct memory manipulation // assert_eq! thinks *executable_bool is equal to false but the if condition thinks it's not, contradictorily. - assert!(!*executable_bool); + assert!(!account.account_meta.executable()); #[cfg(not(target_arch = "aarch64"))] { - const FALSE: bool = false; // keep clippy happy - if *executable_bool == FALSE { + const FALSE: u8 = 0; // keep clippy happy + if *account_flags == FALSE { panic!("This didn't occur if this test passed."); } } - assert_eq!(*account.ref_executable_byte(), crafted_executable); - } - - // we can NOT observe crafted value by value - { - let executable_bool: bool = account.account_meta.executable; - assert!(!executable_bool); - assert_eq!(account.get_executable_byte(), 0); // Wow, not crafted_executable! + assert_eq!(*account.ref_account_flags_byte(), crafted_executable); } av.flush().unwrap(); @@ -1321,8 +1328,96 @@ pub mod tests { 0x08 ); assert_eq!(offset_of!(AccountMeta, owner), 0x10); - assert_eq!(offset_of!(AccountMeta, executable), 0x30); - assert_eq!(offset_of!(AccountMeta, executable), 0x38); - assert_eq!(mem::size_of::(), 0x46); + assert_eq!(offset_of!(AccountMeta, account_flags), 0x30); + assert_eq!(mem::size_of::(), 0x38); + } + + #[test] + fn test_account_flags() { + // executable: false, has_application_fees: false + let account_meta = AccountMeta { + account_flags: AccountFlags::new(false, false), + ..Default::default() + }; + assert_eq!(account_meta.executable(), false); + assert_eq!(account_meta.has_application_fees(), false); + + // executable: false, has_application_fees: true + let account_meta = AccountMeta { + account_flags: AccountFlags::new(false, true), + ..Default::default() + }; + assert_eq!(account_meta.executable(), false); + assert_eq!(account_meta.has_application_fees(), true); + + // executable: true, has_application_fees: false + let account_meta = AccountMeta { + account_flags: AccountFlags::new(true, false), + ..Default::default() + }; + assert_eq!(account_meta.executable(), true); + assert_eq!(account_meta.has_application_fees(), false); + + // executable: true, has_application_fees: true + let account_meta = AccountMeta { + account_flags: AccountFlags::new(true, true), + ..Default::default() + }; + assert_eq!(account_meta.executable(), true); + assert_eq!(account_meta.has_application_fees(), true); + } + + #[test] + fn test_sanatize_for_executable_and_application_fees() { + let file = get_append_vec_path("test_new_from_crafted_executable"); + let path = &file.path; + let mut av = AppendVec::new(path, true, 1024 * 1024); + av.set_no_remove_on_drop(); + // executable false, application fees false + av.append_account_test(&create_test_account(10)).unwrap(); + // executable true, application fees false + { + let mut accounts = create_test_account(10); + accounts.1.set_executable(true); + av.append_account_test(&accounts).unwrap(); + } + // executable false, application fees true + { + let mut accounts = create_test_account(10); + accounts.1.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + accounts.1.set_application_fees(100).unwrap(); + av.append_account_test(&accounts).unwrap(); + } + // executable true, application fees true + { + let mut accounts = create_test_account(10); + accounts.1.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); + accounts.1.set_executable(true); + accounts.1.set_application_fees(100).unwrap(); + av.append_account_test(&accounts).unwrap(); + } + + let accounts = av.accounts(0); + let account = accounts.first().unwrap(); + assert_eq!(account.account_meta.account_flags, AccountFlags::NONE); + assert_eq!(account.sanitize_executable_and_application_fees(), true); + + let account = accounts.get(1).unwrap(); + assert_eq!(account.account_meta.account_flags, AccountFlags::EXECUTABLE); + assert_eq!(account.sanitize_executable_and_application_fees(), true); + + let account = accounts.get(2).unwrap(); + assert_eq!( + account.account_meta.account_flags, + AccountFlags::HAS_APPLICATION_FEES + ); + assert_eq!(account.sanitize_executable_and_application_fees(), true); + + let account = accounts.get(3).unwrap(); + assert_eq!( + account.account_meta.account_flags, + AccountFlags::EXECUTABLE | AccountFlags::HAS_APPLICATION_FEES + ); + assert_eq!(account.sanitize_executable_and_application_fees(), true); } } diff --git a/runtime/src/storable_accounts.rs b/runtime/src/storable_accounts.rs index 3596af2774d..bbaaff231ae 100644 --- a/runtime/src/storable_accounts.rs +++ b/runtime/src/storable_accounts.rs @@ -301,6 +301,8 @@ impl<'a> StorableAccounts<'a, StoredAccountMeta<'a>> #[cfg(test)] pub mod tests { + use crate::append_vec::AccountFlags; + use { super::*, crate::{ @@ -347,8 +349,7 @@ pub mod tests { let account_meta = AccountMeta { lamports, owner, - executable, - has_application_fees, + account_flags: AccountFlags::new(executable, has_application_fees), rent_epoch_or_application_fees, }; let data = Vec::default(); @@ -407,8 +408,10 @@ pub mod tests { AccountMeta { lamports: account.lamports(), owner: *account.owner(), - executable: account.executable(), - has_application_fees: account.has_application_fees(), + account_flags: AccountFlags::new( + account.executable(), + account.has_application_fees(), + ), rent_epoch_or_application_fees: if account.has_application_fees() { account.application_fees() } else { @@ -511,8 +514,10 @@ pub mod tests { AccountMeta { lamports: account.lamports(), owner: *account.owner(), - executable: account.executable(), - has_application_fees: account.has_application_fees(), + account_flags: AccountFlags::new( + account.executable(), + account.has_application_fees(), + ), rent_epoch_or_application_fees: if account.has_application_fees() { account.application_fees() } else { diff --git a/sdk/src/account.rs b/sdk/src/account.rs index 29766f7222e..fc0fb3eeecd 100644 --- a/sdk/src/account.rs +++ b/sdk/src/account.rs @@ -129,9 +129,9 @@ pub struct AccountSharedData { /// this account's data contains a loaded program (and is now read-only) executable: bool, // has application fees - pub has_application_fees: bool, + has_application_fees: bool, /// the epoch at which this account will next owe rent - pub rent_epoch_or_application_fees: u64, + rent_epoch_or_application_fees: u64, } /// Compares two ReadableAccounts @@ -1429,13 +1429,18 @@ pub mod tests { assert_eq!(account2.rent_epoch, deserialized_acc2.rent_epoch); } - #[test] fn test_updating_application_fees_for_account_with_rent_epoch_fails() { let key = Pubkey::new_unique(); - let ( mut account1, mut account2) = make_two_accounts(&key); - assert_eq!(account1.set_application_fees(100), Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch)); - assert_eq!(account2.set_application_fees(100), Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch)); + let (mut account1, mut account2) = make_two_accounts(&key); + assert_eq!( + account1.set_application_fees(100), + Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch) + ); + assert_eq!( + account2.set_application_fees(100), + Err(InstructionError::CannotSetAppFeesForAccountWithRentEpoch) + ); account1.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); account2.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); @@ -1456,7 +1461,7 @@ pub mod tests { #[test] fn test_updating_rent_epoch_for_account_with_application_fee_fails() { let key = Pubkey::new_unique(); - let ( mut account1, mut account2) = make_two_accounts(&key); + let (mut account1, mut account2) = make_two_accounts(&key); account1.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); account2.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); assert_eq!(account1.set_application_fees(100), Ok(())); @@ -1468,7 +1473,13 @@ pub mod tests { assert_eq!(account1.rent_epoch(), RENT_EXEMPT_RENT_EPOCH); assert_eq!(account2.rent_epoch(), RENT_EXEMPT_RENT_EPOCH); - assert_eq!(account1.set_rent_epoch(12),Err(InstructionError::CannotSetRentEpochForAccountWithAppFees)); - assert_eq!(account2.set_rent_epoch(12),Err(InstructionError::CannotSetRentEpochForAccountWithAppFees)); + assert_eq!( + account1.set_rent_epoch(12), + Err(InstructionError::CannotSetRentEpochForAccountWithAppFees) + ); + assert_eq!( + account2.set_rent_epoch(12), + Err(InstructionError::CannotSetRentEpochForAccountWithAppFees) + ); } } From 8782eb2c3756f2714e3241c36f02d717f83baf5e Mon Sep 17 00:00:00 2001 From: Godmode Galactus Date: Wed, 8 Feb 2023 11:31:50 +0100 Subject: [PATCH 6/6] application fees, changes after review from andrew and tao --- cli-output/src/cli_output.rs | 4 +- program-runtime/src/invoke_context.rs | 18 +--- programs/application-fees/src/processor.rs | 2 +- rpc/src/transaction_status_service.rs | 2 +- runtime/src/accounts.rs | 43 +++------ runtime/src/accounts_db.rs | 8 +- runtime/src/append_vec.rs | 15 +-- runtime/src/bank.rs | 20 +--- runtime/src/bank/tests.rs | 33 +++---- runtime/src/rent_collector.rs | 101 ++++++++++----------- sdk/program/src/instruction.rs | 10 +- sdk/src/account.rs | 9 +- sdk/src/reward_type.rs | 2 - storage-proto/src/convert.rs | 1 - 14 files changed, 106 insertions(+), 162 deletions(-) diff --git a/cli-output/src/cli_output.rs b/cli-output/src/cli_output.rs index fdfcaf750e0..f0f905881f1 100644 --- a/cli-output/src/cli_output.rs +++ b/cli-output/src/cli_output.rs @@ -192,11 +192,11 @@ impl fmt::Display for CliAccount { )?; writeln_name_value( f, - "rent_epoch", + "Rent Epoch", &self.keyed_account.account.rent_epoch.to_string(), )?; if let Some(application_fees) = self.keyed_account.account.application_fees { - writeln_name_value(f, "application_fees", &application_fees.to_string())?; + writeln_name_value(f, "Application Fees", &application_fees.to_string())?; } Ok(()) } diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index b7ed9471f17..9178aa014d0 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -102,29 +102,13 @@ struct SyscallContext { allocator: Rc>, } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Default)] pub struct ApplicationFeeChanges { pub application_fees: HashMap, pub rebated: HashMap, pub updated: Vec<(Pubkey, u64)>, } -impl ApplicationFeeChanges { - pub fn new() -> Self { - Self { - application_fees: HashMap::new(), - rebated: HashMap::new(), - updated: Vec::new(), - } - } -} - -impl Default for ApplicationFeeChanges { - fn default() -> Self { - Self::new() - } -} - pub struct InvokeContext<'a> { pub transaction_context: &'a mut TransactionContext, rent: Rent, diff --git a/programs/application-fees/src/processor.rs b/programs/application-fees/src/processor.rs index f42d76941ae..60431e8a971 100644 --- a/programs/application-fees/src/processor.rs +++ b/programs/application-fees/src/processor.rs @@ -185,7 +185,7 @@ impl Processor { let mut rebated_amount = None; if let Some(lamports_rebated) = lamports_rebated { rebated_amount = Some(*lamports_rebated); - // add these in rabates map + // add these in rebates map invoke_context .application_fee_changes .rebated diff --git a/rpc/src/transaction_status_service.rs b/rpc/src/transaction_status_service.rs index 83efb711c77..cd458fd3a24 100644 --- a/rpc/src/transaction_status_service.rs +++ b/rpc/src/transaction_status_service.rs @@ -388,7 +388,7 @@ pub(crate) mod tests { return_data: None, executed_units: 0, accounts_data_len_delta: 0, - application_fees_changes: ApplicationFeeChanges::new(), + application_fees_changes: ApplicationFeeChanges::default(), }); let balances = TransactionBalancesSet { diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index bdcb37ef6e5..5a11dcca771 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -298,7 +298,6 @@ impl Accounts { // There is no way to predict what program will execute without an error // If a fee can pay for execution then the program will be scheduled - let mut validated_fee_payer = false; let mut tx_rent: TransactionRent = 0; let message = tx.message(); let account_keys = message.account_keys(); @@ -313,10 +312,9 @@ impl Accounts { Self::get_requested_loaded_accounts_data_size_limit(feature_set); let mut accumulated_accounts_data_size: usize = 0; let mut application_fees: HashMap = HashMap::new(); - let mut payer_index = 0; + let mut payer_index = None; - // we reverse the iteration over keys so that we collect all the application fees - // and then validate fees at the last + // we fill the application fees map and then calculate the fees accordingly let mut accounts = account_keys .iter() .enumerate() @@ -340,24 +338,13 @@ impl Accounts { .load_with_fixed_root(ancestors, key) .map(|(mut account, _)| { if message.is_writable(i) { - let rent_due_result = rent_collector - .collect_from_existing_account( - key, - &mut account, - self.accounts_db.filler_account_suffix.as_ref(), - set_exempt_rent_epoch_max, - ); - match rent_due_result { - Ok(rent_due) => { - (account, rent_due.rent_amount) - }, - Err(_) => { - // should never happen - error!("trying to set rent epoch for the account with application fees {}", key); - (account, 0) - } - - } + let rent_due = rent_collector.collect_from_existing_account( + key, + &mut account, + self.accounts_db.filler_account_suffix.as_ref(), + set_exempt_rent_epoch_max, + ); + (account, rent_due.rent_amount) } else { (account, 0) } @@ -387,12 +374,11 @@ impl Accounts { application_fees.insert(*key, account.application_fees()); } - if !validated_fee_payer && message.is_non_loader_key(i) { + if payer_index.is_none() && message.is_non_loader_key(i) { if i != 0 { warn!("Payer index should be 0! {:?}", tx); } - payer_index = i; - validated_fee_payer = true; + payer_index = Some(i); } if bpf_loader_upgradeable::check_id(account.owner()) { @@ -443,9 +429,10 @@ impl Accounts { account_found_and_dep_index.push((account_found, account_dep_index)); Ok((*key, account)) - }).collect::>>()?; + }) + .collect::>>()?; - if validated_fee_payer { + if let Some(payer_index) = payer_index { let key_and_account = &mut accounts[payer_index]; let application_fees_sum = application_fees.iter().map(|x| *x.1).sum::(); @@ -1443,7 +1430,7 @@ mod tests { return_data: None, executed_units: 0, accounts_data_len_delta: 0, - application_fees_changes: ApplicationFeeChanges::new(), + application_fees_changes: ApplicationFeeChanges::default(), }, tx_executor_cache: Rc::new(RefCell::new(TransactionExecutorCache::default())), } diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index 11943edd889..517d91ed868 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -18,8 +18,6 @@ //! tracks the number of commits to the entire data store. So the latest //! commit for each slot entry would be indexed. -use solana_sdk::account::RENT_EXEMPT_RENT_EPOCH; - use { crate::{ account_info::{AccountInfo, Offset, StorageLocation, StoredSize}, @@ -73,7 +71,9 @@ use { solana_measure::{measure, measure::Measure, measure_us}, solana_rayon_threadlimit::get_thread_count, solana_sdk::{ - account::{Account, AccountSharedData, ReadableAccount, WritableAccount}, + account::{ + Account, AccountSharedData, ReadableAccount, WritableAccount, RENT_EXEMPT_RENT_EPOCH, + }, clock::{BankId, Epoch, Slot}, epoch_schedule::EpochSchedule, genesis_config::{ClusterType, GenesisConfig}, @@ -9586,7 +9586,7 @@ pub mod tests { let account_meta = AccountMeta { lamports: 1, owner: Pubkey::from([2; 32]), - account_flags: AccountFlags::NONE, + account_flags: AccountFlags::empty(), rent_epoch_or_application_fees: 0, }; let offset = 3; diff --git a/runtime/src/append_vec.rs b/runtime/src/append_vec.rs index 217949db990..b3af7a218c6 100644 --- a/runtime/src/append_vec.rs +++ b/runtime/src/append_vec.rs @@ -159,7 +159,6 @@ pub struct StoredMeta { bitflags! { #[derive(Serialize, Deserialize, Default)] pub struct AccountFlags: u8 { - const NONE = 0b00000000; const EXECUTABLE = 0b00000001; const HAS_APPLICATION_FEES = 0b00000010; } @@ -167,7 +166,7 @@ bitflags! { impl AccountFlags { pub fn new(executable: bool, has_application_fees: bool) -> Self { - let mut flags = AccountFlags::NONE; + let mut flags = AccountFlags::empty(); if executable { flags |= AccountFlags::EXECUTABLE; } @@ -185,7 +184,8 @@ impl AccountFlags { pub struct AccountMeta { /// lamports in the account pub lamports: u64, - /// the epoch at which this account will next owe rent or application fees depending on the account flags + /// the epoch at which this account will next owe rent + /// or application fees depending has_application_fees bit in the account flags pub rent_epoch_or_application_fees: u64, /// the program that owns this account. If executable, the program that loads this account. pub owner: Pubkey, @@ -201,7 +201,8 @@ impl AccountMeta { } pub fn has_application_fees(&self) -> bool { - self.account_flags & AccountFlags::HAS_APPLICATION_FEES == AccountFlags::HAS_APPLICATION_FEES + self.account_flags & AccountFlags::HAS_APPLICATION_FEES + == AccountFlags::HAS_APPLICATION_FEES } } @@ -268,7 +269,9 @@ impl<'a> StoredAccountMeta<'a> { fn sanitize_executable_and_application_fees(&self) -> bool { // Sanitize executable to ensure higher 7-bits are cleared correctly. - self.ref_account_flags_byte() & !3 == 0 + const SANITIZER: u8 = + !(AccountFlags::EXECUTABLE.bits() | AccountFlags::HAS_APPLICATION_FEES.bits()); + self.ref_account_flags_byte() & SANITIZER == 0 } fn sanitize_lamports(&self) -> bool { @@ -1399,7 +1402,7 @@ pub mod tests { let accounts = av.accounts(0); let account = accounts.first().unwrap(); - assert_eq!(account.account_meta.account_flags, AccountFlags::NONE); + assert_eq!(account.account_meta.account_flags, AccountFlags::empty()); assert_eq!(account.sanitize_executable_and_application_fees(), true); let account = accounts.get(1).unwrap(); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index b943038bee2..2078d793207 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -3195,22 +3195,12 @@ impl Bank { let amount = *iter.value(); match operation { ApplicationFeesOperation::Collected => match self.deposit(pubkey, amount) { - Ok(post_balance) => { - self.rewards.write().unwrap().push(( - *pubkey, - RewardInfo { - reward_type: RewardType::ApplicationFee, - lamports: amount as i64, - post_balance, - commission: None, - }, - )); - } Err(_) => { error!("Burning {} fee instead of crediting {}", pubkey, amount); inc_new_counter_error!("bank-burned_fee_lamports", amount as usize); burn += amount; } + Ok(_) => {} }, ApplicationFeesOperation::Updated => { if let Err(err) = self.update_application_fees(pubkey, amount) { @@ -5525,14 +5515,6 @@ impl Bank { )); time_collecting_rent_us += measure.as_us(); - let rent_collected_info = match rent_collected_info { - Ok(info) => info, - Err(_) => { - error!("Trying to collect rent on account with application fees(should not happen)"); - CollectedInfo::default() - } - }; - // only store accounts where we collected rent // but get the hash for all these accounts even if collected rent is 0 (= not updated). // Also, there's another subtle side-effect from rewrites: this diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 7ec87c7c1f5..4d47b13762b 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -1,4 +1,3 @@ -#![cfg(test)] #[allow(deprecated)] use solana_sdk::sysvar::fees::Fees; use { @@ -172,7 +171,7 @@ fn new_execution_result( return_data: None, executed_units: 0, accounts_data_len_delta: 0, - application_fees_changes: ApplicationFeeChanges::new(), + application_fees_changes: ApplicationFeeChanges::default(), }, tx_executor_cache: Rc::new(RefCell::new(TransactionExecutorCache::default())), } @@ -549,15 +548,12 @@ fn test_credit_debit_rent_no_side_effect_on_hash() { { // make sure rent and epoch change are such that we collect all lamports in accounts 4 & 5 let mut account_copy = accounts[4].clone(); - let expected_rent = bank - .rent_collector() - .collect_from_existing_account( - &keypairs[4].pubkey(), - &mut account_copy, - None, - set_exempt_rent_epoch_max, - ) - .unwrap(); + let expected_rent = bank.rent_collector().collect_from_existing_account( + &keypairs[4].pubkey(), + &mut account_copy, + None, + set_exempt_rent_epoch_max, + ); assert_eq!(expected_rent.rent_amount, too_few_lamports); assert_eq!(account_copy.lamports(), 0); } @@ -12121,15 +12117,12 @@ fn test_accounts_data_size_and_rent_collection() { // Ensure if we collect rent from the account that it will be reclaimed { - let info = bank - .rent_collector - .collect_from_existing_account( - &keypair.pubkey(), - &mut account, - None, - set_exempt_rent_epoch_max, - ) - .unwrap(); + let info = bank.rent_collector.collect_from_existing_account( + &keypair.pubkey(), + &mut account, + None, + set_exempt_rent_epoch_max, + ); assert_eq!(info.account_data_len_reclaimed, data_size as u64); } diff --git a/runtime/src/rent_collector.rs b/runtime/src/rent_collector.rs index 2c4a157e259..c0725d3d9ac 100644 --- a/runtime/src/rent_collector.rs +++ b/runtime/src/rent_collector.rs @@ -5,7 +5,6 @@ use solana_sdk::{ epoch_schedule::EpochSchedule, genesis_config::GenesisConfig, incinerator, - instruction::InstructionError, pubkey::Pubkey, rent::{Rent, RentDue}, }; @@ -113,33 +112,35 @@ impl RentCollector { account: &mut AccountSharedData, filler_account_suffix: Option<&Pubkey>, set_exempt_rent_epoch_max: bool, - ) -> Result { + ) -> CollectedInfo { match self.calculate_rent_result(address, account, filler_account_suffix) { RentResult::Exempt => { if set_exempt_rent_epoch_max { - account.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH)?; + // setting rent exempt rent epoch should work even if application has application fees + account.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH).unwrap(); } - Ok(CollectedInfo::default()) + CollectedInfo::default() } - RentResult::NoRentCollectionNow => Ok(CollectedInfo::default()), + RentResult::NoRentCollectionNow => CollectedInfo::default(), RentResult::CollectRent { new_rent_epoch, rent_due, } => match account.lamports().checked_sub(rent_due) { None | Some(0) => { let account = std::mem::take(account); - Ok(CollectedInfo { + CollectedInfo { rent_amount: account.lamports(), account_data_len_reclaimed: account.data().len() as u64, - }) + } } Some(lamports) => { account.set_lamports(lamports); - account.set_rent_epoch(new_rent_epoch)?; - Ok(CollectedInfo { + // here we already tested that account does not have application fees + account.set_rent_epoch(new_rent_epoch).unwrap(); + CollectedInfo { rent_amount: rent_due, account_data_len_reclaimed: 0u64, - }) + } } }, } @@ -153,7 +154,10 @@ impl RentCollector { account: &impl ReadableAccount, filler_account_suffix: Option<&Pubkey>, ) -> RentResult { - if account.rent_epoch() == RENT_EXEMPT_RENT_EPOCH || account.rent_epoch() > self.epoch { + if account.rent_epoch() == RENT_EXEMPT_RENT_EPOCH + || account.rent_epoch() > self.epoch + || account.has_application_fees() + { // potentially rent paying account (or known and already marked exempt) // Maybe collect rent later, leave account alone for now. return RentResult::NoRentCollectionNow; @@ -235,7 +239,6 @@ mod tests { /*filler_account_suffix:*/ None, set_exempt_rent_epoch_max, ) - .unwrap() } } @@ -258,7 +261,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - Ok(CollectedInfo::default()) + CollectedInfo::default() ); assert_eq!(account_clone, account); } @@ -283,7 +286,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - Ok(CollectedInfo::default()) + CollectedInfo::default() ); assert_eq!(account_clone, account_expected); } @@ -308,7 +311,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - Ok(CollectedInfo::default()) + CollectedInfo::default() ); assert_eq!(account_clone, account_expected); } @@ -340,10 +343,10 @@ mod tests { filler_accounts, set_exempt_rent_epoch_max ), - Ok(CollectedInfo { + CollectedInfo { rent_amount: rent_due_expected, account_data_len_reclaimed: 0 - }) + } ); let mut account_expected = account.clone(); account_expected.set_lamports(account.lamports() - rent_due_expected); @@ -377,7 +380,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - Ok(CollectedInfo::default()) + CollectedInfo::default() ); assert_eq!(account_clone, account_expected); } @@ -399,7 +402,7 @@ mod tests { None, set_exempt_rent_epoch_max ), - Ok(CollectedInfo::default()) + CollectedInfo::default() ); assert_eq!(account_clone, account); } @@ -430,7 +433,7 @@ mod tests { Some(&filler_account), set_exempt_rent_epoch_max ), - Ok(CollectedInfo::default()) + CollectedInfo::default() ); assert_eq!(account_clone, account_expected); } @@ -471,14 +474,12 @@ mod tests { assert_eq!(collected.account_data_len_reclaimed, 0); // collect rent on a already-existing account - let collected = rent_collector - .collect_from_existing_account( - &solana_sdk::pubkey::new_rand(), - &mut existing_account, - None, // filler_account_suffix - set_exempt_rent_epoch_max, - ) - .unwrap(); + let collected = rent_collector.collect_from_existing_account( + &solana_sdk::pubkey::new_rand(), + &mut existing_account, + None, // filler_account_suffix + set_exempt_rent_epoch_max, + ); assert!(existing_account.lamports() < old_lamports); assert_eq!( existing_account.lamports() + collected.rent_amount, @@ -518,7 +519,7 @@ mod tests { set_exempt_rent_epoch_max, ); assert_eq!(account.lamports(), huge_lamports); - assert_eq!(collected, Ok(CollectedInfo::default())); + assert_eq!(collected, CollectedInfo::default()); continue; } @@ -528,14 +529,12 @@ mod tests { account.set_lamports(tiny_lamports); // ... and trigger another rent collection on the same epoch and check that rent is working - let collected = rent_collector - .collect_from_existing_account( - &pubkey, - &mut account, - None, // filler_account_suffix - set_exempt_rent_epoch_max, - ) - .unwrap(); + let collected = rent_collector.collect_from_existing_account( + &pubkey, + &mut account, + None, // filler_account_suffix + set_exempt_rent_epoch_max, + ); assert_eq!(account.lamports(), tiny_lamports - collected.rent_amount); assert_ne!(collected, CollectedInfo::default()); } @@ -557,14 +556,12 @@ mod tests { let epoch = 3; let rent_collector = default_rent_collector_clone_with_epoch(epoch); - let collected = rent_collector - .collect_from_existing_account( - &pubkey, - &mut account, - None, // filler_account_suffix - set_exempt_rent_epoch_max, - ) - .unwrap(); + let collected = rent_collector.collect_from_existing_account( + &pubkey, + &mut account, + None, // filler_account_suffix + set_exempt_rent_epoch_max, + ); assert_eq!(account.lamports(), 0); assert_eq!(collected.rent_amount, 1); } @@ -586,14 +583,12 @@ mod tests { }); let rent_collector = default_rent_collector_clone_with_epoch(account_rent_epoch + 1); - let collected = rent_collector - .collect_from_existing_account( - &Pubkey::new_unique(), - &mut account, - None, // filler_account_suffix - set_exempt_rent_epoch_max, - ) - .unwrap(); + let collected = rent_collector.collect_from_existing_account( + &Pubkey::new_unique(), + &mut account, + None, // filler_account_suffix + set_exempt_rent_epoch_max, + ); assert_eq!(collected.rent_amount, account_lamports); assert_eq!( diff --git a/sdk/program/src/instruction.rs b/sdk/program/src/instruction.rs index be7be14e0be..d4e522b83f4 100644 --- a/sdk/program/src/instruction.rs +++ b/sdk/program/src/instruction.rs @@ -261,17 +261,19 @@ pub enum InstructionError { #[error("Max instruction trace length exceeded")] MaxInstructionTraceLengthExceeded, - // Setting rent epoch for account which has an application fees + /// Setting rent epoch for account which has an application fees #[error("Cannot set rent epoch for account which has application fees")] CannotSetRentEpochForAccountWithAppFees, - // Setting application fees for an account which is not rent free + /// Setting application fees for an account which is not rent free #[error("Cannot set application fees for account which has rent epoch")] CannotSetAppFeesForAccountWithRentEpoch, - // Note: For any new error added here an equivalent ProgramError and its - // conversions must also be added + + /// Cannot change the application fees for account while executing instruction #[error("Cannot change application fees")] CannotChangeApplicationFees, + // Note: For any new error added here an equivalent ProgramError and its + // conversions must also be added } /// A directive for a single invocation of a Solana program. diff --git a/sdk/src/account.rs b/sdk/src/account.rs index fc0fb3eeecd..aa1340354b1 100644 --- a/sdk/src/account.rs +++ b/sdk/src/account.rs @@ -42,10 +42,10 @@ pub struct Account { pub owner: Pubkey, /// this account's data contains a loaded program (and is now read-only) pub executable: bool, - // has application fees + /// has application fees pub has_application_fees: bool, - /// the epoch at which this account will next owe rent or application fees for the account - /// switched by the boolean above + /// the epoch at which this account will next owe rent + /// or application fees for the account if has_application_fees is true pub rent_epoch_or_application_fees: u64, } @@ -128,9 +128,10 @@ pub struct AccountSharedData { owner: Pubkey, /// this account's data contains a loaded program (and is now read-only) executable: bool, - // has application fees + /// has application fees has_application_fees: bool, /// the epoch at which this account will next owe rent + /// or application fees for the account if has_application_fees is true rent_epoch_or_application_fees: u64, } diff --git a/sdk/src/reward_type.rs b/sdk/src/reward_type.rs index 0d8102658f2..84bddfcfb97 100644 --- a/sdk/src/reward_type.rs +++ b/sdk/src/reward_type.rs @@ -8,7 +8,6 @@ pub enum RewardType { Rent, Staking, Voting, - ApplicationFee, } impl fmt::Display for RewardType { @@ -21,7 +20,6 @@ impl fmt::Display for RewardType { RewardType::Rent => "rent", RewardType::Staking => "staking", RewardType::Voting => "voting", - RewardType::ApplicationFee => "application_fee", } ) } diff --git a/storage-proto/src/convert.rs b/storage-proto/src/convert.rs index acb2d9cfe2c..f5c63e4ad8b 100644 --- a/storage-proto/src/convert.rs +++ b/storage-proto/src/convert.rs @@ -94,7 +94,6 @@ impl From for generated::Reward { Some(RewardType::Rent) => generated::RewardType::Rent, Some(RewardType::Staking) => generated::RewardType::Staking, Some(RewardType::Voting) => generated::RewardType::Voting, - Some(RewardType::ApplicationFee) => generated::RewardType::Fee, } as i32, commission: reward.commission.map(|c| c.to_string()).unwrap_or_default(), }