From cb9d3243078c886dc427f29b71290afd93ac2fbe Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 21 Mar 2024 07:37:22 +0100 Subject: [PATCH 01/13] Versioned `GasCosts` --- .../transaction/consensus_parameters/gas.rs | 686 +++++++++++++++++- .../gas/default_gas_costs.rs | 3 +- fuel-tx/src/transaction/fee.rs | 8 +- fuel-tx/src/transaction/types/create.rs | 8 +- fuel-tx/src/transaction/types/script.rs | 2 +- fuel-vm/src/checked_transaction.rs | 64 +- fuel-vm/src/interpreter/blockchain.rs | 14 +- .../src/interpreter/blockchain/croo_tests.rs | 6 +- fuel-vm/src/interpreter/contract.rs | 4 +- .../src/interpreter/executors/instruction.rs | 206 +++--- fuel-vm/src/interpreter/flow.rs | 4 +- fuel-vm/src/tests/blockchain.rs | 8 +- fuel-vm/src/tests/external.rs | 2 +- fuel-vm/src/tests/metadata.rs | 4 +- 14 files changed, 849 insertions(+), 170 deletions(-) diff --git a/fuel-tx/src/transaction/consensus_parameters/gas.rs b/fuel-tx/src/transaction/consensus_parameters/gas.rs index 0238a4985a..884af6f3a0 100644 --- a/fuel-tx/src/transaction/consensus_parameters/gas.rs +++ b/fuel-tx/src/transaction/consensus_parameters/gas.rs @@ -198,12 +198,682 @@ impl Default for GasCostsValues { } } +/// The versioned gas costs for every op. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GasCostsValues { + /// Version 1 of the gas costs. + V1(GasCostsValuesV1), +} + +#[allow(missing_docs)] +impl GasCostsValues { + pub fn add(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.add, + } + } + + pub fn addi(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.addi, + } + } + + pub fn aloc(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.aloc, + } + } + + pub fn and(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.and, + } + } + + pub fn andi(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.andi, + } + } + + pub fn bal(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.bal, + } + } + + pub fn bhei(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.bhei, + } + } + + pub fn bhsh(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.bhsh, + } + } + + pub fn burn(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.burn, + } + } + + pub fn cb(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.cb, + } + } + + pub fn cfei(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.cfei, + } + } + + pub fn cfsi(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.cfsi, + } + } + + pub fn div(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.div, + } + } + + pub fn divi(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.divi, + } + } + + pub fn eck1(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.eck1, + } + } + + pub fn ecr1(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.ecr1, + } + } + + pub fn ed19(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.ed19, + } + } + + pub fn eq_(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.eq, + } + } + + pub fn exp(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.exp, + } + } + + pub fn expi(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.expi, + } + } + + pub fn flag(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.flag, + } + } + + pub fn gm(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.gm, + } + } + + pub fn gt(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.gt, + } + } + + pub fn gtf(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.gtf, + } + } + + pub fn ji(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.ji, + } + } + + pub fn jmp(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jmp, + } + } + + pub fn jne(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jne, + } + } + + pub fn jnei(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jnei, + } + } + + pub fn jnzi(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jnzi, + } + } + + pub fn jmpf(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jmpf, + } + } + + pub fn jmpb(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jmpb, + } + } + + pub fn jnzf(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jnzf, + } + } + + pub fn jnzb(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jnzb, + } + } + + pub fn jnef(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jnef, + } + } + + pub fn jneb(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.jneb, + } + } + + pub fn lb(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.lb, + } + } + + pub fn log(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.log, + } + } + + pub fn lt(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.lt, + } + } + + pub fn lw(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.lw, + } + } + + pub fn mint(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.mint, + } + } + + pub fn mlog(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.mlog, + } + } + + pub fn mod_op(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.mod_op, + } + } + + pub fn modi(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.modi, + } + } + + pub fn move_op(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.move_op, + } + } + + pub fn movi(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.movi, + } + } + + pub fn mroo(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.mroo, + } + } + + pub fn mul(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.mul, + } + } + + pub fn muli(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.muli, + } + } + + pub fn mldv(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.mldv, + } + } + + pub fn noop(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.noop, + } + } + + pub fn not(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.not, + } + } + + pub fn or(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.or, + } + } + + pub fn ori(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.ori, + } + } + + pub fn poph(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.poph, + } + } + + pub fn popl(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.popl, + } + } + + pub fn pshh(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.pshh, + } + } + + pub fn pshl(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.pshl, + } + } + + pub fn ret(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.ret, + } + } + + pub fn rvrt(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.rvrt, + } + } + + pub fn sb(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.sb, + } + } + + pub fn sll(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.sll, + } + } + + pub fn slli(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.slli, + } + } + + pub fn srl(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.srl, + } + } + + pub fn srli(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.srli, + } + } + + pub fn srw(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.srw, + } + } + + pub fn sub(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.sub, + } + } + + pub fn subi(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.subi, + } + } + + pub fn sw(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.sw, + } + } + + pub fn sww(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.sww, + } + } + + pub fn time(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.time, + } + } + + pub fn tr(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.tr, + } + } + + pub fn tro(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.tro, + } + } + + pub fn wdcm(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wdcm, + } + } + + pub fn wqcm(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wqcm, + } + } + + pub fn wdop(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wdop, + } + } + + pub fn wqop(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wqop, + } + } + + pub fn wdml(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wdml, + } + } + + pub fn wqml(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wqml, + } + } + + pub fn wddv(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wddv, + } + } + + pub fn wqdv(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wqdv, + } + } + + pub fn wdmd(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wdmd, + } + } + + pub fn wqmd(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wqmd, + } + } + + pub fn wdam(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wdam, + } + } + + pub fn wqam(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wqam, + } + } + + pub fn wdmm(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wdmm, + } + } + + pub fn wqmm(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.wqmm, + } + } + + pub fn xor(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.xor, + } + } + + pub fn xori(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.xori, + } + } + + pub fn call(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.call, + } + } + + pub fn ccp(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.ccp, + } + } + + pub fn croo(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.croo, + } + } + + pub fn csiz(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.csiz, + } + } + + pub fn k256(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.k256, + } + } + + pub fn ldc(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.ldc, + } + } + + pub fn logd(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.logd, + } + } + + pub fn mcl(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.mcl, + } + } + + pub fn mcli(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.mcli, + } + } + + pub fn mcp(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.mcp, + } + } + + pub fn mcpi(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.mcpi, + } + } + + pub fn meq(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.meq, + } + } + + pub fn retd(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.retd, + } + } + + pub fn s256(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.s256, + } + } + + pub fn scwq(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.scwq, + } + } + + pub fn smo(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.smo, + } + } + + pub fn srwq(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.srwq, + } + } + + pub fn swwq(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.swwq, + } + } + + pub fn contract_root(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.contract_root, + } + } + + pub fn state_root(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.state_root, + } + } + + pub fn new_storage_per_byte(&self) -> Word { + match self { + GasCostsValues::V1(v1) => v1.new_storage_per_byte, + } + } + + pub fn vm_initialization(&self) -> DependentCost { + match self { + GasCostsValues::V1(v1) => v1.vm_initialization, + } + } +} + /// Gas costs for every op. #[allow(missing_docs)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(default = "GasCostsValues::unit"))] -pub struct GasCostsValues { +pub struct GasCostsValuesV1 { pub add: Word, pub addi: Word, pub aloc: Word, @@ -367,7 +1037,7 @@ impl GasCosts { impl GasCostsValues { /// Create costs that are all set to zero. pub fn free() -> Self { - Self { + GasCostsValuesV1 { add: 0, addi: 0, aloc: 0, @@ -481,11 +1151,12 @@ impl GasCostsValues { new_storage_per_byte: 0, vm_initialization: DependentCost::free(), } + .into() } /// Create costs that are all set to one. pub fn unit() -> Self { - Self { + GasCostsValuesV1 { add: 1, addi: 1, aloc: 1, @@ -599,6 +1270,7 @@ impl GasCostsValues { new_storage_per_byte: 1, vm_initialization: DependentCost::unit(), } + .into() } } @@ -697,6 +1369,12 @@ impl From for GasCostsValues { } } +impl From for GasCostsValues { + fn from(i: GasCostsValuesV1) -> Self { + GasCostsValues::V1(i) + } +} + #[cfg(test)] mod tests { use crate::DependentCost; diff --git a/fuel-tx/src/transaction/consensus_parameters/gas/default_gas_costs.rs b/fuel-tx/src/transaction/consensus_parameters/gas/default_gas_costs.rs index 3b5f319a51..07f9f332b8 100644 --- a/fuel-tx/src/transaction/consensus_parameters/gas/default_gas_costs.rs +++ b/fuel-tx/src/transaction/consensus_parameters/gas/default_gas_costs.rs @@ -3,7 +3,7 @@ use super::*; /// hash pub const GIT: &str = "98341e564b75d1157e61d7d5f38612f6224a5b30"; pub fn default_gas_costs() -> GasCostsValues { - GasCostsValues { + GasCostsValuesV1 { add: 1, addi: 1, aloc: 1, @@ -180,4 +180,5 @@ pub fn default_gas_costs() -> GasCostsValues { gas_per_unit: 0, }, } + .into() } diff --git a/fuel-tx/src/transaction/fee.rs b/fuel-tx/src/transaction/fee.rs index 3d02de0764..e8e7289c92 100644 --- a/fuel-tx/src/transaction/fee.rs +++ b/fuel-tx/src/transaction/fee.rs @@ -124,7 +124,7 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies { let bytes_size = self.metered_bytes_size(); let vm_initialization_gas = - gas_costs.vm_initialization.resolve(bytes_size as Word); + gas_costs.vm_initialization().resolve(bytes_size as Word); let bytes_gas = bytes_size as u64 * fee.gas_per_byte; // It's okay to saturate because we have the `max_gas_per_tx` rule for transaction @@ -239,7 +239,7 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies { // Charge EC recovery cost for signed inputs Input::CoinSigned(_) | Input::MessageCoinSigned(_) - | Input::MessageDataSigned(_) => gas_costs.ecr1, + | Input::MessageDataSigned(_) => gas_costs.ecr1(), // Charge the cost of the contract root for predicate inputs Input::CoinPredicate(CoinPredicate { predicate, @@ -258,9 +258,9 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies { }) => { let bytes_size = self.metered_bytes_size(); let vm_initialization_gas = - gas_costs.vm_initialization.resolve(bytes_size as Word); + gas_costs.vm_initialization().resolve(bytes_size as Word); gas_costs - .contract_root + .contract_root() .resolve(predicate.len() as u64) .saturating_add(*predicate_gas_used) .saturating_add(vm_initialization_gas) diff --git a/fuel-tx/src/transaction/types/create.rs b/fuel-tx/src/transaction/types/create.rs index 2a47de14c9..63f1f56c34 100644 --- a/fuel-tx/src/transaction/types/create.rs +++ b/fuel-tx/src/transaction/types/create.rs @@ -174,19 +174,19 @@ impl Chargeable for Create { .map(|c| c.as_ref().len()) .unwrap_or(0); - let contract_root_gas = gas_costs.contract_root.resolve(contract_len as Word); + let contract_root_gas = gas_costs.contract_root().resolve(contract_len as Word); let state_root_length = storage_slots.len() as Word; - let state_root_gas = gas_costs.state_root.resolve(state_root_length); + let state_root_gas = gas_costs.state_root().resolve(state_root_length); // See https://github.com/FuelLabs/fuel-specs/blob/master/src/identifiers/contract-id.md let contract_id_input_length = core::mem::size_of::() + core::mem::size_of::() + core::mem::size_of::() + core::mem::size_of::(); - let contract_id_gas = gas_costs.s256.resolve(contract_id_input_length as Word); + let contract_id_gas = gas_costs.s256().resolve(contract_id_input_length as Word); let bytes = canonical::Serialize::size(self); // Gas required to calculate the `tx_id`. - let tx_id_gas = gas_costs.s256.resolve(bytes as u64); + let tx_id_gas = gas_costs.s256().resolve(bytes as u64); contract_root_gas .saturating_add(state_root_gas) diff --git a/fuel-tx/src/transaction/types/script.rs b/fuel-tx/src/transaction/types/script.rs index f5c79fdfbc..30a40579b8 100644 --- a/fuel-tx/src/transaction/types/script.rs +++ b/fuel-tx/src/transaction/types/script.rs @@ -161,7 +161,7 @@ impl Chargeable for Script { fn gas_used_by_metadata(&self, gas_cost: &GasCosts) -> Word { let bytes = Serialize::size(self); // Gas required to calculate the `tx_id`. - gas_cost.s256.resolve(bytes as u64) + gas_cost.s256().resolve(bytes as u64) } } diff --git a/fuel-vm/src/checked_transaction.rs b/fuel-vm/src/checked_transaction.rs index 13739e965f..187352d35b 100644 --- a/fuel-vm/src/checked_transaction.rs +++ b/fuel-vm/src/checked_transaction.rs @@ -1111,9 +1111,9 @@ mod tests { let min_fee = fee.min_fee(); let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte - + gas_costs.vm_initialization.resolve(tx.size() as u64) - + 3 * gas_costs.ecr1 - + gas_costs.s256.resolve(tx.size() as u64)) + + gas_costs.vm_initialization().resolve(tx.size() as u64) + + 3 * gas_costs.ecr1() + + gas_costs.s256().resolve(tx.size() as u64)) * gas_price; assert_eq!(min_fee, expected_min_fee); @@ -1164,9 +1164,9 @@ mod tests { // be recovered once. Therefore, we charge only once for the address // recovery of the signed inputs. let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte - + gas_costs.vm_initialization.resolve(tx.size() as u64) - + gas_costs.ecr1 - + gas_costs.s256.resolve(tx.size() as u64)) + + gas_costs.vm_initialization().resolve(tx.size() as u64) + + gas_costs.ecr1() + + gas_costs.s256().resolve(tx.size() as u64)) * gas_price; assert_eq!(min_fee, expected_min_fee); @@ -1230,15 +1230,15 @@ mod tests { let min_fee = fee.min_fee(); let expected_min_fee = (tx.size() as u64 * fee_params.gas_per_byte - + gas_costs.vm_initialization.resolve(tx.size() as u64) - + gas_costs.contract_root.resolve(predicate_1.len() as u64) - + gas_costs.contract_root.resolve(predicate_2.len() as u64) - + gas_costs.contract_root.resolve(predicate_3.len() as u64) - + 3 * gas_costs.vm_initialization.resolve(tx.size() as u64) + + gas_costs.vm_initialization().resolve(tx.size() as u64) + + gas_costs.contract_root().resolve(predicate_1.len() as u64) + + gas_costs.contract_root().resolve(predicate_2.len() as u64) + + gas_costs.contract_root().resolve(predicate_3.len() as u64) + + 3 * gas_costs.vm_initialization().resolve(tx.size() as u64) + 50 + 100 + 200 - + gas_costs.s256.resolve(tx.size() as u64)) + + gas_costs.s256().resolve(tx.size() as u64)) * gas_price; assert_eq!(min_fee, expected_min_fee); @@ -1316,16 +1316,16 @@ mod tests { let min_fee = fee.min_fee(); let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte - + 3 * gas_costs.ecr1 - + gas_costs.vm_initialization.resolve(tx.size() as u64) - + gas_costs.contract_root.resolve(predicate_1.len() as u64) - + gas_costs.contract_root.resolve(predicate_2.len() as u64) - + gas_costs.contract_root.resolve(predicate_3.len() as u64) - + 3 * gas_costs.vm_initialization.resolve(tx.size() as u64) + + 3 * gas_costs.ecr1() + + gas_costs.vm_initialization().resolve(tx.size() as u64) + + gas_costs.contract_root().resolve(predicate_1.len() as u64) + + gas_costs.contract_root().resolve(predicate_2.len() as u64) + + gas_costs.contract_root().resolve(predicate_3.len() as u64) + + 3 * gas_costs.vm_initialization().resolve(tx.size() as u64) + 50 + 100 + 200 - + gas_costs.s256.resolve(tx.size() as u64)) + + gas_costs.s256().resolve(tx.size() as u64)) * gas_price; assert_eq!(min_fee, expected_min_fee); @@ -1358,11 +1358,11 @@ mod tests { let min_fee = fee.min_fee(); let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte - + gas_costs.state_root.resolve(storage_slots_len as Word) - + gas_costs.contract_root.resolve(bytecode_len as Word) - + gas_costs.vm_initialization.resolve(tx.size() as u64) - + gas_costs.s256.resolve(100) - + gas_costs.s256.resolve(tx.size() as u64)) + + gas_costs.state_root().resolve(storage_slots_len as Word) + + gas_costs.contract_root().resolve(bytecode_len as Word) + + gas_costs.vm_initialization().resolve(tx.size() as u64) + + gas_costs.s256().resolve(100) + + gas_costs.s256().resolve(tx.size() as u64)) * gas_price; assert_eq!(min_fee, expected_min_fee); @@ -1392,11 +1392,11 @@ mod tests { let min_fee = fee.min_fee(); let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte - + gas_costs.state_root.resolve(0) - + gas_costs.contract_root.resolve(0) - + gas_costs.vm_initialization.resolve(tx.size() as u64) - + gas_costs.s256.resolve(100) - + gas_costs.s256.resolve(tx.size() as u64)) + + gas_costs.state_root().resolve(0) + + gas_costs.contract_root().resolve(0) + + gas_costs.vm_initialization().resolve(tx.size() as u64) + + gas_costs.s256().resolve(100) + + gas_costs.s256().resolve(tx.size() as u64)) * gas_price; assert_eq!(min_fee, expected_min_fee); @@ -1762,7 +1762,7 @@ mod tests { let block_height = 1.into(); let gas_costs = GasCosts::default(); - let tx = predicate_tx(&mut rng, 1000000, 1000000, 1000000, gas_costs.ret); + let tx = predicate_tx(&mut rng, 1000000, 1000000, 1000000, gas_costs.ret()); let consensus_params = ConsensusParameters { gas_costs, @@ -1810,7 +1810,7 @@ mod tests { .saturating_add(gas_used_by_metadata) .saturating_add( gas_costs - .vm_initialization + .vm_initialization() .resolve(tx.metered_bytes_size() as u64), ); @@ -1851,7 +1851,7 @@ mod tests { .saturating_add(gas_used_by_metadata) .saturating_add( gas_costs - .vm_initialization + .vm_initialization() .resolve(tx.metered_bytes_size() as u64), ); let total = gas as u128 * gas_price as u128; diff --git a/fuel-vm/src/interpreter/blockchain.rs b/fuel-vm/src/interpreter/blockchain.rs index 2c02cd97de..a77cc59cbb 100644 --- a/fuel-vm/src/interpreter/blockchain.rs +++ b/fuel-vm/src/interpreter/blockchain.rs @@ -103,7 +103,7 @@ where contract_offset: Word, length_unpadded: Word, ) -> IoResult<(), S::DataError> { - let gas_cost = self.gas_costs().ldc; + let gas_cost = self.gas_costs().ldc(); // Charge only for the `base` execution. // We will charge for the contracts size in the `load_contract_code`. self.gas_charge(gas_cost.base())?; @@ -164,7 +164,7 @@ where } pub(crate) fn mint(&mut self, a: Word, b: Word) -> IoResult<(), S::DataError> { - let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte; + let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte(); let ( SystemRegisters { cgas, @@ -199,7 +199,7 @@ where c: Word, d: Word, ) -> IoResult<(), S::DataError> { - let gas_cost = self.gas_costs().ccp; + let gas_cost = self.gas_costs().ccp(); // Charge only for the `base` execution. // We will charge for the contract's size in the `code_copy`. self.gas_charge(gas_cost.base())?; @@ -263,7 +263,7 @@ where } pub(crate) fn code_root(&mut self, a: Word, b: Word) -> IoResult<(), S::DataError> { - let gas_cost = self.gas_costs().croo; + let gas_cost = self.gas_costs().croo(); self.gas_charge(gas_cost.base())?; let current_contract = current_contract(&self.context, self.registers.fp(), self.memory.as_ref())? @@ -299,7 +299,7 @@ where ra: RegisterId, b: Word, ) -> IoResult<(), S::DataError> { - let gas_cost = self.gas_costs().csiz; + let gas_cost = self.gas_costs().csiz(); // Charge only for the `base` execution. // We will charge for the contracts size in the `code_size`. self.gas_charge(gas_cost.base())?; @@ -412,7 +412,7 @@ where rb: RegisterId, c: Word, ) -> IoResult<(), S::DataError> { - let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte; + let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte(); let ( SystemRegisters { cgas, @@ -458,7 +458,7 @@ where c: Word, d: Word, ) -> IoResult<(), S::DataError> { - let new_storage_per_byte = self.gas_costs().new_storage_per_byte; + let new_storage_per_byte = self.gas_costs().new_storage_per_byte(); let contract_id = self.internal_contract().copied(); let ( SystemRegisters { diff --git a/fuel-vm/src/interpreter/blockchain/croo_tests.rs b/fuel-vm/src/interpreter/blockchain/croo_tests.rs index 4587845fe4..f77db532ad 100644 --- a/fuel-vm/src/interpreter/blockchain/croo_tests.rs +++ b/fuel-vm/src/interpreter/blockchain/croo_tests.rs @@ -65,7 +65,7 @@ fn test_code_root() { .storage_contract_insert(&contract_id, &contract) .expect("Failed to insert contract"); - let gas_cost = GasCosts::default().croo; + let gas_cost = GasCosts::default().croo(); let ownership_registers = initialize_ownership_registers(); let SystemRegisters { mut pc, @@ -118,7 +118,7 @@ fn test_code_root_contract_not_found() { let mut memory: Memory = vec![1u8; MEM_SIZE].try_into().unwrap(); memory[0..ContractId::LEN].copy_from_slice(contract_id.as_slice()); - let gas_cost = GasCosts::default().croo; + let gas_cost = GasCosts::default().croo(); let ownership_registers = initialize_ownership_registers(); let SystemRegisters { mut pc, @@ -165,7 +165,7 @@ fn test_code_root_contract_not_in_inputs() { let mut memory: Memory = vec![1u8; MEM_SIZE].try_into().unwrap(); memory[0..ContractId::LEN].copy_from_slice(contract_id.as_slice()); - let gas_cost = GasCosts::default().croo; + let gas_cost = GasCosts::default().croo(); let ownership_registers = initialize_ownership_registers(); let SystemRegisters { mut pc, diff --git a/fuel-vm/src/interpreter/contract.rs b/fuel-vm/src/interpreter/contract.rs index d407070a8b..06f8012fcc 100644 --- a/fuel-vm/src/interpreter/contract.rs +++ b/fuel-vm/src/interpreter/contract.rs @@ -95,7 +95,7 @@ where b: Word, c: Word, ) -> IoResult<(), S::DataError> { - let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte; + let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte(); let tx_offset = self.tx_offset(); let ( SystemRegisters { @@ -135,7 +135,7 @@ where d: Word, ) -> IoResult<(), S::DataError> { let tx_offset = self.tx_offset(); - let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte; + let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte(); let ( SystemRegisters { cgas, diff --git a/fuel-vm/src/interpreter/executors/instruction.rs b/fuel-vm/src/interpreter/executors/instruction.rs index 6a2e90d31b..f231025da3 100644 --- a/fuel-vm/src/interpreter/executors/instruction.rs +++ b/fuel-vm/src/interpreter/executors/instruction.rs @@ -114,7 +114,7 @@ where match instruction { Instruction::ADD(add) => { - self.gas_charge(self.gas_costs().add)?; + self.gas_charge(self.gas_costs().add())?; let (a, b, c) = add.unpack(); self.alu_capture_overflow( a.into(), @@ -125,7 +125,7 @@ where } Instruction::ADDI(addi) => { - self.gas_charge(self.gas_costs().addi)?; + self.gas_charge(self.gas_costs().addi())?; let (a, b, imm) = addi.unpack(); self.alu_capture_overflow( a.into(), @@ -136,64 +136,64 @@ where } Instruction::AND(and) => { - self.gas_charge(self.gas_costs().and)?; + self.gas_charge(self.gas_costs().and())?; let (a, b, c) = and.unpack(); self.alu_set(a.into(), r!(b) & r!(c))?; } Instruction::ANDI(andi) => { - self.gas_charge(self.gas_costs().andi)?; + self.gas_charge(self.gas_costs().andi())?; let (a, b, imm) = andi.unpack(); self.alu_set(a.into(), r!(b) & Word::from(imm))?; } Instruction::DIV(div) => { - self.gas_charge(self.gas_costs().div)?; + self.gas_charge(self.gas_costs().div())?; let (a, b, c) = div.unpack(); let c = r!(c); self.alu_error(a.into(), Word::div, r!(b), c, c == 0)?; } Instruction::DIVI(divi) => { - self.gas_charge(self.gas_costs().divi)?; + self.gas_charge(self.gas_costs().divi())?; let (a, b, imm) = divi.unpack(); let imm = Word::from(imm); self.alu_error(a.into(), Word::div, r!(b), imm, imm == 0)?; } Instruction::EQ(eq) => { - self.gas_charge(self.gas_costs().eq)?; + self.gas_charge(self.gas_costs().eq_())?; let (a, b, c) = eq.unpack(); self.alu_set(a.into(), (r!(b) == r!(c)) as Word)?; } Instruction::EXP(exp) => { - self.gas_charge(self.gas_costs().exp)?; + self.gas_charge(self.gas_costs().exp())?; let (a, b, c) = exp.unpack(); self.alu_boolean_overflow(a.into(), alu::exp, r!(b), r!(c))?; } Instruction::EXPI(expi) => { - self.gas_charge(self.gas_costs().expi)?; + self.gas_charge(self.gas_costs().expi())?; let (a, b, imm) = expi.unpack(); let expo = u32::from(imm); self.alu_boolean_overflow(a.into(), Word::overflowing_pow, r!(b), expo)?; } Instruction::GT(gt) => { - self.gas_charge(self.gas_costs().gt)?; + self.gas_charge(self.gas_costs().gt())?; let (a, b, c) = gt.unpack(); self.alu_set(a.into(), (r!(b) > r!(c)) as Word)?; } Instruction::LT(lt) => { - self.gas_charge(self.gas_costs().lt)?; + self.gas_charge(self.gas_costs().lt())?; let (a, b, c) = lt.unpack(); self.alu_set(a.into(), (r!(b) < r!(c)) as Word)?; } Instruction::WDCM(wdcm) => { - self.gas_charge(self.gas_costs().wdcm)?; + self.gas_charge(self.gas_costs().wdcm())?; let (a, b, c, imm) = wdcm.unpack(); let args = wideint::CompareArgs::from_imm(imm) .ok_or(PanicReason::InvalidImmediateValue)?; @@ -201,7 +201,7 @@ where } Instruction::WQCM(wdcm) => { - self.gas_charge(self.gas_costs().wqcm)?; + self.gas_charge(self.gas_costs().wqcm())?; let (a, b, c, imm) = wdcm.unpack(); let args = wideint::CompareArgs::from_imm(imm) .ok_or(PanicReason::InvalidImmediateValue)?; @@ -209,7 +209,7 @@ where } Instruction::WDOP(wdop) => { - self.gas_charge(self.gas_costs().wdcm)?; + self.gas_charge(self.gas_costs().wdcm())?; let (a, b, c, imm) = wdop.unpack(); let args = wideint::MathArgs::from_imm(imm) .ok_or(PanicReason::InvalidImmediateValue)?; @@ -217,7 +217,7 @@ where } Instruction::WQOP(wqop) => { - self.gas_charge(self.gas_costs().wqcm)?; + self.gas_charge(self.gas_costs().wqcm())?; let (a, b, c, imm) = wqop.unpack(); let args = wideint::MathArgs::from_imm(imm) .ok_or(PanicReason::InvalidImmediateValue)?; @@ -225,7 +225,7 @@ where } Instruction::WDML(wdml) => { - self.gas_charge(self.gas_costs().wdml)?; + self.gas_charge(self.gas_costs().wdml())?; let (a, b, c, imm) = wdml.unpack(); let args = wideint::MulArgs::from_imm(imm) .ok_or(PanicReason::InvalidImmediateValue)?; @@ -233,7 +233,7 @@ where } Instruction::WQML(wqml) => { - self.gas_charge(self.gas_costs().wqml)?; + self.gas_charge(self.gas_costs().wqml())?; let (a, b, c, imm) = wqml.unpack(); let args = wideint::MulArgs::from_imm(imm) .ok_or(PanicReason::InvalidImmediateValue)?; @@ -241,7 +241,7 @@ where } Instruction::WDDV(wddv) => { - self.gas_charge(self.gas_costs().wddv)?; + self.gas_charge(self.gas_costs().wddv())?; let (a, b, c, imm) = wddv.unpack(); let args = wideint::DivArgs::from_imm(imm) .ok_or(PanicReason::InvalidImmediateValue)?; @@ -249,7 +249,7 @@ where } Instruction::WQDV(wqdv) => { - self.gas_charge(self.gas_costs().wqdv)?; + self.gas_charge(self.gas_costs().wqdv())?; let (a, b, c, imm) = wqdv.unpack(); let args = wideint::DivArgs::from_imm(imm) .ok_or(PanicReason::InvalidImmediateValue)?; @@ -257,40 +257,40 @@ where } Instruction::WDMD(wdmd) => { - self.gas_charge(self.gas_costs().wdmd)?; + self.gas_charge(self.gas_costs().wdmd())?; let (a, b, c, d) = wdmd.unpack(); self.alu_wideint_muldiv_u128(r!(a), r!(b), r!(c), r!(d))?; } Instruction::WQMD(wqmd) => { - self.gas_charge(self.gas_costs().wqmd)?; + self.gas_charge(self.gas_costs().wqmd())?; let (a, b, c, d) = wqmd.unpack(); self.alu_wideint_muldiv_u256(r!(a), r!(b), r!(c), r!(d))?; } Instruction::WDAM(wdam) => { - self.gas_charge(self.gas_costs().wdam)?; + self.gas_charge(self.gas_costs().wdam())?; let (a, b, c, d) = wdam.unpack(); self.alu_wideint_addmod_u128(r!(a), r!(b), r!(c), r!(d))?; } Instruction::WQAM(wqam) => { - self.gas_charge(self.gas_costs().wqam)?; + self.gas_charge(self.gas_costs().wqam())?; let (a, b, c, d) = wqam.unpack(); self.alu_wideint_addmod_u256(r!(a), r!(b), r!(c), r!(d))?; } Instruction::WDMM(wdmm) => { - self.gas_charge(self.gas_costs().wdmm)?; + self.gas_charge(self.gas_costs().wdmm())?; let (a, b, c, d) = wdmm.unpack(); self.alu_wideint_mulmod_u128(r!(a), r!(b), r!(c), r!(d))?; } Instruction::WQMM(wqmm) => { - self.gas_charge(self.gas_costs().wqmm)?; + self.gas_charge(self.gas_costs().wqmm())?; let (a, b, c, d) = wqmm.unpack(); self.alu_wideint_mulmod_u256(r!(a), r!(b), r!(c), r!(d))?; } Instruction::MLOG(mlog) => { - self.gas_charge(self.gas_costs().mlog)?; + self.gas_charge(self.gas_costs().mlog())?; let (a, b, c) = mlog.unpack(); let (lhs, rhs) = (r!(b), r!(c)); self.alu_error( @@ -307,33 +307,33 @@ where } Instruction::MOD(mod_) => { - self.gas_charge(self.gas_costs().mod_op)?; + self.gas_charge(self.gas_costs().mod_op())?; let (a, b, c) = mod_.unpack(); let rhs = r!(c); self.alu_error(a.into(), Word::wrapping_rem, r!(b), rhs, rhs == 0)?; } Instruction::MODI(modi) => { - self.gas_charge(self.gas_costs().modi)?; + self.gas_charge(self.gas_costs().modi())?; let (a, b, imm) = modi.unpack(); let rhs = Word::from(imm); self.alu_error(a.into(), Word::wrapping_rem, r!(b), rhs, rhs == 0)?; } Instruction::MOVE(move_) => { - self.gas_charge(self.gas_costs().move_op)?; + self.gas_charge(self.gas_costs().move_op())?; let (a, b) = move_.unpack(); self.alu_set(a.into(), r!(b))?; } Instruction::MOVI(movi) => { - self.gas_charge(self.gas_costs().movi)?; + self.gas_charge(self.gas_costs().movi())?; let (a, imm) = movi.unpack(); self.alu_set(a.into(), Word::from(imm))?; } Instruction::MROO(mroo) => { - self.gas_charge(self.gas_costs().mroo)?; + self.gas_charge(self.gas_costs().mroo())?; let (a, b, c) = mroo.unpack(); let (lhs, rhs) = (r!(b), r!(c)); self.alu_error( @@ -350,7 +350,7 @@ where } Instruction::MUL(mul) => { - self.gas_charge(self.gas_costs().mul)?; + self.gas_charge(self.gas_costs().mul())?; let (a, b, c) = mul.unpack(); self.alu_capture_overflow( a.into(), @@ -361,7 +361,7 @@ where } Instruction::MULI(muli) => { - self.gas_charge(self.gas_costs().muli)?; + self.gas_charge(self.gas_costs().muli())?; let (a, b, imm) = muli.unpack(); self.alu_capture_overflow( a.into(), @@ -372,36 +372,36 @@ where } Instruction::MLDV(mldv) => { - self.gas_charge(self.gas_costs().mldv)?; + self.gas_charge(self.gas_costs().mldv())?; let (a, b, c, d) = mldv.unpack(); self.alu_muldiv(a.into(), r!(b), r!(c), r!(d))?; } Instruction::NOOP(_noop) => { - self.gas_charge(self.gas_costs().noop)?; + self.gas_charge(self.gas_costs().noop())?; self.alu_clear()?; } Instruction::NOT(not) => { - self.gas_charge(self.gas_costs().not)?; + self.gas_charge(self.gas_costs().not())?; let (a, b) = not.unpack(); self.alu_set(a.into(), !r!(b))?; } Instruction::OR(or) => { - self.gas_charge(self.gas_costs().or)?; + self.gas_charge(self.gas_costs().or())?; let (a, b, c) = or.unpack(); self.alu_set(a.into(), r!(b) | r!(c))?; } Instruction::ORI(ori) => { - self.gas_charge(self.gas_costs().ori)?; + self.gas_charge(self.gas_costs().ori())?; let (a, b, imm) = ori.unpack(); self.alu_set(a.into(), r!(b) | Word::from(imm))?; } Instruction::SLL(sll) => { - self.gas_charge(self.gas_costs().sll)?; + self.gas_charge(self.gas_costs().sll())?; let (a, b, c) = sll.unpack(); self.alu_set( @@ -415,14 +415,14 @@ where } Instruction::SLLI(slli) => { - self.gas_charge(self.gas_costs().slli)?; + self.gas_charge(self.gas_costs().slli())?; let (a, b, imm) = slli.unpack(); let rhs = u32::from(imm); self.alu_set(a.into(), r!(b).checked_shl(rhs).unwrap_or_default())?; } Instruction::SRL(srl) => { - self.gas_charge(self.gas_costs().srl)?; + self.gas_charge(self.gas_costs().srl())?; let (a, b, c) = srl.unpack(); self.alu_set( a.into(), @@ -435,14 +435,14 @@ where } Instruction::SRLI(srli) => { - self.gas_charge(self.gas_costs().srli)?; + self.gas_charge(self.gas_costs().srli())?; let (a, b, imm) = srli.unpack(); let rhs = u32::from(imm); self.alu_set(a.into(), r!(b).checked_shr(rhs).unwrap_or_default())?; } Instruction::SUB(sub) => { - self.gas_charge(self.gas_costs().sub)?; + self.gas_charge(self.gas_costs().sub())?; let (a, b, c) = sub.unpack(); self.alu_capture_overflow( a.into(), @@ -453,7 +453,7 @@ where } Instruction::SUBI(subi) => { - self.gas_charge(self.gas_costs().subi)?; + self.gas_charge(self.gas_costs().subi())?; let (a, b, imm) = subi.unpack(); self.alu_capture_overflow( a.into(), @@ -464,25 +464,25 @@ where } Instruction::XOR(xor) => { - self.gas_charge(self.gas_costs().xor)?; + self.gas_charge(self.gas_costs().xor())?; let (a, b, c) = xor.unpack(); self.alu_set(a.into(), r!(b) ^ r!(c))?; } Instruction::XORI(xori) => { - self.gas_charge(self.gas_costs().xori)?; + self.gas_charge(self.gas_costs().xori())?; let (a, b, imm) = xori.unpack(); self.alu_set(a.into(), r!(b) ^ Word::from(imm))?; } Instruction::JI(ji) => { - self.gas_charge(self.gas_costs().ji)?; + self.gas_charge(self.gas_costs().ji())?; let imm = ji.unpack(); self.jump(JumpArgs::new(JumpMode::Absolute).to_address(imm.into()))?; } Instruction::JNEI(jnei) => { - self.gas_charge(self.gas_costs().jnei)?; + self.gas_charge(self.gas_costs().jnei())?; let (a, b, imm) = jnei.unpack(); self.jump( JumpArgs::new(JumpMode::Absolute) @@ -492,7 +492,7 @@ where } Instruction::JNZI(jnzi) => { - self.gas_charge(self.gas_costs().jnzi)?; + self.gas_charge(self.gas_costs().jnzi())?; let (a, imm) = jnzi.unpack(); self.jump( JumpArgs::new(JumpMode::Absolute) @@ -502,13 +502,13 @@ where } Instruction::JMP(jmp) => { - self.gas_charge(self.gas_costs().jmp)?; + self.gas_charge(self.gas_costs().jmp())?; let a = jmp.unpack(); self.jump(JumpArgs::new(JumpMode::Absolute).to_address(r!(a)))?; } Instruction::JNE(jne) => { - self.gas_charge(self.gas_costs().jne)?; + self.gas_charge(self.gas_costs().jne())?; let (a, b, c) = jne.unpack(); self.jump( JumpArgs::new(JumpMode::Absolute) @@ -518,7 +518,7 @@ where } Instruction::JMPF(jmpf) => { - self.gas_charge(self.gas_costs().jmpf)?; + self.gas_charge(self.gas_costs().jmpf())?; let (a, offset) = jmpf.unpack(); self.jump( JumpArgs::new(JumpMode::RelativeForwards) @@ -528,7 +528,7 @@ where } Instruction::JMPB(jmpb) => { - self.gas_charge(self.gas_costs().jmpb)?; + self.gas_charge(self.gas_costs().jmpb())?; let (a, offset) = jmpb.unpack(); self.jump( JumpArgs::new(JumpMode::RelativeBackwards) @@ -538,7 +538,7 @@ where } Instruction::JNZF(jnzf) => { - self.gas_charge(self.gas_costs().jnzf)?; + self.gas_charge(self.gas_costs().jnzf())?; let (a, b, offset) = jnzf.unpack(); self.jump( JumpArgs::new(JumpMode::RelativeForwards) @@ -549,7 +549,7 @@ where } Instruction::JNZB(jnzb) => { - self.gas_charge(self.gas_costs().jnzb)?; + self.gas_charge(self.gas_costs().jnzb())?; let (a, b, offset) = jnzb.unpack(); self.jump( JumpArgs::new(JumpMode::RelativeBackwards) @@ -560,7 +560,7 @@ where } Instruction::JNEF(jnef) => { - self.gas_charge(self.gas_costs().jnef)?; + self.gas_charge(self.gas_costs().jnef())?; let (a, b, c, offset) = jnef.unpack(); self.jump( JumpArgs::new(JumpMode::RelativeForwards) @@ -571,7 +571,7 @@ where } Instruction::JNEB(jneb) => { - self.gas_charge(self.gas_costs().jneb)?; + self.gas_charge(self.gas_costs().jneb())?; let (a, b, c, offset) = jneb.unpack(); self.jump( JumpArgs::new(JumpMode::RelativeBackwards) @@ -582,7 +582,7 @@ where } Instruction::RET(ret) => { - self.gas_charge(self.gas_costs().ret)?; + self.gas_charge(self.gas_costs().ret())?; let a = ret.unpack(); let ra = r!(a); self.ret(ra)?; @@ -592,12 +592,12 @@ where Instruction::RETD(retd) => { let (a, b) = retd.unpack(); let len = r!(b); - self.dependent_gas_charge(self.gas_costs().retd, len)?; + self.dependent_gas_charge(self.gas_costs().retd(), len)?; return Ok(self.ret_data(r!(a), len).map(ExecuteState::ReturnData)?) } Instruction::RVRT(rvrt) => { - self.gas_charge(self.gas_costs().rvrt)?; + self.gas_charge(self.gas_costs().rvrt())?; let a = rvrt.unpack(); let ra = r!(a); self.revert(ra)?; @@ -606,72 +606,72 @@ where Instruction::SMO(smo) => { let (a, b, c, d) = smo.unpack(); - self.dependent_gas_charge(self.gas_costs().smo, r!(c))?; + self.dependent_gas_charge(self.gas_costs().smo(), r!(c))?; self.message_output(r!(a), r!(b), r!(c), r!(d))?; } Instruction::ALOC(aloc) => { - self.gas_charge(self.gas_costs().aloc)?; + self.gas_charge(self.gas_costs().aloc())?; let a = aloc.unpack(); self.malloc(r!(a))?; } Instruction::CFEI(cfei) => { - self.gas_charge(self.gas_costs().cfei)?; + self.gas_charge(self.gas_costs().cfei())?; let imm = cfei.unpack(); self.stack_pointer_overflow(Word::overflowing_add, imm.into())?; } Instruction::CFE(cfe) => { - self.gas_charge(self.gas_costs().cfei)?; + self.gas_charge(self.gas_costs().cfei())?; let a = cfe.unpack(); self.stack_pointer_overflow(Word::overflowing_add, r!(a))?; } Instruction::CFSI(cfsi) => { - self.gas_charge(self.gas_costs().cfsi)?; + self.gas_charge(self.gas_costs().cfsi())?; let imm = cfsi.unpack(); self.stack_pointer_overflow(Word::overflowing_sub, imm.into())?; } Instruction::CFS(cfs) => { - self.gas_charge(self.gas_costs().cfsi)?; + self.gas_charge(self.gas_costs().cfsi())?; let a = cfs.unpack(); self.stack_pointer_overflow(Word::overflowing_sub, r!(a))?; } Instruction::PSHL(pshl) => { - self.gas_charge(self.gas_costs().pshl)?; + self.gas_charge(self.gas_costs().pshl())?; let bitmask = pshl.unpack(); self.push_selected_registers(ProgramRegistersSegment::Low, bitmask)?; } Instruction::PSHH(pshh) => { - self.gas_charge(self.gas_costs().pshh)?; + self.gas_charge(self.gas_costs().pshh())?; let bitmask = pshh.unpack(); self.push_selected_registers(ProgramRegistersSegment::High, bitmask)?; } Instruction::POPL(popl) => { - self.gas_charge(self.gas_costs().popl)?; + self.gas_charge(self.gas_costs().popl())?; let bitmask = popl.unpack(); self.pop_selected_registers(ProgramRegistersSegment::Low, bitmask)?; } Instruction::POPH(poph) => { - self.gas_charge(self.gas_costs().poph)?; + self.gas_charge(self.gas_costs().poph())?; let bitmask = poph.unpack(); self.pop_selected_registers(ProgramRegistersSegment::High, bitmask)?; } Instruction::LB(lb) => { - self.gas_charge(self.gas_costs().lb)?; + self.gas_charge(self.gas_costs().lb())?; let (a, b, imm) = lb.unpack(); self.load_byte(a.into(), r!(b), imm.into())?; } Instruction::LW(lw) => { - self.gas_charge(self.gas_costs().lw)?; + self.gas_charge(self.gas_costs().lw())?; let (a, b, imm) = lw.unpack(); self.load_word(a.into(), r!(b), imm.into())?; } @@ -679,70 +679,70 @@ where Instruction::MCL(mcl) => { let (a, b) = mcl.unpack(); let len = r!(b); - self.dependent_gas_charge(self.gas_costs().mcl, len)?; + self.dependent_gas_charge(self.gas_costs().mcl(), len)?; self.memclear(r!(a), len)?; } Instruction::MCLI(mcli) => { let (a, imm) = mcli.unpack(); let len = Word::from(imm); - self.dependent_gas_charge(self.gas_costs().mcli, len)?; + self.dependent_gas_charge(self.gas_costs().mcli(), len)?; self.memclear(r!(a), len)?; } Instruction::MCP(mcp) => { let (a, b, c) = mcp.unpack(); let len = r!(c); - self.dependent_gas_charge(self.gas_costs().mcp, len)?; + self.dependent_gas_charge(self.gas_costs().mcp(), len)?; self.memcopy(r!(a), r!(b), len)?; } Instruction::MCPI(mcpi) => { let (a, b, imm) = mcpi.unpack(); let len = imm.into(); - self.dependent_gas_charge(self.gas_costs().mcpi, len)?; + self.dependent_gas_charge(self.gas_costs().mcpi(), len)?; self.memcopy(r!(a), r!(b), len)?; } Instruction::MEQ(meq) => { let (a, b, c, d) = meq.unpack(); let len = r!(d); - self.dependent_gas_charge(self.gas_costs().meq, len)?; + self.dependent_gas_charge(self.gas_costs().meq(), len)?; self.memeq(a.into(), r!(b), r!(c), len)?; } Instruction::SB(sb) => { - self.gas_charge(self.gas_costs().sb)?; + self.gas_charge(self.gas_costs().sb())?; let (a, b, imm) = sb.unpack(); self.store_byte(r!(a), r!(b), imm.into())?; } Instruction::SW(sw) => { - self.gas_charge(self.gas_costs().sw)?; + self.gas_charge(self.gas_costs().sw())?; let (a, b, imm) = sw.unpack(); self.store_word(r!(a), r!(b), imm.into())?; } Instruction::BAL(bal) => { - self.gas_charge(self.gas_costs().bal)?; + self.gas_charge(self.gas_costs().bal())?; let (a, b, c) = bal.unpack(); self.contract_balance(a.into(), r!(b), r!(c))?; } Instruction::BHEI(bhei) => { - self.gas_charge(self.gas_costs().bhei)?; + self.gas_charge(self.gas_costs().bhei())?; let a = bhei.unpack(); self.block_height(a.into())?; } Instruction::BHSH(bhsh) => { - self.gas_charge(self.gas_costs().bhsh)?; + self.gas_charge(self.gas_costs().bhsh())?; let (a, b) = bhsh.unpack(); self.block_hash(r!(a), r!(b))?; } Instruction::BURN(burn) => { - self.gas_charge(self.gas_costs().burn)?; + self.gas_charge(self.gas_costs().burn())?; let (a, b) = burn.unpack(); self.burn(r!(a), r!(b))?; } @@ -756,7 +756,7 @@ where } Instruction::CB(cb) => { - self.gas_charge(self.gas_costs().cb)?; + self.gas_charge(self.gas_costs().cb())?; let a = cb.unpack(); self.block_proposer(r!(a))?; } @@ -784,73 +784,73 @@ where } Instruction::LOG(log) => { - self.gas_charge(self.gas_costs().log)?; + self.gas_charge(self.gas_costs().log())?; let (a, b, c, d) = log.unpack(); self.log(r!(a), r!(b), r!(c), r!(d))?; } Instruction::LOGD(logd) => { let (a, b, c, d) = logd.unpack(); - self.dependent_gas_charge(self.gas_costs().logd, r!(d))?; + self.dependent_gas_charge(self.gas_costs().logd(), r!(d))?; self.log_data(r!(a), r!(b), r!(c), r!(d))?; } Instruction::MINT(mint) => { - self.gas_charge(self.gas_costs().mint)?; + self.gas_charge(self.gas_costs().mint())?; let (a, b) = mint.unpack(); self.mint(r!(a), r!(b))?; } Instruction::SCWQ(scwq) => { let (a, b, c) = scwq.unpack(); - self.dependent_gas_charge(self.gas_costs().scwq, r!(c))?; + self.dependent_gas_charge(self.gas_costs().scwq(), r!(c))?; self.state_clear_qword(r!(a), b.into(), r!(c))?; } Instruction::SRW(srw) => { - self.gas_charge(self.gas_costs().srw)?; + self.gas_charge(self.gas_costs().srw())?; let (a, b, c) = srw.unpack(); self.state_read_word(a.into(), b.into(), r!(c))?; } Instruction::SRWQ(srwq) => { let (a, b, c, d) = srwq.unpack(); - self.dependent_gas_charge(self.gas_costs().srwq, r!(d))?; + self.dependent_gas_charge(self.gas_costs().srwq(), r!(d))?; self.state_read_qword(r!(a), b.into(), r!(c), r!(d))?; } Instruction::SWW(sww) => { - self.gas_charge(self.gas_costs().sww)?; + self.gas_charge(self.gas_costs().sww())?; let (a, b, c) = sww.unpack(); self.state_write_word(r!(a), b.into(), r!(c))?; } Instruction::SWWQ(swwq) => { let (a, b, c, d) = swwq.unpack(); - self.dependent_gas_charge(self.gas_costs().swwq, r!(d))?; + self.dependent_gas_charge(self.gas_costs().swwq(), r!(d))?; self.state_write_qword(r!(a), b.into(), r!(c), r!(d))?; } Instruction::TIME(time) => { - self.gas_charge(self.gas_costs().time)?; + self.gas_charge(self.gas_costs().time())?; let (a, b) = time.unpack(); self.timestamp(a.into(), r!(b))?; } Instruction::ECK1(eck1) => { - self.gas_charge(self.gas_costs().eck1)?; + self.gas_charge(self.gas_costs().eck1())?; let (a, b, c) = eck1.unpack(); self.secp256k1_recover(r!(a), r!(b), r!(c))?; } Instruction::ECR1(ecr1) => { - self.gas_charge(self.gas_costs().ecr1)?; + self.gas_charge(self.gas_costs().ecr1())?; let (a, b, c) = ecr1.unpack(); self.secp256r1_recover(r!(a), r!(b), r!(c))?; } Instruction::ED19(ed19) => { - self.gas_charge(self.gas_costs().ed19)?; + self.gas_charge(self.gas_costs().ed19())?; let (a, b, c) = ed19.unpack(); self.ed25519_verify(r!(a), r!(b), r!(c))?; } @@ -858,43 +858,43 @@ where Instruction::K256(k256) => { let (a, b, c) = k256.unpack(); let len = r!(c); - self.dependent_gas_charge(self.gas_costs().k256, len)?; + self.dependent_gas_charge(self.gas_costs().k256(), len)?; self.keccak256(r!(a), r!(b), len)?; } Instruction::S256(s256) => { let (a, b, c) = s256.unpack(); let len = r!(c); - self.dependent_gas_charge(self.gas_costs().s256, len)?; + self.dependent_gas_charge(self.gas_costs().s256(), len)?; self.sha256(r!(a), r!(b), len)?; } Instruction::FLAG(flag) => { - self.gas_charge(self.gas_costs().flag)?; + self.gas_charge(self.gas_costs().flag())?; let a = flag.unpack(); self.set_flag(r!(a))?; } Instruction::GM(gm) => { - self.gas_charge(self.gas_costs().gm)?; + self.gas_charge(self.gas_costs().gm())?; let (a, imm) = gm.unpack(); self.metadata(a.into(), imm.into())?; } Instruction::GTF(gtf) => { - self.gas_charge(self.gas_costs().gtf)?; + self.gas_charge(self.gas_costs().gtf())?; let (a, b, imm) = gtf.unpack(); self.get_transaction_field(a.into(), r!(b), imm.into())?; } Instruction::TR(tr) => { - self.gas_charge(self.gas_costs().tr)?; + self.gas_charge(self.gas_costs().tr())?; let (a, b, c) = tr.unpack(); self.transfer(r!(a), r!(b), r!(c))?; } Instruction::TRO(tro) => { - self.gas_charge(self.gas_costs().tro)?; + self.gas_charge(self.gas_costs().tro())?; let (a, b, c, d) = tro.unpack(); self.transfer_output(r!(a), r!(b), r!(c), r!(d))?; } diff --git a/fuel-vm/src/interpreter/flow.rs b/fuel-vm/src/interpreter/flow.rs index 31de9d544a..de4db6fa42 100644 --- a/fuel-vm/src/interpreter/flow.rs +++ b/fuel-vm/src/interpreter/flow.rs @@ -368,8 +368,8 @@ where asset_id_mem_address, amount_of_gas_to_forward, }; - let gas_cost = self.gas_costs().call; - let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte; + let gas_cost = self.gas_costs().call(); + let new_storage_gas_per_byte = self.gas_costs().new_storage_per_byte(); // Charge only for the `base` execution. // We will charge for the frame size in the `prepare_call`. self.gas_charge(gas_cost.base())?; diff --git a/fuel-vm/src/tests/blockchain.rs b/fuel-vm/src/tests/blockchain.rs index cb89592c8f..ff7f983529 100644 --- a/fuel-vm/src/tests/blockchain.rs +++ b/fuel-vm/src/tests/blockchain.rs @@ -367,12 +367,12 @@ fn ldc__gas_cost_is_not_dependent_on_rC() { let mut client = MemoryClient::default(); let gas_costs = client.gas_costs(); - let ldc_cost = gas_costs.ldc; + let ldc_cost = gas_costs.ldc(); let ldc_dep_len = match ldc_cost { DependentCost::LightOperation { units_per_gas, .. } => units_per_gas, DependentCost::HeavyOperation { gas_per_unit, .. } => gas_per_unit, }; - let noop_cost = gas_costs.noop; + let noop_cost = gas_costs.noop(); let contract_size = 1000; let offset = 0; @@ -472,7 +472,7 @@ fn ldc__offset_affects_read_code() { let mut client = MemoryClient::default(); let gas_costs = client.gas_costs(); - let noop_cost = gas_costs.noop; + let noop_cost = gas_costs.noop(); let number_of_opcodes = 25; let offset = 0; @@ -504,7 +504,7 @@ fn ldc__cost_is_proportional_to_total_contracts_size_not_rC() { let mut client = MemoryClient::default(); let gas_costs = client.gas_costs(); - let ldc_cost = gas_costs.ldc; + let ldc_cost = gas_costs.ldc(); let ldc_dep_len = match ldc_cost { DependentCost::LightOperation { units_per_gas, .. } => units_per_gas, DependentCost::HeavyOperation { gas_per_unit, .. } => gas_per_unit, diff --git a/fuel-vm/src/tests/external.rs b/fuel-vm/src/tests/external.rs index d919c29d79..bd777abb62 100644 --- a/fuel-vm/src/tests/external.rs +++ b/fuel-vm/src/tests/external.rs @@ -32,7 +32,7 @@ impl ::fuel_vm::interpreter::EcalHandler for NoopEcal { _: RegId, _: RegId, ) -> ::fuel_vm::error::SimpleResult<()> { - vm.gas_charge(vm.gas_costs().noop) + vm.gas_charge(vm.gas_costs().noop()) } } diff --git a/fuel-vm/src/tests/metadata.rs b/fuel-vm/src/tests/metadata.rs index b9698ade7a..1590bb4c28 100644 --- a/fuel-vm/src/tests/metadata.rs +++ b/fuel-vm/src/tests/metadata.rs @@ -349,7 +349,7 @@ fn get_transaction_fields() { 1_500, rng.gen(), rng.gen(), - gas_costs.ret, + gas_costs.ret(), predicate.clone(), predicate_data.clone(), ); @@ -373,7 +373,7 @@ fn get_transaction_fields() { owner, 7_500, rng.gen(), - gas_costs.ret, + gas_costs.ret(), m_data.clone(), m_predicate.clone(), m_predicate_data.clone(), From 2feab9264ec0e06871640e95d7e34e1b72a596a6 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 21 Mar 2024 11:42:28 +0100 Subject: [PATCH 02/13] =?UTF-8?q?Versioned=20`ConsensusParameters`=D1=8E?= =?UTF-8?q?=20Reduced=20default=20`MAX=5FSIZE`=20to=20be=20110kb.=20Reduce?= =?UTF-8?q?d=20default=20`MAX=5FCONTRACT=5FSIZE`=20to=20be=20100kb.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fuel-tx/src/builder.rs | 33 ++- fuel-tx/src/lib.rs | 4 - fuel-tx/src/tests/valid_cases.rs | 1 + fuel-tx/src/tests/valid_cases/transaction.rs | 8 +- .../src/transaction/consensus_parameters.rs | 261 ++++++++++++------ fuel-tx/src/transaction/types/create.rs | 11 +- fuel-tx/src/transaction/types/mint.rs | 2 +- fuel-tx/src/transaction/validity.rs | 13 +- fuel-vm/src/checked_transaction.rs | 13 +- fuel-vm/src/checked_transaction/types.rs | 2 +- fuel-vm/src/interpreter/debug.rs | 8 +- .../instruction/tests/reserved_registers.rs | 6 +- fuel-vm/src/interpreter/internal/tests.rs | 4 +- fuel-vm/src/interpreter/memory/tests.rs | 18 +- fuel-vm/src/tests/blockchain.rs | 6 +- fuel-vm/src/tests/gas_factor.rs | 8 +- fuel-vm/src/tests/limits.rs | 6 +- fuel-vm/src/tests/outputs.rs | 1 + fuel-vm/src/tests/test_helpers.rs | 2 +- fuel-vm/src/tests/validation.rs | 6 +- fuel-vm/src/util.rs | 8 +- 21 files changed, 251 insertions(+), 170 deletions(-) diff --git a/fuel-tx/src/builder.rs b/fuel-tx/src/builder.rs index 1ac252ab91..e162053f94 100644 --- a/fuel-tx/src/builder.rs +++ b/fuel-tx/src/builder.rs @@ -228,7 +228,7 @@ impl TransactionBuilder { } pub fn with_tx_params(&mut self, tx_params: TxParameters) -> &mut Self { - self.params.tx_params = tx_params; + self.params.set_tx_params(tx_params); self } @@ -236,12 +236,12 @@ impl TransactionBuilder { &mut self, predicate_params: PredicateParameters, ) -> &mut Self { - self.params.predicate_params = predicate_params; + self.params.set_predicate_params(predicate_params); self } pub fn with_script_params(&mut self, script_params: ScriptParameters) -> &mut Self { - self.params.script_params = script_params; + self.params.set_script_params(script_params); self } @@ -249,22 +249,32 @@ impl TransactionBuilder { &mut self, contract_params: ContractParameters, ) -> &mut Self { - self.params.contract_params = contract_params; + self.params.set_contract_params(contract_params); self } pub fn with_fee_params(&mut self, fee_params: FeeParameters) -> &mut Self { - self.params.fee_params = fee_params; + self.params.set_fee_params(fee_params); self } - pub fn with_base_asset_id(&mut self, base_asset_id: AssetId) -> &mut Self { - self.params.base_asset_id = base_asset_id; + pub fn with_chain_id(&mut self, chain_id: ChainId) -> &mut Self { + self.params.set_chain_id(chain_id); self } pub fn with_gas_costs(&mut self, gas_costs: GasCosts) -> &mut Self { - self.params.gas_costs = gas_costs; + self.params.set_gas_costs(gas_costs); + self + } + + pub fn with_base_asset_id(&mut self, base_asset_id: AssetId) -> &mut Self { + self.params.set_base_asset_id(base_asset_id); + self + } + + pub fn with_block_gas_limit(&mut self, block_gas_limit: u64) -> &mut Self { + self.params.set_block_gas_limit(block_gas_limit); self } } @@ -288,11 +298,6 @@ impl TransactionBuilder { self } - pub fn with_chain_id(&mut self, chain_id: ChainId) -> &mut Self { - self.params.chain_id = chain_id; - self - } - pub fn maturity(&mut self, maturity: BlockHeight) -> &mut Self { self.tx.set_maturity(maturity); @@ -405,7 +410,7 @@ impl TransactionBuilder { let witness_len = u16::try_from(self.witnesses().len()) .expect("The number of witnesses can't exceed `u16::MAX`"); - if u32::from(witness_len) > self.params.tx_params.max_witnesses { + if u32::from(witness_len) > self.params.tx_params().max_witnesses { panic!("Max witnesses exceeded"); } diff --git a/fuel-tx/src/lib.rs b/fuel-tx/src/lib.rs index 341e0dc1bb..8647a1bf61 100644 --- a/fuel-tx/src/lib.rs +++ b/fuel-tx/src/lib.rs @@ -106,10 +106,6 @@ pub use transaction::{ UniqueIdentifier, }; -#[cfg(feature = "alloc")] -#[allow(deprecated)] -pub use transaction::consensus_parameters::default_parameters; - #[cfg(feature = "alloc")] pub use contract::Contract; diff --git a/fuel-tx/src/tests/valid_cases.rs b/fuel-tx/src/tests/valid_cases.rs index 2b45a89ee1..20dc9f6e06 100644 --- a/fuel-tx/src/tests/valid_cases.rs +++ b/fuel-tx/src/tests/valid_cases.rs @@ -38,6 +38,7 @@ pub fn test_params() -> ConsensusParameters { CHAIN_ID, Default::default(), Default::default(), + Default::default(), ) } diff --git a/fuel-tx/src/tests/valid_cases/transaction.rs b/fuel-tx/src/tests/valid_cases/transaction.rs index 868cdef02a..0a21013985 100644 --- a/fuel-tx/src/tests/valid_cases/transaction.rs +++ b/fuel-tx/src/tests/valid_cases/transaction.rs @@ -1006,7 +1006,9 @@ fn script__check__transaction_at_maximum_size_is_valid() { let block_height = 100.into(); let mut params = test_params(); let max_size = 1024usize; - params.tx_params.max_size = max_size as u64; + let mut tx_params = *params.tx_params(); + tx_params.max_size = max_size as u64; + params.set_tx_params(tx_params); let base_size = { let tx = TransactionBuilder::script(vec![], vec![]) @@ -1038,7 +1040,9 @@ fn script__check__transaction_exceeding_maximum_size_is_invalid() { let block_height = 100.into(); let mut params = test_params(); let max_size = 1024usize; - params.tx_params.max_size = max_size as u64; + let mut tx_params = *params.tx_params(); + tx_params.max_size = max_size as u64; + params.set_tx_params(tx_params); let base_size = { let tx = TransactionBuilder::script(vec![], vec![]) diff --git a/fuel-tx/src/transaction/consensus_parameters.rs b/fuel-tx/src/transaction/consensus_parameters.rs index de2202d233..26979c15d6 100644 --- a/fuel-tx/src/transaction/consensus_parameters.rs +++ b/fuel-tx/src/transaction/consensus_parameters.rs @@ -15,21 +15,14 @@ pub use gas::{ }; const MAX_GAS: u64 = 100_000_000; -const MAX_SIZE: u64 = 17 * 1024 * 1024; +const MAX_SIZE: u64 = 110 * 1024; -/// A collection of parameters for convenience +/// A versioned set of consensus parameters. #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(default))] -pub struct ConsensusParameters { - pub tx_params: TxParameters, - pub predicate_params: PredicateParameters, - pub script_params: ScriptParameters, - pub contract_params: ContractParameters, - pub fee_params: FeeParameters, - pub chain_id: ChainId, - pub gas_costs: GasCosts, - pub base_asset_id: AssetId, +pub enum ConsensusParameters { + /// Version 1 of the consensus parameters + V1(ConsensusParametersV1), } impl Default for ConsensusParameters { @@ -41,30 +34,12 @@ impl Default for ConsensusParameters { impl ConsensusParameters { /// Constructor for the `ConsensusParameters` with Standard values. pub fn standard() -> Self { - Self { - tx_params: TxParameters::DEFAULT, - predicate_params: PredicateParameters::DEFAULT, - script_params: ScriptParameters::DEFAULT, - contract_params: ContractParameters::DEFAULT, - fee_params: FeeParameters::DEFAULT, - chain_id: ChainId::default(), - gas_costs: GasCosts::default(), - base_asset_id: Default::default(), - } + ConsensusParametersV1::standard().into() } /// Constructor for the `ConsensusParameters` with Standard values around `ChainId`. pub fn standard_with_id(chain_id: ChainId) -> Self { - Self { - tx_params: TxParameters::DEFAULT, - predicate_params: PredicateParameters::DEFAULT, - script_params: ScriptParameters::DEFAULT, - contract_params: ContractParameters::DEFAULT, - fee_params: FeeParameters::DEFAULT, - chain_id, - gas_costs: GasCosts::default(), - base_asset_id: Default::default(), - } + ConsensusParametersV1::standard_with_id(chain_id).into() } /// Constructor for the `ConsensusParameters` @@ -77,8 +52,9 @@ impl ConsensusParameters { chain_id: ChainId, gas_costs: GasCosts, base_asset_id: AssetId, + block_gas_limit: u64, ) -> Self { - Self { + Self::V1(ConsensusParametersV1 { tx_params, predicate_params, script_params, @@ -87,46 +63,197 @@ impl ConsensusParameters { chain_id, gas_costs, base_asset_id, - } + block_gas_limit, + }) } /// Get the transaction parameters pub fn tx_params(&self) -> &TxParameters { - &self.tx_params + match self { + Self::V1(params) => ¶ms.tx_params, + } } /// Get the predicate parameters pub fn predicate_params(&self) -> &PredicateParameters { - &self.predicate_params + match self { + Self::V1(params) => ¶ms.predicate_params, + } } /// Get the script parameters pub fn script_params(&self) -> &ScriptParameters { - &self.script_params + match self { + Self::V1(params) => ¶ms.script_params, + } } /// Get the contract parameters pub fn contract_params(&self) -> &ContractParameters { - &self.contract_params + match self { + Self::V1(params) => ¶ms.contract_params, + } } /// Get the fee parameters pub fn fee_params(&self) -> &FeeParameters { - &self.fee_params - } - - pub fn base_asset_id(&self) -> &AssetId { - &self.base_asset_id + match self { + Self::V1(params) => ¶ms.fee_params, + } } /// Get the chain ID pub fn chain_id(&self) -> ChainId { - self.chain_id + match self { + Self::V1(params) => params.chain_id, + } } /// Get the gas costs pub fn gas_costs(&self) -> &GasCosts { - &self.gas_costs + match self { + Self::V1(params) => ¶ms.gas_costs, + } + } + + /// Get the base asset ID + pub fn base_asset_id(&self) -> &AssetId { + match self { + Self::V1(params) => ¶ms.base_asset_id, + } + } + + /// Get the block gas limit + pub fn block_gas_limit(&self) -> u64 { + match self { + Self::V1(params) => params.block_gas_limit, + } + } +} + +#[cfg(feature = "builder")] +impl ConsensusParameters { + /// Set the transaction parameters. + pub fn set_tx_params(&mut self, tx_params: TxParameters) { + match self { + Self::V1(params) => params.tx_params = tx_params, + } + } + + /// Set the predicate parameters. + pub fn set_predicate_params(&mut self, predicate_params: PredicateParameters) { + match self { + Self::V1(params) => params.predicate_params = predicate_params, + } + } + + /// Set the script parameters. + pub fn set_script_params(&mut self, script_params: ScriptParameters) { + match self { + Self::V1(params) => params.script_params = script_params, + } + } + + /// Set the contract parameters. + pub fn set_contract_params(&mut self, contract_params: ContractParameters) { + match self { + Self::V1(params) => params.contract_params = contract_params, + } + } + + /// Set the fee parameters. + pub fn set_fee_params(&mut self, fee_params: FeeParameters) { + match self { + Self::V1(params) => params.fee_params = fee_params, + } + } + + /// Set the chain ID. + pub fn set_chain_id(&mut self, chain_id: ChainId) { + match self { + Self::V1(params) => params.chain_id = chain_id, + } + } + + /// Set the gas costs. + pub fn set_gas_costs(&mut self, gas_costs: GasCosts) { + match self { + Self::V1(params) => params.gas_costs = gas_costs, + } + } + + /// Set the base asset ID. + pub fn set_base_asset_id(&mut self, base_asset_id: AssetId) { + match self { + Self::V1(params) => params.base_asset_id = base_asset_id, + } + } + + /// Set the block gas limit. + pub fn set_block_gas_limit(&mut self, block_gas_limit: u64) { + match self { + Self::V1(params) => params.block_gas_limit = block_gas_limit, + } + } +} + +/// A collection of parameters for convenience +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(default))] +pub struct ConsensusParametersV1 { + pub tx_params: TxParameters, + pub predicate_params: PredicateParameters, + pub script_params: ScriptParameters, + pub contract_params: ContractParameters, + pub fee_params: FeeParameters, + pub chain_id: ChainId, + pub gas_costs: GasCosts, + pub base_asset_id: AssetId, + pub block_gas_limit: u64, +} + +impl ConsensusParametersV1 { + /// Constructor for the `ConsensusParameters` with Standard values. + pub fn standard() -> Self { + Self { + tx_params: TxParameters::DEFAULT, + predicate_params: PredicateParameters::DEFAULT, + script_params: ScriptParameters::DEFAULT, + contract_params: ContractParameters::DEFAULT, + fee_params: FeeParameters::DEFAULT, + chain_id: ChainId::default(), + gas_costs: GasCosts::default(), + base_asset_id: Default::default(), + block_gas_limit: TxParameters::DEFAULT.max_gas_per_tx, + } + } + + /// Constructor for the `ConsensusParameters` with Standard values around `ChainId`. + pub fn standard_with_id(chain_id: ChainId) -> Self { + Self { + tx_params: TxParameters::DEFAULT, + predicate_params: PredicateParameters::DEFAULT, + script_params: ScriptParameters::DEFAULT, + contract_params: ContractParameters::DEFAULT, + fee_params: FeeParameters::DEFAULT, + chain_id, + gas_costs: GasCosts::default(), + base_asset_id: Default::default(), + block_gas_limit: TxParameters::DEFAULT.max_gas_per_tx, + } + } +} + +impl Default for ConsensusParametersV1 { + fn default() -> Self { + Self::standard() + } +} + +impl From for ConsensusParameters { + fn from(params: ConsensusParametersV1) -> Self { + Self::V1(params) } } @@ -346,7 +473,7 @@ pub struct ContractParameters { impl ContractParameters { /// Default consensus parameters with settings suggested in fuel-specs pub const DEFAULT: Self = Self { - contract_max_size: 16 * 1024 * 1024, + contract_max_size: 100 * 1024, max_storage_slots: 255, }; @@ -383,45 +510,3 @@ mod typescript { } } } - -/// Arbitrary default consensus parameters. While best-efforts are made to adjust these to -/// reasonable settings, they may not be useful for every network instantiation. -#[deprecated(since = "0.12.2", note = "use `ConsensusParameters` instead.")] -pub mod default_parameters { - use crate::{ - transaction::consensus_parameters::{ - PredicateParameters, - ScriptParameters, - TxParameters, - }, - ContractParameters, - FeeParameters, - }; - use fuel_types::ChainId; - - pub const CONTRACT_MAX_SIZE: u64 = ContractParameters::DEFAULT.contract_max_size; - pub const MAX_INPUTS: u16 = TxParameters::DEFAULT.max_inputs; - pub const MAX_OUTPUTS: u16 = TxParameters::DEFAULT.max_outputs; - pub const MAX_WITNESSES: u32 = TxParameters::DEFAULT.max_witnesses; - pub const MAX_GAS_PER_TX: u64 = TxParameters::DEFAULT.max_gas_per_tx; - - pub const MAX_SCRIPT_LENGTH: u64 = ScriptParameters::DEFAULT.max_script_length; - pub const MAX_SCRIPT_DATA_LENGTH: u64 = - ScriptParameters::DEFAULT.max_script_data_length; - - pub const MAX_STORAGE_SLOTS: u64 = ContractParameters::DEFAULT.max_storage_slots; - - pub const MAX_PREDICATE_LENGTH: u64 = - PredicateParameters::DEFAULT.max_predicate_length; - pub const MAX_PREDICATE_DATA_LENGTH: u64 = - PredicateParameters::DEFAULT.max_predicate_data_length; - pub const MAX_MESSAGE_DATA_LENGTH: u64 = - PredicateParameters::DEFAULT.max_message_data_length; - - pub const MAX_GAS_PER_PREDICATE: u64 = - PredicateParameters::DEFAULT.max_gas_per_predicate; - pub const GAS_PRICE_FACTOR: u64 = FeeParameters::DEFAULT.gas_price_factor; - pub const GAS_PER_BYTE: u64 = FeeParameters::DEFAULT.gas_per_byte; - - pub const CHAIN_ID: ChainId = ChainId::new(0); -} diff --git a/fuel-tx/src/transaction/types/create.rs b/fuel-tx/src/transaction/types/create.rs index 63f1f56c34..60ac6c8bc8 100644 --- a/fuel-tx/src/transaction/types/create.rs +++ b/fuel-tx/src/transaction/types/create.rs @@ -223,12 +223,9 @@ impl FormatValidityChecks for Create { block_height: BlockHeight, consensus_params: &ConsensusParameters, ) -> Result<(), ValidityError> { - let ConsensusParameters { - contract_params, - chain_id, - base_asset_id, - .. - } = consensus_params; + let contract_params = consensus_params.contract_params(); + let chain_id = consensus_params.chain_id(); + let base_asset_id = consensus_params.base_asset_id(); check_common_part(self, block_height, consensus_params)?; @@ -281,7 +278,7 @@ impl FormatValidityChecks for Create { if let Some(metadata) = &self.metadata { (metadata.state_root, metadata.contract_id) } else { - let metadata = CreateMetadata::compute(self, chain_id)?; + let metadata = CreateMetadata::compute(self, &chain_id)?; (metadata.state_root, metadata.contract_id) }; diff --git a/fuel-tx/src/transaction/types/mint.rs b/fuel-tx/src/transaction/types/mint.rs index efc7b0e242..9f63ddb00c 100644 --- a/fuel-tx/src/transaction/types/mint.rs +++ b/fuel-tx/src/transaction/types/mint.rs @@ -111,7 +111,7 @@ impl FormatValidityChecks for Mint { } // It is temporary check until https://github.com/FuelLabs/fuel-core/issues/1205 - if self.mint_asset_id != consensus_params.base_asset_id { + if &self.mint_asset_id != consensus_params.base_asset_id() { return Err(ValidityError::TransactionMintNonBaseAsset); } diff --git a/fuel-tx/src/transaction/validity.rs b/fuel-tx/src/transaction/validity.rs index 640dee10ac..fec1c5a8f6 100644 --- a/fuel-tx/src/transaction/validity.rs +++ b/fuel-tx/src/transaction/validity.rs @@ -317,14 +317,11 @@ pub(crate) fn check_common_part( where T: canonical::Serialize + Chargeable + field::Outputs, { - let ConsensusParameters { - tx_params, - predicate_params, - base_asset_id, - gas_costs, - fee_params, - .. - } = consensus_params; + let tx_params = consensus_params.tx_params(); + let predicate_params = consensus_params.predicate_params(); + let base_asset_id = consensus_params.base_asset_id(); + let gas_costs = consensus_params.gas_costs(); + let fee_params = consensus_params.fee_params(); check_size(tx, tx_params)?; diff --git a/fuel-vm/src/checked_transaction.rs b/fuel-vm/src/checked_transaction.rs index 187352d35b..b285c7499d 100644 --- a/fuel-vm/src/checked_transaction.rs +++ b/fuel-vm/src/checked_transaction.rs @@ -297,7 +297,7 @@ pub trait IntoChecked: FormatValidityChecks + Sized { { let check_predicate_params = consensus_params.into(); self.into_checked_basic(block_height, consensus_params)? - .check_signatures(&consensus_params.chain_id)? + .check_signatures(&consensus_params.chain_id())? .check_predicates(&check_predicate_params) } @@ -350,7 +350,7 @@ impl From<&ConsensusParameters> for CheckPredicateParams { fn from(value: &ConsensusParameters) -> Self { CheckPredicateParams { gas_costs: value.gas_costs().clone(), - chain_id: value.chain_id, + chain_id: value.chain_id(), max_gas_per_predicate: value.predicate_params().max_gas_per_predicate, max_gas_per_tx: value.tx_params().max_gas_per_tx, max_inputs: value.tx_params().max_inputs, @@ -358,7 +358,7 @@ impl From<&ConsensusParameters> for CheckPredicateParams { max_message_data_length: value.predicate_params().max_message_data_length, tx_offset: value.tx_params().tx_offset(), fee_params: *(value.fee_params()), - base_asset_id: value.base_asset_id, + base_asset_id: *value.base_asset_id(), } } } @@ -765,6 +765,7 @@ mod tests { Default::default(), Default::default(), Default::default(), + Default::default(), ) } @@ -1764,10 +1765,8 @@ mod tests { let tx = predicate_tx(&mut rng, 1000000, 1000000, 1000000, gas_costs.ret()); - let consensus_params = ConsensusParameters { - gas_costs, - ..ConsensusParameters::standard() - }; + let mut consensus_params = ConsensusParameters::standard(); + consensus_params.set_gas_costs(gas_costs); let check_predicate_params = CheckPredicateParams::from(&consensus_params); diff --git a/fuel-vm/src/checked_transaction/types.rs b/fuel-vm/src/checked_transaction/types.rs index e7705f0160..f7bb20a373 100644 --- a/fuel-vm/src/checked_transaction/types.rs +++ b/fuel-vm/src/checked_transaction/types.rs @@ -218,7 +218,7 @@ pub mod script { non_retryable_balances: NonRetryableFreeBalances(non_retryable_balances), retryable_balance: RetryableAmount { amount: retryable_balance, - base_asset_id: consensus_params.base_asset_id, + base_asset_id: *consensus_params.base_asset_id(), }, block_height, min_gas: self diff --git a/fuel-vm/src/interpreter/debug.rs b/fuel-vm/src/interpreter/debug.rs index 888ce4ee07..1e33b97d7e 100644 --- a/fuel-vm/src/interpreter/debug.rs +++ b/fuel-vm/src/interpreter/debug.rs @@ -95,8 +95,8 @@ fn breakpoint_script() { .expect("failed to generate checked tx") .into_ready( gas_price, - &consensus_params.gas_costs, - &consensus_params.fee_params, + consensus_params.gas_costs(), + consensus_params.fee_params(), ) .unwrap(); @@ -174,8 +174,8 @@ fn single_stepping() { .expect("failed to generate checked tx") .into_ready( gas_price, - &consensus_params.gas_costs, - &consensus_params.fee_params, + consensus_params.gas_costs(), + consensus_params.fee_params(), ) .unwrap(); diff --git a/fuel-vm/src/interpreter/executors/instruction/tests/reserved_registers.rs b/fuel-vm/src/interpreter/executors/instruction/tests/reserved_registers.rs index b7b54d406d..ecc4e4f8ee 100644 --- a/fuel-vm/src/interpreter/executors/instruction/tests/reserved_registers.rs +++ b/fuel-vm/src/interpreter/executors/instruction/tests/reserved_registers.rs @@ -50,10 +50,8 @@ fn cant_write_to_reserved_registers(raw_random_instruction: u32) -> TestResult { } let fee_params = FeeParameters::default().with_gas_price_factor(1); - let consensus_params = ConsensusParameters { - fee_params, - ..Default::default() - }; + let mut consensus_params = ConsensusParameters::default(); + consensus_params.set_fee_params(fee_params); let mut vm = Interpreter::<_, _>::with_storage( MemoryStorage::default(), diff --git a/fuel-vm/src/interpreter/internal/tests.rs b/fuel-vm/src/interpreter/internal/tests.rs index e2e9ae5259..39286bc3d6 100644 --- a/fuel-vm/src/interpreter/internal/tests.rs +++ b/fuel-vm/src/interpreter/internal/tests.rs @@ -37,7 +37,7 @@ fn external_balance() { let height = Default::default(); let gas_price = 0; let gas_costs = GasCosts::default(); - let fee_params = ConsensusParameters::standard().fee_params; + let fee_params = *ConsensusParameters::standard().fee_params(); let script = op::ret(0x01).to_bytes().to_vec(); let balances = vec![(rng.gen(), 100), (rng.gen(), 500)]; @@ -132,7 +132,7 @@ fn variable_output_updates_in_memory() { .into_ready( zero_gas_price, &GasCosts::default(), - &consensus_params.fee_params, + consensus_params.fee_params(), ) .unwrap(); diff --git a/fuel-vm/src/interpreter/memory/tests.rs b/fuel-vm/src/interpreter/memory/tests.rs index 1122417296..1d4e8857bb 100644 --- a/fuel-vm/src/interpreter/memory/tests.rs +++ b/fuel-vm/src/interpreter/memory/tests.rs @@ -18,10 +18,8 @@ fn memcopy() { let tx_params = TxParameters::default().with_max_gas_per_tx(Word::MAX / 2); let zero_gas_price = 0; - let consensus_params = ConsensusParameters { - tx_params, - ..Default::default() - }; + let mut consensus_params = ConsensusParameters::default(); + consensus_params.set_tx_params(tx_params); let mut vm = Interpreter::<_, _>::with_storage( MemoryStorage::default(), @@ -37,8 +35,8 @@ fn memcopy() { .expect("default tx should produce a valid checked transaction") .into_ready( zero_gas_price, - &consensus_params.gas_costs, - &consensus_params.fee_params, + consensus_params.gas_costs(), + consensus_params.fee_params(), ) .unwrap(); @@ -102,8 +100,8 @@ fn memrange() { .expect("Empty script should be valid") .into_ready( gas_price, - &consensus_params.gas_costs, - &consensus_params.fee_params, + consensus_params.gas_costs(), + consensus_params.fee_params(), ) .unwrap(); let mut vm = Interpreter::<_, _>::with_memory_storage(); @@ -140,8 +138,8 @@ fn stack_alloc_ownership() { .expect("Empty script should be valid") .into_ready( gas_price, - &consensus_params.gas_costs, - &consensus_params.fee_params, + consensus_params.gas_costs(), + consensus_params.fee_params(), ) .unwrap(); vm.init_script(tx).expect("Failed to init VM"); diff --git a/fuel-vm/src/tests/blockchain.rs b/fuel-vm/src/tests/blockchain.rs index ff7f983529..0492b0ee7e 100644 --- a/fuel-vm/src/tests/blockchain.rs +++ b/fuel-vm/src/tests/blockchain.rs @@ -701,10 +701,8 @@ fn ldc_reason_helper(cmd: Vec, expected_reason: PanicReason) { // make gas costs free let gas_costs = GasCosts::default(); - let consensus_params = ConsensusParameters { - gas_costs, - ..Default::default() - }; + let mut consensus_params = ConsensusParameters::default(); + consensus_params.set_gas_costs(gas_costs); let interpreter_params = InterpreterParams::new(gas_price, &consensus_params); diff --git a/fuel-vm/src/tests/gas_factor.rs b/fuel-vm/src/tests/gas_factor.rs index d783818514..a7440cd5a6 100644 --- a/fuel-vm/src/tests/gas_factor.rs +++ b/fuel-vm/src/tests/gas_factor.rs @@ -49,11 +49,9 @@ fn gas_factor_rounds_correctly() { let profiler = GasProfiler::default(); - let consensus_params = ConsensusParameters { - fee_params, - gas_costs, - ..ConsensusParameters::standard() - }; + let mut consensus_params = ConsensusParameters::standard(); + consensus_params.set_gas_costs(gas_costs); + consensus_params.set_fee_params(fee_params); let interpreter_params = InterpreterParams::new(gas_price, &consensus_params); let storage = MemoryStorage::default(); diff --git a/fuel-vm/src/tests/limits.rs b/fuel-vm/src/tests/limits.rs index e368a84e4f..66ac1ce09b 100644 --- a/fuel-vm/src/tests/limits.rs +++ b/fuel-vm/src/tests/limits.rs @@ -25,7 +25,7 @@ fn cannot_exceed_max_inputs() { vec![op::ret(RegId::ONE)].into_iter().collect(), vec![], ); - for _ in 0..=params.tx_params.max_inputs { + for _ in 0..=params.tx_params().max_inputs { script.add_input(Input::coin_signed( rng.gen(), rng.gen(), @@ -50,7 +50,7 @@ fn cannot_exceed_max_outputs() { vec![op::ret(RegId::ONE)].into_iter().collect(), vec![], ); - for _ in 0..=params.tx_params.max_outputs { + for _ in 0..=params.tx_params().max_outputs { script.add_output(Output::variable(rng.gen(), rng.gen(), rng.gen())); } script @@ -68,7 +68,7 @@ fn cannot_exceed_max_witnesses() { vec![op::ret(RegId::ONE)].into_iter().collect(), vec![], ); - for _ in 0..=params.tx_params.max_witnesses { + for _ in 0..=params.tx_params().max_witnesses { script.add_witness(Witness::from(vec![rng.gen::(); 1])); } script diff --git a/fuel-vm/src/tests/outputs.rs b/fuel-vm/src/tests/outputs.rs index 9173b78a17..2676ada155 100644 --- a/fuel-vm/src/tests/outputs.rs +++ b/fuel-vm/src/tests/outputs.rs @@ -168,6 +168,7 @@ fn correct_change_is_provided_for_coin_outputs_create() { context.get_chain_id(), context.get_gas_costs().to_owned(), *context.get_base_asset_id(), + context.get_block_gas_limit(), ); let create = create .into_checked_basic(context.get_block_height(), &consensus_params) diff --git a/fuel-vm/src/tests/test_helpers.rs b/fuel-vm/src/tests/test_helpers.rs index f3661d8cb9..f60fb8357d 100644 --- a/fuel-vm/src/tests/test_helpers.rs +++ b/fuel-vm/src/tests/test_helpers.rs @@ -44,7 +44,7 @@ pub fn run_script(script: Vec) -> Vec { SecretKey::random(&mut rng), rng.gen(), arb_max_fee, - consensus_params.base_asset_id, + *consensus_params.base_asset_id(), Default::default(), ) .finalize() diff --git a/fuel-vm/src/tests/validation.rs b/fuel-vm/src/tests/validation.rs index 643f2e76ce..80b2508c28 100644 --- a/fuel-vm/src/tests/validation.rs +++ b/fuel-vm/src/tests/validation.rs @@ -63,7 +63,7 @@ fn malleable_fields_do_not_affect_validity() { let params = ConsensusParameters::default(); let tx_size_ptr = - 32 + (params.tx_params.max_inputs as usize * (AssetId::LEN + WORD_SIZE)); + 32 + (params.tx_params().max_inputs as usize * (AssetId::LEN + WORD_SIZE)); let tx_start_ptr = tx_size_ptr + 8; let tx = TransactionBuilder::script( @@ -114,7 +114,7 @@ fn malleable_fields_do_not_affect_validity() { ] .into_iter() .collect(), - params.chain_id.to_be_bytes().to_vec(), + params.chain_id().to_be_bytes().to_vec(), ) .add_unsigned_coin_input( SecretKey::random(rng), @@ -127,7 +127,7 @@ fn malleable_fields_do_not_affect_validity() { .finalize(); let run_tx = |tx: Script| { - let original_id = tx.id(¶ms.chain_id); + let original_id = tx.id(¶ms.chain_id()); let vm = Interpreter::<_, Script>::with_memory_storage(); let mut client = MemoryClient::from_txtor(vm.into()); diff --git a/fuel-vm/src/util.rs b/fuel-vm/src/util.rs index 12f91cf0c6..e8348e7ce9 100644 --- a/fuel-vm/src/util.rs +++ b/fuel-vm/src/util.rs @@ -314,12 +314,12 @@ pub mod test_helpers { } pub fn with_fee_params(&mut self, fee_params: FeeParameters) -> &mut TestBuilder { - self.consensus_params.fee_params = fee_params; + self.consensus_params.set_fee_params(fee_params); self } pub fn base_asset_id(&mut self, base_asset_id: AssetId) -> &mut TestBuilder { - self.consensus_params.base_asset_id = base_asset_id; + self.consensus_params.set_base_asset_id(base_asset_id); self } @@ -360,6 +360,10 @@ pub mod test_helpers { self.consensus_params.base_asset_id() } + pub fn get_block_gas_limit(&self) -> u64 { + self.consensus_params.block_gas_limit() + } + pub fn get_chain_id(&self) -> ChainId { self.consensus_params.chain_id() } From 57c7730d532f280d807081fd00a03465070e743e Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 21 Mar 2024 11:47:36 +0100 Subject: [PATCH 03/13] Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4f8a3d6fe..bc291f717d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). #### Breaking +- [#701](https://github.com/FuelLabs/fuel-vm/pull/701): Wrapped `ConsensusParameters` and `GasCosts` into an enum to support versioning. Moved `block_gas_limit` from `fuel_core_chain_config::ChainConfig` to `ConsensusPataremeters`. Reduced default `MAX_SIZE` to be [110kb](https://github.com/FuelLabs/fuel-core/pull/1761) and `MAX_CONTRACT_SIZE` to be [100kb](https://github.com/FuelLabs/fuel-core/pull/1761). - [#692](https://github.com/FuelLabs/fuel-vm/pull/692): Add GTF getters for tx size and address. - [#698](https://github.com/FuelLabs/fuel-vm/pull/698): Store input, output and witness limits to u16, while keeping the values limited to 255. From 41a537c76c96f4830c19cd211ac7e5dc6c7ca545 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 21 Mar 2024 14:37:48 +0100 Subject: [PATCH 04/13] Versioned `FeeParameters` --- .../src/transaction/consensus_parameters.rs | 80 +++++++++++++++---- fuel-tx/src/transaction/fee.rs | 10 +-- fuel-tx/src/transaction/types/script.rs | 2 +- fuel-vm/src/checked_transaction.rs | 33 ++++---- 4 files changed, 89 insertions(+), 36 deletions(-) diff --git a/fuel-tx/src/transaction/consensus_parameters.rs b/fuel-tx/src/transaction/consensus_parameters.rs index 26979c15d6..6c20b05457 100644 --- a/fuel-tx/src/transaction/consensus_parameters.rs +++ b/fuel-tx/src/transaction/consensus_parameters.rs @@ -257,37 +257,85 @@ impl From for ConsensusParameters { } } +/// The versioned fee parameters. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum FeeParameters { + V1(FeeParametersV1), +} + +impl FeeParameters { + /// Default fee parameters just for testing. + pub const DEFAULT: Self = Self::V1(FeeParametersV1::DEFAULT); + + /// Replace the gas price factor with the given argument + pub const fn with_gas_price_factor(self, gas_price_factor: u64) -> Self { + match self { + Self::V1(mut params) => { + params.gas_price_factor = gas_price_factor; + Self::V1(params) + } + } + } + + pub const fn with_gas_per_byte(self, gas_per_byte: u64) -> Self { + match self { + Self::V1(mut params) => { + params.gas_per_byte = gas_per_byte; + Self::V1(params) + } + } + } +} + +impl FeeParameters { + /// Get the gas price factor + pub fn gas_price_factor(&self) -> u64 { + match self { + Self::V1(params) => params.gas_price_factor, + } + } + + /// Get the gas per byte + pub fn gas_per_byte(&self) -> u64 { + match self { + Self::V1(params) => params.gas_per_byte, + } + } +} + +impl Default for FeeParameters { + fn default() -> Self { + Self::DEFAULT + } +} + +impl From for FeeParameters { + fn from(params: FeeParametersV1) -> Self { + Self::V1(params) + } +} + /// Consensus configurable parameters used for verifying transactions #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(default))] -pub struct FeeParameters { +pub struct FeeParametersV1 { /// Factor to convert between gas and transaction assets value. pub gas_price_factor: u64, /// A fixed ratio linking metered bytes to gas price pub gas_per_byte: u64, } -impl FeeParameters { - /// Default consensus parameters with settings suggested in fuel-specs - pub const DEFAULT: Self = Self { +impl FeeParametersV1 { + /// Default fee parameters just for tests. + pub const DEFAULT: Self = FeeParametersV1 { gas_price_factor: 1_000_000_000, gas_per_byte: 4, }; - - /// Replace the gas price factor with the given argument - pub const fn with_gas_price_factor(mut self, gas_price_factor: u64) -> Self { - self.gas_price_factor = gas_price_factor; - self - } - - pub const fn with_gas_per_byte(mut self, gas_per_byte: u64) -> Self { - self.gas_per_byte = gas_per_byte; - self - } } -impl Default for FeeParameters { +impl Default for FeeParametersV1 { fn default() -> Self { Self::DEFAULT } diff --git a/fuel-tx/src/transaction/fee.rs b/fuel-tx/src/transaction/fee.rs index e8e7289c92..254398eaaa 100644 --- a/fuel-tx/src/transaction/fee.rs +++ b/fuel-tx/src/transaction/fee.rs @@ -126,7 +126,7 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies { let vm_initialization_gas = gas_costs.vm_initialization().resolve(bytes_size as Word); - let bytes_gas = bytes_size as u64 * fee.gas_per_byte; + let bytes_gas = bytes_size as u64 * fee.gas_per_byte(); // It's okay to saturate because we have the `max_gas_per_tx` rule for transaction // validity. In the production, the value always will be lower than // `u64::MAX`. @@ -143,7 +143,7 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies { let remaining_allowed_witness_gas = self .witness_limit() .saturating_sub(self.witnesses().size_dynamic() as u64) - .saturating_mul(fee.gas_per_byte); + .saturating_mul(fee.gas_per_byte()); self.min_gas(gas_costs, fee) .saturating_add(remaining_allowed_witness_gas) @@ -160,7 +160,7 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies { let gas_fee = gas_to_fee( self.min_gas(gas_costs, fee), gas_price, - fee.gas_price_factor, + fee.gas_price_factor(), ); gas_fee.saturating_add(tip as u128) } @@ -178,7 +178,7 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies { let gas_fee = gas_to_fee( self.max_gas(gas_costs, fee), gas_price, - fee.gas_price_factor, + fee.gas_price_factor(), ); gas_fee.saturating_add(tip as u128) } @@ -200,7 +200,7 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies { let total_used_gas = min_gas.saturating_add(used_gas); let tip = self.policies().get(PolicyType::Tip).unwrap_or(0); - let used_fee = gas_to_fee(total_used_gas, gas_price, fee.gas_price_factor) + let used_fee = gas_to_fee(total_used_gas, gas_price, fee.gas_price_factor()) .saturating_add(tip as u128); // It is okay to saturate everywhere above because it only can decrease the value diff --git a/fuel-tx/src/transaction/types/script.rs b/fuel-tx/src/transaction/types/script.rs index 30a40579b8..85358af831 100644 --- a/fuel-tx/src/transaction/types/script.rs +++ b/fuel-tx/src/transaction/types/script.rs @@ -145,7 +145,7 @@ impl Chargeable for Script { let remaining_allowed_witness = self .witness_limit() .saturating_sub(self.witnesses().size_dynamic() as u64) - .saturating_mul(fee.gas_per_byte); + .saturating_mul(fee.gas_per_byte()); self.min_gas(gas_costs, fee) .saturating_add(remaining_allowed_witness) diff --git a/fuel-vm/src/checked_transaction.rs b/fuel-vm/src/checked_transaction.rs index b285c7499d..87d37d399b 100644 --- a/fuel-vm/src/checked_transaction.rs +++ b/fuel-vm/src/checked_transaction.rs @@ -1111,7 +1111,8 @@ mod tests { .unwrap(); let min_fee = fee.min_fee(); - let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte + let expected_min_fee = (tx.metered_bytes_size() as u64 + * fee_params.gas_per_byte() + gas_costs.vm_initialization().resolve(tx.size() as u64) + 3 * gas_costs.ecr1() + gas_costs.s256().resolve(tx.size() as u64)) @@ -1164,7 +1165,8 @@ mod tests { // Because all inputs are owned by the same address, the address will only need to // be recovered once. Therefore, we charge only once for the address // recovery of the signed inputs. - let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte + let expected_min_fee = (tx.metered_bytes_size() as u64 + * fee_params.gas_per_byte() + gas_costs.vm_initialization().resolve(tx.size() as u64) + gas_costs.ecr1() + gas_costs.s256().resolve(tx.size() as u64)) @@ -1230,7 +1232,7 @@ mod tests { .unwrap(); let min_fee = fee.min_fee(); - let expected_min_fee = (tx.size() as u64 * fee_params.gas_per_byte + let expected_min_fee = (tx.size() as u64 * fee_params.gas_per_byte() + gas_costs.vm_initialization().resolve(tx.size() as u64) + gas_costs.contract_root().resolve(predicate_1.len() as u64) + gas_costs.contract_root().resolve(predicate_2.len() as u64) @@ -1316,7 +1318,8 @@ mod tests { .unwrap(); let min_fee = fee.min_fee(); - let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte + let expected_min_fee = (tx.metered_bytes_size() as u64 + * fee_params.gas_per_byte() + 3 * gas_costs.ecr1() + gas_costs.vm_initialization().resolve(tx.size() as u64) + gas_costs.contract_root().resolve(predicate_1.len() as u64) @@ -1358,7 +1361,8 @@ mod tests { .unwrap(); let min_fee = fee.min_fee(); - let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte + let expected_min_fee = (tx.metered_bytes_size() as u64 + * fee_params.gas_per_byte() + gas_costs.state_root().resolve(storage_slots_len as Word) + gas_costs.contract_root().resolve(bytecode_len as Word) + gas_costs.vm_initialization().resolve(tx.size() as u64) @@ -1370,7 +1374,7 @@ mod tests { let max_fee = fee.max_fee(); let expected_max_fee = min_fee + (witness_limit - bytecode.size() as u64) - * fee_params.gas_per_byte + * fee_params.gas_per_byte() * gas_price; assert_eq!(max_fee, expected_max_fee); } @@ -1392,7 +1396,8 @@ mod tests { .unwrap(); let min_fee = fee.min_fee(); - let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte + let expected_min_fee = (tx.metered_bytes_size() as u64 + * fee_params.gas_per_byte() + gas_costs.state_root().resolve(0) + gas_costs.contract_root().resolve(0) + gas_costs.vm_initialization().resolve(tx.size() as u64) @@ -1404,7 +1409,7 @@ mod tests { let max_fee = fee.max_fee(); let expected_max_fee = min_fee + (witness_limit - bytecode.size_static() as u64) - * fee_params.gas_per_byte + * fee_params.gas_per_byte() * gas_price; assert_eq!(max_fee, expected_max_fee); } @@ -1800,7 +1805,7 @@ mod tests { // cant overflow as metered bytes * gas_per_byte < u64::MAX let gas_used_by_bytes = fee_params - .gas_per_byte + .gas_per_byte() .saturating_mul(tx.metered_bytes_size() as u64); let gas_used_by_inputs = tx.gas_used_by_inputs(gas_costs); let gas_used_by_metadata = tx.gas_used_by_metadata(gas_costs); @@ -1817,11 +1822,11 @@ mod tests { let witness_limit_allowance = tx .witness_limit() .saturating_sub(tx.witnesses().size_dynamic() as u64) - .saturating_mul(fee_params.gas_per_byte); + .saturating_mul(fee_params.gas_per_byte()); let max_gas = min_gas .saturating_add(*tx.script_gas_limit()) .saturating_add(witness_limit_allowance); - let max_fee = gas_to_fee(max_gas, gas_price, fee_params.gas_price_factor); + let max_fee = gas_to_fee(max_gas, gas_price, fee_params.gas_price_factor()); let max_fee_with_tip = max_fee.saturating_add(tx.tip() as u128); @@ -1841,7 +1846,7 @@ mod tests { // cant overflow as (metered bytes + gas_used_by_predicates) * gas_per_byte < // u64::MAX let gas_used_by_bytes = fee_params - .gas_per_byte + .gas_per_byte() .saturating_mul(tx.metered_bytes_size() as u64); let gas_used_by_inputs = tx.gas_used_by_inputs(gas_costs); let gas_used_by_metadata = tx.gas_used_by_metadata(gas_costs); @@ -1855,9 +1860,9 @@ mod tests { ); let total = gas as u128 * gas_price as u128; // use different division mechanism than impl - let fee = total / fee_params.gas_price_factor as u128; + let fee = total / fee_params.gas_price_factor() as u128; let fee_remainder = - (total.rem_euclid(fee_params.gas_price_factor as u128) > 0) as u128; + (total.rem_euclid(fee_params.gas_price_factor() as u128) > 0) as u128; let rounded_fee = fee .saturating_add(fee_remainder) .saturating_add(tx.tip() as u128); From 83721d91f10c30c5a15d796a1c68aa95c476afea Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 21 Mar 2024 19:43:30 +0100 Subject: [PATCH 05/13] Versioned `PredicateParameters`, `ScriptParameters`, `ContractParameters`, --- fuel-tx/src/tests/valid_cases/input.rs | 10 +- fuel-tx/src/tests/valid_cases/transaction.rs | 24 +- .../src/transaction/consensus_parameters.rs | 322 ++++++++++++++---- fuel-tx/src/transaction/types/create.rs | 4 +- fuel-tx/src/transaction/types/script.rs | 4 +- fuel-tx/src/transaction/validity.rs | 10 +- fuel-vm/src/checked_transaction.rs | 6 +- fuel-vm/src/interpreter.rs | 5 +- 8 files changed, 290 insertions(+), 95 deletions(-) diff --git a/fuel-tx/src/tests/valid_cases/input.rs b/fuel-tx/src/tests/valid_cases/input.rs index 8a0e026d4e..5e504b7dab 100644 --- a/fuel-tx/src/tests/valid_cases/input.rs +++ b/fuel-tx/src/tests/valid_cases/input.rs @@ -380,7 +380,7 @@ fn message_metadata() { assert_eq!(ValidityError::InputPredicateOwner { index: 1 }, err); - let data = vec![0xff; PREDICATE_PARAMS.max_message_data_length as usize + 1]; + let data = vec![0xff; PREDICATE_PARAMS.max_message_data_length() as usize + 1]; let err = Input::message_data_signed( rng.gen(), @@ -417,7 +417,7 @@ fn message_metadata() { assert_eq!(ValidityError::InputMessageDataLength { index: 1 }, err,); - let predicate = vec![0xff; PREDICATE_PARAMS.max_predicate_length as usize + 1]; + let predicate = vec![0xff; PREDICATE_PARAMS.max_predicate_length() as usize + 1]; let err = Input::message_data_predicate( rng.gen(), @@ -435,7 +435,7 @@ fn message_metadata() { assert_eq!(ValidityError::InputPredicateLength { index: 1 }, err,); let predicate_data = - vec![0xff; PREDICATE_PARAMS.max_predicate_data_length as usize + 1]; + vec![0xff; PREDICATE_PARAMS.max_predicate_data_length() as usize + 1]; let err = Input::message_data_predicate( rng.gen(), @@ -503,7 +503,7 @@ fn message_message_coin() { assert_eq!(ValidityError::InputPredicateOwner { index: 1 }, err); - let predicate = vec![0xff; PREDICATE_PARAMS.max_predicate_length as usize + 1]; + let predicate = vec![0xff; PREDICATE_PARAMS.max_predicate_length() as usize + 1]; let err = Input::message_coin_predicate( rng.gen(), @@ -520,7 +520,7 @@ fn message_message_coin() { assert_eq!(ValidityError::InputPredicateLength { index: 1 }, err,); let predicate_data = - vec![0xff; PREDICATE_PARAMS.max_predicate_data_length as usize + 1]; + vec![0xff; PREDICATE_PARAMS.max_predicate_data_length() as usize + 1]; let err = Input::message_coin_predicate( rng.gen(), diff --git a/fuel-tx/src/tests/valid_cases/transaction.rs b/fuel-tx/src/tests/valid_cases/transaction.rs index 0a21013985..c7a6edc494 100644 --- a/fuel-tx/src/tests/valid_cases/transaction.rs +++ b/fuel-tx/src/tests/valid_cases/transaction.rs @@ -542,8 +542,8 @@ fn script__check__happy_path() { let asset_id: AssetId = rng.gen(); TransactionBuilder::script( - vec![0xfa; SCRIPT_PARAMS.max_script_length as usize], - vec![0xfb; SCRIPT_PARAMS.max_script_data_length as usize], + vec![0xfa; SCRIPT_PARAMS.max_script_length() as usize], + vec![0xfb; SCRIPT_PARAMS.max_script_data_length() as usize], ) .maturity(maturity) .add_unsigned_coin_input(secret, rng.gen(), rng.gen(), asset_id, rng.gen()) @@ -564,8 +564,8 @@ fn script__check__cannot_create_contract() { let asset_id: AssetId = rng.gen(); let err = TransactionBuilder::script( - vec![0xfa; SCRIPT_PARAMS.max_script_length as usize], - vec![0xfb; SCRIPT_PARAMS.max_script_data_length as usize], + vec![0xfa; SCRIPT_PARAMS.max_script_length() as usize], + vec![0xfb; SCRIPT_PARAMS.max_script_data_length() as usize], ) .maturity(maturity) .add_unsigned_coin_input(secret, rng.gen(), rng.gen(), asset_id, rng.gen()) @@ -591,8 +591,8 @@ fn script__check__errors_if_script_too_long() { let asset_id: AssetId = rng.gen(); let err = TransactionBuilder::script( - vec![0xfa; 1 + SCRIPT_PARAMS.max_script_length as usize], - vec![0xfb; SCRIPT_PARAMS.max_script_data_length as usize], + vec![0xfa; 1 + SCRIPT_PARAMS.max_script_length() as usize], + vec![0xfb; SCRIPT_PARAMS.max_script_data_length() as usize], ) .maturity(maturity) .add_unsigned_coin_input(secret, rng.gen(), rng.gen(), asset_id, rng.gen()) @@ -615,8 +615,8 @@ fn script__check__errors_if_script_data_too_long() { let asset_id: AssetId = rng.gen(); let err = TransactionBuilder::script( - vec![0xfa; SCRIPT_PARAMS.max_script_length as usize], - vec![0xfb; 1 + SCRIPT_PARAMS.max_script_data_length as usize], + vec![0xfa; SCRIPT_PARAMS.max_script_length() as usize], + vec![0xfb; 1 + SCRIPT_PARAMS.max_script_data_length() as usize], ) .maturity(maturity) .add_unsigned_coin_input(secret, rng.gen(), rng.gen(), asset_id, rng.gen()) @@ -843,7 +843,7 @@ fn create__check__something_else() { let secret = SecretKey::random(rng); TransactionBuilder::create( - vec![0xfa; CONTRACT_PARAMS.contract_max_size as usize / 4].into(), + vec![0xfa; CONTRACT_PARAMS.contract_max_size() as usize / 4].into(), rng.gen(), vec![], ) @@ -865,7 +865,7 @@ fn create__check__errors_if_witness_bytecode_too_long() { let secret = SecretKey::random(rng); let err = TransactionBuilder::create( - vec![0xfa; 1 + CONTRACT_PARAMS.contract_max_size as usize].into(), + vec![0xfa; 1 + CONTRACT_PARAMS.contract_max_size() as usize].into(), rng.gen(), vec![], ) @@ -940,7 +940,7 @@ fn create__check__can_max_out_storage_slots() { let secret = SecretKey::random(rng); - let storage_slots = (0..CONTRACT_PARAMS.max_storage_slots) + let storage_slots = (0..CONTRACT_PARAMS.max_storage_slots()) .map(|i| { let mut slot_data = StorageSlot::default().to_bytes(); slot_data[..8].copy_from_slice(&i.to_be_bytes()); // Force ordering @@ -972,7 +972,7 @@ fn create__check__cannot_exceed_max_storage_slot() { let secret = SecretKey::random(rng); // Test max slots can't be exceeded - let mut storage_slots_max = (0..CONTRACT_PARAMS.max_storage_slots) + let mut storage_slots_max = (0..CONTRACT_PARAMS.max_storage_slots()) .map(|i| { let mut slot_data = StorageSlot::default().to_bytes(); slot_data[..8].copy_from_slice(&i.to_be_bytes()); // Force ordering diff --git a/fuel-tx/src/transaction/consensus_parameters.rs b/fuel-tx/src/transaction/consensus_parameters.rs index 6c20b05457..642317e413 100644 --- a/fuel-tx/src/transaction/consensus_parameters.rs +++ b/fuel-tx/src/transaction/consensus_parameters.rs @@ -341,53 +341,97 @@ impl Default for FeeParametersV1 { } } -/// Consensus configurable parameters used for verifying transactions +/// Versioned predicate parameters. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "typescript", wasm_bindgen::prelude::wasm_bindgen)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(default))] -pub struct PredicateParameters { - /// Maximum length of predicate, in instructions. - pub max_predicate_length: u64, - /// Maximum length of predicate data, in bytes. - pub max_predicate_data_length: u64, - /// Maximum length of message data, in bytes. - pub max_message_data_length: u64, - /// Maximum gas spent per predicate - pub max_gas_per_predicate: u64, +pub enum PredicateParameters { + V1(PredicateParametersV1), } impl PredicateParameters { - /// Default consensus parameters with settings suggested in fuel-specs - pub const DEFAULT: Self = Self { - max_predicate_length: 1024 * 1024, - max_predicate_data_length: 1024 * 1024, - max_message_data_length: 1024 * 1024, - max_gas_per_predicate: MAX_GAS, - }; + /// Default parameters just for testing. + pub const DEFAULT: Self = Self::V1(PredicateParametersV1::DEFAULT); /// Replace the max predicate length with the given argument - pub const fn with_max_predicate_length(mut self, max_predicate_length: u64) -> Self { - self.max_predicate_length = max_predicate_length; - self + pub const fn with_max_predicate_length(self, max_predicate_length: u64) -> Self { + match self { + Self::V1(mut params) => { + params.max_predicate_length = max_predicate_length; + Self::V1(params) + } + } } /// Replace the max predicate data length with the given argument pub const fn with_max_predicate_data_length( - mut self, + self, max_predicate_data_length: u64, ) -> Self { - self.max_predicate_data_length = max_predicate_data_length; - self + match self { + Self::V1(mut params) => { + params.max_predicate_data_length = max_predicate_data_length; + Self::V1(params) + } + } } /// Replace the max message data length with the given argument pub const fn with_max_message_data_length( - mut self, + self, max_message_data_length: u64, ) -> Self { - self.max_message_data_length = max_message_data_length; - self + match self { + Self::V1(mut params) => { + params.max_message_data_length = max_message_data_length; + Self::V1(params) + } + } + } + + /// Replace the max gas per predicate. + pub const fn with_max_gas_per_predicate(self, max_gas_per_predicate: u64) -> Self { + match self { + Self::V1(mut params) => { + params.max_gas_per_predicate = max_gas_per_predicate; + Self::V1(params) + } + } + } +} + +impl PredicateParameters { + /// Get the maximum predicate length + pub fn max_predicate_length(&self) -> u64 { + match self { + Self::V1(params) => params.max_predicate_length, + } + } + + /// Get the maximum predicate data length + pub fn max_predicate_data_length(&self) -> u64 { + match self { + Self::V1(params) => params.max_predicate_data_length, + } + } + + /// Get the maximum message data length + pub fn max_message_data_length(&self) -> u64 { + match self { + Self::V1(params) => params.max_message_data_length, + } + } + + /// Get the maximum gas per predicate + pub fn max_gas_per_predicate(&self) -> u64 { + match self { + Self::V1(params) => params.max_gas_per_predicate, + } + } +} + +impl From for PredicateParameters { + fn from(params: PredicateParametersV1) -> Self { + Self::V1(params) } } @@ -397,6 +441,37 @@ impl Default for PredicateParameters { } } +/// Consensus configurable parameters used for verifying transactions +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(default))] +pub struct PredicateParametersV1 { + /// Maximum length of predicate, in instructions. + pub max_predicate_length: u64, + /// Maximum length of predicate data, in bytes. + pub max_predicate_data_length: u64, + /// Maximum length of message data, in bytes. + pub max_message_data_length: u64, + /// Maximum gas spent per predicate + pub max_gas_per_predicate: u64, +} + +impl PredicateParametersV1 { + /// Default parameters just for testing. + pub const DEFAULT: Self = Self { + max_predicate_length: 1024 * 1024, + max_predicate_data_length: 1024 * 1024, + max_message_data_length: 1024 * 1024, + max_gas_per_predicate: MAX_GAS, + }; +} + +impl Default for PredicateParametersV1 { + fn default() -> Self { + Self::DEFAULT + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(default))] @@ -414,7 +489,7 @@ pub struct TxParameters { } impl TxParameters { - /// Default consensus parameters with settings suggested in fuel-specs + /// Default parameters just for testing. pub const DEFAULT: Self = Self { max_inputs: 255, max_outputs: 255, @@ -468,40 +543,145 @@ impl Default for TxParameters { } } +/// Versioned script parameters. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ScriptParameters { + V1(ScriptParametersV1), +} + +impl ScriptParameters { + /// Default parameters just for testing. + pub const DEFAULT: Self = Self::V1(ScriptParametersV1::DEFAULT); + + /// Replace the max script length with the given argument + pub const fn with_max_script_length(self, max_script_length: u64) -> Self { + match self { + Self::V1(mut params) => { + params.max_script_length = max_script_length; + Self::V1(params) + } + } + } + + /// Replace the max script data length with the given argument + pub const fn with_max_script_data_length(self, max_script_data_length: u64) -> Self { + match self { + Self::V1(mut params) => { + params.max_script_data_length = max_script_data_length; + Self::V1(params) + } + } + } +} + +impl ScriptParameters { + /// Get the maximum script length + pub fn max_script_length(&self) -> u64 { + match self { + Self::V1(params) => params.max_script_length, + } + } + + /// Get the maximum script data length + pub fn max_script_data_length(&self) -> u64 { + match self { + Self::V1(params) => params.max_script_data_length, + } + } +} + +impl From for ScriptParameters { + fn from(params: ScriptParametersV1) -> Self { + Self::V1(params) + } +} + +impl Default for ScriptParameters { + fn default() -> Self { + Self::DEFAULT + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(default))] -pub struct ScriptParameters { +pub struct ScriptParametersV1 { /// Maximum length of script, in instructions. pub max_script_length: u64, /// Maximum length of script data, in bytes. pub max_script_data_length: u64, } -impl ScriptParameters { - /// Default consensus parameters with settings suggested in fuel-specs +impl ScriptParametersV1 { + /// Default parameters just for testing. pub const DEFAULT: Self = Self { max_script_length: 1024 * 1024, max_script_data_length: 1024 * 1024, }; +} - /// Replace the max script length with the given argument - pub const fn with_max_script_length(mut self, max_script_length: u64) -> Self { - self.max_script_length = max_script_length; - self +impl Default for ScriptParametersV1 { + fn default() -> Self { + Self::DEFAULT } +} - /// Replace the max script data length with the given argument - pub const fn with_max_script_data_length( - mut self, - max_script_data_length: u64, - ) -> Self { - self.max_script_data_length = max_script_data_length; - self +/// Versioned contract parameters. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ContractParameters { + V1(ContractParametersV1), +} + +impl ContractParameters { + /// Default parameters just for testing. + pub const DEFAULT: Self = Self::V1(ContractParametersV1::DEFAULT); + + /// Replace the max contract size with the given argument + pub const fn with_contract_max_size(self, contract_max_size: u64) -> Self { + match self { + Self::V1(mut params) => { + params.contract_max_size = contract_max_size; + Self::V1(params) + } + } + } + + /// Replace the max storage slots with the given argument + pub const fn with_max_storage_slots(self, max_storage_slots: u64) -> Self { + match self { + Self::V1(mut params) => { + params.max_storage_slots = max_storage_slots; + Self::V1(params) + } + } } } -impl Default for ScriptParameters { +impl ContractParameters { + /// Get the maximum contract size + pub fn contract_max_size(&self) -> u64 { + match self { + Self::V1(params) => params.contract_max_size, + } + } + + /// Get the maximum storage slots + pub fn max_storage_slots(&self) -> u64 { + match self { + Self::V1(params) => params.max_storage_slots, + } + } +} + +impl From for ContractParameters { + fn from(params: ContractParametersV1) -> Self { + Self::V1(params) + } +} + +impl Default for ContractParameters { fn default() -> Self { Self::DEFAULT } @@ -510,7 +690,7 @@ impl Default for ScriptParameters { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(default))] -pub struct ContractParameters { +pub struct ContractParametersV1 { /// Maximum contract size, in bytes. pub contract_max_size: u64, @@ -518,43 +698,57 @@ pub struct ContractParameters { pub max_storage_slots: u64, } -impl ContractParameters { - /// Default consensus parameters with settings suggested in fuel-specs +impl ContractParametersV1 { + /// Default parameters just for testing. pub const DEFAULT: Self = Self { contract_max_size: 100 * 1024, max_storage_slots: 255, }; - - /// Replace the max contract size with the given argument - pub const fn with_contract_max_size(mut self, contract_max_size: u64) -> Self { - self.contract_max_size = contract_max_size; - self - } - - /// Replace the max storage slots with the given argument - pub const fn with_max_storage_slots(mut self, max_storage_slots: u64) -> Self { - self.max_storage_slots = max_storage_slots; - self - } } -impl Default for ContractParameters { +impl Default for ContractParametersV1 { fn default() -> Self { Self::DEFAULT } } #[cfg(feature = "typescript")] -mod typescript { +pub mod typescript { use wasm_bindgen::prelude::*; - use super::PredicateParameters; + use super::PredicateParameters as PredicateParametersRust; + + #[derive(Clone, Debug, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "typescript", wasm_bindgen::prelude::wasm_bindgen)] + pub struct PredicateParameters(Box); + + impl AsRef for PredicateParameters { + fn as_ref(&self) -> &PredicateParametersRust { + &self.0 + } + } #[wasm_bindgen] impl PredicateParameters { #[wasm_bindgen(constructor)] - pub fn typescript_new() -> Self { - Self::DEFAULT + pub fn typescript_default() -> Self { + PredicateParameters(PredicateParametersRust::DEFAULT.into()) + } + + #[wasm_bindgen(constructor)] + pub fn typescript_new( + max_predicate_length: u64, + max_predicate_data_length: u64, + max_message_data_length: u64, + max_gas_per_predicate: u64, + ) -> Self { + let params = PredicateParametersRust::default() + .with_max_predicate_length(max_predicate_length) + .with_max_predicate_data_length(max_predicate_data_length) + .with_max_message_data_length(max_message_data_length) + .with_max_gas_per_predicate(max_gas_per_predicate); + + PredicateParameters(params.into()) } } } diff --git a/fuel-tx/src/transaction/types/create.rs b/fuel-tx/src/transaction/types/create.rs index 60ac6c8bc8..585edd6ac9 100644 --- a/fuel-tx/src/transaction/types/create.rs +++ b/fuel-tx/src/transaction/types/create.rs @@ -235,7 +235,7 @@ impl FormatValidityChecks for Create { .map(|w| w.as_ref().len() as Word) .ok_or(ValidityError::TransactionCreateBytecodeWitnessIndex)?; - if bytecode_witness_len > contract_params.contract_max_size + if bytecode_witness_len > contract_params.contract_max_size() || bytecode_witness_len / 4 != self.bytecode_length { return Err(ValidityError::TransactionCreateBytecodeLen); @@ -243,7 +243,7 @@ impl FormatValidityChecks for Create { // Restrict to subset of u16::MAX, allowing this to be increased in the future // in a non-breaking way. - if self.storage_slots.len() as u64 > contract_params.max_storage_slots { + if self.storage_slots.len() as u64 > contract_params.max_storage_slots() { return Err(ValidityError::TransactionCreateStorageSlotMax); } diff --git a/fuel-tx/src/transaction/types/script.rs b/fuel-tx/src/transaction/types/script.rs index 85358af831..5305029888 100644 --- a/fuel-tx/src/transaction/types/script.rs +++ b/fuel-tx/src/transaction/types/script.rs @@ -191,11 +191,11 @@ impl FormatValidityChecks for Script { ) -> Result<(), ValidityError> { check_common_part(self, block_height, consensus_params)?; let script_params = consensus_params.script_params(); - if self.script.len() as u64 > script_params.max_script_length { + if self.script.len() as u64 > script_params.max_script_length() { Err(ValidityError::TransactionScriptLength)?; } - if self.script_data.len() as u64 > script_params.max_script_data_length { + if self.script_data.len() as u64 > script_params.max_script_data_length() { Err(ValidityError::TransactionScriptDataLength)?; } diff --git a/fuel-tx/src/transaction/validity.rs b/fuel-tx/src/transaction/validity.rs index fec1c5a8f6..38f105fdd2 100644 --- a/fuel-tx/src/transaction/validity.rs +++ b/fuel-tx/src/transaction/validity.rs @@ -158,7 +158,7 @@ impl Input { Self::CoinPredicate(CoinPredicate { predicate, .. }) | Self::MessageCoinPredicate(MessageCoinPredicate { predicate, .. }) | Self::MessageDataPredicate(MessageDataPredicate { predicate, .. }) - if predicate.len() as u64 > predicate_params.max_predicate_length => + if predicate.len() as u64 > predicate_params.max_predicate_length() => { Err(ValidityError::InputPredicateLength { index }) } @@ -170,7 +170,7 @@ impl Input { | Self::MessageDataPredicate(MessageDataPredicate { predicate_data, .. }) if predicate_data.len() as u64 - > predicate_params.max_predicate_data_length => + > predicate_params.max_predicate_data_length() => { Err(ValidityError::InputPredicateDataLength { index }) } @@ -203,7 +203,7 @@ impl Input { Self::MessageDataSigned(MessageDataSigned { data, .. }) | Self::MessageDataPredicate(MessageDataPredicate { data, .. }) if data.is_empty() - || data.len() as u64 > predicate_params.max_message_data_length => + || data.len() as u64 > predicate_params.max_message_data_length() => { Err(ValidityError::InputMessageDataLength { index }) } @@ -496,7 +496,7 @@ where #[cfg(feature = "typescript")] mod typescript { use crate::{ - PredicateParameters, + transaction::consensus_parameters::typescript::PredicateParameters, Witness, }; use fuel_types::Bytes32; @@ -540,7 +540,7 @@ mod typescript { txhash, &outputs, &witnesses, - predicate_params, + predicate_params.as_ref(), &mut None, ) .map_err(|e| js_sys::Error::new(&format!("{:?}", e))) diff --git a/fuel-vm/src/checked_transaction.rs b/fuel-vm/src/checked_transaction.rs index 87d37d399b..6d6616f28c 100644 --- a/fuel-vm/src/checked_transaction.rs +++ b/fuel-vm/src/checked_transaction.rs @@ -351,11 +351,11 @@ impl From<&ConsensusParameters> for CheckPredicateParams { CheckPredicateParams { gas_costs: value.gas_costs().clone(), chain_id: value.chain_id(), - max_gas_per_predicate: value.predicate_params().max_gas_per_predicate, + max_gas_per_predicate: value.predicate_params().max_gas_per_predicate(), max_gas_per_tx: value.tx_params().max_gas_per_tx, max_inputs: value.tx_params().max_inputs, - contract_max_size: value.contract_params().contract_max_size, - max_message_data_length: value.predicate_params().max_message_data_length, + contract_max_size: value.contract_params().contract_max_size(), + max_message_data_length: value.predicate_params().max_message_data_length(), tx_offset: value.tx_params().tx_offset(), fee_params: *(value.fee_params()), base_asset_id: *value.base_asset_id(), diff --git a/fuel-vm/src/interpreter.rs b/fuel-vm/src/interpreter.rs index 71720f1b77..96d23d5ee3 100644 --- a/fuel-vm/src/interpreter.rs +++ b/fuel-vm/src/interpreter.rs @@ -163,9 +163,10 @@ impl Default for InterpreterParams { gas_price: 0, gas_costs: Default::default(), max_inputs: TxParameters::DEFAULT.max_inputs, - contract_max_size: ContractParameters::DEFAULT.contract_max_size, + contract_max_size: ContractParameters::DEFAULT.contract_max_size(), tx_offset: TxParameters::DEFAULT.tx_offset(), - max_message_data_length: PredicateParameters::DEFAULT.max_message_data_length, + max_message_data_length: PredicateParameters::DEFAULT + .max_message_data_length(), chain_id: ChainId::default(), fee_params: FeeParameters::default(), base_asset_id: Default::default(), From ed2e94b7ac769b3db4b9733d5be4042109ef2a87 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 21 Mar 2024 21:57:01 +0100 Subject: [PATCH 06/13] Versioned `TxParameters` --- fuel-tx/src/builder.rs | 2 +- fuel-tx/src/tests/valid_cases/transaction.rs | 34 +-- .../src/transaction/consensus_parameters.rs | 203 +++++++++++++----- fuel-tx/src/transaction/types/script.rs | 2 +- fuel-tx/src/transaction/validity.rs | 10 +- fuel-vm/src/checked_transaction.rs | 4 +- fuel-vm/src/interpreter.rs | 2 +- fuel-vm/src/tests/limits.rs | 6 +- fuel-vm/src/tests/validation.rs | 2 +- fuel-vm/src/util.rs | 2 +- 10 files changed, 179 insertions(+), 88 deletions(-) diff --git a/fuel-tx/src/builder.rs b/fuel-tx/src/builder.rs index e162053f94..a4e9090c3d 100644 --- a/fuel-tx/src/builder.rs +++ b/fuel-tx/src/builder.rs @@ -410,7 +410,7 @@ impl TransactionBuilder { let witness_len = u16::try_from(self.witnesses().len()) .expect("The number of witnesses can't exceed `u16::MAX`"); - if u32::from(witness_len) > self.params.tx_params().max_witnesses { + if u32::from(witness_len) > self.params.tx_params().max_witnesses() { panic!("Max witnesses exceeded"); } diff --git a/fuel-tx/src/tests/valid_cases/transaction.rs b/fuel-tx/src/tests/valid_cases/transaction.rs index c7a6edc494..61d7db9656 100644 --- a/fuel-tx/src/tests/valid_cases/transaction.rs +++ b/fuel-tx/src/tests/valid_cases/transaction.rs @@ -55,7 +55,7 @@ fn gas_limit() { .expect("Failed to validate transaction"); let err = Transaction::script( - TX_PARAMS.max_gas_per_tx + 1, + TX_PARAMS.max_gas_per_tx() + 1, generate_bytes(rng), generate_bytes(rng), Policies::new().with_max_fee(0), @@ -328,11 +328,11 @@ fn max_iow() { rng.gen(), ); - while builder.outputs().len() < TX_PARAMS.max_outputs as usize { + while builder.outputs().len() < TX_PARAMS.max_outputs() as usize { builder.add_output(Output::coin(rng.gen(), rng.gen(), asset_id)); } - while builder.witnesses().len() < TX_PARAMS.max_witnesses as usize { + while builder.witnesses().len() < TX_PARAMS.max_witnesses() as usize { builder.add_witness(generate_bytes(rng).into()); } @@ -348,7 +348,7 @@ fn max_iow() { builder.maturity(maturity); let secrets = - cmp::min(TX_PARAMS.max_inputs as u32, TX_PARAMS.max_witnesses - 1) as usize; + cmp::min(TX_PARAMS.max_inputs() as u32, TX_PARAMS.max_witnesses() - 1) as usize; let secrets: Vec = (0..secrets - builder.inputs().len()) .map(|_| SecretKey::random(rng)) .collect(); @@ -358,11 +358,11 @@ fn max_iow() { builder.add_unsigned_coin_input(*k, rng.gen(), rng.gen(), asset_id, rng.gen()); }); - while builder.outputs().len() < TX_PARAMS.max_outputs as usize { + while builder.outputs().len() < TX_PARAMS.max_outputs() as usize { builder.add_output(Output::coin(rng.gen(), rng.gen(), asset_id)); } - while builder.witnesses().len() < TX_PARAMS.max_witnesses as usize { + while builder.witnesses().len() < TX_PARAMS.max_witnesses() as usize { builder.add_witness(generate_bytes(rng).into()); } @@ -377,7 +377,7 @@ fn max_iow() { builder.maturity(maturity); - let secrets: Vec = (0..1 + TX_PARAMS.max_inputs as usize + let secrets: Vec = (0..1 + TX_PARAMS.max_inputs() as usize - builder.inputs().len()) .map(|_| SecretKey::random(rng)) .collect(); @@ -386,11 +386,11 @@ fn max_iow() { builder.add_unsigned_coin_input(*k, rng.gen(), rng.gen(), rng.gen(), rng.gen()); }); - while builder.outputs().len() < TX_PARAMS.max_outputs as usize { + while builder.outputs().len() < TX_PARAMS.max_outputs() as usize { builder.add_output(Output::coin(rng.gen(), rng.gen(), rng.gen())); } - while builder.witnesses().len() < TX_PARAMS.max_witnesses as usize { + while builder.witnesses().len() < TX_PARAMS.max_witnesses() as usize { builder.add_witness(generate_bytes(rng).into()); } @@ -407,7 +407,7 @@ fn max_iow() { builder.maturity(maturity); - let secrets: Vec = (0..TX_PARAMS.max_inputs as usize + let secrets: Vec = (0..TX_PARAMS.max_inputs() as usize - builder.inputs().len()) .map(|_| SecretKey::random(rng)) .collect(); @@ -416,11 +416,11 @@ fn max_iow() { builder.add_unsigned_coin_input(*k, rng.gen(), rng.gen(), rng.gen(), rng.gen()); }); - while builder.outputs().len() < 1 + TX_PARAMS.max_outputs as usize { + while builder.outputs().len() < 1 + TX_PARAMS.max_outputs() as usize { builder.add_output(Output::coin(rng.gen(), rng.gen(), rng.gen())); } - while builder.witnesses().len() < TX_PARAMS.max_witnesses as usize { + while builder.witnesses().len() < TX_PARAMS.max_witnesses() as usize { builder.add_witness(generate_bytes(rng).into()); } @@ -437,7 +437,7 @@ fn max_iow() { builder.maturity(maturity); - let secrets: Vec = (0..TX_PARAMS.max_inputs as usize + let secrets: Vec = (0..TX_PARAMS.max_inputs() as usize - builder.inputs().len()) .map(|_| SecretKey::random(rng)) .collect(); @@ -446,11 +446,11 @@ fn max_iow() { builder.add_unsigned_coin_input(*k, rng.gen(), rng.gen(), rng.gen(), rng.gen()); }); - while builder.outputs().len() < TX_PARAMS.max_outputs as usize { + while builder.outputs().len() < TX_PARAMS.max_outputs() as usize { builder.add_output(Output::coin(rng.gen(), rng.gen(), rng.gen())); } - while builder.witnesses().len() < 1 + TX_PARAMS.max_witnesses as usize { + while builder.witnesses().len() < 1 + TX_PARAMS.max_witnesses() as usize { builder.add_witness(generate_bytes(rng).into()); } @@ -1007,7 +1007,7 @@ fn script__check__transaction_at_maximum_size_is_valid() { let mut params = test_params(); let max_size = 1024usize; let mut tx_params = *params.tx_params(); - tx_params.max_size = max_size as u64; + tx_params.set_max_size(max_size as u64); params.set_tx_params(tx_params); let base_size = { @@ -1041,7 +1041,7 @@ fn script__check__transaction_exceeding_maximum_size_is_invalid() { let mut params = test_params(); let max_size = 1024usize; let mut tx_params = *params.tx_params(); - tx_params.max_size = max_size as u64; + tx_params.set_max_size(max_size as u64); params.set_tx_params(tx_params); let base_size = { diff --git a/fuel-tx/src/transaction/consensus_parameters.rs b/fuel-tx/src/transaction/consensus_parameters.rs index 642317e413..a76967f640 100644 --- a/fuel-tx/src/transaction/consensus_parameters.rs +++ b/fuel-tx/src/transaction/consensus_parameters.rs @@ -68,63 +68,63 @@ impl ConsensusParameters { } /// Get the transaction parameters - pub fn tx_params(&self) -> &TxParameters { + pub const fn tx_params(&self) -> &TxParameters { match self { Self::V1(params) => ¶ms.tx_params, } } /// Get the predicate parameters - pub fn predicate_params(&self) -> &PredicateParameters { + pub const fn predicate_params(&self) -> &PredicateParameters { match self { Self::V1(params) => ¶ms.predicate_params, } } /// Get the script parameters - pub fn script_params(&self) -> &ScriptParameters { + pub const fn script_params(&self) -> &ScriptParameters { match self { Self::V1(params) => ¶ms.script_params, } } /// Get the contract parameters - pub fn contract_params(&self) -> &ContractParameters { + pub const fn contract_params(&self) -> &ContractParameters { match self { Self::V1(params) => ¶ms.contract_params, } } /// Get the fee parameters - pub fn fee_params(&self) -> &FeeParameters { + pub const fn fee_params(&self) -> &FeeParameters { match self { Self::V1(params) => ¶ms.fee_params, } } /// Get the chain ID - pub fn chain_id(&self) -> ChainId { + pub const fn chain_id(&self) -> ChainId { match self { Self::V1(params) => params.chain_id, } } /// Get the gas costs - pub fn gas_costs(&self) -> &GasCosts { + pub const fn gas_costs(&self) -> &GasCosts { match self { Self::V1(params) => ¶ms.gas_costs, } } /// Get the base asset ID - pub fn base_asset_id(&self) -> &AssetId { + pub const fn base_asset_id(&self) -> &AssetId { match self { Self::V1(params) => ¶ms.base_asset_id, } } /// Get the block gas limit - pub fn block_gas_limit(&self) -> u64 { + pub const fn block_gas_limit(&self) -> u64 { match self { Self::V1(params) => params.block_gas_limit, } @@ -225,7 +225,7 @@ impl ConsensusParametersV1 { chain_id: ChainId::default(), gas_costs: GasCosts::default(), base_asset_id: Default::default(), - block_gas_limit: TxParameters::DEFAULT.max_gas_per_tx, + block_gas_limit: TxParameters::DEFAULT.max_gas_per_tx(), } } @@ -240,7 +240,7 @@ impl ConsensusParametersV1 { chain_id, gas_costs: GasCosts::default(), base_asset_id: Default::default(), - block_gas_limit: TxParameters::DEFAULT.max_gas_per_tx, + block_gas_limit: TxParameters::DEFAULT.max_gas_per_tx(), } } } @@ -290,14 +290,14 @@ impl FeeParameters { impl FeeParameters { /// Get the gas price factor - pub fn gas_price_factor(&self) -> u64 { + pub const fn gas_price_factor(&self) -> u64 { match self { Self::V1(params) => params.gas_price_factor, } } /// Get the gas per byte - pub fn gas_per_byte(&self) -> u64 { + pub const fn gas_per_byte(&self) -> u64 { match self { Self::V1(params) => params.gas_per_byte, } @@ -401,28 +401,28 @@ impl PredicateParameters { impl PredicateParameters { /// Get the maximum predicate length - pub fn max_predicate_length(&self) -> u64 { + pub const fn max_predicate_length(&self) -> u64 { match self { Self::V1(params) => params.max_predicate_length, } } /// Get the maximum predicate data length - pub fn max_predicate_data_length(&self) -> u64 { + pub const fn max_predicate_data_length(&self) -> u64 { match self { Self::V1(params) => params.max_predicate_data_length, } } /// Get the maximum message data length - pub fn max_message_data_length(&self) -> u64 { + pub const fn max_message_data_length(&self) -> u64 { match self { Self::V1(params) => params.max_message_data_length, } } /// Get the maximum gas per predicate - pub fn max_gas_per_predicate(&self) -> u64 { + pub const fn max_gas_per_predicate(&self) -> u64 { match self { Self::V1(params) => params.max_gas_per_predicate, } @@ -472,68 +472,111 @@ impl Default for PredicateParametersV1 { } } +/// Versioned transaction parameters. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(default))] -pub struct TxParameters { - /// Maximum number of inputs. - pub max_inputs: u16, - /// Maximum number of outputs. - pub max_outputs: u16, - /// Maximum number of witnesses. - pub max_witnesses: u32, - /// Maximum gas per transaction. - pub max_gas_per_tx: u64, - /// Maximum size in bytes - pub max_size: u64, +pub enum TxParameters { + /// Version 1 of the transaction parameters. + V1(TxParametersV1), } impl TxParameters { /// Default parameters just for testing. - pub const DEFAULT: Self = Self { - max_inputs: 255, - max_outputs: 255, - max_witnesses: 255, - max_gas_per_tx: MAX_GAS, - max_size: MAX_SIZE, - }; + pub const DEFAULT: Self = Self::V1(TxParametersV1::DEFAULT); /// Transaction memory offset in VM runtime pub const fn tx_offset(&self) -> usize { Bytes32::LEN // Tx ID + WORD_SIZE // Tx size // Asset ID/Balance coin input pairs - + self.max_inputs as usize * (AssetId::LEN + WORD_SIZE) + + self.max_inputs() as usize * (AssetId::LEN + WORD_SIZE) } /// Replace the max inputs with the given argument - pub const fn with_max_inputs(mut self, max_inputs: u16) -> Self { - self.max_inputs = max_inputs; - self + pub const fn with_max_inputs(self, max_inputs: u16) -> Self { + match self { + Self::V1(mut params) => { + params.max_inputs = max_inputs; + Self::V1(params) + } + } } /// Replace the max outputs with the given argument - pub const fn with_max_outputs(mut self, max_outputs: u16) -> Self { - self.max_outputs = max_outputs; - self + pub const fn with_max_outputs(self, max_outputs: u16) -> Self { + match self { + Self::V1(mut params) => { + params.max_outputs = max_outputs; + Self::V1(params) + } + } } /// Replace the max witnesses with the given argument - pub const fn with_max_witnesses(mut self, max_witnesses: u32) -> Self { - self.max_witnesses = max_witnesses; - self + pub const fn with_max_witnesses(self, max_witnesses: u32) -> Self { + match self { + Self::V1(mut params) => { + params.max_witnesses = max_witnesses; + Self::V1(params) + } + } } /// Replace the max gas per transaction with the given argument - pub const fn with_max_gas_per_tx(mut self, max_gas_per_tx: u64) -> Self { - self.max_gas_per_tx = max_gas_per_tx; - self + pub const fn with_max_gas_per_tx(self, max_gas_per_tx: u64) -> Self { + match self { + Self::V1(mut params) => { + params.max_gas_per_tx = max_gas_per_tx; + Self::V1(params) + } + } } /// Replace the max size of the transaction with the given argument - pub const fn with_max_size(mut self, max_size: u64) -> Self { - self.max_size = max_size; - self + pub const fn with_max_size(self, max_size: u64) -> Self { + match self { + Self::V1(mut params) => { + params.max_size = max_size; + Self::V1(params) + } + } + } +} + +impl TxParameters { + /// Get the maximum number of inputs + pub const fn max_inputs(&self) -> u16 { + match self { + Self::V1(params) => params.max_inputs, + } + } + + /// Get the maximum number of outputs + pub const fn max_outputs(&self) -> u16 { + match self { + Self::V1(params) => params.max_outputs, + } + } + + /// Get the maximum number of witnesses + pub const fn max_witnesses(&self) -> u32 { + match self { + Self::V1(params) => params.max_witnesses, + } + } + + /// Get the maximum gas per transaction + pub const fn max_gas_per_tx(&self) -> u64 { + match self { + Self::V1(params) => params.max_gas_per_tx, + } + } + + /// Get the maximum size in bytes + pub const fn max_size(&self) -> u64 { + match self { + Self::V1(params) => params.max_size, + } } } @@ -543,6 +586,54 @@ impl Default for TxParameters { } } +#[cfg(feature = "builder")] +impl TxParameters { + pub fn set_max_size(&mut self, max_size: u64) { + match self { + Self::V1(params) => params.max_size = max_size, + } + } +} + +impl From for TxParameters { + fn from(params: TxParametersV1) -> Self { + Self::V1(params) + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(default))] +pub struct TxParametersV1 { + /// Maximum number of inputs. + pub max_inputs: u16, + /// Maximum number of outputs. + pub max_outputs: u16, + /// Maximum number of witnesses. + pub max_witnesses: u32, + /// Maximum gas per transaction. + pub max_gas_per_tx: u64, + /// Maximum size in bytes + pub max_size: u64, +} + +impl TxParametersV1 { + /// Default parameters just for testing. + pub const DEFAULT: Self = Self { + max_inputs: 255, + max_outputs: 255, + max_witnesses: 255, + max_gas_per_tx: MAX_GAS, + max_size: MAX_SIZE, + }; +} + +impl Default for TxParametersV1 { + fn default() -> Self { + Self::DEFAULT + } +} + /// Versioned script parameters. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -577,14 +668,14 @@ impl ScriptParameters { impl ScriptParameters { /// Get the maximum script length - pub fn max_script_length(&self) -> u64 { + pub const fn max_script_length(&self) -> u64 { match self { Self::V1(params) => params.max_script_length, } } /// Get the maximum script data length - pub fn max_script_data_length(&self) -> u64 { + pub const fn max_script_data_length(&self) -> u64 { match self { Self::V1(params) => params.max_script_data_length, } @@ -661,14 +752,14 @@ impl ContractParameters { impl ContractParameters { /// Get the maximum contract size - pub fn contract_max_size(&self) -> u64 { + pub const fn contract_max_size(&self) -> u64 { match self { Self::V1(params) => params.contract_max_size, } } /// Get the maximum storage slots - pub fn max_storage_slots(&self) -> u64 { + pub const fn max_storage_slots(&self) -> u64 { match self { Self::V1(params) => params.max_storage_slots, } diff --git a/fuel-tx/src/transaction/types/script.rs b/fuel-tx/src/transaction/types/script.rs index 5305029888..6e61b59fb1 100644 --- a/fuel-tx/src/transaction/types/script.rs +++ b/fuel-tx/src/transaction/types/script.rs @@ -85,7 +85,7 @@ impl Default for Script { // We want to use any values much less than `max_gas_per_tx` // to avoid the `TransactionMaxGasExceeded` error. For example, // `max_gas_per_tx / 4`. - script_gas_limit: TxParameters::DEFAULT.max_gas_per_tx / 4, + script_gas_limit: TxParameters::DEFAULT.max_gas_per_tx() / 4, script, script_data: Default::default(), policies: Policies::new() diff --git a/fuel-tx/src/transaction/validity.rs b/fuel-tx/src/transaction/validity.rs index 38f105fdd2..98d9350272 100644 --- a/fuel-tx/src/transaction/validity.rs +++ b/fuel-tx/src/transaction/validity.rs @@ -302,7 +302,7 @@ pub(crate) fn check_size(tx: &T, tx_params: &TxParameters) -> Result<(), Vali where T: canonical::Serialize, { - if tx.size() as u64 > tx_params.max_size { + if tx.size() as u64 > tx_params.max_size() { Err(ValidityError::TransactionSizeLimitExceeded)?; } @@ -337,7 +337,7 @@ where } let max_gas = tx.max_gas(gas_costs, fee_params); - if max_gas > tx_params.max_gas_per_tx { + if max_gas > tx_params.max_gas_per_tx() { Err(ValidityError::TransactionMaxGasExceeded)? } @@ -349,15 +349,15 @@ where Err(ValidityError::TransactionMaturity)?; } - if tx.inputs().len() > tx_params.max_inputs as usize { + if tx.inputs().len() > tx_params.max_inputs() as usize { Err(ValidityError::TransactionInputsMax)? } - if tx.outputs().len() > tx_params.max_outputs as usize { + if tx.outputs().len() > tx_params.max_outputs() as usize { Err(ValidityError::TransactionOutputsMax)? } - if tx.witnesses().len() > tx_params.max_witnesses as usize { + if tx.witnesses().len() > tx_params.max_witnesses() as usize { Err(ValidityError::TransactionWitnessesMax)? } diff --git a/fuel-vm/src/checked_transaction.rs b/fuel-vm/src/checked_transaction.rs index 6d6616f28c..18f8806241 100644 --- a/fuel-vm/src/checked_transaction.rs +++ b/fuel-vm/src/checked_transaction.rs @@ -352,8 +352,8 @@ impl From<&ConsensusParameters> for CheckPredicateParams { gas_costs: value.gas_costs().clone(), chain_id: value.chain_id(), max_gas_per_predicate: value.predicate_params().max_gas_per_predicate(), - max_gas_per_tx: value.tx_params().max_gas_per_tx, - max_inputs: value.tx_params().max_inputs, + max_gas_per_tx: value.tx_params().max_gas_per_tx(), + max_inputs: value.tx_params().max_inputs(), contract_max_size: value.contract_params().contract_max_size(), max_message_data_length: value.predicate_params().max_message_data_length(), tx_offset: value.tx_params().tx_offset(), diff --git a/fuel-vm/src/interpreter.rs b/fuel-vm/src/interpreter.rs index 96d23d5ee3..66bcbf2ae6 100644 --- a/fuel-vm/src/interpreter.rs +++ b/fuel-vm/src/interpreter.rs @@ -162,7 +162,7 @@ impl Default for InterpreterParams { Self { gas_price: 0, gas_costs: Default::default(), - max_inputs: TxParameters::DEFAULT.max_inputs, + max_inputs: TxParameters::DEFAULT.max_inputs(), contract_max_size: ContractParameters::DEFAULT.contract_max_size(), tx_offset: TxParameters::DEFAULT.tx_offset(), max_message_data_length: PredicateParameters::DEFAULT diff --git a/fuel-vm/src/tests/limits.rs b/fuel-vm/src/tests/limits.rs index 66ac1ce09b..5976232d55 100644 --- a/fuel-vm/src/tests/limits.rs +++ b/fuel-vm/src/tests/limits.rs @@ -25,7 +25,7 @@ fn cannot_exceed_max_inputs() { vec![op::ret(RegId::ONE)].into_iter().collect(), vec![], ); - for _ in 0..=params.tx_params().max_inputs { + for _ in 0..=params.tx_params().max_inputs() { script.add_input(Input::coin_signed( rng.gen(), rng.gen(), @@ -50,7 +50,7 @@ fn cannot_exceed_max_outputs() { vec![op::ret(RegId::ONE)].into_iter().collect(), vec![], ); - for _ in 0..=params.tx_params().max_outputs { + for _ in 0..=params.tx_params().max_outputs() { script.add_output(Output::variable(rng.gen(), rng.gen(), rng.gen())); } script @@ -68,7 +68,7 @@ fn cannot_exceed_max_witnesses() { vec![op::ret(RegId::ONE)].into_iter().collect(), vec![], ); - for _ in 0..=params.tx_params().max_witnesses { + for _ in 0..=params.tx_params().max_witnesses() { script.add_witness(Witness::from(vec![rng.gen::(); 1])); } script diff --git a/fuel-vm/src/tests/validation.rs b/fuel-vm/src/tests/validation.rs index 80b2508c28..9cc8e68bc3 100644 --- a/fuel-vm/src/tests/validation.rs +++ b/fuel-vm/src/tests/validation.rs @@ -63,7 +63,7 @@ fn malleable_fields_do_not_affect_validity() { let params = ConsensusParameters::default(); let tx_size_ptr = - 32 + (params.tx_params().max_inputs as usize * (AssetId::LEN + WORD_SIZE)); + 32 + (params.tx_params().max_inputs() as usize * (AssetId::LEN + WORD_SIZE)); let tx_start_ptr = tx_size_ptr + 8; let tx = TransactionBuilder::script( diff --git a/fuel-vm/src/util.rs b/fuel-vm/src/util.rs index e8348e7ce9..aef8e59997 100644 --- a/fuel-vm/src/util.rs +++ b/fuel-vm/src/util.rs @@ -609,7 +609,7 @@ pub mod test_helpers { let tx_params = TxParameters::default().with_max_gas_per_tx(Word::MAX / 2); // The gas should be huge enough to cover the execution but still much less than // `MAX_GAS_PER_TX`. - let gas_limit = tx_params.max_gas_per_tx / 2; + let gas_limit = tx_params.max_gas_per_tx() / 2; let maturity = Default::default(); let height = Default::default(); let zero_fee_limit = 0; From 34aa7dc030692b37586d2457ca6949c96259afd4 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 21 Mar 2024 22:00:48 +0100 Subject: [PATCH 07/13] Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc291f717d..e0ac23dd70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). #### Breaking +- [#702](https://github.com/FuelLabs/fuel-vm/pull/702): Wrapped `FeeParameters`, `PredicateParameters`, `TxParameters`, `ScriptParameters` and `ContractParameters` into an enum to support versioning. - [#701](https://github.com/FuelLabs/fuel-vm/pull/701): Wrapped `ConsensusParameters` and `GasCosts` into an enum to support versioning. Moved `block_gas_limit` from `fuel_core_chain_config::ChainConfig` to `ConsensusPataremeters`. Reduced default `MAX_SIZE` to be [110kb](https://github.com/FuelLabs/fuel-core/pull/1761) and `MAX_CONTRACT_SIZE` to be [100kb](https://github.com/FuelLabs/fuel-core/pull/1761). - [#692](https://github.com/FuelLabs/fuel-vm/pull/692): Add GTF getters for tx size and address. - [#698](https://github.com/FuelLabs/fuel-vm/pull/698): Store input, output and witness limits to u16, while keeping the values limited to 255. From 0ca4ddfeff7aa8be6a1822daf99abff13d1bda2d Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 21 Mar 2024 22:59:17 +0100 Subject: [PATCH 08/13] Make CI happy --- .npm/packages/fuel-tx/index.test.cjs | 460 +++++++++--------- .npm/packages/fuel-tx/index.test.mjs | 460 +++++++++--------- .../src/transaction/consensus_parameters.rs | 7 +- 3 files changed, 461 insertions(+), 466 deletions(-) diff --git a/.npm/packages/fuel-tx/index.test.cjs b/.npm/packages/fuel-tx/index.test.cjs index f1c6683875..ae6d8d5b77 100644 --- a/.npm/packages/fuel-tx/index.test.cjs +++ b/.npm/packages/fuel-tx/index.test.cjs @@ -1,243 +1,243 @@ -const { expect } = require('chai') +const {expect} = require('chai') const path = require('node:path') const fs = require('node:fs') const tx = require('.') describe('fuel-tx [cjs]', () => { - it('should export all types', () => { - expect(tx.UtxoId).to.be.ok - expect(tx.TxPointer).to.be.ok - expect(tx.PredicateParameters).to.be.ok - expect(tx.Input).to.be.ok - expect(tx.Output).to.be.ok - expect(tx.Script).to.be.ok - expect(tx.Create).to.be.ok - expect(tx.Mint).to.be.ok - expect(tx.Transaction).to.be.ok - expect(tx.Policies).to.be.ok - }) - - it('should serialize and deserialize UtxoId correctly', () => { - let utxo_id = new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b00001a"); - let bytes = utxo_id.to_bytes(); - let utxo_id2 = tx.UtxoId.from_bytes(bytes); - expect(utxo_id.toString()).to.equal(utxo_id2.toString()) - }) - - it('should serialize and deserialize TxPointer correctly', () => { - let utxo_id = new tx.TxPointer("0123456789ab"); - let bytes = utxo_id.to_bytes(); - let utxo_id2 = tx.TxPointer.from_bytes(bytes); - expect(utxo_id.toString()).to.equal(utxo_id2.toString()) - }) - - - it('should serialize and deserialize all input variants correctly', () => { - [ - tx.Input.coin_predicate( - new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), - tx.Address.zeroed(), - 1234n, - tx.AssetId.zeroed(), - new tx.TxPointer("0123456789ab"), - 9012n, - [1, 2, 3, 4], - [5, 6, 7, 8], - ), - tx.Input.coin_signed( - new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), - tx.Address.zeroed(), - BigInt(1234), - tx.AssetId.zeroed(), - new tx.TxPointer("0123456789ab"), - 2, - ), - tx.Input.contract( - new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), - tx.Bytes32.zeroed(), - tx.Bytes32.zeroed(), - new tx.TxPointer("0123456789ab"), - tx.ContractId.zeroed(), - ), - tx.Input.message_coin_signed( - tx.Address.zeroed(), - tx.Address.zeroed(), - BigInt(1234), - tx.Nonce.zeroed(), - 2, - ), - tx.Input.message_coin_predicate( - tx.Address.zeroed(), - tx.Address.zeroed(), - BigInt(1234), - tx.Nonce.zeroed(), - BigInt(1234), - [1, 2, 3, 4], - [5, 6, 7, 8], - ), - tx.Input.message_data_signed( - tx.Address.zeroed(), - tx.Address.zeroed(), - BigInt(1234), - tx.Nonce.zeroed(), - 2, - [1, 2, 3, 4], - ), - tx.Input.message_data_predicate( - tx.Address.zeroed(), - tx.Address.zeroed(), - BigInt(1234), - tx.Nonce.zeroed(), - BigInt(1234), - [0, 1, 2, 3], - [1, 2, 3, 4], - [5, 6, 7, 8], - ), - ].forEach(input => { - let bytes = input.to_bytes(); - let input2 = tx.Input.from_bytes(bytes); - expect(input.toString()).to.equal(input2.toString()) + it('should export all types', () => { + expect(tx.UtxoId).to.be.ok + expect(tx.TxPointer).to.be.ok + expect(tx.PredicateParameters).to.be.ok + expect(tx.Input).to.be.ok + expect(tx.Output).to.be.ok + expect(tx.Script).to.be.ok + expect(tx.Create).to.be.ok + expect(tx.Mint).to.be.ok + expect(tx.Transaction).to.be.ok + expect(tx.Policies).to.be.ok }) - }) - - - it('should serialize and deserialize all output variants correctly', () => { - [ - tx.Output.coin( - tx.Address.zeroed(), - BigInt(1234), - tx.AssetId.zeroed(), - ), - tx.Output.contract( - 2, - tx.Bytes32.zeroed(), - tx.Bytes32.zeroed(), - ), - tx.Output.change( - tx.Address.zeroed(), - BigInt(1234), - tx.AssetId.zeroed(), - ), - tx.Output.variable( - tx.Address.zeroed(), - BigInt(1234), - tx.AssetId.zeroed(), - ), - tx.Output.contract_created( - tx.ContractId.zeroed(), - tx.Bytes32.zeroed(), - ), - ].forEach(output => { - let bytes = output.to_bytes(); - let output2 = tx.Output.from_bytes(bytes); - expect(output.toString()).to.equal(output2.toString()) + + it('should serialize and deserialize UtxoId correctly', () => { + let utxo_id = new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b00001a"); + let bytes = utxo_id.to_bytes(); + let utxo_id2 = tx.UtxoId.from_bytes(bytes); + expect(utxo_id.toString()).to.equal(utxo_id2.toString()) }) - }) - - - it('should serialize and deserialize all transaction variants correctly', () => { - [ - [tx.Script, tx.Transaction.script( - 1234n, - [1, 2, 3, 4], - [5, 6, 7, 8], - new tx.Policies(), - [], - [], - [], - )], - [tx.Create, tx.Transaction.create( - 1, - new tx.Policies(), - tx.Salt.zeroed(), - [], - [], - [], - [], - )], - [tx.Mint, tx.Transaction.mint( - new tx.TxPointer("0123456789ab"), - new tx.InputContract( - new tx.UtxoId("0xc49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2:18ab"), - tx.Bytes32.zeroed(), - tx.Bytes32.zeroed(), - new tx.TxPointer("0123456789ab"), - tx.ContractId.zeroed(), - ), - new tx.OutputContract( - 3, - tx.Bytes32.zeroed(), - tx.Bytes32.zeroed(), - ), - 1234n, - tx.AssetId.zeroed(), - 1234n, - )], - ].forEach(([tx_variant_type, tx_variant]) => { - let bytes = tx_variant.to_bytes(); - let tx_variant2 = tx_variant_type.from_bytes(bytes); - expect(tx_variant.toString()).to.equal(tx_variant2.toString()) - - let wrapped_tx = tx_variant.as_tx(); - let tx_bytes = wrapped_tx.to_bytes(); - let wrapped_tx2 = tx.Transaction.from_bytes(tx_bytes); - expect(wrapped_tx.toString()).to.equal(wrapped_tx2.toString()) + + it('should serialize and deserialize TxPointer correctly', () => { + let utxo_id = new tx.TxPointer("0123456789ab"); + let bytes = utxo_id.to_bytes(); + let utxo_id2 = tx.TxPointer.from_bytes(bytes); + expect(utxo_id.toString()).to.equal(utxo_id2.toString()) }) - }) - // Hex string to byte string conversion. - const hexToBytes = hex => { - if (hex.length % 2 != 0) { - throw new Error("Needs full bytes"); - } - const lookup = "0123456789abcdef"; - let result = new Uint8Array(hex.length / 2); - for (let i = 0; i < result.length; i += 1) { - let high = lookup.indexOf(hex[i * 2]); - let low = lookup.indexOf(hex[i * 2 + 1]); - if (high === -1 || low === -1) { - throw new Error("Invalid hex char"); - } - result[i] = (high << 4) | low; + + it('should serialize and deserialize all input variants correctly', () => { + [ + tx.Input.coin_predicate( + new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), + tx.Address.zeroed(), + 1234n, + tx.AssetId.zeroed(), + new tx.TxPointer("0123456789ab"), + 9012n, + [1, 2, 3, 4], + [5, 6, 7, 8], + ), + tx.Input.coin_signed( + new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), + tx.Address.zeroed(), + BigInt(1234), + tx.AssetId.zeroed(), + new tx.TxPointer("0123456789ab"), + 2, + ), + tx.Input.contract( + new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), + tx.Bytes32.zeroed(), + tx.Bytes32.zeroed(), + new tx.TxPointer("0123456789ab"), + tx.ContractId.zeroed(), + ), + tx.Input.message_coin_signed( + tx.Address.zeroed(), + tx.Address.zeroed(), + BigInt(1234), + tx.Nonce.zeroed(), + 2, + ), + tx.Input.message_coin_predicate( + tx.Address.zeroed(), + tx.Address.zeroed(), + BigInt(1234), + tx.Nonce.zeroed(), + BigInt(1234), + [1, 2, 3, 4], + [5, 6, 7, 8], + ), + tx.Input.message_data_signed( + tx.Address.zeroed(), + tx.Address.zeroed(), + BigInt(1234), + tx.Nonce.zeroed(), + 2, + [1, 2, 3, 4], + ), + tx.Input.message_data_predicate( + tx.Address.zeroed(), + tx.Address.zeroed(), + BigInt(1234), + tx.Nonce.zeroed(), + BigInt(1234), + [0, 1, 2, 3], + [1, 2, 3, 4], + [5, 6, 7, 8], + ), + ].forEach(input => { + let bytes = input.to_bytes(); + let input2 = tx.Input.from_bytes(bytes); + expect(input.toString()).to.equal(input2.toString()) + }) + }) + + + it('should serialize and deserialize all output variants correctly', () => { + [ + tx.Output.coin( + tx.Address.zeroed(), + BigInt(1234), + tx.AssetId.zeroed(), + ), + tx.Output.contract( + 2, + tx.Bytes32.zeroed(), + tx.Bytes32.zeroed(), + ), + tx.Output.change( + tx.Address.zeroed(), + BigInt(1234), + tx.AssetId.zeroed(), + ), + tx.Output.variable( + tx.Address.zeroed(), + BigInt(1234), + tx.AssetId.zeroed(), + ), + tx.Output.contract_created( + tx.ContractId.zeroed(), + tx.Bytes32.zeroed(), + ), + ].forEach(output => { + let bytes = output.to_bytes(); + let output2 = tx.Output.from_bytes(bytes); + expect(output.toString()).to.equal(output2.toString()) + }) + }) + + + it('should serialize and deserialize all transaction variants correctly', () => { + [ + [tx.Script, tx.Transaction.script( + 1234n, + [1, 2, 3, 4], + [5, 6, 7, 8], + new tx.Policies(), + [], + [], + [], + )], + [tx.Create, tx.Transaction.create( + 1, + new tx.Policies(), + tx.Salt.zeroed(), + [], + [], + [], + [], + )], + [tx.Mint, tx.Transaction.mint( + new tx.TxPointer("0123456789ab"), + new tx.InputContract( + new tx.UtxoId("0xc49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2:18ab"), + tx.Bytes32.zeroed(), + tx.Bytes32.zeroed(), + new tx.TxPointer("0123456789ab"), + tx.ContractId.zeroed(), + ), + new tx.OutputContract( + 3, + tx.Bytes32.zeroed(), + tx.Bytes32.zeroed(), + ), + 1234n, + tx.AssetId.zeroed(), + 1234n, + )], + ].forEach(([tx_variant_type, tx_variant]) => { + let bytes = tx_variant.to_bytes(); + let tx_variant2 = tx_variant_type.from_bytes(bytes); + expect(tx_variant.toString()).to.equal(tx_variant2.toString()) + + let wrapped_tx = tx_variant.as_tx(); + let tx_bytes = wrapped_tx.to_bytes(); + let wrapped_tx2 = tx.Transaction.from_bytes(tx_bytes); + expect(wrapped_tx.toString()).to.equal(wrapped_tx2.toString()) + }) + }) + + // Hex string to byte string conversion. + const hexToBytes = hex => { + if (hex.length % 2 != 0) { + throw new Error("Needs full bytes"); + } + const lookup = "0123456789abcdef"; + let result = new Uint8Array(hex.length / 2); + for (let i = 0; i < result.length; i += 1) { + let high = lookup.indexOf(hex[i * 2]); + let low = lookup.indexOf(hex[i * 2 + 1]); + if (high === -1 || low === -1) { + throw new Error("Invalid hex char"); + } + result[i] = (high << 4) | low; + } + return result; } - return result; - } - - it('should validate input correctly', () => { - let input = tx.Input.coin_signed( - new tx.UtxoId("0xc49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2:18ab"), - tx.Address.from_bytes(hexToBytes("f1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e")), - 10599410012256088338n, - tx.AssetId.from_bytes(hexToBytes("2cafad611543e0265d89f1c2b60d9ebf5d56ad7e23d9827d6b522fd4d6e44bc3")), - new tx.TxPointer("000000000000"), - 0, - new tx.BlockHeight(0), - ); - - tx.check_input(input, 0, tx.Bytes32.from_bytes(hexToBytes("108eae4147d2c1c86ef4c2ab7c9fe94126645c8d8737495a0574ef1518ae74d8")), [], [{ data: hexToBytes("7ce4de2225f041b7f9fec727343a501d99e5b7b58d33f3d4a2cf218d3489959bdec24d13770b5d3bb084b4dac3474f95153e6ecc98f6f0f8ca37a2897b9562ee") }], new tx.PredicateParameters()); - }) - - it('should validate output correctly', () => { - let output = tx.Output.change( - tx.Address.zeroed(), - 1234n, - tx.AssetId.zeroed(), - ); - - tx.check_output(output, 0, []); - }) - - it('should be able to deserialize snapshots', () => { - const snapshots = '../../../fuel-tx/src/transaction/types/input/snapshots'; - fs.readdirSync(snapshots).forEach(file => { - fs.readFile(path.join(snapshots, file), 'utf8', (err, data) => { - expect(err).to.be.null; - let dataBytes = hexToBytes(data.split('---\n').at(-1).trim()); - let inTx = tx.Transaction.from_bytes(dataBytes); - let serialized = inTx.to_bytes(); - expect(serialized.toString()).to.eq(dataBytes.toString()); - }) + + it('should validate input correctly', () => { + let input = tx.Input.coin_signed( + new tx.UtxoId("0xc49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2:18ab"), + tx.Address.from_bytes(hexToBytes("f1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e")), + 10599410012256088338n, + tx.AssetId.from_bytes(hexToBytes("2cafad611543e0265d89f1c2b60d9ebf5d56ad7e23d9827d6b522fd4d6e44bc3")), + new tx.TxPointer("000000000000"), + 0, + new tx.BlockHeight(0), + ); + + tx.check_input(input, 0, tx.Bytes32.from_bytes(hexToBytes("108eae4147d2c1c86ef4c2ab7c9fe94126645c8d8737495a0574ef1518ae74d8")), [], [{data: hexToBytes("7ce4de2225f041b7f9fec727343a501d99e5b7b58d33f3d4a2cf218d3489959bdec24d13770b5d3bb084b4dac3474f95153e6ecc98f6f0f8ca37a2897b9562ee")}], new tx.PredicateParameters(10000n, 10000n, 10000n, 10000n)); + }) + + it('should validate output correctly', () => { + let output = tx.Output.change( + tx.Address.zeroed(), + 1234n, + tx.AssetId.zeroed(), + ); + + tx.check_output(output, 0, []); + }) + + it('should be able to deserialize snapshots', () => { + const snapshots = '../../../fuel-tx/src/transaction/types/input/snapshots'; + fs.readdirSync(snapshots).forEach(file => { + fs.readFile(path.join(snapshots, file), 'utf8', (err, data) => { + expect(err).to.be.null; + let dataBytes = hexToBytes(data.split('---\n').at(-1).trim()); + let inTx = tx.Transaction.from_bytes(dataBytes); + let serialized = inTx.to_bytes(); + expect(serialized.toString()).to.eq(dataBytes.toString()); + }) + }) }) - }) }) diff --git a/.npm/packages/fuel-tx/index.test.mjs b/.npm/packages/fuel-tx/index.test.mjs index dda3bc9981..d0a960efc1 100644 --- a/.npm/packages/fuel-tx/index.test.mjs +++ b/.npm/packages/fuel-tx/index.test.mjs @@ -1,243 +1,243 @@ -import { expect } from 'chai' +import {expect} from 'chai' import * as path from 'node:path' import * as fs from 'node:fs' import * as tx from './dist/web/index.mjs' describe('fuel-tx [mjs]', () => { - it('should export all types', () => { - expect(tx.UtxoId).to.be.ok - expect(tx.TxPointer).to.be.ok - expect(tx.PredicateParameters).to.be.ok - expect(tx.Input).to.be.ok - expect(tx.Output).to.be.ok - expect(tx.Script).to.be.ok - expect(tx.Create).to.be.ok - expect(tx.Mint).to.be.ok - expect(tx.Transaction).to.be.ok - expect(tx.Policies).to.be.ok - }) - - it('should serialize and deserialize UtxoId correctly', () => { - let utxo_id = new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"); - let bytes = utxo_id.to_bytes(); - let utxo_id2 = tx.UtxoId.from_bytes(bytes); - expect(utxo_id.toString()).to.equal(utxo_id2.toString()) - }) - - it('should serialize and deserialize TxPointer correctly', () => { - let utxo_id = new tx.TxPointer("0123456789ab"); - let bytes = utxo_id.to_bytes(); - let utxo_id2 = tx.TxPointer.from_bytes(bytes); - expect(utxo_id.toString()).to.equal(utxo_id2.toString()) - }) - - - it('should serialize and deserialize all input variants correctly', () => { - [ - tx.Input.coin_predicate( - new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), - tx.Address.zeroed(), - BigInt(1234), - tx.AssetId.zeroed(), - new tx.TxPointer("0123456789ab"), - BigInt(9012), - [1, 2, 3, 4], - [5, 6, 7, 8], - ), - tx.Input.coin_signed( - new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), - tx.Address.zeroed(), - BigInt(1234), - tx.AssetId.zeroed(), - new tx.TxPointer("0123456789ab"), - 2, - ), - tx.Input.contract( - new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), - tx.Bytes32.zeroed(), - tx.Bytes32.zeroed(), - new tx.TxPointer("0123456789ab"), - tx.ContractId.zeroed(), - ), - tx.Input.message_coin_signed( - tx.Address.zeroed(), - tx.Address.zeroed(), - BigInt(1234), - tx.Nonce.zeroed(), - 2, - ), - tx.Input.message_coin_predicate( - tx.Address.zeroed(), - tx.Address.zeroed(), - BigInt(1234), - tx.Nonce.zeroed(), - BigInt(1234), - [1, 2, 3, 4], - [5, 6, 7, 8], - ), - tx.Input.message_data_signed( - tx.Address.zeroed(), - tx.Address.zeroed(), - BigInt(1234), - tx.Nonce.zeroed(), - 2, - [1, 2, 3, 4], - ), - tx.Input.message_data_predicate( - tx.Address.zeroed(), - tx.Address.zeroed(), - BigInt(1234), - tx.Nonce.zeroed(), - BigInt(1234), - [0, 1, 2, 3], - [1, 2, 3, 4], - [5, 6, 7, 8], - ), - ].forEach(input => { - let bytes = input.to_bytes(); - let input2 = tx.Input.from_bytes(bytes); - expect(input.toString()).to.equal(input2.toString()) + it('should export all types', () => { + expect(tx.UtxoId).to.be.ok + expect(tx.TxPointer).to.be.ok + expect(tx.PredicateParameters).to.be.ok + expect(tx.Input).to.be.ok + expect(tx.Output).to.be.ok + expect(tx.Script).to.be.ok + expect(tx.Create).to.be.ok + expect(tx.Mint).to.be.ok + expect(tx.Transaction).to.be.ok + expect(tx.Policies).to.be.ok }) - }) - - - it('should serialize and deserialize all output variants correctly', () => { - [ - tx.Output.coin( - tx.Address.zeroed(), - BigInt(1234), - tx.AssetId.zeroed(), - ), - tx.Output.contract( - 2, - tx.Bytes32.zeroed(), - tx.Bytes32.zeroed(), - ), - tx.Output.change( - tx.Address.zeroed(), - BigInt(1234), - tx.AssetId.zeroed(), - ), - tx.Output.variable( - tx.Address.zeroed(), - BigInt(1234), - tx.AssetId.zeroed(), - ), - tx.Output.contract_created( - tx.ContractId.zeroed(), - tx.Bytes32.zeroed(), - ), - ].forEach(output => { - let bytes = output.to_bytes(); - let output2 = tx.Output.from_bytes(bytes); - expect(output.toString()).to.equal(output2.toString()) + + it('should serialize and deserialize UtxoId correctly', () => { + let utxo_id = new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"); + let bytes = utxo_id.to_bytes(); + let utxo_id2 = tx.UtxoId.from_bytes(bytes); + expect(utxo_id.toString()).to.equal(utxo_id2.toString()) }) - }) - - - it('should serialize and deserialize all transaction variants correctly', () => { - [ - [tx.Script, tx.Transaction.script( - 1234n, - [1, 2, 3, 4], - [5, 6, 7, 8], - new tx.Policies(), - [], - [], - [], - )], - [tx.Create, tx.Transaction.create( - 1, - new tx.Policies(), - tx.Salt.zeroed(), - [], - [], - [], - [], - )], - [tx.Mint, tx.Transaction.mint( - new tx.TxPointer("0123456789ab"), - new tx.InputContract( - new tx.UtxoId("0xc49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2:18ab"), - tx.Bytes32.zeroed(), - tx.Bytes32.zeroed(), - new tx.TxPointer("0123456789ab"), - tx.ContractId.zeroed(), - ), - new tx.OutputContract( - 3, - tx.Bytes32.zeroed(), - tx.Bytes32.zeroed(), - ), - 1234n, - tx.AssetId.zeroed(), - 1234n, - )], - ].forEach(([tx_variant_type, tx_variant]) => { - let bytes = tx_variant.to_bytes(); - let tx_variant2 = tx_variant_type.from_bytes(bytes); - expect(tx_variant.toString()).to.equal(tx_variant2.toString()) - - let wrapped_tx = tx_variant.as_tx(); - let tx_bytes = wrapped_tx.to_bytes(); - let wrapped_tx2 = tx.Transaction.from_bytes(tx_bytes); - expect(wrapped_tx.toString()).to.equal(wrapped_tx2.toString()) + + it('should serialize and deserialize TxPointer correctly', () => { + let utxo_id = new tx.TxPointer("0123456789ab"); + let bytes = utxo_id.to_bytes(); + let utxo_id2 = tx.TxPointer.from_bytes(bytes); + expect(utxo_id.toString()).to.equal(utxo_id2.toString()) }) - }) - // Hex string to byte string conversion. - const hexToBytes = hex => { - if (hex.length % 2 != 0) { - throw new Error("Needs full bytes"); - } - const lookup = "0123456789abcdef"; - let result = new Uint8Array(hex.length / 2); - for (let i = 0; i < result.length; i += 1) { - let high = lookup.indexOf(hex[i * 2]); - let low = lookup.indexOf(hex[i * 2 + 1]); - if (high === -1 || low === -1) { - throw new Error("Invalid hex char"); - } - result[i] = (high << 4) | low; + + it('should serialize and deserialize all input variants correctly', () => { + [ + tx.Input.coin_predicate( + new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), + tx.Address.zeroed(), + BigInt(1234), + tx.AssetId.zeroed(), + new tx.TxPointer("0123456789ab"), + BigInt(9012), + [1, 2, 3, 4], + [5, 6, 7, 8], + ), + tx.Input.coin_signed( + new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), + tx.Address.zeroed(), + BigInt(1234), + tx.AssetId.zeroed(), + new tx.TxPointer("0123456789ab"), + 2, + ), + tx.Input.contract( + new tx.UtxoId("0x0c0000000000000000000000000000000000000000000000000000000000000b001a"), + tx.Bytes32.zeroed(), + tx.Bytes32.zeroed(), + new tx.TxPointer("0123456789ab"), + tx.ContractId.zeroed(), + ), + tx.Input.message_coin_signed( + tx.Address.zeroed(), + tx.Address.zeroed(), + BigInt(1234), + tx.Nonce.zeroed(), + 2, + ), + tx.Input.message_coin_predicate( + tx.Address.zeroed(), + tx.Address.zeroed(), + BigInt(1234), + tx.Nonce.zeroed(), + BigInt(1234), + [1, 2, 3, 4], + [5, 6, 7, 8], + ), + tx.Input.message_data_signed( + tx.Address.zeroed(), + tx.Address.zeroed(), + BigInt(1234), + tx.Nonce.zeroed(), + 2, + [1, 2, 3, 4], + ), + tx.Input.message_data_predicate( + tx.Address.zeroed(), + tx.Address.zeroed(), + BigInt(1234), + tx.Nonce.zeroed(), + BigInt(1234), + [0, 1, 2, 3], + [1, 2, 3, 4], + [5, 6, 7, 8], + ), + ].forEach(input => { + let bytes = input.to_bytes(); + let input2 = tx.Input.from_bytes(bytes); + expect(input.toString()).to.equal(input2.toString()) + }) + }) + + + it('should serialize and deserialize all output variants correctly', () => { + [ + tx.Output.coin( + tx.Address.zeroed(), + BigInt(1234), + tx.AssetId.zeroed(), + ), + tx.Output.contract( + 2, + tx.Bytes32.zeroed(), + tx.Bytes32.zeroed(), + ), + tx.Output.change( + tx.Address.zeroed(), + BigInt(1234), + tx.AssetId.zeroed(), + ), + tx.Output.variable( + tx.Address.zeroed(), + BigInt(1234), + tx.AssetId.zeroed(), + ), + tx.Output.contract_created( + tx.ContractId.zeroed(), + tx.Bytes32.zeroed(), + ), + ].forEach(output => { + let bytes = output.to_bytes(); + let output2 = tx.Output.from_bytes(bytes); + expect(output.toString()).to.equal(output2.toString()) + }) + }) + + + it('should serialize and deserialize all transaction variants correctly', () => { + [ + [tx.Script, tx.Transaction.script( + 1234n, + [1, 2, 3, 4], + [5, 6, 7, 8], + new tx.Policies(), + [], + [], + [], + )], + [tx.Create, tx.Transaction.create( + 1, + new tx.Policies(), + tx.Salt.zeroed(), + [], + [], + [], + [], + )], + [tx.Mint, tx.Transaction.mint( + new tx.TxPointer("0123456789ab"), + new tx.InputContract( + new tx.UtxoId("0xc49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2:18ab"), + tx.Bytes32.zeroed(), + tx.Bytes32.zeroed(), + new tx.TxPointer("0123456789ab"), + tx.ContractId.zeroed(), + ), + new tx.OutputContract( + 3, + tx.Bytes32.zeroed(), + tx.Bytes32.zeroed(), + ), + 1234n, + tx.AssetId.zeroed(), + 1234n, + )], + ].forEach(([tx_variant_type, tx_variant]) => { + let bytes = tx_variant.to_bytes(); + let tx_variant2 = tx_variant_type.from_bytes(bytes); + expect(tx_variant.toString()).to.equal(tx_variant2.toString()) + + let wrapped_tx = tx_variant.as_tx(); + let tx_bytes = wrapped_tx.to_bytes(); + let wrapped_tx2 = tx.Transaction.from_bytes(tx_bytes); + expect(wrapped_tx.toString()).to.equal(wrapped_tx2.toString()) + }) + }) + + // Hex string to byte string conversion. + const hexToBytes = hex => { + if (hex.length % 2 != 0) { + throw new Error("Needs full bytes"); + } + const lookup = "0123456789abcdef"; + let result = new Uint8Array(hex.length / 2); + for (let i = 0; i < result.length; i += 1) { + let high = lookup.indexOf(hex[i * 2]); + let low = lookup.indexOf(hex[i * 2 + 1]); + if (high === -1 || low === -1) { + throw new Error("Invalid hex char"); + } + result[i] = (high << 4) | low; + } + return result; } - return result; - } - - it('should validate input correctly', () => { - let input = tx.Input.coin_signed( - new tx.UtxoId("0xc49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2:18ab"), - tx.Address.from_bytes(hexToBytes("f1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e")), - 10599410012256088338n, - tx.AssetId.from_bytes(hexToBytes("2cafad611543e0265d89f1c2b60d9ebf5d56ad7e23d9827d6b522fd4d6e44bc3")), - new tx.TxPointer("000000000000"), - 0, - new tx.BlockHeight(0), - ); - - tx.check_input(input, 0, tx.Bytes32.from_bytes(hexToBytes("108eae4147d2c1c86ef4c2ab7c9fe94126645c8d8737495a0574ef1518ae74d8")), [], [{ data: hexToBytes("7ce4de2225f041b7f9fec727343a501d99e5b7b58d33f3d4a2cf218d3489959bdec24d13770b5d3bb084b4dac3474f95153e6ecc98f6f0f8ca37a2897b9562ee") }], new tx.PredicateParameters()); - }) - - it('should validate output correctly', () => { - let output = tx.Output.change( - tx.Address.zeroed(), - 1234n, - tx.AssetId.zeroed(), - ); - - tx.check_output(output, 0, []); - }) - - it('should be able to deserialize snapshots', () => { - const snapshots = '../../../fuel-tx/src/transaction/types/input/snapshots'; - fs.readdirSync(snapshots).forEach(file => { - fs.readFile(path.join(snapshots, file), 'utf8', (err, data) => { - expect(err).to.be.null; - let dataBytes = hexToBytes(data.split('---\n').at(-1).trim()); - let inTx = tx.Transaction.from_bytes(dataBytes); - let serialized = inTx.to_bytes(); - expect(serialized.toString()).to.eq(dataBytes.toString()); - }) + + it('should validate input correctly', () => { + let input = tx.Input.coin_signed( + new tx.UtxoId("0xc49d65de61cf04588a764b557d25cc6c6b4bc0d7429227e2a21e61c213b3a3e2:18ab"), + tx.Address.from_bytes(hexToBytes("f1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e")), + 10599410012256088338n, + tx.AssetId.from_bytes(hexToBytes("2cafad611543e0265d89f1c2b60d9ebf5d56ad7e23d9827d6b522fd4d6e44bc3")), + new tx.TxPointer("000000000000"), + 0, + new tx.BlockHeight(0), + ); + + tx.check_input(input, 0, tx.Bytes32.from_bytes(hexToBytes("108eae4147d2c1c86ef4c2ab7c9fe94126645c8d8737495a0574ef1518ae74d8")), [], [{data: hexToBytes("7ce4de2225f041b7f9fec727343a501d99e5b7b58d33f3d4a2cf218d3489959bdec24d13770b5d3bb084b4dac3474f95153e6ecc98f6f0f8ca37a2897b9562ee")}], new tx.PredicateParameters(10000n, 10000n, 10000n, 10000n)); + }) + + it('should validate output correctly', () => { + let output = tx.Output.change( + tx.Address.zeroed(), + 1234n, + tx.AssetId.zeroed(), + ); + + tx.check_output(output, 0, []); + }) + + it('should be able to deserialize snapshots', () => { + const snapshots = '../../../fuel-tx/src/transaction/types/input/snapshots'; + fs.readdirSync(snapshots).forEach(file => { + fs.readFile(path.join(snapshots, file), 'utf8', (err, data) => { + expect(err).to.be.null; + let dataBytes = hexToBytes(data.split('---\n').at(-1).trim()); + let inTx = tx.Transaction.from_bytes(dataBytes); + let serialized = inTx.to_bytes(); + expect(serialized.toString()).to.eq(dataBytes.toString()); + }) + }) }) - }) }) diff --git a/fuel-tx/src/transaction/consensus_parameters.rs b/fuel-tx/src/transaction/consensus_parameters.rs index a76967f640..2d3b73c293 100644 --- a/fuel-tx/src/transaction/consensus_parameters.rs +++ b/fuel-tx/src/transaction/consensus_parameters.rs @@ -811,7 +811,7 @@ pub mod typescript { #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "typescript", wasm_bindgen::prelude::wasm_bindgen)] - pub struct PredicateParameters(Box); + pub struct PredicateParameters(alloc::boxed::Box); impl AsRef for PredicateParameters { fn as_ref(&self) -> &PredicateParametersRust { @@ -821,11 +821,6 @@ pub mod typescript { #[wasm_bindgen] impl PredicateParameters { - #[wasm_bindgen(constructor)] - pub fn typescript_default() -> Self { - PredicateParameters(PredicateParametersRust::DEFAULT.into()) - } - #[wasm_bindgen(constructor)] pub fn typescript_new( max_predicate_length: u64, From 5c5b009693e0413d5e0eaca215c1fcdda877d467 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Fri, 22 Mar 2024 14:23:24 +0100 Subject: [PATCH 09/13] Reshuffled fields `Script` and `Create` transactions to unify part used by all chargeable transactions --- fuel-tx/src/transaction.rs | 2 +- fuel-tx/src/transaction/types/create.rs | 52 +++++++++---------- ...shot_tests__tx_with_contract_snapshot.snap | 3 +- ...ests__tx_with_predicate_coin_snapshot.snap | 3 +- ...tests__tx_with_predicate_message_coin.snap | 3 +- ...tests__tx_with_predicate_message_data.snap | 3 +- ...t_tests__tx_with_signed_coin_snapshot.snap | 3 +- ...ot_tests__tx_with_signed_message_coin.snap | 3 +- ...ot_tests__tx_with_signed_message_data.snap | 3 +- fuel-tx/src/transaction/types/script.rs | 17 +++--- fuel-vm/src/tests/validation.rs | 12 ++--- 11 files changed, 48 insertions(+), 56 deletions(-) diff --git a/fuel-tx/src/transaction.rs b/fuel-tx/src/transaction.rs index d5ee80e686..370a7bbc18 100644 --- a/fuel-tx/src/transaction.rs +++ b/fuel-tx/src/transaction.rs @@ -724,7 +724,7 @@ pub mod field { pub trait StorageSlots { fn storage_slots(&self) -> &Vec; fn storage_slots_mut(&mut self) -> StorageSlotRef; - fn storage_slots_offset(&self) -> usize; + fn storage_slots_offset_static() -> usize; /// Returns the offset to the `StorageSlot` at `idx` index, if any. fn storage_slots_offset_at(&self, idx: usize) -> Option; diff --git a/fuel-tx/src/transaction/types/create.rs b/fuel-tx/src/transaction/types/create.rs index 585edd6ac9..c91bd46192 100644 --- a/fuel-tx/src/transaction/types/create.rs +++ b/fuel-tx/src/transaction/types/create.rs @@ -113,12 +113,12 @@ impl CreateMetadata { pub struct Create { pub(crate) bytecode_length: Word, pub(crate) bytecode_witness_index: u16, - pub(crate) policies: Policies, + pub(crate) salt: Salt, pub(crate) storage_slots: Vec, + pub(crate) policies: Policies, pub(crate) inputs: Vec, pub(crate) outputs: Vec, pub(crate) witnesses: Vec, - pub(crate) salt: Salt, #[cfg_attr(feature = "serde", serde(skip))] #[derivative(PartialEq = "ignore", Hash = "ignore")] #[canonical(skip)] @@ -385,20 +385,6 @@ mod field { } } - impl PoliciesField for Create { - fn policies(&self) -> &Policies { - &self.policies - } - - fn policies_mut(&mut self) -> &mut Policies { - &mut self.policies - } - - fn policies_offset(&self) -> usize { - Self::salt_offset_static() + Salt::LEN - } - } - impl SaltField for Create { #[inline(always)] fn salt(&self) -> &Salt { @@ -413,11 +399,6 @@ mod field { #[inline(always)] fn salt_offset_static() -> usize { Self::bytecode_witness_index_offset_static() + WORD_SIZE - + WORD_SIZE // Policies size - + WORD_SIZE // Storage slots size - + WORD_SIZE // Inputs size - + WORD_SIZE // Outputs size - + WORD_SIZE // Witnesses size } } @@ -435,19 +416,39 @@ mod field { } #[inline(always)] - fn storage_slots_offset(&self) -> usize { - self.policies_offset() + self.policies.size_dynamic() + fn storage_slots_offset_static() -> usize { + Self::salt_offset_static() + Salt::LEN + + WORD_SIZE // Policies size + + WORD_SIZE // Storage slots size + + WORD_SIZE // Inputs size + + WORD_SIZE // Outputs size + + WORD_SIZE // Witnesses size } fn storage_slots_offset_at(&self, idx: usize) -> Option { if idx < self.storage_slots.len() { - Some(self.storage_slots_offset() + idx * StorageSlot::SLOT_SIZE) + Some(Self::storage_slots_offset_static() + idx * StorageSlot::SLOT_SIZE) } else { None } } } + impl PoliciesField for Create { + fn policies(&self) -> &Policies { + &self.policies + } + + fn policies_mut(&mut self) -> &mut Policies { + &mut self.policies + } + + fn policies_offset(&self) -> usize { + Self::storage_slots_offset_static() + + self.storage_slots.len() * StorageSlot::SLOT_SIZE + } + } + impl Inputs for Create { #[inline(always)] fn inputs(&self) -> &Vec { @@ -461,8 +462,7 @@ mod field { #[inline(always)] fn inputs_offset(&self) -> usize { - self.storage_slots_offset() - + self.storage_slots.len() * StorageSlot::SLOT_SIZE + self.policies_offset() + self.policies.size_dynamic() } #[inline(always)] diff --git a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_contract_snapshot.snap b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_contract_snapshot.snap index 3092daffb9..34679e26d6 100644 --- a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_contract_snapshot.snap +++ b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_contract_snapshot.snap @@ -1,6 +1,5 @@ --- source: fuel-tx/src/transaction/types/input/snapshot_tests.rs -assertion_line: 75 expression: hex --- -0000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000007b00000000000f424000000000000000010101010101010101010101010101010101010101010101010101010101010101000000000000000202020202020202020202020202020202020202020202020202020202020202020303030303030303030303030303030303030303030303030303030303030303000000000000002e00000000000000050505050505050505050505050505050505050505050505050505050505050505 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0000000000000001000000000000000000000000000000000000000000000001000000000000007b00000000000f424000000000000000010101010101010101010101010101010101010101010101010101010101010101000000000000000202020202020202020202020202020202020202020202020202020202020202020303030303030303030303030303030303030303030303030303030303030303000000000000002e00000000000000050505050505050505050505050505050505050505050505050505050505050505 diff --git a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_coin_snapshot.snap b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_coin_snapshot.snap index 7a13cfc2cb..6f6ce42451 100644 --- a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_coin_snapshot.snap +++ b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_coin_snapshot.snap @@ -1,6 +1,5 @@ --- source: fuel-tx/src/transaction/types/input/snapshot_tests.rs -assertion_line: 55 expression: hex --- -0000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000007b00000000000f42400000000000000000010101010101010101010101010101010101010101010101010101010101010100000000000000020202020202020202020202020202020202020202020202020202020202020202000000000000000b0505050505050505050505050505050505050505050505050505050505050505000000000000002e0000000000000005000000000000000000000000000186a0000000000000000a000000000000000c0303030303030303030300000000000004040404040404040404040400000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0000000000000001000000000000000000000000000000000000000000000001000000000000007b00000000000f42400000000000000000010101010101010101010101010101010101010101010101010101010101010100000000000000020202020202020202020202020202020202020202020202020202020202020202000000000000000b0505050505050505050505050505050505050505050505050505050505050505000000000000002e0000000000000005000000000000000000000000000186a0000000000000000a000000000000000c0303030303030303030300000000000004040404040404040404040400000000 diff --git a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_message_coin.snap b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_message_coin.snap index a955dd7fda..bf42f441c5 100644 --- a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_message_coin.snap +++ b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_message_coin.snap @@ -1,6 +1,5 @@ --- source: fuel-tx/src/transaction/types/input/snapshot_tests.rs -assertion_line: 124 expression: hex --- -0000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000007b00000000000f424000000000000000020202020202020202020202020202020202020202020202020202020202020202030303030303030303030303030303030303030303030303030303030303030300000000000000040505050505050505050505050505050505050505050505050505050505050505000000000000000000000000000186a00000000000000000000000000000000b000000000000000c0707070707070707070707000000000008080808080808080808080800000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0000000000000001000000000000000000000000000000000000000000000001000000000000007b00000000000f424000000000000000020202020202020202020202020202020202020202020202020202020202020202030303030303030303030303030303030303030303030303030303030303030300000000000000040505050505050505050505050505050505050505050505050505050505050505000000000000000000000000000186a00000000000000000000000000000000b000000000000000c0707070707070707070707000000000008080808080808080808080800000000 diff --git a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_message_data.snap b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_message_data.snap index 9fc1fbb9ec..9b21b56acb 100644 --- a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_message_data.snap +++ b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_predicate_message_data.snap @@ -1,6 +1,5 @@ --- source: fuel-tx/src/transaction/types/input/snapshot_tests.rs -assertion_line: 173 expression: hex --- -0000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000007b00000000000f424000000000000000020202020202020202020202020202020202020202020202020202020202020202030303030303030303030303030303030303030303030303030303030303030300000000000000040505050505050505050505050505050505050505050505050505050505050505000000000000000000000000000186a0000000000000000a000000000000000b000000000000000c060606060606060606060000000000000707070707070707070707000000000008080808080808080808080800000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0000000000000001000000000000000000000000000000000000000000000001000000000000007b00000000000f424000000000000000020202020202020202020202020202020202020202020202020202020202020202030303030303030303030303030303030303030303030303030303030303030300000000000000040505050505050505050505050505050505050505050505050505050505050505000000000000000000000000000186a0000000000000000a000000000000000b000000000000000c060606060606060606060000000000000707070707070707070707000000000008080808080808080808080800000000 diff --git a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_coin_snapshot.snap b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_coin_snapshot.snap index bf230daea7..4c5b48f81e 100644 --- a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_coin_snapshot.snap +++ b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_coin_snapshot.snap @@ -1,6 +1,5 @@ --- source: fuel-tx/src/transaction/types/input/snapshot_tests.rs -assertion_line: 30 expression: hex --- -0000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000003e8000000000000007b00000000000f42400000000000000000010101010101010101010101010101010101010101010101010101010101010100000000000000020202020202020202020202020202020202020202020202020202020202020202000000000000000b0505050505050505050505050505050505050505050505050505050505050505000000000000002e00000000000000050000000000000004000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000000000000000100000000000000000000000000000000000000000000000100000000000003e8000000000000007b00000000000f42400000000000000000010101010101010101010101010101010101010101010101010101010101010100000000000000020202020202020202020202020202020202020202020202020202020202020202000000000000000b0505050505050505050505050505050505050505050505050505050505050505000000000000002e00000000000000050000000000000004000000000000000000000000000000000000000000000000 diff --git a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_message_coin.snap b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_message_coin.snap index ecb09cda6b..a7c67135e2 100644 --- a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_message_coin.snap +++ b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_message_coin.snap @@ -1,6 +1,5 @@ --- source: fuel-tx/src/transaction/types/input/snapshot_tests.rs -assertion_line: 100 expression: hex --- -0000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000003e8000000000000007b00000000000f42400000000000000002020202020202020202020202020202020202020202020202020202020202020203030303030303030303030303030303030303030303030303030303030303030000000000000004050505050505050505050505050505050505050505050505050505050505050500000000000000060000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000000000000000100000000000000000000000000000000000000000000000100000000000003e8000000000000007b00000000000f42400000000000000002020202020202020202020202020202020202020202020202020202020202020203030303030303030303030303030303030303030303030303030303030303030000000000000004050505050505050505050505050505050505050505050505050505050505050500000000000000060000000000000000000000000000000000000000000000000000000000000000 diff --git a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_message_data.snap b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_message_data.snap index dc72b9df4c..5ca3af76bc 100644 --- a/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_message_data.snap +++ b/fuel-tx/src/transaction/types/input/snapshots/fuel_tx__transaction__types__input__snapshot_tests__tx_with_signed_message_data.snap @@ -1,6 +1,5 @@ --- source: fuel-tx/src/transaction/types/input/snapshot_tests.rs -assertion_line: 149 expression: hex --- -0000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000003e8000000000000007b00000000000f42400000000000000002020202020202020202020202020202020202020202020202020202020202020203030303030303030303030303030303030303030303030303030303030303030000000000000004050505050505050505050505050505050505050505050505050505050505050500000000000000060000000000000000000000000000000a0000000000000000000000000000000007070707070707070707000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000000000000000100000000000000000000000000000000000000000000000100000000000003e8000000000000007b00000000000f42400000000000000002020202020202020202020202020202020202020202020202020202020202020203030303030303030303030303030303030303030303030303030303030303030000000000000004050505050505050505050505050505050505050505050505050505050505050500000000000000060000000000000000000000000000000a0000000000000000000000000000000007070707070707070707000000000000 diff --git a/fuel-tx/src/transaction/types/script.rs b/fuel-tx/src/transaction/types/script.rs index 6e61b59fb1..eaeac558fd 100644 --- a/fuel-tx/src/transaction/types/script.rs +++ b/fuel-tx/src/transaction/types/script.rs @@ -59,6 +59,7 @@ pub(crate) struct ScriptMetadata { #[derivative(Eq, PartialEq, Hash, Debug)] pub struct Script { pub(crate) script_gas_limit: Word, + pub(crate) receipts_root: Bytes32, #[derivative(Debug(format_with = "fmt_truncated_hex::<16>"))] pub(crate) script: Vec, #[derivative(Debug(format_with = "fmt_truncated_hex::<16>"))] @@ -67,7 +68,6 @@ pub struct Script { pub(crate) inputs: Vec, pub(crate) outputs: Vec, pub(crate) witnesses: Vec, - pub(crate) receipts_root: Bytes32, #[cfg_attr(feature = "serde", serde(skip))] #[derivative(PartialEq = "ignore", Hash = "ignore")] #[canonical(skip)] @@ -262,12 +262,6 @@ mod field { #[inline(always)] fn receipts_root_offset_static() -> usize { Self::script_gas_limit_offset_static() + WORD_SIZE - + WORD_SIZE // Script size - + WORD_SIZE // Script data size - + WORD_SIZE // Policies size - + WORD_SIZE // Inputs size - + WORD_SIZE // Outputs size - + WORD_SIZE // Witnesses size } } @@ -284,7 +278,14 @@ mod field { #[inline(always)] fn script_offset_static() -> usize { - Self::receipts_root_offset_static() + Bytes32::LEN // Receipts root + Self::receipts_root_offset_static() + + Bytes32::LEN // Receipts root + + WORD_SIZE // Script size + + WORD_SIZE // Script data size + + WORD_SIZE // Policies size + + WORD_SIZE // Inputs size + + WORD_SIZE // Outputs size + + WORD_SIZE // Witnesses size } } diff --git a/fuel-vm/src/tests/validation.rs b/fuel-vm/src/tests/validation.rs index 9cc8e68bc3..3e2864dab2 100644 --- a/fuel-vm/src/tests/validation.rs +++ b/fuel-vm/src/tests/validation.rs @@ -23,8 +23,6 @@ use rand::{ #[cfg(feature = "alloc")] use alloc::vec; -use crate::consts::WORD_SIZE; - #[test] fn transaction_can_be_executed_after_maturity() { const MATURITY: BlockHeight = BlockHeight::new(1); @@ -62,9 +60,8 @@ fn malleable_fields_do_not_affect_validity() { let params = ConsensusParameters::default(); - let tx_size_ptr = - 32 + (params.tx_params().max_inputs() as usize * (AssetId::LEN + WORD_SIZE)); - let tx_start_ptr = tx_size_ptr + 8; + let tx_start_ptr = params.tx_params().tx_offset(); + let tx_size_ptr = tx_start_ptr - 8; let tx = TransactionBuilder::script( vec![ @@ -99,9 +96,10 @@ fn malleable_fields_do_not_affect_validity() { op::mcl(0x26, 0x27), // Zero out witness count op::gtf_args(0x26, 0x00, GTFArgs::Script), - op::sub(0x26, 0x26, 32 + 8), // Offset to get the witness count address + op::subi(0x26, 0x26, 8), // Offset to get the witness count address + op::sub(0x26, 0x26, 0x20), // Offset in relative to the tx bytes op::add(0x26, 0x26, RegId::HP), // Redirect the pointer to heap - op::sub(0x26, 0x26, 0x20), // Offset in relative to the tx bytes + op::addi(0x26, 0x26, 32 + 8), // Offset of tx bytes in heap op::sw(0x26, RegId::ZERO, 0), // Zero out the witness count // Actually hash op::subi(0x24, 0x21, 64 + 8 - 8), // Offset ptr From 5eae221da34819d53e464ee09496d4c11a3036c9 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Fri, 22 Mar 2024 14:34:02 +0100 Subject: [PATCH 10/13] Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0ac23dd70..088190245e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). #### Breaking +- [#703](https://github.com/FuelLabs/fuel-vm/pull/703): Reshuffled fields `Script` and `Create` transactions to unify part used by all chargeable transactions. It breaks the serialization and deserialization and requires adoption on the SDK side. - [#702](https://github.com/FuelLabs/fuel-vm/pull/702): Wrapped `FeeParameters`, `PredicateParameters`, `TxParameters`, `ScriptParameters` and `ContractParameters` into an enum to support versioning. - [#701](https://github.com/FuelLabs/fuel-vm/pull/701): Wrapped `ConsensusParameters` and `GasCosts` into an enum to support versioning. Moved `block_gas_limit` from `fuel_core_chain_config::ChainConfig` to `ConsensusPataremeters`. Reduced default `MAX_SIZE` to be [110kb](https://github.com/FuelLabs/fuel-core/pull/1761) and `MAX_CONTRACT_SIZE` to be [100kb](https://github.com/FuelLabs/fuel-core/pull/1761). - [#692](https://github.com/FuelLabs/fuel-vm/pull/692): Add GTF getters for tx size and address. From b57047a1582802a93d02556c0b3b60a7c19adc37 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Sun, 24 Mar 2024 17:12:38 +0100 Subject: [PATCH 11/13] Unified `Create` and `Script` logic via `ChargeableTransaction` --- fuel-derive/src/deserialize.rs | 10 + fuel-derive/src/serialize.rs | 76 ++-- fuel-tx/src/builder.rs | 24 +- fuel-tx/src/lib.rs | 1 + fuel-tx/src/transaction.rs | 119 ++++-- fuel-tx/src/transaction/id.rs | 6 + fuel-tx/src/transaction/metadata.rs | 2 +- fuel-tx/src/transaction/types.rs | 11 +- .../types/chargeable_transaction.rs | 388 ++++++++++++++++++ fuel-tx/src/transaction/types/create.rs | 357 +++------------- .../transaction/types/create/ser_de_tests.rs | 12 +- fuel-tx/src/transaction/types/input.rs | 7 +- fuel-tx/src/transaction/types/mint.rs | 1 - fuel-tx/src/transaction/types/output.rs | 2 +- fuel-tx/src/transaction/types/script.rs | 351 ++-------------- fuel-vm/src/interpreter.rs | 24 +- fuel-vm/src/interpreter/executors/main.rs | 6 +- .../src/interpreter/internal/message_tests.rs | 8 +- fuel-vm/src/tests/metadata.rs | 2 +- 19 files changed, 667 insertions(+), 740 deletions(-) create mode 100644 fuel-tx/src/transaction/types/chargeable_transaction.rs diff --git a/fuel-derive/src/deserialize.rs b/fuel-derive/src/deserialize.rs index 0edbfb17e5..21ad09ba00 100644 --- a/fuel-derive/src/deserialize.rs +++ b/fuel-derive/src/deserialize.rs @@ -50,6 +50,11 @@ fn deserialize_struct(s: &mut synstructure::Structure) -> TokenStream2 { quote! {} }; + let mut s = s.clone(); + + let variant: &mut synstructure::VariantInfo = &mut s.variants_mut()[0]; + variant.filter(|binding| !should_skip_field_binding(binding)); + s.gen_impl(quote! { gen impl ::fuel_types::canonical::Deserialize for @Self { fn decode_static(buffer: &mut I) -> ::core::result::Result { @@ -138,6 +143,11 @@ fn deserialize_enum(s: &synstructure::Structure) -> TokenStream2 { } }; + let mut s = s.clone(); + s.variants_mut().iter_mut().for_each(|v| { + v.filter(|binding| !should_skip_field_binding(binding)); + }); + s.gen_impl(quote! { gen impl ::fuel_types::canonical::Deserialize for @Self { fn decode_static(buffer: &mut I) -> ::core::result::Result { diff --git a/fuel-derive/src/serialize.rs b/fuel-derive/src/serialize.rs index 5a17dec106..d468d46dfd 100644 --- a/fuel-derive/src/serialize.rs +++ b/fuel-derive/src/serialize.rs @@ -8,37 +8,28 @@ use crate::attribute::{ fn serialize_struct(s: &synstructure::Structure) -> TokenStream2 { let attrs = StructAttrs::parse(s); + let mut s = s.clone(); assert_eq!(s.variants().len(), 1, "structs must have one variant"); - let variant: &synstructure::VariantInfo = &s.variants()[0]; + let variant: &mut synstructure::VariantInfo = &mut s.variants_mut()[0]; + variant.filter(|binding| !should_skip_field_binding(binding)); + let encode_static = variant.each(|binding| { - if should_skip_field_binding(binding) { - quote! {} - } else { - quote! { - ::fuel_types::canonical::Serialize::encode_static(#binding, buffer)?; - } + quote! { + ::fuel_types::canonical::Serialize::encode_static(#binding, buffer)?; } }); let encode_dynamic = variant.each(|binding| { - if should_skip_field_binding(binding) { - quote! {} - } else { - quote! { - ::fuel_types::canonical::Serialize::encode_dynamic(#binding, buffer)?; - } + quote! { + ::fuel_types::canonical::Serialize::encode_dynamic(#binding, buffer)?; } }); let size_static_code = variant.each(|binding| { - if should_skip_field_binding(binding) { - quote! {} - } else { - quote! { - size = ::fuel_types::canonical::add_sizes(size, #binding.size_static()); - } + quote! { + size = ::fuel_types::canonical::add_sizes(size, #binding.size_static()); } }); @@ -50,12 +41,8 @@ fn serialize_struct(s: &synstructure::Structure) -> TokenStream2 { let size_static_code = quote! { #initial_size match self { #size_static_code}; size }; let size_dynamic_code = variant.each(|binding| { - if should_skip_field_binding(binding) { - quote! {} - } else { - quote! { - size = ::fuel_types::canonical::add_sizes(size, #binding.size_dynamic()); - } + quote! { + size = ::fuel_types::canonical::add_sizes(size, #binding.size_dynamic()); } }); let size_dynamic_code = @@ -104,16 +91,19 @@ fn serialize_struct(s: &synstructure::Structure) -> TokenStream2 { fn serialize_enum(s: &synstructure::Structure) -> TokenStream2 { assert!(!s.variants().is_empty(), "got invalid empty enum"); + let mut s = s.clone(); let mut next_discriminant = quote! { { 0u64 } }; + + s.variants_mut().iter_mut().for_each(|v| { + v.filter(|binding| !should_skip_field_binding(binding)); + }); + let encode_static = s.variants().iter().map(|v| { let pat = v.pat(); + let encode_static_iter = v.bindings().iter().map(|binding| { - if should_skip_field_binding(binding) { - quote! {} - } else { - quote! { - ::fuel_types::canonical::Serialize::encode_static(#binding, buffer)?; - } + quote! { + ::fuel_types::canonical::Serialize::encode_static(#binding, buffer)?; } }); @@ -138,12 +128,8 @@ fn serialize_enum(s: &synstructure::Structure) -> TokenStream2 { }); let encode_dynamic = s.variants().iter().map(|v| { let encode_dynamic_iter = v.each(|binding| { - if should_skip_field_binding(binding) { - quote! {} - } else { - quote! { - ::fuel_types::canonical::Serialize::encode_dynamic(#binding, buffer)?; - } + quote! { + ::fuel_types::canonical::Serialize::encode_dynamic(#binding, buffer)?; } }); quote! { @@ -156,12 +142,8 @@ fn serialize_enum(s: &synstructure::Structure) -> TokenStream2 { .iter() .map(|variant| { variant.each(|binding| { - if should_skip_field_binding(binding) { - quote! {} - } else { - quote! { - size = ::fuel_types::canonical::add_sizes(size, #binding.size_static()); - } + quote! { + size = ::fuel_types::canonical::add_sizes(size, #binding.size_static()); } }) }) @@ -177,12 +159,8 @@ fn serialize_enum(s: &synstructure::Structure) -> TokenStream2 { .iter() .map(|variant| { variant.each(|binding| { - if should_skip_field_binding(binding) { - quote! {} - } else { - quote! { - size = ::fuel_types::canonical::add_sizes(size, #binding.size_dynamic()); - } + quote! { + size = ::fuel_types::canonical::add_sizes(size, #binding.size_dynamic()); } }) }) diff --git a/fuel-tx/src/builder.rs b/fuel-tx/src/builder.rs index a4e9090c3d..0bcda3b0b9 100644 --- a/fuel-tx/src/builder.rs +++ b/fuel-tx/src/builder.rs @@ -42,6 +42,10 @@ use crate::{ WitnessLimit, }, policies::Policies, + transaction::{ + CreateBody, + ScriptBody, + }, }; use alloc::{ collections::BTreeMap, @@ -116,14 +120,16 @@ pub struct TransactionBuilder { impl TransactionBuilder