From 773226cb326c2607d274717348ff50aab30b0828 Mon Sep 17 00:00:00 2001 From: Brandon Kite Date: Sat, 5 Oct 2024 15:54:29 -0700 Subject: [PATCH] Support blobs in predicates (#2299) ## Linked Issues/PRs https://github.com/FuelLabs/fuel-vm/pull/848 https://github.com/FuelLabs/fuel-vm/pull/849 ## Description ## Checklist - [x] Breaking changes are clearly marked as such in the PR description and changelog - [x] New behavior is reflected in tests - [ ] [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 --------- Co-authored-by: AurelienFT Co-authored-by: green Co-authored-by: Ahmed Sagdati <37515857+segfault-magnet@users.noreply.github.com> --- CHANGELOG.md | 4 + Cargo.lock | 86 ++++---- Cargo.toml | 4 +- benches/benches/block_target_gas.rs | 2 + benches/benches/transaction_throughput.rs | 33 ++- benches/src/default_gas_costs.rs | 4 +- benches/src/lib.rs | 3 +- .../chainspec/local-testnet/chain_config.json | 4 +- crates/client/src/client.rs | 6 + crates/client/src/client/schema/blob.rs | 17 ++ crates/fuel-core/src/executor.rs | 19 +- crates/fuel-core/src/graphql_api.rs | 4 +- crates/fuel-core/src/graphql_api/database.rs | 27 +++ crates/fuel-core/src/graphql_api/ports.rs | 3 +- crates/fuel-core/src/schema/blob.rs | 1 + crates/fuel-core/src/schema/tx.rs | 7 +- crates/fuel-core/src/schema/tx/types.rs | 2 +- .../fuel-core/src/state/generic_database.rs | 17 +- crates/services/executor/src/executor.rs | 41 +++- .../txpool/src/containers/dependency.rs | 2 +- crates/services/txpool/src/mock_db.rs | 76 +++++++ crates/services/txpool/src/ports.rs | 7 +- crates/services/txpool/src/service.rs | 23 +- crates/services/txpool/src/test_helpers.rs | 7 +- crates/services/txpool/src/txpool.rs | 26 ++- crates/services/txpool/src/txpool/tests.rs | 18 +- .../txpool_v2/src/heavy_async_processing.rs | 3 +- crates/services/txpool_v2/src/ports.rs | 9 +- crates/services/txpool_v2/src/service.rs | 15 +- .../services/txpool_v2/src/tests/context.rs | 7 +- crates/services/txpool_v2/src/tests/mocks.rs | 84 +++++++- crates/services/txpool_v2/src/tests/pool.rs | 12 +- .../services/txpool_v2/src/verifications.rs | 18 +- .../wasm-executor/Cargo.toml | 4 +- crates/storage/src/lib.rs | 1 + crates/storage/src/structured_storage.rs | 24 ++- crates/types/src/blockchain/primitives.rs | 4 +- crates/types/src/lib.rs | 1 + tests/tests/blob.rs | 198 +++++++++++++++++- tests/tests/contract.rs | 2 +- tests/tests/da_compression.rs | 2 +- tests/tests/dos.rs | 4 +- tests/tests/fee_collection_contract.rs | 6 +- tests/tests/gas_price.rs | 4 +- tests/tests/messages.rs | 2 +- tests/tests/metrics.rs | 2 +- tests/tests/trigger_integration/instant.rs | 2 +- tests/tests/trigger_integration/never.rs | 2 +- tests/tests/tx.rs | 12 +- tests/tests/tx/predicates.rs | 2 + tests/tests/tx/txn_status_subscription.rs | 17 +- tests/tests/tx/utxo_validation.rs | 2 +- 52 files changed, 704 insertions(+), 178 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 914e70ea894..1ca78151e1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,10 +16,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [2162](https://github.com/FuelLabs/fuel-core/pull/2162): Pool structure with dependencies, etc.. for the next transaction pool module. Also adds insertion/verification process in PoolV2 and tests refactoring - [2265](https://github.com/FuelLabs/fuel-core/pull/2265): Integrate Block Committer API for DA Block Costs. - [2280](https://github.com/FuelLabs/fuel-core/pull/2280): Allow comma separated relayer addresses in cli +- [2299](https://github.com/FuelLabs/fuel-core/pull/2299): Support blobs in the predicates. +- [2300](https://github.com/FuelLabs/fuel-core/pull/2300): Added new function to `fuel-core-client` for checking whether a blob exists. ### Changed #### Breaking +- [2299](https://github.com/FuelLabs/fuel-core/pull/2299): Anyone who wants to participate in the transaction broadcasting via p2p must upgrade to support new predicates on the TxPool level. +- [2299](https://github.com/FuelLabs/fuel-core/pull/2299): Upgraded `fuel-vm` to `0.58.0`. More information in the [release](https://github.com/FuelLabs/fuel-vm/releases/tag/v0.58.0). - [2276](https://github.com/FuelLabs/fuel-core/pull/2276): Changed how complexity for blocks is calculated. The default complexity now is 80_000. All queries that somehow touch the block header now are more expensive. - [2290](https://github.com/FuelLabs/fuel-core/pull/2290): Added a new GraphQL limit on number of `directives`. The default value is `10`. - [2206](https://github.com/FuelLabs/fuel-core/pull/2206): Use timestamp of last block when dry running transactions. diff --git a/Cargo.lock b/Cargo.lock index 6448b1b7168..c3bf90399bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3139,24 +3139,24 @@ dependencies = [ [[package]] name = "fuel-asm" -version = "0.57.1" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b83807968cd62babe6cd70c94b76c86f302c8573da18b3c69135688eceecd" +checksum = "79ca07227658105bdf873556dea09fa7fbfe792fbc084b4b9568f5ba3d64c411" dependencies = [ "bitflags 2.6.0", - "fuel-types 0.57.1", + "fuel-types 0.58.0", "serde", "strum 0.24.1", ] [[package]] name = "fuel-compression" -version = "0.57.1" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d62c1ba6352f7bbcf1f2abcdd1c1092c7f5155653d75243b915c4e9ae500b4" +checksum = "3af97bfc2c2b4f0a7f471141663557f13462d7ac278922b01ebaf2127e7515f3" dependencies = [ - "fuel-derive 0.57.1", - "fuel-types 0.57.1", + "fuel-derive 0.58.0", + "fuel-types 0.58.0", "serde", ] @@ -3651,7 +3651,7 @@ dependencies = [ "enum-iterator", "fuel-core-storage", "fuel-core-types 0.36.0", - "fuel-vm 0.57.1", + "fuel-vm 0.58.0", "impl-tools", "itertools 0.12.1", "mockall", @@ -3817,7 +3817,7 @@ dependencies = [ "bs58", "derivative", "derive_more", - "fuel-vm 0.57.1", + "fuel-vm 0.58.0", "rand", "secrecy", "serde", @@ -3875,15 +3875,15 @@ dependencies = [ [[package]] name = "fuel-crypto" -version = "0.57.1" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a4ca62d0a8a361b66a6eab3456285883d0aa92c407e249fc76f195c332fbb2" +checksum = "f53b06525aa7754bf7c3ef23daf15fd798ae990a82f8b7b813d25cedfeacfe5c" dependencies = [ "coins-bip32", "coins-bip39", "ecdsa", "ed25519-dalek", - "fuel-types 0.57.1", + "fuel-types 0.58.0", "k256", "lazy_static", "p256", @@ -3908,9 +3908,9 @@ dependencies = [ [[package]] name = "fuel-derive" -version = "0.57.1" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca99d9c264fec231a01e55bbdb6adb3080266dc44c4cc88de870b089ee2a015" +checksum = "c8e34d6eec30d04506607cc0bc85fc97c57c964580cd233fd557e346c5273535" dependencies = [ "proc-macro2", "quote", @@ -3945,13 +3945,13 @@ dependencies = [ [[package]] name = "fuel-merkle" -version = "0.57.1" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f3c08f22f7c24170a4ac255e7dfe52d52ae2e85c4a8e26ed6df4f1bd380210" +checksum = "7a9fa3708405eba32fd2b947b827dc52484377ba6a238260b03a07b642395e6c" dependencies = [ "derive_more", "digest 0.10.7", - "fuel-storage 0.57.1", + "fuel-storage 0.58.0", "hashbrown 0.13.2", "hex", "serde", @@ -3966,9 +3966,9 @@ checksum = "4c1b711f28553ddc5f3546711bd220e144ce4c1af7d9e9a1f70b2f20d9f5b791" [[package]] name = "fuel-storage" -version = "0.57.1" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d676ea5d926bf90c8ea442e5f6fc23c0e86c2e4d663f303842b4afe5b7928084" +checksum = "f6f678f1c900d0632d77e15d4a4946048d4d517fefeba72607390c03288ca127" [[package]] name = "fuel-tx" @@ -3994,24 +3994,23 @@ dependencies = [ [[package]] name = "fuel-tx" -version = "0.57.1" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86158d08fe2a936ac765a1e2cb9bf60be704203b3085882e7cc6cd4c48de38ef" +checksum = "1e3065c12eecc9121514694f4b01009c9a83d8842af11c43ec9e2bbc0a7f36cb" dependencies = [ "bitflags 2.6.0", "derivative", "derive_more", - "fuel-asm 0.57.1", + "fuel-asm 0.58.0", "fuel-compression", - "fuel-crypto 0.57.1", - "fuel-merkle 0.57.1", - "fuel-types 0.57.1", + "fuel-crypto 0.58.0", + "fuel-merkle 0.58.0", + "fuel-types 0.58.0", "hashbrown 0.14.5", "itertools 0.10.5", "postcard", "rand", "serde", - "serde_json", "strum 0.24.1", "strum_macros 0.24.3", ] @@ -4029,11 +4028,11 @@ dependencies = [ [[package]] name = "fuel-types" -version = "0.57.1" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b4430c6a20669fffd8f2c17d2be6809a356f623243a78b5eedf8ba7897c036" +checksum = "a93d5f3fd028d874d8927be439fcdea01cb04499049bc68a874c73dd0c7e32b7" dependencies = [ - "fuel-derive 0.57.1", + "fuel-derive 0.58.0", "hex", "rand", "serde", @@ -4072,9 +4071,9 @@ dependencies = [ [[package]] name = "fuel-vm" -version = "0.57.1" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1b04a4e971d58b3662ff8b84b3176094e25f4b372728a13ea903fdf79c7e426" +checksum = "cb0562398978e501e8ee2caeb747a2852cc4a8c5fff250eb58e38f1c03217311" dependencies = [ "anyhow", "async-trait", @@ -4083,13 +4082,13 @@ dependencies = [ "derivative", "derive_more", "ethnum", - "fuel-asm 0.57.1", + "fuel-asm 0.58.0", "fuel-compression", - "fuel-crypto 0.57.1", - "fuel-merkle 0.57.1", - "fuel-storage 0.57.1", - "fuel-tx 0.57.1", - "fuel-types 0.57.1", + "fuel-crypto 0.58.0", + "fuel-merkle 0.58.0", + "fuel-storage 0.58.0", + "fuel-tx 0.58.0", + "fuel-types 0.58.0", "hashbrown 0.14.5", "itertools 0.10.5", "libm", @@ -4784,7 +4783,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core", ] [[package]] @@ -9910,7 +9909,7 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ - "windows-core 0.51.1", + "windows-core", "windows-targets 0.48.5", ] @@ -9923,15 +9922,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index a6416d7b638..21a2d8f85c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,7 +89,7 @@ fuel-core-xtask = { version = "0.0.0", path = "./xtask" } fuel-gas-price-algorithm = { version = "0.36.0", path = "crates/fuel-gas-price-algorithm" } # Fuel dependencies -fuel-vm-private = { version = "0.57.0", package = "fuel-vm", default-features = false } +fuel-vm-private = { version = "0.58.0", package = "fuel-vm", default-features = false } # Common dependencies anyhow = "1.0" @@ -116,7 +116,7 @@ postcard = "1.0" tracing-attributes = "0.1" tracing-subscriber = "0.3" serde = "1.0" -serde_json = { version = "1.0", default-features = false } +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } serde_with = { version = "3.4", default-features = false } strum = { version = "0.25" } strum_macros = "0.25" diff --git a/benches/benches/block_target_gas.rs b/benches/benches/block_target_gas.rs index 8cb4d1fd9a7..0518d4f1ae5 100644 --- a/benches/benches/block_target_gas.rs +++ b/benches/benches/block_target_gas.rs @@ -83,6 +83,7 @@ use fuel_core_types::{ checked_transaction::EstimatePredicates, consts::WORD_SIZE, interpreter::MemoryInstance, + predicate::EmptyStorage, }, services::executor::TransactionExecutionResult, }; @@ -418,6 +419,7 @@ fn run_with_service_with_extra_inputs( tx.estimate_predicates( &chain_config.consensus_parameters.clone().into(), MemoryInstance::new(), + &EmptyStorage, ) .unwrap(); async move { diff --git a/benches/benches/transaction_throughput.rs b/benches/benches/transaction_throughput.rs index 55a2f11990e..c49055d50db 100644 --- a/benches/benches/transaction_throughput.rs +++ b/benches/benches/transaction_throughput.rs @@ -39,6 +39,7 @@ use fuel_core_types::{ EstimatePredicates, }, interpreter::MemoryInstance, + predicate::EmptyStorage, }, }; use rand::{ @@ -194,8 +195,12 @@ fn signed_transfers(c: &mut Criterion) { .add_output(Output::coin(rng.gen(), 50, AssetId::default())) .add_output(Output::change(rng.gen(), 0, AssetId::default())) .finalize(); - tx.estimate_predicates(&checked_parameters(), MemoryInstance::new()) - .expect("Predicate check failed"); + tx.estimate_predicates( + &checked_parameters(), + MemoryInstance::new(), + &EmptyStorage, + ) + .expect("Predicate check failed"); tx }; bench_txs("signed transfers", c, generator); @@ -220,8 +225,12 @@ fn predicate_transfers(c: &mut Criterion) { .add_output(Output::coin(rng.gen(), 50, AssetId::default())) .add_output(Output::change(rng.gen(), 0, AssetId::default())) .finalize(); - tx.estimate_predicates(&checked_parameters(), MemoryInstance::new()) - .expect("Predicate check failed"); + tx.estimate_predicates( + &checked_parameters(), + MemoryInstance::new(), + &EmptyStorage, + ) + .expect("Predicate check failed"); tx }; bench_txs("predicate transfers", c, generator); @@ -288,8 +297,12 @@ fn predicate_transfers_eck1(c: &mut Criterion) { .add_output(Output::coin(rng.gen(), 50, AssetId::default())) .add_output(Output::change(rng.gen(), 0, AssetId::default())) .finalize(); - tx.estimate_predicates(&checked_parameters(), MemoryInstance::new()) - .expect("Predicate check failed"); + tx.estimate_predicates( + &checked_parameters(), + MemoryInstance::new(), + &EmptyStorage, + ) + .expect("Predicate check failed"); tx }; bench_txs("predicate transfers eck1", c, generator); @@ -358,8 +371,12 @@ fn predicate_transfers_ed19(c: &mut Criterion) { .add_output(Output::coin(rng.gen(), 50, AssetId::default())) .add_output(Output::change(rng.gen(), 0, AssetId::default())) .finalize(); - tx.estimate_predicates(&checked_parameters(), MemoryInstance::new()) - .expect("Predicate check failed"); + tx.estimate_predicates( + &checked_parameters(), + MemoryInstance::new(), + &EmptyStorage, + ) + .expect("Predicate check failed"); tx }; bench_txs("predicate transfers ed19", c, generator); diff --git a/benches/src/default_gas_costs.rs b/benches/src/default_gas_costs.rs index 4ef866f9a27..ed10c1c3333 100644 --- a/benches/src/default_gas_costs.rs +++ b/benches/src/default_gas_costs.rs @@ -57,8 +57,8 @@ pub fn default_gas_costs() -> GasCostsValues { ori: 2, poph: 2, popl: 2, - pshh: 3073, - pshl: 3016, + pshh: 5, + pshl: 5, move_op: 2, ret: 43, sb: 2, diff --git a/benches/src/lib.rs b/benches/src/lib.rs index 4aa68c51656..c84fb4e6418 100644 --- a/benches/src/lib.rs +++ b/benches/src/lib.rs @@ -494,7 +494,7 @@ impl TryFrom for VmBenchPrepared { }); // add at least one coin input - tx.add_random_fee_input(); + tx.add_fee_input(); let mut tx = tx .script_gas_limit(gas_limit) @@ -504,6 +504,7 @@ impl TryFrom for VmBenchPrepared { tx.estimate_predicates( &CheckPredicateParams::from(¶ms), MemoryInstance::new(), + db.database_mut(), ) .unwrap(); let tx = tx.into_checked(height, ¶ms).unwrap(); diff --git a/bin/fuel-core/chainspec/local-testnet/chain_config.json b/bin/fuel-core/chainspec/local-testnet/chain_config.json index e6325f21e1b..18e934d73f8 100644 --- a/bin/fuel-core/chainspec/local-testnet/chain_config.json +++ b/bin/fuel-core/chainspec/local-testnet/chain_config.json @@ -93,8 +93,8 @@ "ori": 2, "poph": 2, "popl": 2, - "pshh": 3073, - "pshl": 3016, + "pshh": 5, + "pshl": 5, "ret_contract": 43, "rvrt_contract": 39, "sb": 2, diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index 2fabf630ccb..763ceb0ac75 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -905,6 +905,12 @@ impl FuelClient { Ok(blob) } + /// Check whether a blob with ID exists + pub async fn blob_exists(&self, id: BlobId) -> io::Result { + let query = schema::blob::BlobExistsQuery::build(BlobByIdArgs { id: id.into() }); + Ok(self.query(query).await?.blob.is_some()) + } + /// Retrieve multiple blocks pub async fn blocks( &self, diff --git a/crates/client/src/client/schema/blob.rs b/crates/client/src/client/schema/blob.rs index 3ea99f287dc..3a3b9e65b76 100644 --- a/crates/client/src/client/schema/blob.rs +++ b/crates/client/src/client/schema/blob.rs @@ -26,3 +26,20 @@ pub struct Blob { pub id: BlobId, pub bytecode: HexString, } + +#[derive(cynic::QueryFragment, Clone, Debug)] +#[cynic(schema_path = "./assets/schema.sdl", graphql_type = "Blob")] +pub struct BlobIdFragment { + pub id: BlobId, +} + +#[derive(cynic::QueryFragment, Clone, Debug)] +#[cynic( + schema_path = "./assets/schema.sdl", + graphql_type = "Query", + variables = "BlobByIdArgs" +)] +pub struct BlobExistsQuery { + #[arguments(id: $id)] + pub blob: Option, +} diff --git a/crates/fuel-core/src/executor.rs b/crates/fuel-core/src/executor.rs index 8d1a1fd37f2..86e899452c7 100644 --- a/crates/fuel-core/src/executor.rs +++ b/crates/fuel-core/src/executor.rs @@ -3,9 +3,6 @@ #[allow(non_snake_case)] #[cfg(test)] mod tests { - - use std::sync::Mutex; - use crate as fuel_core; use fuel_core::database::Database; use fuel_core_executor::{ @@ -127,6 +124,7 @@ mod tests { ExecutableTransaction, MemoryInstance, }, + predicate::EmptyStorage, script_with_data_offset, util::test_helpers::TestBuilder as TxBuilder, Call, @@ -153,6 +151,7 @@ mod tests { Rng, SeedableRng, }; + use std::sync::Mutex; #[derive(Clone, Debug, Default)] struct Config { @@ -355,7 +354,7 @@ mod tests { let tx = TransactionBuilder::create(contract_code.into(), salt, Default::default()) - .add_random_fee_input() + .add_fee_input() .add_output(Output::contract_created(contract_id, state_root)) .finalize(); (tx, contract_id) @@ -1478,7 +1477,7 @@ mod tests { header: Default::default(), transactions: vec![TransactionBuilder::script(vec![], vec![]) .max_fee_limit(100_000_000) - .add_random_fee_input() + .add_fee_input() .script_gas_limit(0) .tip(123) .finalize_as_transaction()], @@ -1494,7 +1493,7 @@ mod tests { for i in 0..10 { let tx = TransactionBuilder::script(vec![], vec![]) .max_fee_limit(100_000_000) - .add_random_fee_input() + .add_fee_input() .script_gas_limit(0) .tip(i * 100) .finalize_as_transaction(); @@ -1533,7 +1532,7 @@ mod tests { // The test checks that execution for the block with transactions [tx1, tx2, tx3] skips // transaction `tx1` and produce a block [tx2, tx3] with the expected order. let tx1 = TransactionBuilder::script(vec![], vec![]) - .add_random_fee_input() + .add_fee_input() .script_gas_limit(1000000) .tip(1000000) .finalize_as_transaction(); @@ -2633,7 +2632,7 @@ mod tests { .collect(), vec![], ) - .add_random_fee_input() + .add_fee_input() .script_gas_limit(1000000) .finalize_as_transaction(); @@ -2697,7 +2696,7 @@ mod tests { .collect(), vec![], ) - .add_random_fee_input() + .add_fee_input() .script_gas_limit(1000000) .finalize_as_transaction(); @@ -2886,6 +2885,7 @@ mod tests { tx.estimate_predicates( &consensus_parameters.clone().into(), MemoryInstance::new(), + &EmptyStorage, ) .unwrap(); let db = &mut Database::default(); @@ -2954,6 +2954,7 @@ mod tests { tx.estimate_predicates( &cheap_consensus_parameters.clone().into(), MemoryInstance::new(), + &EmptyStorage, ) .unwrap(); diff --git a/crates/fuel-core/src/graphql_api.rs b/crates/fuel-core/src/graphql_api.rs index f169a775ca1..e81216d366e 100644 --- a/crates/fuel-core/src/graphql_api.rs +++ b/crates/fuel-core/src/graphql_api.rs @@ -38,7 +38,6 @@ pub struct Costs { pub submit: usize, pub submit_and_await: usize, pub status_change: usize, - pub raw_payload: usize, pub storage_read: usize, pub tx_get: usize, pub tx_status_read: usize, @@ -65,8 +64,7 @@ pub const QUERY_COSTS: Costs = Costs { submit: 40001, submit_and_await: 40001, status_change: 40001, - raw_payload: 10, - storage_read: 10, + storage_read: 40, tx_get: 50, tx_status_read: 50, tx_raw_payload: 150, diff --git a/crates/fuel-core/src/graphql_api/database.rs b/crates/fuel-core/src/graphql_api/database.rs index 53d2dbb39bf..752b324529d 100644 --- a/crates/fuel-core/src/graphql_api/database.rs +++ b/crates/fuel-core/src/graphql_api/database.rs @@ -23,8 +23,11 @@ use fuel_core_storage::{ Error as StorageError, IsNotFound, Mappable, + PredicateStorageRequirements, Result as StorageResult, StorageInspect, + StorageRead, + StorageSize, }; use fuel_core_txpool::types::{ ContractId, @@ -56,9 +59,11 @@ use fuel_core_types::{ UtxoId, }, fuel_types::{ + BlobId, BlockHeight, Nonce, }, + fuel_vm::BlobData, services::{ graphql_api::ContractBalance, txpool::TransactionStatus, @@ -238,6 +243,28 @@ where } } +impl StorageSize for ReadView { + fn size_of_value(&self, key: &BlobId) -> Result, Self::Error> { + self.on_chain.size_of_value(key) + } +} + +impl StorageRead for ReadView { + fn read(&self, key: &BlobId, buf: &mut [u8]) -> Result, Self::Error> { + self.on_chain.read(key, buf) + } + + fn read_alloc(&self, key: &BlobId) -> Result>, Self::Error> { + self.on_chain.read_alloc(key) + } +} + +impl PredicateStorageRequirements for ReadView { + fn storage_error_to_string(error: Self::Error) -> String { + error.to_string() + } +} + impl DatabaseMessages for ReadView { fn all_messages( &self, diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index e9a9e5255b4..e30715e92da 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -17,6 +17,7 @@ use fuel_core_storage::{ Error as StorageError, Result as StorageResult, StorageInspect, + StorageRead, }; use fuel_core_txpool::service::TxStatusMessage; use fuel_core_types::{ @@ -123,7 +124,7 @@ pub trait OnChainDatabase: + DatabaseBlocks + DatabaseMessages + StorageInspect - + StorageInspect + + StorageRead + StorageInspect + StorageInspect + DatabaseContracts diff --git a/crates/fuel-core/src/schema/blob.rs b/crates/fuel-core/src/schema/blob.rs index ae043e81049..938c2a6a1f3 100644 --- a/crates/fuel-core/src/schema/blob.rs +++ b/crates/fuel-core/src/schema/blob.rs @@ -49,6 +49,7 @@ pub struct BlobQuery; #[Object] impl BlobQuery { + #[graphql(complexity = "QUERY_COSTS.storage_read + child_complexity")] async fn blob( &self, ctx: &Context<'_>, diff --git a/crates/fuel-core/src/schema/tx.rs b/crates/fuel-core/src/schema/tx.rs index d99de0faf2d..00a2aface70 100644 --- a/crates/fuel-core/src/schema/tx.rs +++ b/crates/fuel-core/src/schema/tx.rs @@ -1,3 +1,4 @@ +use super::scalars::U64; use crate::{ fuel_core_graphql_api::{ api_service::{ @@ -78,8 +79,6 @@ use types::{ Transaction, }; -use super::scalars::U64; - pub mod input; pub mod output; pub mod receipt; @@ -227,6 +226,8 @@ impl TxQuery { ctx: &Context<'_>, tx: HexString, ) -> async_graphql::Result { + let query = ctx.read_view()?.into_owned(); + let mut tx = FuelTx::from_bytes(&tx.0)?; let params = ctx @@ -238,7 +239,7 @@ impl TxQuery { let parameters = CheckPredicateParams::from(params.as_ref()); let tx = tokio_rayon::spawn_fifo(move || { - let result = tx.estimate_predicates(¶meters, memory); + let result = tx.estimate_predicates(¶meters, memory, &query); result.map(|_| tx) }) .await diff --git a/crates/fuel-core/src/schema/tx/types.rs b/crates/fuel-core/src/schema/tx/types.rs index b7394fd1751..060d18ae5dc 100644 --- a/crates/fuel-core/src/schema/tx/types.rs +++ b/crates/fuel-core/src/schema/tx/types.rs @@ -846,7 +846,7 @@ impl Transaction { } } - #[graphql(complexity = "QUERY_COSTS.raw_payload")] + #[graphql(complexity = "QUERY_COSTS.tx_raw_payload")] /// Return the transaction bytes using canonical encoding async fn raw_payload(&self) -> HexString { HexString(self.0.clone().to_bytes()) diff --git a/crates/fuel-core/src/state/generic_database.rs b/crates/fuel-core/src/state/generic_database.rs index bbf42e40038..8306df1b1fb 100644 --- a/crates/fuel-core/src/state/generic_database.rs +++ b/crates/fuel-core/src/state/generic_database.rs @@ -10,17 +10,22 @@ use fuel_core_storage::{ Value, }, structured_storage::StructuredStorage, + tables::BlobData, Error as StorageError, Mappable, MerkleRoot, MerkleRootStorage, + PredicateStorageRequirements, Result as StorageResult, StorageAsRef, StorageInspect, StorageRead, StorageSize, }; -use std::borrow::Cow; +use std::{ + borrow::Cow, + fmt::Debug, +}; #[derive(Debug, Clone)] pub struct GenericDatabase { @@ -176,3 +181,13 @@ impl core::ops::DerefMut for GenericDatabase { self.as_mut() } } + +impl PredicateStorageRequirements for GenericDatabase +where + Self: StorageRead, + Error: Debug, +{ + fn storage_error_to_string(error: Error) -> String { + format!("{:?}", error) + } +} diff --git a/crates/services/executor/src/executor.rs b/crates/services/executor/src/executor.rs index 23017477481..c8d6e3b7363 100644 --- a/crates/services/executor/src/executor.rs +++ b/crates/services/executor/src/executor.rs @@ -923,6 +923,7 @@ where block_height, &self.consensus_params, memory, + block_storage_tx, ); match checked_tx_res { Ok(checked_tx) => { @@ -949,12 +950,16 @@ where } /// Parse forced transaction payloads and perform basic checks - fn validate_forced_tx( + fn validate_forced_tx( relayed_tx: RelayedTransaction, block_height: BlockHeight, consensus_params: &ConsensusParameters, memory: &mut MemoryInstance, - ) -> Result { + block_storage_tx: &BlockStorageTransaction, + ) -> Result + where + D: KeyValueInspect, + { let parsed_tx = Self::parse_tx_bytes(&relayed_tx)?; Self::tx_is_valid_variant(&parsed_tx)?; Self::relayed_tx_claimed_enough_max_gas( @@ -962,8 +967,13 @@ where &relayed_tx, consensus_params, )?; - let checked_tx = - Self::get_checked_tx(parsed_tx, block_height, consensus_params, memory)?; + let checked_tx = Self::get_checked_tx( + parsed_tx, + block_height, + consensus_params, + memory, + block_storage_tx, + )?; Ok(CheckedTransaction::from(checked_tx)) } @@ -976,14 +986,23 @@ where Ok(tx) } - fn get_checked_tx( + fn get_checked_tx( tx: Transaction, height: BlockHeight, consensus_params: &ConsensusParameters, memory: &mut MemoryInstance, - ) -> Result, ForcedTransactionFailure> { + block_storage_tx: &BlockStorageTransaction, + ) -> Result, ForcedTransactionFailure> + where + D: KeyValueInspect, + { let checked_tx = tx - .into_checked_reusable_memory(height, consensus_params, memory) + .into_checked_reusable_memory( + height, + consensus_params, + memory, + block_storage_tx, + ) .map_err(ForcedTransactionFailure::CheckError)?; Ok(checked_tx) } @@ -1521,7 +1540,7 @@ where &self, mut checked_tx: Checked, header: &PartialBlockHeader, - storage_tx: &mut TxStorageTransaction, + storage_tx: &TxStorageTransaction, memory: &mut MemoryInstance, ) -> ExecutorResult> where @@ -1530,7 +1549,11 @@ where T: KeyValueInspect, { checked_tx = checked_tx - .check_predicates(&CheckPredicateParams::from(&self.consensus_params), memory) + .check_predicates( + &CheckPredicateParams::from(&self.consensus_params), + memory, + storage_tx, + ) .map_err(|e| { ExecutorError::TransactionValidity(TransactionValidityError::Validation( e, diff --git a/crates/services/txpool/src/containers/dependency.rs b/crates/services/txpool/src/containers/dependency.rs index ed3561c645f..97e288d49ed 100644 --- a/crates/services/txpool/src/containers/dependency.rs +++ b/crates/services/txpool/src/containers/dependency.rs @@ -204,7 +204,7 @@ impl Dependency { fn check_for_collision<'a>( &'a self, txs: &'a HashMap, - db: &dyn TxPoolDb, + db: &impl TxPoolDb, tx: &'a ArcPoolTx, ) -> Result< ( diff --git a/crates/services/txpool/src/mock_db.rs b/crates/services/txpool/src/mock_db.rs index 371d214f0c2..220820335f9 100644 --- a/crates/services/txpool/src/mock_db.rs +++ b/crates/services/txpool/src/mock_db.rs @@ -1,7 +1,13 @@ use crate::ports::TxPoolDb; use fuel_core_storage::{ + tables::BlobData, transactional::AtomicView, + Mappable, + PredicateStorageRequirements, Result as StorageResult, + StorageInspect, + StorageRead, + StorageSize, }; use fuel_core_types::{ entities::{ @@ -21,6 +27,7 @@ use fuel_core_types::{ fuel_vm::BlobBytes, }; use std::{ + borrow::Cow, collections::{ HashMap, HashSet, @@ -75,6 +82,74 @@ impl MockDb { } } +impl StorageRead for MockDb { + fn read( + &self, + key: &::Key, + buf: &mut [u8], + ) -> Result, Self::Error> { + let table = self.data.lock().unwrap(); + let bytes = table.blobs.get(key); + + let len = bytes.map(|bytes| { + buf.copy_from_slice(bytes.0.as_slice()); + bytes.0.len() + }); + Ok(len) + } + + fn read_alloc( + &self, + key: &::Key, + ) -> Result>, Self::Error> { + let table = self.data.lock().unwrap(); + let bytes = table.blobs.get(key); + let bytes = bytes.map(|bytes| bytes.clone().0); + Ok(bytes) + } +} + +impl StorageInspect for MockDb { + type Error = (); + + fn get( + &self, + key: &::Key, + ) -> Result::OwnedValue>>, Self::Error> { + let table = self.data.lock().unwrap(); + let bytes = table.blobs.get(key); + Ok(bytes.map(|b| Cow::Owned(b.clone()))) + } + + fn contains_key( + &self, + key: &::Key, + ) -> Result { + Ok(self.data.lock().unwrap().blobs.contains_key(key)) + } +} + +impl StorageSize for MockDb { + fn size_of_value( + &self, + key: &::Key, + ) -> Result, Self::Error> { + Ok(self + .data + .lock() + .unwrap() + .blobs + .get(key) + .map(|blob| blob.0.len())) + } +} + +impl PredicateStorageRequirements for MockDb { + fn storage_error_to_string(error: Self::Error) -> String { + format!("{:?}", error) + } +} + impl TxPoolDb for MockDb { fn utxo(&self, utxo_id: &UtxoId) -> StorageResult> { Ok(self.data.lock().unwrap().coins.get(utxo_id).cloned()) @@ -98,6 +173,7 @@ impl TxPoolDb for MockDb { } } +#[derive(Clone)] pub struct MockDBProvider(pub MockDb); impl AtomicView for MockDBProvider { diff --git a/crates/services/txpool/src/ports.rs b/crates/services/txpool/src/ports.rs index 4a247ff21db..3f87fff8a5d 100644 --- a/crates/services/txpool/src/ports.rs +++ b/crates/services/txpool/src/ports.rs @@ -3,7 +3,10 @@ use crate::{ Result as TxPoolResult, }; use fuel_core_services::stream::BoxStream; -use fuel_core_storage::Result as StorageResult; +use fuel_core_storage::{ + PredicateStorageRequirements, + Result as StorageResult, +}; use fuel_core_types::{ blockchain::header::ConsensusParametersVersion, entities::{ @@ -75,7 +78,7 @@ pub trait BlockImporter: Send + Sync { fn block_events(&self) -> BoxStream; } -pub trait TxPoolDb: Send + Sync { +pub trait TxPoolDb: Clone + PredicateStorageRequirements + Send + Sync + 'static { fn utxo(&self, utxo_id: &UtxoId) -> StorageResult>; fn contract_exist(&self, contract_id: &ContractId) -> StorageResult; diff --git a/crates/services/txpool/src/service.rs b/crates/services/txpool/src/service.rs index 6bef4b021bc..d17f8a00a86 100644 --- a/crates/services/txpool/src/service.rs +++ b/crates/services/txpool/src/service.rs @@ -1,10 +1,9 @@ +use anyhow::anyhow; +use parking_lot::Mutex as ParkingMutex; use std::{ sync::Arc, time::Duration, }; - -use anyhow::anyhow; -use parking_lot::Mutex as ParkingMutex; use tokio::{ sync::broadcast, time::MissedTickBehavior, @@ -135,6 +134,7 @@ pub struct SharedState< > { tx_status_sender: TxStatusChange, txpool: Arc>>, + provider: Arc, p2p: Arc, utxo_validation: bool, current_height: Arc>, @@ -157,6 +157,7 @@ impl Cl Self { tx_status_sender: self.tx_status_sender.clone(), txpool: self.txpool.clone(), + provider: self.provider.clone(), p2p: self.p2p.clone(), utxo_validation: self.utxo_validation, current_height: self.current_height.clone(), @@ -296,6 +297,7 @@ where .consensus_parameters_provider .latest_consensus_parameters(); + let view = self.tx_pool_shared_state.provider.latest_view()?; // verify tx let checked_tx = check_single_tx( tx, @@ -304,6 +306,7 @@ where params.as_ref(), &self.tx_pool_shared_state.gas_price_provider, self.tx_pool_shared_state.memory_pool.get_memory().await, + view, ).await; let acceptance = match checked_tx { @@ -453,7 +456,7 @@ impl where P2P: PeerToPeer, - ViewProvider: AtomicView, + ViewProvider: AtomicView + 'static, View: TxPoolDb, WasmChecker: WasmCheckerConstraint + Send + Sync, GasPriceProvider: GasPriceProviderConstraint + Send + Sync, @@ -507,16 +510,22 @@ where .consensus_parameters_provider .latest_consensus_parameters(); - let checked_txs = check_transactions( + let result = check_transactions( &txs, current_height, self.utxo_validation, params.as_ref(), &self.gas_price_provider, self.memory_pool.clone(), + &self.provider, ) .await; + let checked_txs = match result { + Ok(checked_txs) => checked_txs, + Err(err) => return vec![Err(TxPoolError::Other(err.to_string()))], + }; + let mut valid_txs = vec![]; let checked_txs: Vec<_> = checked_txs @@ -632,9 +641,10 @@ where let mut ttl_timer = tokio::time::interval(config.transaction_ttl); ttl_timer.set_missed_tick_behavior(MissedTickBehavior::Skip); let number_of_active_subscription = config.number_of_active_subscription; + let provider = Arc::new(provider); let txpool = Arc::new(ParkingMutex::new(TxPool::new( config.clone(), - provider, + provider.clone(), wasm_checker, ))); let task = Task { @@ -651,6 +661,7 @@ where config.transaction_ttl.saturating_mul(2), ), txpool, + provider, p2p, utxo_validation: config.utxo_validation, current_height: Arc::new(ParkingMutex::new(current_height)), diff --git a/crates/services/txpool/src/test_helpers.rs b/crates/services/txpool/src/test_helpers.rs index 193f397a934..5f3d8749049 100644 --- a/crates/services/txpool/src/test_helpers.rs +++ b/crates/services/txpool/src/test_helpers.rs @@ -46,8 +46,10 @@ use fuel_core_types::{ fuel_vm::{ checked_transaction::EstimatePredicates, interpreter::MemoryInstance, + predicate::EmptyStorage, }, }; +use std::sync::Arc; // use some arbitrary large amount, this shouldn't affect the txpool logic except for covering // the byte and gas price fees. @@ -93,7 +95,7 @@ impl TextContext { pub(crate) fn build(self) -> TxPool { TxPool::new( self.config.unwrap_or_default(), - MockDBProvider(self.mock_db), + Arc::new(MockDBProvider(self.mock_db)), self.wasm_checker, ) } @@ -233,7 +235,8 @@ impl IntoEstimated for Input { let mut tx = TransactionBuilder::script(vec![], vec![]) .add_input(self) .finalize(); - let _ = tx.estimate_predicates(¶ms.into(), MemoryInstance::new()); + let _ = + tx.estimate_predicates(¶ms.into(), MemoryInstance::new(), &EmptyStorage); tx.inputs()[0].clone() } } diff --git a/crates/services/txpool/src/txpool.rs b/crates/services/txpool/src/txpool.rs index 64294a858ae..d01c78411b9 100644 --- a/crates/services/txpool/src/txpool.rs +++ b/crates/services/txpool/src/txpool.rs @@ -87,14 +87,14 @@ pub struct TxPool { by_time: TimeSort, by_dependency: Dependency, config: Config, - database: ViewProvider, + database: Arc, wasm_checker: WasmChecker, } impl TxPool { pub fn new( config: Config, - database: ViewProvider, + database: Arc, wasm_checker: WasmChecker, ) -> Self { let max_depth = config.max_depth; @@ -482,20 +482,24 @@ where } } -pub async fn check_transactions( +pub async fn check_transactions( txs: &[Arc], current_height: BlockHeight, utxp_validation: bool, consensus_params: &ConsensusParameters, gas_price_provider: &Provider, memory_pool: Arc, -) -> Vec, Error>> + provider: &Arc, +) -> anyhow::Result, Error>>> where Provider: GasPriceProvider, MP: MemoryPool, + ViewProvider: AtomicView, + View: TxPoolDb, { let mut checked_txs = Vec::with_capacity(txs.len()); + let view = provider.latest_view()?; for tx in txs.iter() { checked_txs.push( check_single_tx( @@ -505,25 +509,28 @@ where consensus_params, gas_price_provider, memory_pool.get_memory().await, + view.clone(), ) .await, ); } - checked_txs + Ok(checked_txs) } -pub async fn check_single_tx( +pub async fn check_single_tx( tx: Transaction, current_height: BlockHeight, utxo_validation: bool, consensus_params: &ConsensusParameters, gas_price_provider: &GasPrice, memory: M, + view: View, ) -> Result, Error> where GasPrice: GasPriceProvider, M: Memory + Send + Sync + 'static, + View: TxPoolDb, { if tx.is_mint() { return Err(Error::NotSupportedTransactionType) @@ -535,9 +542,10 @@ where .check_signatures(&consensus_params.chain_id())?; let parameters = CheckPredicateParams::from(consensus_params); - let tx = - tokio_rayon::spawn_fifo(move || tx.check_predicates(¶meters, memory)) - .await?; + let tx = tokio_rayon::spawn_fifo(move || { + tx.check_predicates(¶meters, memory, &view) + }) + .await?; debug_assert!(tx.checks().contains(Checks::all())); diff --git a/crates/services/txpool/src/txpool/tests.rs b/crates/services/txpool/src/txpool/tests.rs index 64d94349bd3..155d00f4904 100644 --- a/crates/services/txpool/src/txpool/tests.rs +++ b/crates/services/txpool/src/txpool/tests.rs @@ -18,6 +18,7 @@ use crate::{ types::GasPrice, Config, Error, + MockDb, }; use fuel_core_types::{ fuel_asm::{ @@ -79,6 +80,7 @@ async fn check_unwrap_tx_with_gas_price( &ConsensusParameters::default(), &gas_price_provider, MemoryInstance::new(), + MockDb::default(), ) .await .expect("Transaction should be checked") @@ -105,6 +107,7 @@ async fn check_tx_with_gas_price( &ConsensusParameters::default(), &gas_price_provider, MemoryInstance::new(), + MockDb::default(), ) .await } @@ -392,7 +395,7 @@ async fn not_inserted_known_tx() { let mut txpool = context.build(); let tx = TransactionBuilder::script(vec![], vec![]) - .add_random_fee_input() + .add_fee_input() .finalize() .into(); let tx = check_unwrap_tx(tx, &txpool.config).await; @@ -1370,7 +1373,7 @@ async fn insert_single__blob_tx_works() { witness_index: 0, }) .add_witness(program.into()) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let config = Config { @@ -1401,7 +1404,7 @@ async fn insert_single__blob_tx_fails_if_blob_already_inserted_and_lower_tip() { witness_index: 0, }) .add_witness(program.clone().into()) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let config = Config { @@ -1418,7 +1421,7 @@ async fn insert_single__blob_tx_fails_if_blob_already_inserted_and_lower_tip() { id: blob_id, witness_index: 1, }) - .add_random_fee_input() + .add_fee_input() .add_witness(program.into()) .finalize_as_transaction(); let same_blob_tx = check_unwrap_tx(same_blob_tx, &txpool.config).await; @@ -1439,7 +1442,7 @@ async fn insert_single__blob_tx_succeeds_if_blob_already_inserted_but_higher_tip witness_index: 0, }) .add_witness(program.clone().into()) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let config = Config { @@ -1456,7 +1459,7 @@ async fn insert_single__blob_tx_succeeds_if_blob_already_inserted_but_higher_tip id: blob_id, witness_index: 1, }) - .add_random_fee_input() + .add_fee_input() .add_witness(program.into()) .tip(100) .max_fee_limit(100) @@ -1479,7 +1482,7 @@ async fn insert_single__blob_tx_fails_if_blob_already_exists_in_database() { witness_index: 0, }) .add_witness(program.clone().into()) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let config = Config { @@ -1541,6 +1544,7 @@ async fn insert_inner__rejects_upgrade_tx_with_invalid_wasm() { ¶ms, &gas_price_provider, MemoryInstance::new(), + MockDb::default(), ) .await .expect("Transaction should be checked"); diff --git a/crates/services/txpool_v2/src/heavy_async_processing.rs b/crates/services/txpool_v2/src/heavy_async_processing.rs index 94fabad1fc7..e2876a7ef3c 100644 --- a/crates/services/txpool_v2/src/heavy_async_processing.rs +++ b/crates/services/txpool_v2/src/heavy_async_processing.rs @@ -36,7 +36,8 @@ impl HeavyAsyncProcessor { if let Ok(permit) = permit { self.rayon_thread_pool.spawn_fifo(move || { - let _drop = permit; + // When task started its works we can free the space. + drop(permit); futures::executor::block_on(future); }); Ok(()) diff --git a/crates/services/txpool_v2/src/ports.rs b/crates/services/txpool_v2/src/ports.rs index e09b04a24a6..5da145fc3f2 100644 --- a/crates/services/txpool_v2/src/ports.rs +++ b/crates/services/txpool_v2/src/ports.rs @@ -1,6 +1,9 @@ use std::sync::Arc; -use fuel_core_storage::Result as StorageResult; +use fuel_core_storage::{ + PredicateStorageRequirements, + Result as StorageResult, +}; use fuel_core_types::{ blockchain::header::ConsensusParametersVersion, entities::{ @@ -34,7 +37,9 @@ pub trait ConsensusParametersProvider { ) -> (ConsensusParametersVersion, Arc); } -pub trait TxPoolPersistentStorage: Send + Sync { +pub trait TxPoolPersistentStorage: + Clone + PredicateStorageRequirements + Send + Sync + 'static +{ /// Get the UTXO by its ID. fn utxo(&self, utxo_id: &UtxoId) -> StorageResult>; diff --git a/crates/services/txpool_v2/src/service.rs b/crates/services/txpool_v2/src/service.rs index e9df937b16f..f0da3209901 100644 --- a/crates/services/txpool_v2/src/service.rs +++ b/crates/services/txpool_v2/src/service.rs @@ -61,6 +61,7 @@ pub struct SharedState< MemoryPool, > { pool: TxPool, + persistent_storage_provider: Arc, current_height: Arc>, consensus_parameters_provider: Arc, gas_price_provider: Arc, @@ -82,6 +83,7 @@ impl Self { SharedState { pool: self.pool.clone(), + persistent_storage_provider: self.persistent_storage_provider.clone(), current_height: self.current_height.clone(), consensus_parameters_provider: self.consensus_parameters_provider.clone(), gas_price_provider: self.gas_price_provider.clone(), @@ -109,7 +111,7 @@ impl< MemoryPool, > where - PSProvider: AtomicView + 'static, + PSProvider: AtomicView + Send + Sync + 'static, PSView: TxPoolPersistentStorage, ConsensusParamsProvider: ConsensusParametersProvider + 'static, GasPriceProvider: GasPriceProviderTrait + Send + Sync + 'static, @@ -121,10 +123,17 @@ where let (version, params) = self .consensus_parameters_provider .latest_consensus_parameters(); + + let view = self + .persistent_storage_provider + .latest_view() + .map_err(|e| Error::Database(e.to_string()))?; + for transaction in transactions { self.heavy_async_processor.spawn({ let shared_state = self.clone(); let params = params.clone(); + let view = view.clone(); async move { // TODO: Return the error in the status update channel (see: https://github.com/FuelLabs/fuel-core/issues/2185) let checked_tx = perform_all_verifications( @@ -136,6 +145,7 @@ where shared_state.gas_price_provider.as_ref(), shared_state.wasm_checker.as_ref(), shared_state.memory.get_memory().await, + view, ) .await .unwrap(); @@ -291,7 +301,7 @@ pub fn new_service< memory_pool: MemoryPool, ) -> Service where - PSProvider: AtomicView, + PSProvider: AtomicView + Clone + Send + Sync, PSView: TxPoolPersistentStorage, ConsensusParamsProvider: ConsensusParametersProvider + Send + Sync, GasPriceProvider: GasPriceProviderTrait + Send + Sync, @@ -300,6 +310,7 @@ where { Service::new(Task { shared_state: SharedState { + persistent_storage_provider: Arc::new(ps_provider.clone()), consensus_parameters_provider: Arc::new(consensus_parameters_provider), gas_price_provider: Arc::new(gas_price_provider), wasm_checker: Arc::new(wasm_checker), diff --git a/crates/services/txpool_v2/src/tests/context.rs b/crates/services/txpool_v2/src/tests/context.rs index ed1a8658846..0e2bc1711f2 100644 --- a/crates/services/txpool_v2/src/tests/context.rs +++ b/crates/services/txpool_v2/src/tests/context.rs @@ -44,6 +44,7 @@ use fuel_core_types::{ fuel_vm::{ checked_transaction::EstimatePredicates, interpreter::MemoryInstance, + predicate::EmptyStorage, }, }; use parking_lot::RwLock; @@ -161,6 +162,7 @@ impl TestPoolUniverse { &MockTxPoolGasPrice::new(0), &MockWasmChecker::new(Ok(())), MemoryInstance::new(), + MockDb::default(), ) .await?; pool.write().insert(tx) @@ -184,6 +186,7 @@ impl TestPoolUniverse { &MockTxPoolGasPrice::new(gas_price), &MockWasmChecker::new(Ok(())), MemoryInstance::new(), + MockDb::default(), ) .await?; pool.write().insert(tx) @@ -208,6 +211,7 @@ impl TestPoolUniverse { &MockTxPoolGasPrice::new(0), &wasm_checker, MemoryInstance::new(), + MockDb::default(), ) .await?; pool.write().insert(tx) @@ -369,7 +373,8 @@ impl IntoEstimated for Input { let mut tx = TransactionBuilder::script(vec![], vec![]) .add_input(self) .finalize(); - let _ = tx.estimate_predicates(¶ms.into(), MemoryInstance::new()); + let _ = + tx.estimate_predicates(¶ms.into(), MemoryInstance::new(), &EmptyStorage); tx.inputs()[0].clone() } } diff --git a/crates/services/txpool_v2/src/tests/mocks.rs b/crates/services/txpool_v2/src/tests/mocks.rs index 2c3c5e3d28d..348ed544887 100644 --- a/crates/services/txpool_v2/src/tests/mocks.rs +++ b/crates/services/txpool_v2/src/tests/mocks.rs @@ -9,7 +9,14 @@ use crate::{ }, GasPrice, }; -use fuel_core_storage::Result as StorageResult; +use fuel_core_storage::{ + Mappable, + PredicateStorageRequirements, + Result as StorageResult, + StorageInspect, + StorageRead, + StorageSize, +}; use fuel_core_types::{ entities::{ coins::coin::{ @@ -26,9 +33,13 @@ use fuel_core_types::{ UtxoId, }, fuel_types::Nonce, - fuel_vm::BlobBytes, + fuel_vm::{ + BlobBytes, + BlobData, + }, }; use std::{ + borrow::Cow, collections::{ HashMap, HashSet, @@ -106,6 +117,75 @@ impl TxPoolPersistentStorage for MockDb { } } +impl StorageRead for MockDb { + fn read( + &self, + key: &::Key, + buf: &mut [u8], + ) -> Result, Self::Error> { + let table = self.data.lock().unwrap(); + let bytes = table.blobs.get(key); + + let len = bytes.map(|bytes| { + buf.copy_from_slice(bytes.0.as_slice()); + bytes.0.len() + }); + Ok(len) + } + + fn read_alloc( + &self, + key: &::Key, + ) -> Result>, Self::Error> { + let table = self.data.lock().unwrap(); + let bytes = table.blobs.get(key); + let bytes = bytes.map(|bytes| bytes.clone().0); + Ok(bytes) + } +} + +impl StorageInspect for MockDb { + type Error = (); + + fn get( + &self, + key: &::Key, + ) -> Result::OwnedValue>>, Self::Error> { + let table = self.data.lock().unwrap(); + let bytes = table.blobs.get(key); + Ok(bytes.map(|b| Cow::Owned(b.clone()))) + } + + fn contains_key( + &self, + key: &::Key, + ) -> Result { + Ok(self.data.lock().unwrap().blobs.contains_key(key)) + } +} + +impl StorageSize for MockDb { + fn size_of_value( + &self, + key: &::Key, + ) -> Result, Self::Error> { + Ok(self + .data + .lock() + .unwrap() + .blobs + .get(key) + .map(|blob| blob.0.len())) + } +} + +impl PredicateStorageRequirements for MockDb { + fn storage_error_to_string(error: Self::Error) -> String { + format!("{:?}", error) + } +} + +#[derive(Clone)] pub struct MockDBProvider(pub MockDb); impl AtomicView for MockDBProvider { diff --git a/crates/services/txpool_v2/src/tests/pool.rs b/crates/services/txpool_v2/src/tests/pool.rs index 43e6412efc6..6758ebaf1af 100644 --- a/crates/services/txpool_v2/src/tests/pool.rs +++ b/crates/services/txpool_v2/src/tests/pool.rs @@ -1053,7 +1053,7 @@ async fn insert_tx_with_blob() { witness_index: 0, }) .add_witness(program.into()) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); // When @@ -1078,7 +1078,7 @@ async fn insert__tx_with_blob_already_inserted_at_higher_tip() { witness_index: 0, }) .add_witness(program.clone().into()) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); universe.verify_and_insert(tx).await.unwrap(); @@ -1087,7 +1087,7 @@ async fn insert__tx_with_blob_already_inserted_at_higher_tip() { id: blob_id, witness_index: 1, }) - .add_random_fee_input() + .add_fee_input() .add_witness(program.into()) .finalize_as_transaction(); @@ -1114,7 +1114,7 @@ async fn insert_tx_with_blob_already_insert_at_lower_tip() { witness_index: 0, }) .add_witness(program.clone().into()) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); universe.verify_and_insert(tx).await.unwrap(); @@ -1123,7 +1123,7 @@ async fn insert_tx_with_blob_already_insert_at_lower_tip() { id: blob_id, witness_index: 1, }) - .add_random_fee_input() + .add_fee_input() .add_witness(program.into()) .tip(100) .max_fee_limit(100) @@ -1150,7 +1150,7 @@ async fn insert__tx_blob_already_in_db() { witness_index: 0, }) .add_witness(program.clone().into()) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); // Given diff --git a/crates/services/txpool_v2/src/verifications.rs b/crates/services/txpool_v2/src/verifications.rs index 10a43247480..f5e3fa5da45 100644 --- a/crates/services/txpool_v2/src/verifications.rs +++ b/crates/services/txpool_v2/src/verifications.rs @@ -1,3 +1,6 @@ +use std::sync::Arc; + +use fuel_core_storage::PredicateStorageRequirements; use fuel_core_types::{ blockchain::header::ConsensusParametersVersion, fuel_tx::{ @@ -96,19 +99,21 @@ impl BasicVerifiedTx { } impl InputDependenciesVerifiedTx { - pub fn perform_input_computation_verifications( + pub fn perform_input_computation_verifications( self, consensus_params: &ConsensusParameters, wasm_checker: &impl WasmChecker, memory: M, + view: View, ) -> Result where M: Memory + Send + Sync + 'static, + View: TxPoolPersistentStorage, { let tx = self.0.check_signatures(&consensus_params.chain_id())?; let parameters = CheckPredicateParams::from(consensus_params); - let tx = tx.check_predicates(¶meters, memory)?; + let tx = tx.check_predicates(¶meters, memory, &view)?; if let Transaction::Upgrade(upgrade) = tx.transaction() { if let UpgradePurpose::StateTransition { root } = upgrade.upgrade_purpose() { @@ -134,7 +139,7 @@ impl FullyVerifiedTx { } #[allow(clippy::too_many_arguments)] -pub async fn perform_all_verifications( +pub async fn perform_all_verifications( tx: Transaction, pool: TxPool, current_height: BlockHeight, @@ -143,11 +148,12 @@ pub async fn perform_all_verifications( gas_price_provider: &impl GasPriceProvider, wasm_checker: &impl WasmChecker, memory: M, + view: View, ) -> Result where M: Memory + Send + Sync + 'static, - PSProvider: AtomicView, - PSView: TxPoolPersistentStorage, + PSProvider: AtomicView, + View: TxPoolPersistentStorage, { let unverified = UnverifiedTx(tx); let basically_verified_tx = unverified @@ -155,10 +161,12 @@ where .await?; let inputs_verified_tx = basically_verified_tx .perform_inputs_verifications(pool, consensus_params_version)?; + let fully_verified_tx = inputs_verified_tx.perform_input_computation_verifications( consensus_params, wasm_checker, memory, + view, )?; fully_verified_tx.into_pool_transaction(consensus_params_version) } diff --git a/crates/services/upgradable-executor/wasm-executor/Cargo.toml b/crates/services/upgradable-executor/wasm-executor/Cargo.toml index 687a338e046..6b64b98d698 100644 --- a/crates/services/upgradable-executor/wasm-executor/Cargo.toml +++ b/crates/services/upgradable-executor/wasm-executor/Cargo.toml @@ -33,7 +33,9 @@ fuel-core-types-v0 = { package = "fuel-core-types", version = "0.35.0", default- ], optional = true } postcard = { workspace = true } serde = { workspace = true } -serde_json = { workspace = true, default-features = false } +serde_json = { workspace = true, default-features = false, features = [ + "alloc", +] } [dev-dependencies] proptest = { workspace = true } diff --git a/crates/storage/src/lib.rs b/crates/storage/src/lib.rs index 8fd5a0a9b80..c54fbf889b8 100644 --- a/crates/storage/src/lib.rs +++ b/crates/storage/src/lib.rs @@ -27,6 +27,7 @@ use alloc::{ pub use fuel_vm_private::{ fuel_storage::*, storage::{ + predicate::PredicateStorageRequirements, ContractsAssetsStorage, InterpreterStorage, }, diff --git a/crates/storage/src/structured_storage.rs b/crates/storage/src/structured_storage.rs index 507cd1f26d0..e78e9637484 100644 --- a/crates/storage/src/structured_storage.rs +++ b/crates/storage/src/structured_storage.rs @@ -47,13 +47,23 @@ use crate::{ use core::ops::Deref; #[cfg(feature = "std")] -use std::borrow::Cow; +use std::{ + borrow::Cow, + fmt::Debug, +}; #[cfg(not(feature = "std"))] -use alloc::borrow::Cow; +use alloc::{ + borrow::Cow, + fmt::Debug, +}; #[cfg(feature = "alloc")] use alloc::vec::Vec; +use fuel_vm_private::storage::{ + predicate::PredicateStorageRequirements, + BlobData, +}; pub mod balances; pub mod blobs; @@ -144,6 +154,16 @@ where } } +impl PredicateStorageRequirements for StructuredStorage +where + Self: StorageRead, + Self::Error: Debug, +{ + fn storage_error_to_string(error: Self::Error) -> alloc::string::String { + alloc::format!("{:?}", error) + } +} + impl KeyValueMutate for StructuredStorage where S: KeyValueMutate, diff --git a/crates/types/src/blockchain/primitives.rs b/crates/types/src/blockchain/primitives.rs index 6d98e63e75d..f05826e186e 100644 --- a/crates/types/src/blockchain/primitives.rs +++ b/crates/types/src/blockchain/primitives.rs @@ -153,9 +153,7 @@ impl rand::distributions::Distribution for rand::distributions::S } /// Wrapper around [`fuel_crypto::SecretKey`] to implement [`secrecy`] marker traits -#[derive( - Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Zeroize, Deref, From, -)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Zeroize, Deref, From)] #[repr(transparent)] pub struct SecretKeyWrapper(SecretKey); diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 1f3d40ac444..7bf1d2b24ec 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -64,6 +64,7 @@ pub mod fuel_vm { }, script_with_data_offset, state, + storage::predicate, storage::ContractsAssetKey, storage::ContractsStateKey, storage::UploadedBytecode, diff --git a/tests/tests/blob.rs b/tests/tests/blob.rs index 1894970efc4..813dfea1418 100644 --- a/tests/tests/blob.rs +++ b/tests/tests/blob.rs @@ -1,6 +1,7 @@ #![allow(non_snake_case)] use fuel_core::{ + chain_config::StateConfig, database::{ database_description::on_chain::OnChain, Database, @@ -12,20 +13,36 @@ use fuel_core_client::client::{ types::TransactionStatus, FuelClient, }; +use fuel_core_storage::transactional::AtomicView; use fuel_core_types::{ fuel_asm::{ op, GTFArgs, + Instruction, RegId, }, fuel_tx::{ BlobBody, BlobId, BlobIdExt, + Finalizable, + Input, + Transaction, TransactionBuilder, }, fuel_types::canonical::Serialize, - fuel_vm::checked_transaction::IntoChecked, + fuel_vm::{ + checked_transaction::IntoChecked, + constraints::reg_key::{ + IS, + SSP, + ZERO, + }, + interpreter::{ + ExecutableTransaction, + MemoryInstance, + }, + }, }; use tokio::io; @@ -41,6 +58,10 @@ impl TestContext { ..Config::local_node() }; + Self::new_with_config(config).await + } + + async fn new_with_config(config: Config) -> Self { let node = FuelService::from_database(Database::::in_memory(), config) .await .unwrap(); @@ -55,23 +76,59 @@ impl TestContext { async fn new_blob( &mut self, blob_data: Vec, + ) -> io::Result<(TransactionStatus, BlobId)> { + self.new_blob_with_input(blob_data, None).await + } + + async fn new_blob_with_input( + &mut self, + blob_data: Vec, + input: Option, ) -> io::Result<(TransactionStatus, BlobId)> { let blob_id = BlobId::compute(&blob_data); - let tx = TransactionBuilder::blob(BlobBody { + let mut builder = TransactionBuilder::blob(BlobBody { id: blob_id, witness_index: 0, - }) - .add_witness(blob_data.into()) - .add_random_fee_input() - .finalize_as_transaction() - .into_checked(Default::default(), &Default::default()) - .expect("Cannot check transaction"); + }); + builder.add_witness(blob_data.into()); + + if let Some(input) = input { + builder.add_input(input); + } else { + builder.add_fee_input(); + } + + let tx = builder.finalize(); + let status = self.submit(tx).await?; + + Ok((status, blob_id)) + } + + async fn submit(&mut self, mut tx: Tx) -> io::Result + where + Tx: ExecutableTransaction, + { + let consensus_parameters = + self.client.chain_info().await.unwrap().consensus_parameters; + + let database = self._node.shared.database.on_chain().latest_view().unwrap(); + tx.estimate_predicates( + &consensus_parameters.clone().into(), + MemoryInstance::new(), + &database, + ) + .unwrap(); + + let tx: Transaction = tx.into(); + let tx = tx + .into_checked_basic(Default::default(), &consensus_parameters) + .expect("Cannot check transaction"); let status = self .client .submit_and_await_commit(tx.transaction()) .await?; - Ok((status, blob_id)) + Ok(status) } } @@ -99,7 +156,7 @@ async fn blob__upload_works() { blob_id.to_bytes(), ) .script_gas_limit(1000000) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let tx_status = ctx .client @@ -143,7 +200,7 @@ async fn blob__accessing_nonexitent_blob_panics_vm() { blob_id.to_bytes(), ) .script_gas_limit(1000000) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let tx_status = ctx .client @@ -175,3 +232,122 @@ async fn blob__can_be_queried_if_uploaded() { assert_eq!(queried_blob.id, blob_id); assert_eq!(queried_blob.bytecode, bytecode); } + +#[tokio::test] +async fn blob__exists_if_uploaded() { + // Given + let mut ctx = TestContext::new().await; + let bytecode: Vec = [op::ret(RegId::ONE)].into_iter().collect(); + let (status, blob_id) = ctx.new_blob(bytecode.clone()).await.unwrap(); + assert!(matches!(status, TransactionStatus::Success { .. })); + + // When + let blob_exists = ctx + .client + .blob_exists(blob_id) + .await + .expect("blob query failed"); + + // Then + assert!(blob_exists); +} + +#[tokio::test] +async fn blob__ask_whether_a_nonexisting_blob_exists() { + // Given + let ctx = TestContext::new().await; + + // When + let blob_exists = ctx + .client + .blob_exists(Default::default()) + .await + .expect("blob query failed"); + + // Then + assert!(!blob_exists); +} + +#[tokio::test] +async fn predicate_can_load_blob() { + let blob_predicate = vec![op::ret(RegId::ONE)].into_iter().collect::>(); + + // Use `LDC` with mode `1` to load the blob into the predicate. + let predicate = vec![ + // Take the pointer to the predicate data section + // where the blob ID is stored + op::gtf(0x10, ZERO, GTFArgs::InputCoinPredicateData as u16), + // Store the size of the blob + op::bsiz(0x11, 0x10), + // Store start of the blob code + op::move_(0x12, SSP), + // Subtract the start of the code from the end of the code + op::sub(0x12, 0x12, IS), + // Divide the code by the instruction size to get the number of + // instructions + op::divi(0x12, 0x12, Instruction::SIZE as u16), + // Load the blob by `0x10` ID with the `0x11` size + op::ldc(0x10, ZERO, 0x11, 1), + // Jump to a new code location + op::jmp(0x12), + ] + .into_iter() + .collect::>(); + + let owner = Input::predicate_owner(predicate.clone()); + let blob_owner = Input::predicate_owner(blob_predicate.clone()); + + let mut state = StateConfig::local_testnet(); + + state.coins[0].owner = blob_owner; + let blob_coin = state.coins[0].clone(); + let blob_input = Input::coin_predicate( + blob_coin.utxo_id(), + blob_owner, + blob_coin.amount, + blob_coin.asset_id, + Default::default(), + 0, + blob_predicate, + vec![], + ); + + state.coins[1].owner = owner; + let predicate_coin = state.coins[1].clone(); + + let mut config = Config::local_node_with_state_config(state); + config.debug = true; + config.utxo_validation = true; + + let mut ctx = TestContext::new_with_config(config).await; + + let bytecode: Vec = [op::ret(RegId::ONE)].into_iter().collect(); + let (status, blob_id) = ctx + .new_blob_with_input(bytecode.clone(), Some(blob_input)) + .await + .unwrap(); + assert!(matches!(status, TransactionStatus::Success { .. })); + + // Given + let predicate_data = blob_id.to_bytes(); + let predicate_input = Input::coin_predicate( + predicate_coin.utxo_id(), + owner, + predicate_coin.amount, + predicate_coin.asset_id, + Default::default(), + 0, + predicate, + predicate_data, + ); + + // When + let mut builder = TransactionBuilder::script(vec![], vec![]); + builder.add_input(predicate_input); + let tx_with_blobed_predicate = builder.finalize(); + let result = ctx.submit(tx_with_blobed_predicate).await; + + // Then + let status = result.expect("Transaction failed"); + assert!(matches!(status, TransactionStatus::Success { .. })); +} diff --git a/tests/tests/contract.rs b/tests/tests/contract.rs index 66fc7660e29..9a0fa4d213c 100644 --- a/tests/tests/contract.rs +++ b/tests/tests/contract.rs @@ -291,7 +291,7 @@ async fn can_get_message_proof() { // Create the contract deploy transaction. let mut contract_deploy = TransactionBuilder::create(bytecode, salt, vec![]) - .add_random_fee_input() + .add_fee_input() .add_output(output) .finalize_as_transaction(); diff --git a/tests/tests/da_compression.rs b/tests/tests/da_compression.rs index 1aadd50728e..43fce2a27e6 100644 --- a/tests/tests/da_compression.rs +++ b/tests/tests/da_compression.rs @@ -54,7 +54,7 @@ async fn can_fetch_da_compressed_block_from_graphql() { .max_fee_limit(0) .script_gas_limit(1_000_000) .with_gas_costs(GasCosts::free()) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let status = client.submit_and_await_commit(&tx).await.unwrap(); diff --git a/tests/tests/dos.rs b/tests/tests/dos.rs index 1bfc527555c..ef1174f264c 100644 --- a/tests/tests/dos.rs +++ b/tests/tests/dos.rs @@ -121,9 +121,7 @@ const FULL_BLOCK_QUERY: &str = r#" } ... on SuccessStatus { transactionId - block { - height - } + blockHeight time programState { returnType diff --git a/tests/tests/fee_collection_contract.rs b/tests/tests/fee_collection_contract.rs index 4105efc6202..54426b5c293 100644 --- a/tests/tests/fee_collection_contract.rs +++ b/tests/tests/fee_collection_contract.rs @@ -63,7 +63,7 @@ async fn setup(rng: &mut StdRng) -> TestContext { let state_root = Contract::default_state_root(); let contract_id = contract.id(&salt, &root, &state_root); let mut create_tx = TransactionBuilder::create(witness.clone(), salt, vec![]) - .add_random_fee_input() + .add_fee_input() .add_output(Output::contract_created(contract_id, state_root)) .finalize(); create_tx @@ -166,7 +166,7 @@ async fn collect_fees(ctx: &TestContext) { .chain(0u64.to_bytes().into_iter()) .collect(), ) - .add_random_fee_input() // No coinbase fee for this block + .add_fee_input() // No coinbase fee for this block .script_gas_limit(1_000_000) .add_input(Input::contract( Default::default(), @@ -298,7 +298,7 @@ async fn missing_variable_output() { .chain(0u64.to_bytes().into_iter()) .collect(), ) - .add_random_fee_input() // No coinbase fee for this block + .add_fee_input() // No coinbase fee for this block .script_gas_limit(1_000_000) .add_input(Input::contract( Default::default(), diff --git a/tests/tests/gas_price.rs b/tests/tests/gas_price.rs index ad982886c74..18507785eec 100644 --- a/tests/tests/gas_price.rs +++ b/tests/tests/gas_price.rs @@ -57,7 +57,7 @@ use test_helpers::fuel_core_driver::FuelCoreDriver; fn tx_for_gas_limit(max_fee_limit: Word) -> Transaction { TransactionBuilder::script(vec![], vec![]) .max_fee_limit(max_fee_limit) - .add_random_fee_input() + .add_fee_input() .finalize() .into() } @@ -309,7 +309,7 @@ async fn dry_run_opt__zero_gas_price_equal_to_none_gas_price() { op::ret(RegId::ONE).to_bytes().into_iter().collect(), vec![], ) - .add_random_fee_input() + .add_fee_input() .script_gas_limit(1000) .max_fee_limit(600000) .finalize_as_transaction(); diff --git a/tests/tests/messages.rs b/tests/tests/messages.rs index 84404041185..bee948105ea 100644 --- a/tests/tests/messages.rs +++ b/tests/tests/messages.rs @@ -355,7 +355,7 @@ async fn can_get_message_proof() { // Create the contract deploy transaction. let mut contract_deploy = TransactionBuilder::create(bytecode, salt, vec![]) - .add_random_fee_input() + .add_fee_input() .add_output(output) .finalize_as_transaction(); diff --git a/tests/tests/metrics.rs b/tests/tests/metrics.rs index 5e6a4da69dc..4cd577a9065 100644 --- a/tests/tests/metrics.rs +++ b/tests/tests/metrics.rs @@ -42,7 +42,7 @@ async fn test_metrics_endpoint() { .submit_and_await_commit( &TransactionBuilder::script(script, vec![]) .script_gas_limit(1000000) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(), ) .await diff --git a/tests/tests/trigger_integration/instant.rs b/tests/tests/trigger_integration/instant.rs index 3e9cc773e4d..df18da60190 100644 --- a/tests/tests/trigger_integration/instant.rs +++ b/tests/tests/trigger_integration/instant.rs @@ -50,7 +50,7 @@ async fn poa_instant_trigger_is_produces_instantly() { .collect(), vec![], ) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let _tx_id = client.submit(&tx).await.unwrap(); let count = client diff --git a/tests/tests/trigger_integration/never.rs b/tests/tests/trigger_integration/never.rs index 50cdda4af49..747df2e406d 100644 --- a/tests/tests/trigger_integration/never.rs +++ b/tests/tests/trigger_integration/never.rs @@ -43,7 +43,7 @@ async fn poa_never_trigger_doesnt_produce_blocks() { for i in 0..10 { let tx = TransactionBuilder::script([op::movi(0x10, i)].into_iter().collect(), vec![]) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let _tx_id = client.submit(&tx).await.unwrap(); tokio::time::advance(tokio::time::Duration::new(10, 0)).await; diff --git a/tests/tests/tx.rs b/tests/tests/tx.rs index 58acbaf0dfe..2d9bc81915f 100644 --- a/tests/tests/tx.rs +++ b/tests/tests/tx.rs @@ -96,7 +96,7 @@ async fn dry_run_script() { let tx = TransactionBuilder::script(script, vec![]) .script_gas_limit(gas_limit) .maturity(maturity) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let tx_statuses = client.dry_run(&[tx.clone()]).await.unwrap(); @@ -139,7 +139,7 @@ async fn dry_run_create() { let contract_id = contract.id(&salt, &root, &state_root); let tx = TransactionBuilder::create(contract_code.into(), salt, vec![]) - .add_random_fee_input() + .add_fee_input() .add_output(Output::contract_created(contract_id, state_root)) .finalize_as_transaction(); @@ -188,7 +188,7 @@ async fn dry_run_above_block_gas_limit() { let tx = TransactionBuilder::script(script, vec![]) .script_gas_limit(gas_limit) .maturity(maturity) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); // When @@ -352,7 +352,7 @@ async fn submit() { let tx = TransactionBuilder::script(script, vec![]) .script_gas_limit(gas_limit) .maturity(maturity) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); client.submit_and_await_commit(&tx).await.unwrap(); @@ -388,7 +388,7 @@ async fn submit_and_await_status() { let tx = TransactionBuilder::script(script, vec![]) .script_gas_limit(gas_limit) .maturity(maturity) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); let mut status_stream = client.submit_and_await_status(&tx).await.unwrap(); @@ -429,7 +429,7 @@ async fn dry_run_transaction_should_use_latest_block_time() { let tx = TransactionBuilder::script(script, vec![]) .script_gas_limit(gas_limit) .maturity(maturity) - .add_random_fee_input() + .add_fee_input() .finalize_as_transaction(); // When diff --git a/tests/tests/tx/predicates.rs b/tests/tests/tx/predicates.rs index 998b33f064c..7dc2ab190f7 100644 --- a/tests/tests/tx/predicates.rs +++ b/tests/tests/tx/predicates.rs @@ -17,6 +17,7 @@ use fuel_core_types::{ EstimatePredicates, }, interpreter::MemoryInstance, + predicate::EmptyStorage, }, }; use rand::{ @@ -72,6 +73,7 @@ async fn transaction_with_valid_predicate_is_executed() { .consensus_parameters, ), MemoryInstance::new(), + &EmptyStorage, ) .expect("Predicate check failed"); diff --git a/tests/tests/tx/txn_status_subscription.rs b/tests/tests/tx/txn_status_subscription.rs index f1bd14f2ffc..4dedfb47321 100644 --- a/tests/tests/tx/txn_status_subscription.rs +++ b/tests/tests/tx/txn_status_subscription.rs @@ -25,6 +25,7 @@ use fuel_core_types::{ EstimatePredicates, }, interpreter::MemoryInstance, + predicate::EmptyStorage, }, }; use futures::StreamExt; @@ -63,8 +64,12 @@ fn create_transaction(rng: &mut R, script: Vec) -> Transact .add_output(Output::coin(rng.gen(), 50, AssetId::default())) .add_output(Output::change(rng.gen(), 0, AssetId::default())) .finalize(); - tx.estimate_predicates(&CheckPredicateParams::default(), MemoryInstance::new()) - .expect("Predicate check failed"); + tx.estimate_predicates( + &CheckPredicateParams::default(), + MemoryInstance::new(), + &EmptyStorage, + ) + .expect("Predicate check failed"); tx.into() } @@ -116,8 +121,12 @@ async fn subscribe_txn_status() { ) .into(); // estimate predicate gas for coin_input predicate - tx.estimate_predicates(&CheckPredicateParams::default(), MemoryInstance::new()) - .expect("should estimate predicate"); + tx.estimate_predicates( + &CheckPredicateParams::default(), + MemoryInstance::new(), + &EmptyStorage, + ) + .expect("should estimate predicate"); tx }; diff --git a/tests/tests/tx/utxo_validation.rs b/tests/tests/tx/utxo_validation.rs index 286f5c096a4..afdbd95e4e5 100644 --- a/tests/tests/tx/utxo_validation.rs +++ b/tests/tests/tx/utxo_validation.rs @@ -110,7 +110,7 @@ async fn submit_utxo_verified_tx_below_min_gas_price_fails() { op::ret(RegId::ONE).to_bytes().into_iter().collect(), vec![], ) - .add_random_fee_input() + .add_fee_input() .script_gas_limit(100) .finalize_as_transaction();