From fd5de5e76c7b9377fa2b6f7693d5a4bf1f07e903 Mon Sep 17 00:00:00 2001 From: Hannes Karppila Date: Sun, 6 Oct 2024 11:56:47 +0300 Subject: [PATCH] Rewrite predicate section --- src/fuel-vm/index.md | 47 ++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/src/fuel-vm/index.md b/src/fuel-vm/index.md index fb443a20..5b74d52a 100644 --- a/src/fuel-vm/index.md +++ b/src/fuel-vm/index.md @@ -95,54 +95,37 @@ Then the following registers are initialized (without explicit initialization, a ## Contexts -There are 4 _contexts_ in the FuelVM: [predicate estimation](#predicate-estimation), [predicate verification](#predicate-verification), [scripts](#script-execution), and [calls](./instruction-set.md#call-call-contract). A context is an isolated execution environment with defined [memory ownership](#ownership) and can be _external_ or _internal_: +There are 4 _contexts_ in the FuelVM: [predicate estimation and verification](#predicate-estimation-and-verification), [scripts](#script-execution), and [calls](#call). A context is an isolated execution environment with defined [memory ownership](#ownership) and can be _external_ or _internal_: - External: predicate and script. `$fp` will be zero. - Internal: call. `$fp` will be non-zero. [Returning](./instruction-set.md#return-return-from-call) from a context behaves differently depending on whether the context is external or internal. -## Predicate Estimation +### Predicate Estimation and Verification -For any input of type [`InputType.Coin`](../tx-format/index.md) or [`InputType.Message`](../tx-format/index.md), a non-zero `predicateLength` field means the UTXO being spent is a [`P2SH`](https://en.bitcoin.it/wiki/P2SH) rather than a [`P2PKH`](https://en.bitcoin.it/P2PKH) output. - -For each such input in the transaction, the VM is [initialized](#vm-initialization), then: - -1. `$pc` and `$is` are set to the start of the input's `predicate` field. -1. `$ggas` and `$cgas` are set to `MAX_GAS_PER_PREDICATE`. - -Predicate estimation will fail if gas is exhausted during execution. - -During predicate mode, hitting any of the following instructions causes predicate estimation to halt, returning Boolean `false`: - -1. Any [contract instruction](./instruction-set.md#contract-instructions). - -In addition, during predicate mode if `$pc` is set to a value greater than the end of predicate bytecode (this would allow bytecode outside the actual predicate), predicate estimation halts returning Boolean `false`. - -A predicate that halts without returning Boolean `true` would not pass verification, making the entire transaction invalid. Note that predicate validity is monotonic with respect to time (i.e. if a predicate evaluates to `true` then it will always evaluate to `true` in the future). - -After successful execution, `predicateGasUsed` is set to `MAX_GAS_PER_PREDICATE - $ggas`. - -## Predicate Verification +There are two ways to run predicates on the VM: +1. Estimation: runs the predicate and updates the amount of gas used +1. Verification: runs the predicate and verifies the amount of gas used matches the input For any input of type [`InputType.Coin`](../tx-format/input.md#inputcoin) or [`InputType.Message`](../tx-format/input.md#inputmessage), a non-zero `predicateLength` field means the UTXO being spent is a [`P2SH`](https://en.bitcoin.it/P2SH) rather than a [`P2PKH`](https://en.bitcoin.it/P2PKH) output. For each such input in the transaction, the VM is [initialized](#vm-initialization), then: 1. `$pc` and `$is` are set to the start of the input's `predicate` field. -1. `$ggas` and `$cgas` are set to `predicateGasUsed`. +1. `$ggas` and `$cgas` are set to `MAX_GAS_PER_PREDICATE` for estimation, and `predicateGasUsed` for verification. -Predicate verification will fail if gas is exhausted during execution. +Predicate execution will fail if gas is exhausted during execution. -During predicate mode, hitting any [contract instruction](./instruction-set.md#contract-instructions) causes predicate verification to halt, returning Boolean `false`. +During predicate mode, hitting any [contract instruction](./instruction-set.md#contract-instructions) (except `ldc` with non-contract target) causes predicate verification to halt, returning Boolean `false`. -In addition, during predicate mode if `$pc` is set to a value greater than the end of predicate bytecode (this would allow bytecode outside the actual predicate), predicate verification halts returning Boolean `false`. +A predicate that halts without returning Boolean `true` would not pass verification, making the entire transaction invalid. Note that predicate return value is monotonic with respect to time (i.e. if a predicate evaluates to `true` then it will always evaluate to `true` in the future). -A predicate that halts without returning Boolean `true` does not pass verification, making the entire transaction invalid. Note that predicate validity is monotonic with respect to time (i.e. if a predicate evaluates to `true` then it will always evaluate to `true` in the future). +After successful execution, the run mode is determines the final step: +1. Estimation: `predicateGasUsed` is set to `MAX_GAS_PER_PREDICATE - $ggas`. +1. Verification: if `$ggas` is non-zero, predicate verification fails. -After execution, if `$ggas` is non-zero, predicate verification fails. - -## Script Execution +### Script Execution If script bytecode is present, transaction validation requires execution. @@ -157,6 +140,10 @@ For each instruction, its gas cost `gc` is first computed. If `gc > $cgas`, dedu After the script has been executed, `tx.receiptsRoot` is updated to contain the Merkle root of the receipts, [as described in the `TransactionScript` spec](../tx-format/transaction.md#`TransactionScript`). +### Call + +Call context is entered via [`CALL` instruction](./instruction-set.md#call-call-contract). It's also called *internal context*, or *contract context*. Call context is used to access state of a contract. + ## Call Frames Cross-contract calls push a _call frame_ onto the stack, similar to a stack frame used in regular languages for function calls (which may be used by a high-level language that targets the FuelVM). The distinction is as follows: