Use hash-based balance_root and state_root fields (#3099)
## Description @xgreenx writes on [slack](https://fuellabs.slack.com/archives/C01KVGRDZHB/p1755856188397269?thread_ts=1749203886.570819&cid=C01KVGRDZHB): > Storing storage slots in the transaction makes the blob really, really big; it can even be bigger than the allowance for the block, but we will only know about its size after the execution. So having a malleable list of storage slots is a bad idea, not taking into account that it is not compressible and will make p2p worse. Also, on the fraud-proving side, in the case of the Validium solution, these storage slots are useless, because we need to prove in one go the latest values for storage slots(which requires a global merkle root). In the case of V2 fraud proof solution(where we prove the execution only of the transaction), it is more useful because it allows executing the transaction in one go(assuming storage slots are correct). But it is needed only in the case that a block producer used incorrect values during the execution of the transaction. We can get almost the same properties by going another route: > 1. Use a hash of all storage slots/balances(hash over sorted list of (Key, Option<Value>)) and use balance_root and state_root fields in the input and output. > 2. For input of the contract, we will use all storage slots/balances accessed during the execution, even if the value for them is None in the storage. In this case, we can be sure that the block producer listed all the required information to execute the transaction. > 3. Output will contain a hash of the same storage slots/balances after the execution. > 4. Regular blocks and transactions that we use to sync with the network(and on UI) will not be affected. But anyone will be able to request additional metadata for a transaction, like storage slots before and after the execution(we will store them in the off-chain database). > 5. For the validium case, we will just create a global merkle root of the storage and balances for all contracts. It will be much faster, because it is just one bulk update into SMT(a bulk update of 100_000 updates is faster than 100_000 single updates in 50-100 times). > 6. In the case of V2 fraud proofs, the case with incorrect initial values is already a 2-round game; we will just add an additional round, where the block producer should reveal initial values(it can be done on-chain or off-chain). If we don't want to have an additional step here, then we can post this data along with transactions to DA. In this case, we don't change the layout of the transaction(we use all the fields that we have right now; the tx_pointer field is useless in this context, but it is fine). We don't affect the network. This information will be accessible via GraphQL. Implementation, then, is very straightforward and fast. The only problem that we need to solve is how to post the old state of the network(old storage slots and balances before we started to use this approach with storage slots). But we have this issue regardless of the approach we use. So it is a separate topic. ## Checklist - [ ] Breaking changes are clearly marked as such in the PR description and changelog - [ ] New behavior is reflected in tests - [ ] [The specification](https://github.com/FuelLabs/fuel-specs/) matches the implemented behavior (link update PR if changes are needed) ### Before requesting review - [ ] I have reviewed the code myself - [x] I have created follow-up issues caused by this PR and linked them here --------- Co-authored-by: green <xgreenx9999@gmail.com>
H
Hannes Karppila committed
5bda22ece0a324239fe5407ba7baf13a978f4165
Parent: 0803cac
Committed by GitHub <noreply@github.com>
on 10/17/2025, 2:06:47 PM