All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
- 1008: Skip zero-amount burns and clear empty asset slots
- 1009: Do not modify storage for zero-amount mints
- 1010: Storage cache: Use HashMap, group by ContractId
- 1011: Rename default_gas_costs to default_gas_costs_for_tests
- 1004: SCLR now correctly validates that the U256 key will not overflow
- 1002: Expose methods for accessing
storage_slot_cachefor benchmarking purposes
- 1002: Fixed
reset_vm_statenot resetting slot cache correctly
- 998: Pin wasm-bindgen and tooling to 0.2.108 due to breaking changes
- 982: Adds immediate offset operand to SRW instruction. Binary backwards compatibility is retained, as the field was previously required to be zeroed.
Reworked
StorageReadto include the full size of the storage value when it succeeds, and a typed error when it fails due to a caller-handleble reason. - 992: Bumped rust version to 1.93.
- 996: Removed bulk storage methods from InterpreterStorage. Changed remove range to not return the status.
- 976: Add a test case showing minted tokens can be transferred out using tro instruction
- 982: New storage opcodes
SCLR,SRDD,SRDI,SWRD,SWRI,SUPD,SUPIandSPLDthat allow working with variably-sized storage slots. - 989: Dynamic storage opcodes now charge gas properly for new bytes written.
- 988: New ID function exports to TypeScript WASM target.
- 977: Use more accurate names for instruction constructor parameters in fuel-asm
- 980: Use fuel-core storage implementations for memory storage
- 982:
SRWinstruction now allows and offset argument. All existing storage operations are internally changed to function with variably sized slots, maintaining full backwards compatibility. - 990: Refactor: Use saturating_add instead of erroring in inc_pc
- 994: Optimization: Leverage ggas >= cgas invariant in gas charging.
- 995: Optimization: Delay opcode parsing until absolutely necessary
- 996: Introduce a storage slot cache and split storage read costs into storage_read_cold (first access, fetches from backing storage) and storage_read_hot (cache hit). All storage opcodes now charge these semantic costs instead of per-opcode flat rates. The cache is keyed by (ContractId, slot), is write-through, and persists across contract calls.
- 974: Bump Rust version to
1.90.0.
- 971: All
Vec<u8>fields in the transaction now useBytestype. This type has truncatedDebugstring, and has optimized serialization and deserialization forpostcardandbinacodeencodings. The new encoding is compatible(was tested) forserde_json,bincode,postcard.StateTransitionandStateTransitionRefnow containsVerifiergeneric from the VM. - 972: A new policy has been added to track the owner of the transaction. Serialization and deserialization should now support a new variant to decode a new policy.
- 971: Added a new
into_transactmethod for theInterpreterto returnStateTransitionwithreceipts. It allows caller to avoid cloning of receipts which can be critical in some scenarios. Added benchmarks forBytestype to show serialization and deserialization performance. - 972: Added a new
Ownerpolicy. The policy stores the index of the transaction input, which is nominated as the owner. In the case of multiple inputs with different owners, it helps to identify the owner of the transaction. Added a newGM::GetOwneropcode, which retrieves the owner of the transaction. If theOwnerpolicy is set, the opcode returns a pointer to the owner from the policy. If policy is not set, but all inputs have the same owner, it returns the pointer to the owner. Otherwise, it panics withOwnerIsUnknown.
- 971: Increased performance of the postcard bytes serialization and deserialization in 40 times.
Increased performance of the canonical bytes deserialization in 200 times.
Contract::idmethod now a static function, instead of the method of the instance. Removeimpl TryFrom<&Create> for Contractimplementation for theCreatetransaction. Instead, useCreate::bytecodeto get the contract bytecode. RemovedAsFieldFmttrait and its implementations.Bytestype truncates itsDebugoutput by default. Optimized interactions withCreatetransaction to avoid unnecessary cloning of the bytecode.
- 963: Adds
ECALstate parameter to some predicate-related APIs. AllowsECALinstruction during predicate execution. ExposesInterpreter::contextfunction that can be used by theECALhandler to determine if it's inside a predicate.
- 959: Add Borrow trait bounds to owned types in Mappable trait.
- 922: Add NIOP instruction to perform overflow-checked calculations on u8, u16, and u32 integers
- 923: Load and store instructions for u16 and u32
- 925: Add jump-and-link instruction
JAL offsetthat can be used to implement efficient subroutine calls. - 953: feat: Expose SubAssetId in fuel-tx
- 899: Add a feature that propose
u32tx_pointerinstead ofu16infuel-txandfuel-vm. - 939: Add new
GetGasPriceGMopcode argument
- 778: Add
SubAssetIdnewtype that's used instead ofBytes32. - 933: Don't perform balance update if the change is zero
- 934: Add
input_indexof the failed predicate toCheckError::PredicateVerificationFailed. - 935: Bump Rust version to
1.85.0. - 936: Update Rust edition to 2024.
- 938: Rename
updatemethod toinserton sparse merkle tree, and allow inserting empty values.
- 913: Change the way we are building the changelog to avoids conflicts.
- 940: Zero out heap memory when reallocating after reset.
- 942: Fix heap memory reallocation after reset.
- 901: Add
Displayimplementation toReceiptenum. - 896: Expose
leaf_sumand allow binaryMerkleTreeto be built from existing precomputed leafs. - 882: Add a lot of new
GTFArgsincluding generic ones that will replace old tx type specific. - 909: Add the
remove_recovery_id()toSignature. - 915: Added support for
AttemptContinueverifier, that collects and ignores some errors instead of terminating execution. This is meant to help with gathering tx dependencies.
- 900: Change the error variant
DuplicateMessageInputIdtoDuplicateInputNoncewhich now contains a nonce instead ofMessageIdfor performance improvements. - 907:
StorageReadandStorageWritetraits no longer return the number of bytes written. They already required that the whole buffer is used, but now this is reflected in signature and documentation as well. - 914: The built-in profiler is removed. Use the debugger with single-stepping instead.
- 918: Interpreter is now generic over the validation error handling. No behavioural changes, but the
Interpreterhas one extra type parameter. - 920:
Interpreter::executeand friends are now generic over predicateness of the context. This forces monomorphization so the predicate branch is optimized away on non-predicate execution.
- 904: Moved the logic of each opcode into its own function. It helps so reduce the size of the
instruction_innerfunction, allowing compiler to do better optimizations. The Mira swaps receive performance improvement in 16.5%.
- 917: Ignore predicate verification during the estimation.
- 895: Fix elided lifetimes compilation warnings that became errors after the release of rust 1.83.0.
- 895: Bump proptest-derive to version
0.5.1to fix non-local impl errors on the derivation ofproptest_derive::Arbitraryintroduced by rust 1.83.0. - 889 and 908: Debugger breakpoint caused receipts to be produced incorrectly.
- 903: Fixed warning being emitted when using packages with Node@22+.
- 912: Fix serialization/deserialization of
Policiesin compressed transactions to be backward compatible.
- 942: Fix heap memory reallocation after reset.
- 910: Fix serialization/deserialization of
Policiesin compressed transactions to be backward compatible.
- 879: Debugger state wasn't propagated in contract contexts.
- 878: Fix the transaction de/serialization that wasn't backward compatible with the addition of the new policy.
- 871: Add
expirationpolicy that prevent a transaction to be inserted after a given block height. - 870: Add 3 new ZK-related opcodes: eadd (ecAdd on EVM), emul (ecMul on EVM), epar (ecPairing on EVM)
- 875: Updated
wasm-bindgento0.2.97
- 860: Fixed missing fuzzing coverage report in CI.
- 863: Changed StorageRead::read to load a serialized value starting from a offset. The function returns an optional value equal to the number of bytes read when defined, or none if the offset specified in input is outside the boundaries of the serialized value read.
- 868: Fixed error message when having a nonexistent contract in inputs. Instead of saying "contract was in inputs, but doesn't exist", the message was just "contract not in inputs". Now there's a separate error for that.
- 837: Change
difffunction to get VM instance diff to arollback_tothat allow to fetch changes to make self -> previous state. However, this support the new memory management that allow memory to grow between instances instead of fixed memory size.
- 847: Changed
interpreter::blockchain::load_contract_codeandinterpreter::blockchain::code_copyto use the new version ofStorageRead::readwhere the contract is loaded into a buffer starting from an offset. The contract is copied directly into the portion of memory starting at the destination address, rather than having to be copied indirectly after being fetched from storage.
- #854: Fixed a bug where LDC mode 2 padding bytes would be copied from memory instead of using zeroes.
- #852: Fixed incorrect predicate estimation when max predicate gas is less than max tx gas.
- #849: Add a new mode
2to the LDC that allows to use the memory as a source for code. - #848: Allow usage of the blob opcode
BSIZ,BLDD, andLDCwith mode1in the predicates. - #838: Implemented
AsRef<[u8]>andTryFrom<&[u8]>for DA compression types: ScriptCode, PredicateCode, RegistryKey. - #820: Add fuzzing in CI with ClusterFuzzLite.
- #848: All estimation and verification of predicate functionality is reworked and now requires the instance of the storage with predicates.
- #843: Remove
serdefeature from thefuel-txcrate. It is default behaviour now if you enableallocfeature. - #766: Use correct gas price when validating native signatures
- #829: Updated
add_random_fee_input()to accept anrngfor true randomization. Introducedadd_fee_input()to retain the previous behavior ofadd_random_fee_input(). - #845: Removed
Defaultimplementation ofSecretKey. - #844:
WDCMandWQCMreset$ofand$err.
- #835: Fixing WASM-NPM packaging and publishing
- #670: Add DA compression functionality to
Transactionand any types within - #733: Add LibAFL based fuzzer and update
secp256k1version to 0.29.1. - #825: Avoid leaking partially allocated memory when array deserialization fails
- #824: Use
selfinstead of&selfduring decompression. - #823: Returned the old behaviour of the json serialization for policies.
- #826: Skip the panic reason from canonical serialization of the panic receipt.
- #821: Added
block_transaction_size_limittoConsensusParameters. It adds a newConensusParametersV2as a variant of theConsensusParameters. - #670: The
predicatefield offuel_tx::input::Coinis now a wrapper structPredicateCode.
- #822: Return recipient as an owner for the message inputs.
- #796: Added implementation of the
MerkleRootStoragefor references.
- #806: Update MSRV to 1.79.0.
- #780: Added
Blobtransaction, andBSIZandBLDDinstructions. Also allowsLDCto load blobs. - #795: Fixed
ed19instruction to take variable length message instead of a fixed-length one. Changed the gas cost to beDependentCost.
- #781: Added
base_asset_idto checked metadata.
- #784: Avoid storage lookups for side nodes in the SMT.
- #787: Fixed charge functions to profile cost before charging.
- #783: Remove unnecessary look up for old values by adding new methods to the
StorageMutatetrait. The oldinsertandremoveare nowreplaceandtake. The newinsertandremovedon't return a value. - #783: Renamed methods of
StorageWritetrait fromwrite,replace,taketowrite_bytes,replace_bytes,take_bytes. - #788: Fix truncating
sptoMEM_SIZEingrow_stack, and allow empty writes to zero-length ranges at$hp.
- #789: Avoid conversion into
usizetype and useu32oru64instead. The change is breaking since could return other errors for 32-bit systems. - #786: Fixed the CCP opcode to charge for the length from the input arguments.
- #785: Require
ContractCreatedoutput in theCreatetransaction. TheTransactionBuilder<Create>has aadd_contract_createdmethod to simplify the creation of theContractCreatedoutput for tests.
- #776: Charge for max length in LDC opcode.
- #770: Cache contract inputs in the VM.
-
#768: Charge for LDC opcode before loading the contract into memory.
-
#771: Take into account spent gas during synchronous predicates estimation.
- #769: Use
DependentCostforCFEandCFEIopcodes. - #767: Fixed no zeroing malleable fields for
Createtransaction. - #765: Corrected the gas units for WDOP and WQOP.
- #772: Removed redundant
self.receipts.root()call.
- #751: Improve test coverage.
- #753: Fix an ownership check bug in
CCPinstruction.
- #748: Make
VmMemoryPool::get_newasync. - #747: Use
DependentCostforalocopcode. The cost of thealocopcode is now dependent on the size of the allocation.
- #732: Adds
resetmethod to VM memory.
- #732: Makes the VM generic over the memory type, allowing reuse of relatively expensive-to-allocate VM memories through
VmMemoryPool. Functions and traits which require VM initalization such asestimate_predicatesnow take either the memory orVmMemoryPoolas an argument. TheInterpterter::eqmethod now only compares accessible memory regions.Memorywas renamed intoMemoryInstanceandMemoryis a trait now.
- #743: Zeroes
$flagonCALL, so that contracts can assume clean$flagstate. - #737: Panic on instructions with non-zero reserved part.
- #725: Adds more clippy lints to catch possible integer overflow and casting bugs on compile time.
- #729: Adds more clippy lints to
fuel-merkleto catch possible integer overflow and casting bugs on compile time. It also does some internal refactoring.
- #725:
UtxoId::from_strnow rejects inputs with multiple0xprefixes. Many::from_strimplementations also reject extra data in the end of the input, instead of silently ignoring it.UtxoId::from_strallows a single:between the fields. UnusedGasUnitstruct removed. - #726: Removed code related to Binary Merkle Sum Trees (BMSTs). The BMST is deprecated and not used in production environments.
- #729: Removed default implementation of
Node::key_size_bits, implementors must now define it themselves. Also some helper traits have been merged together, or their types changed.
- #736: LDC instruction now works in internal contexts as well. Call frames use code size padded to word alignment.
- #721: Added additional logic to the BMT proof verification algorithm to check the length of the provided proof set against the index provided in the proof.
-
#719: Fix overflow in
LDCinstruction when contract size with padding would overflow. -
#715: The
Interpretersupports the processing of theUploadtransaction. The change affectsInterpreterStorage, addingStorageMutate<UploadedBytes>constrain. -
#714: The change adds a new
Uploadtransaction that allows uploading huge byte code on chain subsection by subsection. This transaction is chargeable and is twice as expensive as theCreatetransaction. Anyone can submit this transaction. -
#712: The
Interpretersupports the processing of theUpgradetransaction. The change affectsInterpreterStorage, adding 5 new methods that must be implemented. -
#707: The change adds a new
Upgradetransaction that allows upgrading either consensus parameters or state transition function used by the network to produce future blocks. The purpose of the upgrade is defined by theUpgrade Purposetype:pub enum UpgradePurpose { /// The upgrade is performed to change the consensus parameters. ConsensusParameters { /// The index of the witness in the [`Witnesses`] field that contains /// the serialized consensus parameters. witness_index: u16, /// The hash of the serialized consensus parameters. /// Since the serialized consensus parameters live inside witnesses(malleable /// data), any party can override them. The `checksum` is used to verify that the /// data was not modified. checksum: Bytes32, }, /// The upgrade is performed to change the state transition function. StateTransition { /// The Merkle root of the new bytecode of the state transition function. /// The bytecode must be present on the blockchain(should be known by the /// network) at the moment of inclusion of this transaction. root: Bytes32, }, }
The
Upgradetransaction is chargeable, and the sender should pay for it. Transaction inputs should contain only base assets.Only the privileged address can upgrade the network. The privileged address can be either a real account or a predicate.
Since serialized consensus parameters are small(< 2kb), they can be part of the upgrade transaction and live inside of witness data. The bytecode of the blockchain state transition function is huge ~1.6MB(relative to consensus parameters), and it is impossible to fit it into one transaction. So when we perform the upgrade of the state transition function, it should already be available on the blockchain. The transaction to actually upload the bytecode(
Uploadtransaction) will implemented in the FuelLabs/fuel-core#1754.
-
#707: Used the same pattern everywhere in the codebase:
Self::Script(tx) => tx.encode_static(buffer), Self::Create(tx) => tx.encode_static(buffer), Self::Mint(tx) => tx.encode_static(buffer), Self::Upgrade(tx) => tx.encode_static(buffer),
Instead of:
Transaction::Script(script) => script.encode_static(buffer), Transaction::Create(create) => create.encode_static(buffer), Transaction::Mint(mint) => mint.encode_static(buffer), Transaction::Upgrade(upgrade) => upgrade.encode_static(buffer),
-
#714: Added
max_bytecode_subsectionsfield to theTxParametersto limit the number of subsections that can be uploaded. -
#707: Side small breaking for tests changes from the
Upgradetransaction:- Moved
fuel-tx-test-helperslogic into thefuel_tx::test_helpersmodule. - Added a new rule for
Createtransaction: all inputs should use base asset otherwise it returnsTransactionInputContainsNonBaseAssetIderror. - Renamed some errors because now they are used for several transactions(
Upgradeuses some errors fromCreateand some fromScripttransactions):TransactionScriptOutputContractCreated->TransactionOutputContainsContractCreated.TransactionCreateOutputContract->TransactionOutputContainsContract.TransactionCreateOutputVariable->TransactionOutputContainsVariable.TransactionCreateOutputChangeNotBaseAsset->TransactionChangeChangeUsesNotBaseAsset.TransactionCreateInputContract->TransactionInputContainsContract.TransactionCreateMessageData->TransactionInputContainsMessageData.
- The combination of
serdeandpostcardis used to serialize and deserializeConsensusParametersduring the upgrade. This means the protocol and state transition function requires theserdefeature by default forConsensusParametersandfuel-types.
- Moved
-
#697: Changed the VM to internally use separate buffers for the stack and the heap to improve startup time. After this change, memory that was never part of the stack or the heap cannot be accessed, even for reading. Also, even if the whole memory is allocated, accesses spanning from the stack to the heap are not allowed. This PR also fixes a bug that required one-byte gap between the stack and the heap. Multiple errors have been changed to be more sensible ones, and sometimes the order of which error is returned has changed.
ALOCopcode now zeroes the newly allocated memory.
- #705: Added
privileged_addressto theConsensusParametersfor permissioned operations(like upgrade of the network). - #648: Added support for generating proofs for Sparse Merkle Trees (SMTs) and proof verification. Proofs can be used to attest to the inclusion or exclusion of data from the set.
- #709: Removed
bytecode_lengthfrom theCreatetransaction. - #706: Unified
CreateandScriptlogic viaChargeableTransaction. The change is breaking because affects JSON serialization and deserialization. NowScriptandCreatetransactions havebodyfields that include unique transactions. - #703: Reshuffled fields
ScriptandCreatetransactions to unify part used by all chargeable transactions. It breaks the serialization and deserialization and requires adoption on the SDK side. - #708: Hidden
Defaultparams under the "test-helper" feature to avoid accidental use in production code. It is a huge breaking change for any code that has used them before in production, and instead, it should be fetched from the network. In the case of tests simply use the "test-helper" feature in your[dev-dependencies]section. - #702: Wrapped
FeeParameters,PredicateParameters,TxParameters,ScriptParametersandContractParametersinto an enum to support versioning. - #701: Wrapped
ConsensusParametersandGasCostsinto an enum to support versioning. Movedblock_gas_limitfromfuel_core_chain_config::ChainConfigtoConsensusPataremeters. Reduced defaultMAX_SIZEto be 110kb andMAX_CONTRACT_SIZEto be 100kb. - #692: Add GTF getters for tx size and address.
- #698: Store input, output and witness limits to u16, while keeping the values limited to 255.
- #689: Re-add fields to the checked tx
Metadatafor min and max gas. - #689: Add test helpers and additional getters.
- #686: Implement
serdeforInterpreterError.
- #685:
The
MaxFeeis a mandatory policy to set. TheMaxFeepolicy is used to check that the transaction is valid. Added a new stage for theCheckedtransaction -Ready. This type can be constructed with thegas_pricebefore being transacted by theInterpreter. - #671: Support dynamically sized values in the ContractsState table by
using a vector data type (
Vec<u8>). - #682: Include
Tippolicy in fee calculation - #683: Simplify
InterpreterStorageby removing dependency onMerkleRootStorageand removingmerkle_prefix from method names. - #678: Zero malleable fields before execution. Remove some now-obsolete
GTF getters. Don't update
tx.receiptsRootafter pushing receipts, and do it after execution instead. - #672: Remove
GasPricepolicy - #672: Add
gas_pricefield to transaction execution - #684: Remove
maturityfield fromInputcoin types. Also remove relatedGTFgetter. - #675: Add
GTFaccess forasset_idandtofields forChangeoutputs.
- #679: Require less restricted constraint on
MerkleRootStoragetrait. Now it requiresStorageInspectinstead of theStorageMutate. - #673: Removed
ContractsInfotable. Contract salts and roots are no longer stored in on-chain data. - #673: Opcode
CROOnow calculates the given contract's root on demand.CROOhas therefore been changed to aDependentCostgas cost.
- #672: Add
Tippolicy
- #668: Remove
non_exhaustivefrom versionable types for security reasons
- #653:
ECALopcode handler can now hold internal state. - #657: Add debugger methods to remove or replace all breakpoints at once.
- #654: Make public types versionable by making non-exhaustive.
- #658: Make
key!-generated types likeAddress,AssetId,ContractIdandBytes32consume one less byte when serialized with a binary serde serializer like postcard.
- #645: Add wasm support for
fuel-txcrate.
- #643: Fixed json deserialization of array fuel types from the file.
- #640: Update VM initialization cost to dependent cost; this is required because the time it takes to initialize the VM depends on the size of the transaction.
- #637: Charge for the actual size of the contract in
ccpopcode.
-
#676 Add
gas_pricetoMinttransaction -
#629: Charge the user for VM initialization.
-
#628: Renamed
transaction::CheckErrortotransaction::ValidityError. Created a newchecked_transaction::CheckErrorthat combinesValidityErrorandPredicateVerificationFailederrors into one. It allows the return of thePredicateVerificationFailedto the end user instead of losing the reason why predicate verification failed. -
#625: Use
ArithmeticErroronly for arithmetic operations, and introduce new errors likeBalanceOverflowfor others. Whenever an error is internally caused by a type conversion tousize, so that an overflowing value wouldn't map to a valid index anyway, return the missing item error instead. -
#623: Added support for transaction policies. The
ScriptandCreatetransactions received a new field,policies. Policies allow the addition of some limits to the transaction to protect the user or specify some details regarding execution. This change makes theGasPriceandMaturityfields optional, allowing to save space in the future. Also, this will enable us to support multidimensional prices later.GasLimitwas renamed toScriptGasLimit.Along with this change, we introduced two new policies:
WitnessLimit- allows the limitation of the maximum size of witnesses in bytes for the contract. Because of the changes in the gas calculation model(the blockchain also charges the user for the witness data), the user should protect himself from the block producer or third parties blowing up witness data and draining the user's funds.MaxFee- allows the upper bound for the maximum fee that users agree to pay for the transaction.
This change brings the following modification to the gas model:
- The
ScriptGasLimitonly limits script execution. Previously, theScriptGasLimitalso limited the predicate execution time, instead predicate gas is now directly included intomin_fee. So, it is not possible to use theScriptGasLimitfor transaction cost limitations. A newMaxFeepolicy is a way to do that. TheGasLimitfield was removed from theCreatetransaction because it only relates to the script execution (which theCreatetransaction doesn't have). - The blockchain charges the user for the size of witness data (before it was free). There is no separate price for
the storage, so it uses gas to charge the user. This change affects
min_gasandmin_feecalculation. - A new policy called
WitnessLimitalso impacts themax_gasandmax_feecalculation in addition toScriptGasLimit(in the case ofCreatetransaction onlyWitnessLimitaffects themax_gasandmax_fee). - The minimal gas also charges the user for transaction ID calculation.
The change has the following modification to the transaction layout:
- The
Createtransaction doesn't have theScriptGasLimitfield anymore. Because theCreatetransaction doesn't have any script to execute - The
CreateandScripttransactions don't have explicitmaturityandgas_pricefields. Instead, these fields can be set via a newpoliciesfield. - The
CreateandScripttransactions have a newpoliciesfield with a unique canonical serialization and deserialization for optimal space consumption.
Other breaking changes caused by the change:
- Each transaction requires setting the
GasPricepolicy. - Previously,
ScriptGasLimitshould be less than theMAX_GAS_PER_TXconstant. After removing this field from theCreatetransaction, it is impossible to require it. Instead, it requires thatmax_gas <= MAX_GAS_PER_TXfor any transaction. Consequently, anyScripttransaction that usesMAX_GAS_PER_TXas aScriptGasLimitwill always fail because of a new rule. Setting the estimated gas usage instead solves the problem. - If the
max_fee > policies.max_fee, then transaction will be rejected. - If the
witnessses_size > policies.witness_limit, then transaction will be rejected. - GTF opcode changed its hardcoded constants for fields. It should be updated according to the values from the specification on the Sway side.
-
#633: Limit receipt count to
u16::MAX. -
#634: Charge for storage per new byte written. Write opcodes now return the number of new storage slots created, instead of just a boolean on whether the value existed before.
- #627: Added removal of obsolete SMT nodes along the path
during
updateanddeleteoperations.
- #622: Divide
DependentCostinto "light" and "heavy" operations: Light operations consume0 < x < 1gas per unit, while heavy operations consumexgas per unit. This distinction provides more precision when calculating dependent costs.
- #607: Added
ECALinstruction support.
- #612: Reduced the memory consumption in all places where we calculate BMT root.
- #615: Made
ReceiptsCtxof the VM modifiable withtest-helpersfeature.
- #618: Transaction fees for
Createnow include the cost of metadata calculations, including: contract root calculation, state root calculation, and contract id calculation. - #613: Transaction fees now include the cost of signature verification for each input. For signed inputs, the cost of an EC recovery is charged. For predicate inputs, the cost of a BMT root of bytecode is charged.
- #607: The
Interpreterexpects the third generic argument during type definition that specifies the implementer of theEcalHandlertrait forecalopcode. - #609: Checked transactions (
Create,Script, andMint) now enforce a maximum size. The maximum size is specified byMAX_TRANSACTION_SIZEin the transaction parameters, under consensus parameters. Checking a transaction above this size raisesCheckError::TransactionSizeLimitExceeded. - #617: Makes memory outside
$is..$ssprange not executable. SeparatesErrorFlagintoInvalidFlags,MemoryNotExecutableandInvalidInstruction. Fixes related tests. - #619: Avoid possible truncation of higher bits. It may invalidate the code that truncated higher bits causing different behavior on 32-bit vs. 64-bit systems.
- #603: Added
MerkleRootCalculatorfor efficient in-memory Merkle root calculation. - #603: Added Serialization and Deserialization support
to
MerkleRootCalculator.
- #595: Removed
wee_allocdependency fromfuel-asm. It now uses the builtin allocator on web targets as well.
- #598: Update cost model for
ldcopcode to take into account contract size. - #604: Removed
ChainIdfromPredicateIdcalculation. It changes the generated address of the predicates and may break tests or logic that uses hard-coded predicate IDs. - #594: Add new predicate input validation tests. Also improves error propagation so that predicate error message better reflects the reason for invalidity.
- #596: Remove
core::ops::{Add, Sub}impls fromBlockHeight. Usesuccandpredto access adjacent blocks, or perform arithmetic directly on the wrapped integer instead. - #593: Reworked
Minttransaction to work withInput::ContractandOutput::Contractinstead ofOutput::Coin. It allows account-based fee collection for the block producer.
- #586: Added
default_assetmethod to theContractIdExttrait implementation, to mirror thedefaultmethod on AssetId in the Sway std lib.
- #578: Support
no_stdenvironments forfuel-crypto, falling back to a pure-Rust crypto implementation. - #582: Make
fuel-vmandfuel-txcrates compatible withno_std+alloc. This includes reworking all error handling that usedstd::io::Error, replacing somestd::collection::{HashMap, HashSet}withhashbrown::{HashMap, HashSet}and many changes to feature-gating of APIs. - #587: Replace
thiserrordependency withderive_more, so thatcore::fmt::Displayis implemented without thestdfeature. Removesstd::io::Errortrait impls from the affected types. - #588: Re-worked the size calculation of the canonical serialization/deserialization.
- #700: Add
BASE_ASSET_IDtoGMinstruction.
- #588: Removed
SerializedSizeandSerializedFixedSizetraits. Removed support forSIZE_NO_DYNAMICandSIZE_STATIC. Removed enum attributes from derive macro forSerializeandDeserializetraits.
- #573: Added
base_asset_idas a required field toFeeParameters.base_asset_idis used to supply the ID of the base asset. - #554: Removed
debugfeature from thefuel-vm. The debugger is always available and becomes active after calling anyset_*method. - #537: Use dependent cost for
k256,s256,mcpi,scwq,swwqopcodes. These opcodes charged inadequately low costs in comparison to the amount of work. This change should make all transactions that used these opcodes much more expensive than before. - #533: Use custom serialization for fuel-types to allow no_std compilation.
- #546: Improve debug formatting of instruction in panic receipts.
- #574: Enforce fixed 32-byte input length for LHS and RHS inputs to the BMT's internal node sum.
- #547: Bump
ed25519-dalekto2.0.0to deal with RustSec Advisory.
- #524: Fix a crash in
CCPinstruction when overflowing contract bounds. Fix a bug inCCPwhere overflowing contract bounds in a different way would not actually copy the contract bytes, but just zeroes out the section. Fix a bug inLDCwhere it would revert the transaction when the contract bounds were exceeded, when it's just supposed to fill the rest of the bytes with zeroes.
- #525: The
$hpregister is no longer restored to it's previous value when returning from a call, making it possible to return heap-allocated types fromCALL. - #535: Add better test coverage for TR and TRO.
- #514: Add
ChainIdandGasCoststoConsensusParameters. Break downConsensusParametersinto sub-structs to match usage. Change signatures of functions to ask for necessary fields only. - #532: The
TROinstruction now reverts when attempting to send zero coins to an output. Panic reason of thisTransferZeroCoins, andTRwas changed to use the same panic reason as well.
-
#511: Changes multiple panic reasons to be more accurate, and internally refactors instruction fetch logic to be less error-prone.
-
#529 #534: Enforcing async WASM initialization for all NPM wrapper packages.
-
#531: UtxoId::from_str and TxPointer::from_str no longer crash on invalid input with multibyte characters. Also adds clippy lints to prevent future issues.
- #527: The balances are empty during predicate estimation/verification.
- #542: Make the
fuel-txWASM compatible withserdefeature enabled.
- #539: Rollbacked the change for the gas charging formula. Actualized the gas prices for opcodes.
- #499: The
wasm_bindgensupport offuel-asmandfuel-types. Each new release also publish a typescript analog of thefuel-asmandfuel-typescrates to the npm.
The release mostly fixes funding during the audit and integration with the bridge. But the release also contains some new features like:
- Asynchronous predicate estimation/verification.
- Multi-asset support per contract.
- Support Secp256r1 signature recovery and Ed25519 verificaiton.
-
#486: Adds
ed25519signature verification andsecp256r1signature recovery tofuel-crypto, and corresponding opcodesED19andECR1tofuel-vm. -
#486: Adds
PSHL,PSHH,POPHandPOPLinstructions, which allow cheap push and pop stack operations with multiple registers. -
#500: Introduced
ParallelExecutortrait and made available async versions of verify and estimate predicates. Updated tests to test for both parallel and sequential execution. Fixed a bug intransaction/check_predicate_owners.
- #506: Added new
MintandBurnvariants toReceiptenum. It affects serialization and deserialization with new variants.
-
#506: The
mintandburnopcodes accept a new$rBregister. It is a sub-identifier used to generate anAssetIdby this rule. This feature allows having multi-asset per one contract. It is a huge breaking change, and after this point,ContractIdcan't be equal toAssetId.The conversion like
AssetId::from(*contract_id)is no longer valid. Instead, theContractIdimplements theContractIdExttrait:/// Trait extends the functionality of the `ContractId` type. pub trait ContractIdExt { /// Creates an `AssetId` from the `ContractId` and `sub_id`. fn asset_id(&self, sub_id: &Bytes32) -> AssetId; }
-
#506: The
mintandburnopcodes affect thereceipts_rootof theScripttransaction.
- #486: Removes apparently unused
KeystoreandSignertraits fromfuel-crypto. Also renamesECRopcode toECK1.
- #500: Fixed a bug where
MessageCoinPredicatewasn't checked for incheck_predicate_owners.
-
#502: The algorithm used by the binary Merkle tree for generating Merkle proofs has been updated to remove the leaf data from the proof set. This change allows BMT proofs to conform to the format expected by the Solidity contracts used for verifying proofs.
-
#503: Use correct amount of gas in call receipts when limited by cgas. Before this change, the
Receipt::Callcould show an incorrect value for the gas limit. -
#504: The
CROOandCSIZopcodes require the existence of correspondingContractIdin the transaction's inputs(the same behavior as for theCROOopcode). -
#504: The size of the contract was incorrectly padded. It affects the end of the call frame in the memory, making it not 8 bytes align. Also, it affects the cost of the contract call(in some cases, we charged less in some more).
-
#504: The charging for
DependentCostwas done incorrectly, devaluing thedep_per_unitpart. After the fixing of this, the execution should become much more expensive. -
#505: The
datafield of theReceiptis not part of the canonical serialization and deserialization anymore. The SDK should use theReceipttype instead ofOpaqueReceipt. TheReceipt.raw_payloadwill be removed for thefuel-core 0.20. Thedatafield is optional now. The SDK should update serialization and deserialization forMessageOut,LogData, andReturnDatareceipts. -
#505: The
lenfield of theReceiptis not padded anymore and represents an initial value.
Mainly new opcodes prices and small performance improvements in the BinaryMerkleTree.
- #492: Minor improvements to BMT
internals, including a reduction in usage of
Box, usingexpect(...)overunwrap(), and additional comments.
- #493: The default
GasCostsValuesis updated according to the benches withfuel-core 0.19. It may break some unit tests that compare actual gas usage with expected.
This release contains fixes for critical issues that we found before the audit. Mainly, these changes pertain to the Sparse Merkle Tree (SMT) and related code. The SMT API was extended to provide more flexibility and to allow users to select the most appropriate method for their performance needs. Where possible, sequential SMT updates were replaced with constructors that take in a complete data set.
-
#476: The
fuel_vm::CallsupportsFrom<[u8; Self::LEN]>andInto<[u8; Self::LEN]>. -
#484: The
sparse::in_memory::MerkleTreegot new methodsfrom_set,root_from_set, andnodes_from_setmethods. These methods allow a more optimal way to build and calculate the SMT when you know all leaves. TheContract::initial_state_rootis much faster now (by ~15 times).
- #478: The
CheckedMemRangeis replaced by theMemoryRange.
-
#477: The
PanicReason::UnknownPanicReasonis0x00. ThePanicReasonnow implementsFrom<u8>instead ofTryFrom<u8>and can't return an error anymore. -
#478: The
memcopymethod is updated and returnsMemoryWriteOverlapinstead ofMemoryOverflow.
-
#482: This PR address a security issue where updates to a Sparse Merkle Tree could deliberately overwrite existing leaves by setting the leaf key to the hash of an existing leaf or node. This is done by removing the insertion of the leaf using the leaf key.
-
#484: Fixed bug with not-working
CreateMetadata.
-
#473: CFS and CFSI were not validating that the new
$spvalue isn't below$ssp, allowing write access to non-owned memory. This is now fixed, and attempting to set an incorrect$spvalue panics. -
#485: This PR addresses a security issue where the user may manipulate the structure of the Sparse Merkle Tree. SMT expects hashed storage key wrapped into a
MerkleTreeKeystructure. The change is breaking because it changes thestate_rootgenerated by the SMT and may change theContractIdif theCreatetransaction has non-emptyStoargeSlots.
The release contains a lot of breaking changes. Most of them are audit blockers and affect the protocol itself. Starting this release we plan to maintain the changelog file and describe all minor and major changes that make sense.
-
#386: The coin and message inputs got a new field -
predicate_gas_used. So it breaks the constructor API of these inputs.The value of this field is zero for non-predicate inputs, but for the predicates, it indicates the exact amount of gas used by the predicate to execute. If after the execution of the predicate remaining gas is not zero, then the predicate execution failed.
This field is malleable but will be used by the VM, and each predicate should be estimated before performing the verification logic. The
Transaction,Create, andScripttypes implement theEstimatePredicatesfor these purposes./// Provides predicate estimation functionality for the transaction. pub trait EstimatePredicates: Sized { /// Estimates predicates of the transaction. fn estimate_predicates(&mut self, params: &ConsensusParameters, gas_costs: &GasCosts) -> Result<(), CheckError>; }
During the creation of the
Input, the best strategy is to use a default value like0and call theestimate_predicatesmethod to actualize thepredicate_gas_usedafter. -
#454: VM native array-backed types
Address,AssetId,ContractId,Bytes4,Bytes8,Bytes20,Bytes32,Nonce,MessageId,Saltnow use more compact representation instead of hex-encoded string when serialized using serde format that setsis_human_readableto false. -
#456: Added a new type -
ChainIdto represent the identifier of the chain. It is a wrapper around theu64, so anyu64can be converted into this type via.into()orChainId::new(...). -
#459 Require witness index to be specified when adding an unsigned coin to a transaction. This allows for better reuse of witness data when using the transaction builder and helper methods to make transactions compact.
-
#462: Adds a
cacheparameter toInput::checkandInput::check_signature. This is used to avoid redundant signature recovery when multiple inputs share the same witness index.
- #458: Automatically sort storage slots for creation transactions.
-
#386: Several methods of the
TransactionFeeare renamedtotal->max_feeandbytes->min_fee. TheTransactionFee::min_feetake into account the gas used by predicates. -
#450: The Merkle root of a contract's code is now calculated by partitioning the code into chunks of 16 KiB, instead of 8 bytes. If the last leaf is does not a full 16 KiB, it is padded with
0up to the nearest multiple of 8 bytes. This affects theContractIdandPredicateIdcalculations, breaking all code that used hardcoded values. -
#456: The basic methods
UniqueIdentifier::id,Signable::sign_inputs, andInput::predicate_owneruseChainIdinstead of theConsensusParameters. It is a less strict requirement than before because you can getChainIdfromConsensusParameters.chain_id, and it makes the API cleaner. It affects all downstream functions that use listed methods. -
#463: Moves verification that the
Output::ContractCreatedoutput contains validcontract_idandstate_root(the values from theOutputmatch with calculated values from the bytecode, storage slots, and salt) fromfuel-vmtofuel-tx. It means the end-user will receive this error earlier on the SDK side beforedry_runinstead of after.
-
#457: Transactions got one more validity rule: Each
ScriptorCreatetransaction requires at least one input coin or message to be spendable. It may break code/tests that previously didn't set any spendable inputs. Note:Messagewith non-emptydatafield is not spendable. -
#458: The storage slots with the same key inside the
Createtransaction are forbidden.