From c2a31ef4a26f4e838a972165dd62a3bdd159522c Mon Sep 17 00:00:00 2001 From: AurelienFT <32803821+AurelienFT@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:29:43 +0100 Subject: [PATCH] Use expiration policy (#2447) ## Linked Issues/PRs Spec PR : https://github.com/FuelLabs/fuel-specs/pull/616 VM PR : https://github.com/FuelLabs/fuel-vm/pull/871 ## Description This PR use the new policy `expiration` in transaction pool to prune transactions when they are expired to prevent them to be included in a block. Also verification is added when executing transaction in the executor. ## Checklist - [x] Breaking changes are clearly marked as such in the PR description and changelog - [x] New behavior is reflected in tests - [x] [The specification](https://github.com/FuelLabs/fuel-specs/) matches the implemented behavior (link update PR if changes are needed) ### Before requesting review - [x] I have reviewed the code myself - [x] I have created follow-up issues caused by this PR and linked them here ### After merging, notify other teams [Add or remove entries as needed] - [ ] [Rust SDK](https://github.com/FuelLabs/fuels-rs/) - [ ] [Sway compiler](https://github.com/FuelLabs/sway/) - [ ] [Platform documentation](https://github.com/FuelLabs/devrel-requests/issues/new?assignees=&labels=new+request&projects=&template=NEW-REQUEST.yml&title=%5BRequest%5D%3A+) (for out-of-organization contributors, the person merging the PR will do this) - [ ] Someone else? --------- Co-authored-by: acerone85 Co-authored-by: Andrea Cerone <22031682+acerone85@users.noreply.github.com> --- CHANGELOG.md | 1 + Cargo.lock | 313 +++++++++--------- crates/services/executor/src/executor.rs | 9 + crates/services/executor/src/ports.rs | 51 ++- crates/services/p2p/src/service.rs | 2 +- crates/services/txpool_v2/src/service.rs | 33 ++ .../services/txpool_v2/src/service/pruner.rs | 11 +- crates/services/txpool_v2/src/tests/mocks.rs | 10 + .../txpool_v2/src/tests/tests_service.rs | 209 +++++++++++- .../services/txpool_v2/src/tests/universe.rs | 3 + crates/types/src/services/executor.rs | 4 + crates/types/src/services/txpool.rs | 12 + 12 files changed, 501 insertions(+), 157 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf05f3f92a4..ec2cb49a3a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [2361](https://github.com/FuelLabs/fuel-core/pull/2361): Add caches to the sync service to not reask for data it already fetched from the network. - [2327](https://github.com/FuelLabs/fuel-core/pull/2327): Add more services tests and more checks of the pool. Also add an high level documentation for users of the pool and contributors. - [2416](https://github.com/FuelLabs/fuel-core/issues/2416): Define the `GasPriceServiceV1` task. +- [2447](https://github.com/FuelLabs/fuel-core/pull/2447): Use new `expiration` policy in the transaction pool. Add a mechanism to prune the transactions when they expired. - [1922](https://github.com/FuelLabs/fuel-core/pull/1922): Added support for posting blocks to the shared sequencer. - [2033](https://github.com/FuelLabs/fuel-core/pull/2033): Remove `Option` in favor of `BlockHeightQuery` where applicable. - [2439](https://github.com/FuelLabs/fuel-core/pull/2439): Add gas costs for the two new zk opcodes `ecop` and `eadd` and the benches that allow to calibrate them. diff --git a/Cargo.lock b/Cargo.lock index 06916aec7a7..a797d35f850 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -230,7 +230,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "synstructure", ] @@ -242,7 +242,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -381,7 +381,7 @@ dependencies = [ "proc-macro2", "quote", "strum 0.26.3", - "syn 2.0.94", + "syn 2.0.95", "thiserror 1.0.69", ] @@ -423,7 +423,7 @@ dependencies = [ "log", "parking", "polling 2.8.0", - "rustix 0.37.27", + "rustix 0.37.28", "slab", "socket2 0.4.10", "waker-fn", @@ -442,7 +442,7 @@ dependencies = [ "futures-lite 2.5.0", "parking", "polling 3.7.4", - "rustix 0.38.42", + "rustix 0.38.43", "slab", "tracing", "windows-sys 0.59.0", @@ -463,7 +463,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.0", "event-listener-strategy", "pin-project-lite", ] @@ -492,9 +492,9 @@ dependencies = [ "async-task", "blocking", "cfg-if", - "event-listener 5.3.1", + "event-listener 5.4.0", "futures-lite 2.5.0", - "rustix 0.38.42", + "rustix 0.38.43", "tracing", ] @@ -510,7 +510,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 0.38.42", + "rustix 0.38.43", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -561,7 +561,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -572,13 +572,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.84" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1244b10dcd56c92219da4e14caa97e312079e185f04ba3eea25061561dc0a0" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -663,7 +663,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -1225,7 +1225,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -1578,9 +1578,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.23" +version = "4.5.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "b95dca1b68188a08ca6af9d96a6576150f598824bdb528c1190460c2940a0b48" dependencies = [ "clap_builder", "clap_derive", @@ -1588,9 +1588,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "9ab52925392148efd3f7562f2136a81ffb778076bcc85727c6e020d6dd57cf15" dependencies = [ "anstream", "anstyle", @@ -1600,14 +1600,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2202,7 +2202,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2246,7 +2246,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.94", + "syn 2.0.95", "thiserror 1.0.69", ] @@ -2270,7 +2270,7 @@ dependencies = [ "cynic-codegen", "darling", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2294,7 +2294,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2305,7 +2305,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2398,7 +2398,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2418,7 +2418,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "unicode-xid", ] @@ -2535,7 +2535,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2638,7 +2638,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2729,7 +2729,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2749,7 +2749,7 @@ checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2769,7 +2769,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2924,7 +2924,7 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "syn 2.0.94", + "syn 2.0.95", "toml 0.8.19", "walkdir", ] @@ -2942,7 +2942,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -2968,7 +2968,7 @@ dependencies = [ "serde", "serde_json", "strum 0.26.3", - "syn 2.0.94", + "syn 2.0.95", "tempfile", "thiserror 1.0.69", "tiny-keccak", @@ -3121,9 +3121,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.3.1" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ "concurrent-queue", "parking", @@ -3136,7 +3136,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.0", "pin-project-lite", ] @@ -4094,7 +4094,7 @@ checksum = "3f49fdbfc1615d88d2849650afc2b0ac2fecd69661ebadd31a073d8416747764" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "synstructure", ] @@ -4106,7 +4106,7 @@ checksum = "8703ee10001e6a52ad9a0d8411ca5a92098de978ccfbdddd0ba185f3a7405b4c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "synstructure", ] @@ -4421,7 +4421,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -5223,7 +5223,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -5348,7 +5348,7 @@ dependencies = [ "autocfg", "impl-tools-lib", "proc-macro-error2", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -5360,7 +5360,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -5371,7 +5371,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -5426,13 +5426,13 @@ dependencies = [ [[package]] name = "insta" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9ffc4d4892617c50a928c52b2961cb5174b6fc6ebf252b2fac9d21955c48b8" +checksum = "6513e4067e16e69ed1db5ab56048ed65db32d10ba5fc1217f5393f8f17d8b5a5" dependencies = [ "console", - "lazy_static", "linked-hash-map", + "once_cell", "similar", ] @@ -5530,6 +5530,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.14" @@ -6088,7 +6097,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -6297,9 +6306,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" dependencies = [ "cc", "pkg-config", @@ -6320,9 +6329,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" @@ -6376,7 +6385,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.8.5", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -6474,7 +6483,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.42", + "rustix 0.38.43", ] [[package]] @@ -6881,7 +6890,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -7003,7 +7012,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -7214,7 +7223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 2.0.9", + "thiserror 2.0.10", "ucd-trie", ] @@ -7238,7 +7247,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -7274,35 +7283,35 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", - "phf_shared 0.11.2", + "phf_shared 0.11.3", ] [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared 0.11.2", + "phf_shared 0.11.3", "rand", ] [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", - "phf_shared 0.11.2", + "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -7311,43 +7320,43 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ - "siphasher", + "siphasher 0.3.11", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher", + "siphasher 1.0.1", ] [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -7436,7 +7445,7 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.42", + "rustix 0.38.43", "tracing", "windows-sys 0.59.0", ] @@ -7506,7 +7515,7 @@ dependencies = [ "smallvec", "symbolic-demangle", "tempfile", - "thiserror 2.0.9", + "thiserror 2.0.10", ] [[package]] @@ -7577,12 +7586,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "483f8c21f64f3ea09fe0f30f5d48c3e8eefe5dac9129f0075f76593b4c1da705" dependencies = [ "proc-macro2", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -7655,7 +7664,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "version_check", "yansi 1.0.1", ] @@ -7680,7 +7689,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -7756,7 +7765,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -7766,10 +7775,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -7918,7 +7927,7 @@ dependencies = [ "rustc-hash 2.1.0", "rustls 0.23.20", "socket2 0.5.8", - "thiserror 2.0.9", + "thiserror 2.0.10", "tokio", "tracing", ] @@ -7937,7 +7946,7 @@ dependencies = [ "rustls 0.23.20", "rustls-pki-types", "slab", - "thiserror 2.0.9", + "thiserror 2.0.10", "tinyvec", "tracing", "web-time", @@ -8104,7 +8113,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -8452,9 +8461,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.27" +version = "0.37.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" dependencies = [ "bitflags 1.3.2", "errno", @@ -8466,14 +8475,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.14", + "linux-raw-sys 0.4.15", "windows-sys 0.59.0", ] @@ -8637,7 +8646,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -8760,9 +8769,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -8821,14 +8830,14 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -8844,7 +8853,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -8895,7 +8904,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -9035,6 +9044,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.9" @@ -9225,7 +9240,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -9236,7 +9251,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -9289,7 +9304,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -9302,7 +9317,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -9361,9 +9376,9 @@ dependencies = [ [[package]] name = "symbolic-common" -version = "12.12.4" +version = "12.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd33e73f154e36ec223c18013f7064a2c120f1162fc086ac9933542def186b00" +checksum = "bf08b42a6f9469bd8584daee39a1352c8133ccabc5151ccccb15896ef047d99a" dependencies = [ "debugid", "memmap2", @@ -9373,9 +9388,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.12.4" +version = "12.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e51191290147f071777e37fe111800bb82a9059f9c95b19d2dd41bfeddf477" +checksum = "32f73b5a5bd4da72720c45756a2d11edf110116b87f998bda59b97be8c2c7cf1" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -9395,9 +9410,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.94" +version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" +checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", @@ -9427,7 +9442,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -9503,7 +9518,7 @@ dependencies = [ "fastrand 2.3.0", "getrandom", "once_cell", - "rustix 0.38.42", + "rustix 0.38.43", "windows-sys 0.59.0", ] @@ -9700,7 +9715,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -9711,7 +9726,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "test-case-core", ] @@ -9748,7 +9763,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -9762,11 +9777,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.9" +version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +checksum = "a3ac7f54ca534db81081ef1c1e7f6ea8a3ef428d2fc069097c079443d24124d3" dependencies = [ - "thiserror-impl 2.0.9", + "thiserror-impl 2.0.10", ] [[package]] @@ -9777,18 +9792,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] name = "thiserror-impl" -version = "2.0.9" +version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +checksum = "9e9465d30713b56a37ede7185763c3492a91be2f5fa68d958c44e41ab9248beb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -9918,9 +9933,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -9946,13 +9961,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -10243,7 +10258,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -10595,7 +10610,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "wasm-bindgen-shared", ] @@ -10630,7 +10645,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -10699,7 +10714,7 @@ dependencies = [ "postcard", "psm", "rayon", - "rustix 0.38.42", + "rustix 0.38.43", "serde", "serde_derive", "smallvec", @@ -10737,7 +10752,7 @@ dependencies = [ "directories-next", "log", "postcard", - "rustix 0.38.42", + "rustix 0.38.43", "serde", "serde_derive", "sha2 0.10.8", @@ -10755,7 +10770,7 @@ dependencies = [ "anyhow", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "wasmtime-component-util", "wasmtime-wit-bindgen", "wit-parser", @@ -10854,7 +10869,7 @@ checksum = "a2bde986038b819bc43a21fef0610aeb47aabfe3ea09ca3533a7b81023b84ec6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -11265,9 +11280,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" +checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" [[package]] name = "xmlparser" @@ -11364,7 +11379,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "synstructure", ] @@ -11386,7 +11401,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -11406,7 +11421,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", "synstructure", ] @@ -11427,7 +11442,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] @@ -11449,7 +11464,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.95", ] [[package]] diff --git a/crates/services/executor/src/executor.rs b/crates/services/executor/src/executor.rs index 1277b143d9c..383dcea5e68 100644 --- a/crates/services/executor/src/executor.rs +++ b/crates/services/executor/src/executor.rs @@ -1156,11 +1156,20 @@ where ) -> ExecutorResult { let block_height = *header.height(); let actual_version = header.consensus_parameters_version; + let expiration = tx.expiration(); let checked_tx = match tx { MaybeCheckedTransaction::Transaction(tx) => tx .into_checked_basic(block_height, &self.consensus_params)? .into(), MaybeCheckedTransaction::CheckedTransaction(checked_tx, checked_version) => { + // If you plan to add an other check of validity like this one on the checked_tx + // then probably the `CheckedTransaction` type isn't useful anymore. + if block_height > expiration { + return Err(ExecutorError::TransactionExpired( + expiration, + block_height, + )); + } if actual_version == checked_version { checked_tx } else { diff --git a/crates/services/executor/src/ports.rs b/crates/services/executor/src/ports.rs index 36f89bcbfdb..2304a5ef904 100644 --- a/crates/services/executor/src/ports.rs +++ b/crates/services/executor/src/ports.rs @@ -5,13 +5,17 @@ use fuel_core_types::{ }, fuel_tx::{ self, + field::Expiration, Chargeable, ConsensusParameters, Transaction, TxId, UniqueIdentifier, }, - fuel_types::ChainId, + fuel_types::{ + BlockHeight, + ChainId, + }, fuel_vm::checked_transaction::CheckedTransaction, services::{ executor::{ @@ -65,6 +69,51 @@ impl MaybeCheckedTransaction { MaybeCheckedTransaction::Transaction(tx) => tx.id(chain_id), } } + + pub fn expiration(&self) -> BlockHeight { + match self { + MaybeCheckedTransaction::CheckedTransaction( + CheckedTransaction::Script(tx), + _, + ) => tx.transaction().expiration(), + MaybeCheckedTransaction::CheckedTransaction( + CheckedTransaction::Create(tx), + _, + ) => tx.transaction().expiration(), + MaybeCheckedTransaction::CheckedTransaction( + CheckedTransaction::Mint(_), + _, + ) => u32::MAX.into(), + MaybeCheckedTransaction::CheckedTransaction( + CheckedTransaction::Upgrade(tx), + _, + ) => tx.transaction().expiration(), + MaybeCheckedTransaction::CheckedTransaction( + CheckedTransaction::Upload(tx), + _, + ) => tx.transaction().expiration(), + MaybeCheckedTransaction::CheckedTransaction( + CheckedTransaction::Blob(tx), + _, + ) => tx.transaction().expiration(), + MaybeCheckedTransaction::Transaction(Transaction::Script(tx)) => { + tx.expiration() + } + MaybeCheckedTransaction::Transaction(Transaction::Create(tx)) => { + tx.expiration() + } + MaybeCheckedTransaction::Transaction(Transaction::Mint(_)) => u32::MAX.into(), + MaybeCheckedTransaction::Transaction(Transaction::Upgrade(tx)) => { + tx.expiration() + } + MaybeCheckedTransaction::Transaction(Transaction::Upload(tx)) => { + tx.expiration() + } + MaybeCheckedTransaction::Transaction(Transaction::Blob(tx)) => { + tx.expiration() + } + } + } } pub trait TransactionExt { diff --git a/crates/services/p2p/src/service.rs b/crates/services/p2p/src/service.rs index 5a12de61abf..87047994c83 100644 --- a/crates/services/p2p/src/service.rs +++ b/crates/services/p2p/src/service.rs @@ -1039,7 +1039,7 @@ where #[derive(Clone)] pub struct SharedState { - /// Sender of p2p with peer gossip subscription (vec represent the peer_id) + /// Sender of p2p with peer gossip subscription (`Vec` represent the peer_id) new_tx_subscription_broadcast: broadcast::Sender, /// Sender of p2p transaction used for subscribing. tx_broadcast: broadcast::Sender, diff --git a/crates/services/txpool_v2/src/service.rs b/crates/services/txpool_v2/src/service.rs index 91c96964802..5306490d968 100644 --- a/crates/services/txpool_v2/src/service.rs +++ b/crates/services/txpool_v2/src/service.rs @@ -80,6 +80,7 @@ use futures::StreamExt; use parking_lot::RwLock; use std::{ collections::{ + BTreeMap, HashSet, VecDeque, }, @@ -323,6 +324,29 @@ where let mut block_height = self.current_height.write(); *block_height = new_height; } + + // Remove expired transactions + let mut removed_txs = vec![]; + { + let mut height_expiration_txs = self.pruner.height_expiration_txs.write(); + let range_to_remove = height_expiration_txs + .range(..=new_height) + .map(|(k, _)| *k) + .collect::>(); + for height in range_to_remove { + let expired_txs = height_expiration_txs.remove(&height); + if let Some(expired_txs) = expired_txs { + let mut tx_pool = self.pool.write(); + removed_txs + .extend(tx_pool.remove_transaction_and_dependents(expired_txs)); + } + } + } + for tx in removed_txs { + self.shared_state + .tx_status_sender + .send_squeezed_out(tx.id(), Error::Removed(RemovedReason::Ttl)); + } } fn borrow_txpool(&self, request: BorrowTxPoolRequest) { @@ -392,6 +416,7 @@ where let shared_state = self.shared_state.clone(); let current_height = self.current_height.clone(); let time_txs_submitted = self.pruner.time_txs_submitted.clone(); + let height_expiration_txs = self.pruner.height_expiration_txs.clone(); let tx_id = transaction.id(&self.chain_id); let utxo_validation = self.utxo_validation; @@ -431,6 +456,7 @@ where }; let tx = Arc::new(checked_tx); + let expiration = tx.expiration(); let result = { let mut pool = pool.write(); @@ -449,6 +475,12 @@ where .write() .push_front((submitted_time, tx_id)); + if expiration < u32::MAX.into() { + let mut lock = height_expiration_txs.write(); + let block_height_expiration = lock.entry(expiration).or_default(); + block_height_expiration.push(tx_id); + } + let duration = submitted_time .duration_since(SystemTime::UNIX_EPOCH) .expect("Time can't be less than UNIX EPOCH"); @@ -764,6 +796,7 @@ where let pruner = TransactionPruner { txs_ttl: config.max_txs_ttl, time_txs_submitted: Arc::new(RwLock::new(VecDeque::new())), + height_expiration_txs: Arc::new(RwLock::new(BTreeMap::new())), ttl_timer, }; diff --git a/crates/services/txpool_v2/src/service/pruner.rs b/crates/services/txpool_v2/src/service/pruner.rs index f36aa1b6531..7551afa31f3 100644 --- a/crates/services/txpool_v2/src/service/pruner.rs +++ b/crates/services/txpool_v2/src/service/pruner.rs @@ -1,12 +1,19 @@ use crate::service::Shared; -use fuel_core_types::fuel_tx::TxId; +use fuel_core_types::{ + fuel_tx::TxId, + fuel_types::BlockHeight, +}; use std::{ - collections::VecDeque, + collections::{ + BTreeMap, + VecDeque, + }, time::SystemTime, }; pub(super) struct TransactionPruner { pub time_txs_submitted: Shared>, + pub height_expiration_txs: Shared>>, pub ttl_timer: tokio::time::Interval, pub txs_ttl: tokio::time::Duration, } diff --git a/crates/services/txpool_v2/src/tests/mocks.rs b/crates/services/txpool_v2/src/tests/mocks.rs index eed1bf5f84f..765bced3d7c 100644 --- a/crates/services/txpool_v2/src/tests/mocks.rs +++ b/crates/services/txpool_v2/src/tests/mocks.rs @@ -67,6 +67,8 @@ use std::{ Mutex, }, }; +use tokio::sync::mpsc::Receiver; +use tokio_stream::wrappers::ReceiverStream; #[derive(Default)] pub struct Data { @@ -340,4 +342,12 @@ impl MockImporter { }); importer } + + pub fn with_block_provider(block_provider: Receiver) -> Self { + let mut importer = MockImporter::default(); + importer + .expect_block_events() + .return_once(move || Box::pin(ReceiverStream::new(block_provider))); + importer + } } diff --git a/crates/services/txpool_v2/src/tests/tests_service.rs b/crates/services/txpool_v2/src/tests/tests_service.rs index b492872e78a..0b806d5b7df 100644 --- a/crates/services/txpool_v2/src/tests/tests_service.rs +++ b/crates/services/txpool_v2/src/tests/tests_service.rs @@ -1,15 +1,34 @@ use fuel_core_services::Service as ServiceTrait; use fuel_core_types::{ - fuel_tx::UniqueIdentifier, + blockchain::{ + block::Block, + consensus::Sealed, + }, + fuel_tx::{ + UniqueIdentifier, + UtxoId, + }, fuel_types::ChainId, - services::txpool::TransactionStatus, + services::{ + block_importer::ImportResult, + txpool::TransactionStatus, + }, +}; +use std::{ + sync::Arc, + time::Duration, }; -use std::time::Duration; use tokio_stream::StreamExt; use crate::{ config::Config, - tests::universe::TestPoolUniverse, + tests::{ + mocks::MockImporter, + universe::{ + TestPoolUniverse, + DEFAULT_EXPIRATION_HEIGHT, + }, + }, tx_status_stream::TxStatusMessage, }; @@ -236,6 +255,188 @@ async fn test_prune_transactions_the_oldest() { service.stop_and_await().await.unwrap(); } +#[tokio::test] +async fn prune_expired_transactions() { + let mut universe = TestPoolUniverse::default(); + let (sender, receiver) = tokio::sync::mpsc::channel(10); + + let tx1 = universe.build_script_transaction(None, None, 10); + let tx2 = universe.build_script_transaction(None, None, 20); + let tx3 = universe.build_script_transaction(None, None, 30); + + let service = + universe.build_service(None, Some(MockImporter::with_block_provider(receiver))); + service.start_and_await().await.unwrap(); + + // Given + let expiration_block = Sealed { + entity: { + let mut block = Block::default(); + let header = block.header_mut(); + header.set_block_height(DEFAULT_EXPIRATION_HEIGHT); + block + }, + consensus: Default::default(), + }; + let ids = vec![ + tx1.id(&Default::default()), + tx2.id(&Default::default()), + tx3.id(&Default::default()), + ]; + service + .shared + .try_insert(vec![tx1.clone(), tx2.clone(), tx3.clone()]) + .unwrap(); + + universe + .waiting_txs_insertion(service.shared.new_tx_notification_subscribe(), ids) + .await; + + assert_eq!( + service + .shared + .find(vec![ + tx1.id(&Default::default()), + tx2.id(&Default::default()), + tx3.id(&Default::default()), + ]) + .await + .unwrap() + .iter() + .filter(|x| x.is_some()) + .count(), + 3 + ); + + // When + sender + .send(Arc::new(ImportResult::new_from_local( + expiration_block, + vec![], + vec![], + ))) + .await + .unwrap(); + + // Then + assert_eq!( + service + .shared + .find(vec![ + tx1.id(&Default::default()), + tx2.id(&Default::default()), + tx3.id(&Default::default()), + ]) + .await + .unwrap() + .iter() + .filter(|x| x.is_some()) + .count(), + 0 + ); + + service.stop_and_await().await.unwrap(); +} + +#[tokio::test] +async fn prune_expired_doesnt_trigger_twice() { + let mut universe = TestPoolUniverse::default(); + let (sender, receiver) = tokio::sync::mpsc::channel(10); + + let (output_1, input_1) = universe.create_output_and_input(); + let (output_2, input_2) = universe.create_output_and_input(); + let tx1 = universe.build_script_transaction(None, Some(vec![output_1]), 10); + let tx2 = universe.build_script_transaction(None, Some(vec![output_2]), 20); + + let service = + universe.build_service(None, Some(MockImporter::with_block_provider(receiver))); + service.start_and_await().await.unwrap(); + + let ids = vec![tx1.id(&Default::default()), tx2.id(&Default::default())]; + service + .shared + .try_insert(vec![tx1.clone(), tx2.clone()]) + .unwrap(); + + universe + .waiting_txs_insertion(service.shared.new_tx_notification_subscribe(), ids) + .await; + + let tx3 = universe.build_script_transaction( + Some(vec![ + input_1.into_input(UtxoId::new(tx1.id(&ChainId::default()), 0)), + input_2.into_input(UtxoId::new(tx2.id(&ChainId::default()), 0)), + ]), + None, + 30, + ); + + let ids = vec![tx3.id(&Default::default())]; + service.shared.try_insert(vec![tx3.clone()]).unwrap(); + + universe + .waiting_txs_insertion(service.shared.new_tx_notification_subscribe(), ids) + .await; + + // Given + let expiration_block = Sealed { + entity: { + let mut block = Block::default(); + let header = block.header_mut(); + header.set_block_height(DEFAULT_EXPIRATION_HEIGHT); + block + }, + consensus: Default::default(), + }; + + assert_eq!( + service + .shared + .find(vec![ + tx1.id(&Default::default()), + tx2.id(&Default::default()), + tx3.id(&Default::default()), + ]) + .await + .unwrap() + .iter() + .filter(|x| x.is_some()) + .count(), + 3 + ); + + // When + let mut update_1 = service + .shared + .tx_update_subscribe(tx1.id(&ChainId::default())) + .unwrap(); + let mut update_2 = service + .shared + .tx_update_subscribe(tx2.id(&ChainId::default())) + .unwrap(); + let mut update_3 = service + .shared + .tx_update_subscribe(tx3.id(&ChainId::default())) + .unwrap(); + sender + .send(Arc::new(ImportResult::new_from_local( + expiration_block, + vec![], + vec![], + ))) + .await + .unwrap(); + update_1.next().await.expect("tx1 should be pruned"); + update_2.next().await.expect("tx2 should be pruned"); + update_3.next().await.expect("tx3 should be pruned"); + + // Then + // Verify that their no new messages on `update_3` + assert!(update_3.next().await.is_none()); + + service.stop_and_await().await.unwrap(); +} + #[tokio::test] async fn simple_insert_removal_subscription() { const TIMEOUT: u64 = 2; diff --git a/crates/services/txpool_v2/src/tests/universe.rs b/crates/services/txpool_v2/src/tests/universe.rs index 2813421d8da..d2f1a747e33 100644 --- a/crates/services/txpool_v2/src/tests/universe.rs +++ b/crates/services/txpool_v2/src/tests/universe.rs @@ -43,6 +43,7 @@ use fuel_core_types::{ }, fuel_types::{ AssetId, + BlockHeight, ChainId, Word, }, @@ -93,6 +94,7 @@ use super::mocks::{ // the byte and gas price fees. pub const TEST_COIN_AMOUNT: u64 = 100_000_000u64; pub const GAS_LIMIT: Word = 100000; +pub const DEFAULT_EXPIRATION_HEIGHT: BlockHeight = BlockHeight::new(1000); pub struct TestPoolUniverse { mock_db: MockDb, @@ -197,6 +199,7 @@ impl TestPoolUniverse { } tx_builder.tip(tip); tx_builder.max_fee_limit(10000); + tx_builder.expiration(DEFAULT_EXPIRATION_HEIGHT); tx_builder.finalize().into() } diff --git a/crates/types/src/services/executor.rs b/crates/types/src/services/executor.rs index 357e3697638..810bcdb44c3 100644 --- a/crates/types/src/services/executor.rs +++ b/crates/types/src/services/executor.rs @@ -336,6 +336,10 @@ pub enum Error { RelayerGivesIncorrectMessages, #[display(fmt = "Consensus parameters not found for version {_0}")] ConsensusParametersNotFound(ConsensusParametersVersion), + #[display( + fmt = "The expiration block height {_0} of the transaction is more than the current block height {_1}" + )] + TransactionExpired(BlockHeight, BlockHeight), /// It is possible to occur untyped errors in the case of the upgrade. #[display(fmt = "Occurred untyped error: {_0}")] Other(String), diff --git a/crates/types/src/services/txpool.rs b/crates/types/src/services/txpool.rs index c684a78b092..7b5006d2073 100644 --- a/crates/types/src/services/txpool.rs +++ b/crates/types/src/services/txpool.rs @@ -35,6 +35,7 @@ use crate::{ use fuel_vm_private::{ checked_transaction::CheckedTransaction, fuel_types::BlockHeight, + prelude::field::Expiration, }; use std::sync::Arc; use tai64::Tai64; @@ -142,6 +143,17 @@ impl PoolTransaction { } } + /// Returns the expiration block for a transaction. + pub fn expiration(&self) -> BlockHeight { + match self { + PoolTransaction::Script(tx, _) => tx.transaction().expiration(), + PoolTransaction::Create(tx, _) => tx.transaction().expiration(), + PoolTransaction::Upgrade(tx, _) => tx.transaction().expiration(), + PoolTransaction::Upload(tx, _) => tx.transaction().expiration(), + PoolTransaction::Blob(tx, _) => tx.transaction().expiration(), + } + } + #[cfg(feature = "test-helpers")] fn id_inner(&self) -> TxId { match self {