From 5132778fcb1c98c09f90cdf8943f55d2f5c50864 Mon Sep 17 00:00:00 2001 From: PixelCircuits Date: Fri, 9 Dec 2022 00:23:23 -0500 Subject: [PATCH 01/15] message retryable and not spendable on gas --- src/protocol/tx_format/input.md | 2 ++ src/protocol/tx_format/transaction.md | 4 ++-- src/protocol/tx_validity.md | 26 +++++++++++++++++++------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/protocol/tx_format/input.md b/src/protocol/tx_format/input.md index b80bd4ad..d61e3dea 100644 --- a/src/protocol/tx_format/input.md +++ b/src/protocol/tx_format/input.md @@ -107,3 +107,5 @@ Transaction is invalid if: - `predicateDataLength != len(predicateData)` The predicate root is computed identically to the contract root, used to compute the contract ID, [here](../id/contract.md). + +> **Note:** `InputMessages` are not considered spent until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit diff --git a/src/protocol/tx_format/transaction.md b/src/protocol/tx_format/transaction.md index 66e5799f..a7472647 100644 --- a/src/protocol/tx_format/transaction.md +++ b/src/protocol/tx_format/transaction.md @@ -110,8 +110,8 @@ The receipts root `receiptsRoot` is the root of the [binary Merkle tree](../cryp Transaction is invalid if: -- Any input is of type `InputType.Contract` -- Any output is of type `OutputType.Contract` or `OutputType.Variable` +- Any input is of type `InputType.Contract` or `InputType.Message` +- Any output is of type `OutputType.Contract` or `OutputType.Variable` or `OutputType.Message` - More than one output is of type `OutputType.Change` with `asset_id` of zero - Any output is of type `OutputType.Change` with non-zero `asset_id` - It does not have exactly one output of type `OutputType.ContractCreated` diff --git a/src/protocol/tx_validity.md b/src/protocol/tx_validity.md index 63823835..cdec170f 100644 --- a/src/protocol/tx_validity.md +++ b/src/protocol/tx_validity.md @@ -56,6 +56,8 @@ This section defines _VM precondition validity rules_ for transactions: the bare For a transaction `tx`, UTXO set `state`, contract set `contracts`, and message set `messages`, the following checks must pass. +> **Note:** [InputMessages](./tx_format/input.md#inputmessage) don't exit the `messages` message set until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit + ### Base Sanity Checks Base sanity checks are defined in the [transaction format](./tx_format/index.md). @@ -83,22 +85,30 @@ If this check passes, the UTXO ID `(txID, outputIndex)` fields of each contract For each asset ID `asset_id` in the input and output set: ```py +def sum_messages(tx, asset_id) -> int: + total: int = 0 + if asset_id == 0: + for input in tx.inputs: + if input.type == InputType.Message: + total += input.amount + return total + def sum_inputs(tx, asset_id) -> int: total: int = 0 for input in tx.inputs: - if (input.type == InputType.Coin and input.asset_id == asset_id) or (input.type == InputType.Message and asset_id == 0): + if input.type == InputType.Coin and input.asset_id == asset_id: total += input.amount return total def sum_outputs(tx, asset_id) -> int: total: int = 0 for output in tx.outputs: - if (output.type == OutputType.Coin and output.asset_id == asset_id) or (output.type == OutputType.Message and asset_id == 0): + if output.type == OutputType.Coin and output.asset_id == asset_id: total += output.amount return total def available_balance(tx, asset_id) -> int: - availableBalance = sum_inputs(tx, asset_id) + availableBalance = sum_inputs(tx, asset_id) + sum_messages(tx, asset_id) return availableBalance def unavailable_balance(tx, asset_id) -> int: @@ -106,16 +116,18 @@ def unavailable_balance(tx, asset_id) -> int: Note: we don't charge for predicate verification because predicates are monotonic and the cost of bytes should approximately makes up for this. """ - sentBalance = sum_outputs(tx, col) + sentBalance = sum_outputs(tx, asset_id) gasBalance = gasPrice * gasLimit / GAS_PRICE_FACTOR # Size excludes witness data as it is malleable (even by third parties!) bytesBalance = size(tx) * GAS_PER_BYTE * gasPrice / GAS_PRICE_FACTOR # Total fee balance feeBalance = ceiling(gasBalance + bytesBalance) + # Total message balance + messageBalance = sum_messages(tx, asset_id) # Only base asset can be used to pay for gas - if asset_id != 0: - return sentBalance - return sentBalance + feeBalance + if asset_id == 0: + return sentBalance + feeBalance + messageBalance + return sentBalance return available_balance(tx, asset_id) >= unavailable_balance(tx, asset_id) ``` From 0996faa002fc68b74c1f7129b1f6140811620408 Mon Sep 17 00:00:00 2001 From: PixelCircuits Date: Sat, 10 Dec 2022 00:28:11 -0500 Subject: [PATCH 02/15] message with no data spendable as coin --- src/SUMMARY.md | 1 + src/protocol/tx_format/index.md | 1 + src/protocol/tx_format/input.md | 75 +++++++++++++---------- src/protocol/tx_format/message_pointer.md | 9 +++ src/protocol/tx_validity.md | 6 +- src/vm/instruction_set.md | 50 +++++++-------- 6 files changed, 85 insertions(+), 57 deletions(-) create mode 100644 src/protocol/tx_format/message_pointer.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 7d098df5..170336e9 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -10,6 +10,7 @@ - [Output](./protocol/tx_format/output.md) - [Witness](./protocol/tx_format/witness.md) - [TXPointer](./protocol/tx_format/tx_pointer.md) + - [MessagePointer](./protocol/tx_format/message_pointer.md) - [Computing Identifiers](./protocol/id/index.md) - [Transaction ID](./protocol/id/transaction.md) - [Contract ID](./protocol/id/contract.md) diff --git a/src/protocol/tx_format/index.md b/src/protocol/tx_format/index.md index 52eb8324..b23d8ac3 100644 --- a/src/protocol/tx_format/index.md +++ b/src/protocol/tx_format/index.md @@ -20,3 +20,4 @@ The Fuel Transaction Format. - [OutputContractCreated](./output.md#outputcontractcreated) - [Witness](./witness.md) - [TXPointer](./tx_pointer.md) +- [MessagePointer](./message_pointer.md) diff --git a/src/protocol/tx_format/input.md b/src/protocol/tx_format/input.md index d61e3dea..df50cfab 100644 --- a/src/protocol/tx_format/input.md +++ b/src/protocol/tx_format/input.md @@ -19,20 +19,21 @@ Transaction is invalid if: ## InputCoin -| name | type | description | -|-----------------------|------------------------------|------------------------------------------------------------------------| -| `txID` | `byte[32]` | Hash of transaction. | -| `outputIndex` | `uint8` | Index of transaction output. | -| `owner` | `byte[32]` | Owning address or predicate root. | -| `amount` | `uint64` | Amount of coins. | -| `asset_id` | `byte[32]` | Asset ID of the coins. | -| `txPointer` | [TXPointer](./tx_pointer.md) | Points to the TX whose output is being spent. | -| `witnessIndex` | `uint8` | Index of witness that authorizes spending the coin. | -| `maturity` | `uint32` | UTXO being spent must have been created at least this many blocks ago. | -| `predicateLength` | `uint16` | Length of predicate, in instructions. | -| `predicateDataLength` | `uint16` | Length of predicate input data, in bytes. | -| `predicate` | `byte[]` | Predicate bytecode. | -| `predicateData` | `byte[]` | Predicate input data (parameters). | +| name | type | description | +|-----------------------|----------------------------------------|------------------------------------------------------------------------| +| `txID` | `byte[32]` | Hash of transaction or ID of originating message ID. | +| `outputIndex` | `uint8` | Index of transaction output. | +| `owner` | `byte[32]` | Owning address or predicate root. | +| `amount` | `uint64` | Amount of coins. | +| `asset_id` | `byte[32]` | Asset ID of the coins. | +| `txPointer` | [TXPointer](./tx_pointer.md) | Points to the TX whose output is being spent. | +| `messagePointer` | [MessagePointer](./message_pointer.md) | Points to the message being spent. | +| `witnessIndex` | `uint8` | Index of witness that authorizes spending the coin. | +| `maturity` | `uint32` | UTXO being spent must have been created at least this many blocks ago. | +| `predicateLength` | `uint16` | Length of predicate, in instructions. | +| `predicateDataLength` | `uint16` | Length of predicate input data, in bytes. | +| `predicate` | `byte[]` | Predicate bytecode. | +| `predicateData` | `byte[]` | Predicate input data (parameters). | Given helper `len()` that returns the number of bytes of a field. @@ -47,11 +48,13 @@ Transaction is invalid if: If `h` is the block height the UTXO being spent was created, transaction is invalid if `blockheight() < h + maturity`. -> **Note:** when signing a transaction, `txPointer` is set to zero. +> **Note:** when signing a transaction, `txPointer` and `messagePointer` are set to zero. > -> **Note:** when verifying a predicate, `txPointer` is initialized to zero. +> **Note:** when verifying a predicate, `txPointer` and `messagePointer` are initialized to zero. > -> **Note:** when executing a script, `txPointer` is initialized to zero. +> **Note:** when executing a script, `txPointer` and `messagePointer` are initialized to zero. +> +> **Note:** a message from the base chain with data length of zero is spent as a coin input using the message ID as the `txID` and `outputIndex` set to zero. The predicate root is computed identically to the contract root, used to compute the contract ID, [here](../id/contract.md). @@ -78,26 +81,28 @@ Transaction is invalid if: ## InputMessage -| name | type | description | -|-----------------------|------------|--------------------------------------------------------------| -| `messageID` | `byte[32]` | The messageID as described [here](../id/utxo.md#message-id). | -| `sender` | `byte[32]` | The address of the message sender. | -| `recipient` | `byte[32]` | The address or predicate root of the message recipient. | -| `amount` | `uint64` | Amount of base asset coins sent with message. | -| `nonce` | `uint64` | The message nonce. | -| `witnessIndex` | `uint8` | Index of witness that authorizes spending the coin. | -| `dataLength` | `uint16` | Length of message data, in bytes. | -| `predicateLength` | `uint16` | Length of predicate, in instructions. | -| `predicateDataLength` | `uint16` | Length of predicate input data, in bytes. | -| `data` | `byte[]` | The message data. | -| `predicate` | `byte[]` | Predicate bytecode. | -| `predicateData` | `byte[]` | Predicate input data (parameters). | +| name | type | description | +|-----------------------|----------------------------------------|--------------------------------------------------------------| +| `messageID` | `byte[32]` | The messageID as described [here](../id/utxo.md#message-id). | +| `sender` | `byte[32]` | The address of the message sender. | +| `recipient` | `byte[32]` | The address or predicate root of the message recipient. | +| `amount` | `uint64` | Amount of base asset coins sent with message. | +| `nonce` | `uint64` | The message nonce. | +| `messagePointer` | [MessagePointer](./message_pointer.md) | Points to the message being spent. | +| `witnessIndex` | `uint8` | Index of witness that authorizes spending the coin. | +| `dataLength` | `uint16` | Length of message data, in bytes. | +| `predicateLength` | `uint16` | Length of predicate, in instructions. | +| `predicateDataLength` | `uint16` | Length of predicate input data, in bytes. | +| `data` | `byte[]` | The message data. | +| `predicate` | `byte[]` | Predicate bytecode. | +| `predicateData` | `byte[]` | Predicate input data (parameters). | Given helper `len()` that returns the number of bytes of a field. Transaction is invalid if: - `witnessIndex >= tx.witnessesCount` +- `dataLength == 0` - `dataLength > MAX_MESSAGE_DATA_LENGTH` - `predicateLength > MAX_PREDICATE_LENGTH` - `predicateDataLength > MAX_PREDICATE_DATA_LENGTH` @@ -108,4 +113,12 @@ Transaction is invalid if: The predicate root is computed identically to the contract root, used to compute the contract ID, [here](../id/contract.md). +> **Note:** when signing a transaction, `messagePointer` is set to zero. +> +> **Note:** when verifying a predicate, `messagePointer` is initialized to zero. +> +> **Note:** when executing a script, `messagePointer` is initialized to zero. +> +> **Note:** a message from the base chain with data length of zero is spent as a coin input using the message ID as the `txID` and `outputIndex` set to zero. +> > **Note:** `InputMessages` are not considered spent until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit diff --git a/src/protocol/tx_format/message_pointer.md b/src/protocol/tx_format/message_pointer.md new file mode 100644 index 00000000..1691180c --- /dev/null +++ b/src/protocol/tx_format/message_pointer.md @@ -0,0 +1,9 @@ +# MessagePointer + +The location of the message on the base chain. It can be used by UTXOs as a reference to the message or by the transaction itself to make it unique. + +| name | type | description | +|---------------|----------|--------------------| +| `blockHeight` | `uint32` | Block height. | +| `txIndex` | `uint16` | Transaction index. | +| `logIndex` | `uint16` | Log index. | diff --git a/src/protocol/tx_validity.md b/src/protocol/tx_validity.md index cdec170f..b9179462 100644 --- a/src/protocol/tx_validity.md +++ b/src/protocol/tx_validity.md @@ -56,7 +56,9 @@ This section defines _VM precondition validity rules_ for transactions: the bare For a transaction `tx`, UTXO set `state`, contract set `contracts`, and message set `messages`, the following checks must pass. -> **Note:** [InputMessages](./tx_format/input.md#inputmessage) don't exit the `messages` message set until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit +> **Note:** [InputMessages](./tx_format/input.md#inputmessage) don't exit the `messages` message set until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit. +> +> **Note:** Messages with no data are included as part of the UTXO set `state` using the message ID as `txID` and `outputIndex` set to zero. Messages with no data are not included in the `messages` message set. ### Base Sanity Checks @@ -78,7 +80,7 @@ for input in tx.inputs: return True ``` -If this check passes, the UTXO ID `(txID, outputIndex)` fields of each contract input is set to the UTXO ID of the respective contract. The `txPointer` of each input is also set to the TX pointer of the UTXO with ID `utxoID`. +If this check passes, the UTXO ID `(txID, outputIndex)` fields of each contract input is set to the UTXO ID of the respective contract. The `txPointer` or `messagePointer` of each input is also set to the TX pointer of the UTXO with ID `utxoID` or the message pointer of the base chain message. ### Sufficient Balance diff --git a/src/vm/instruction_set.md b/src/vm/instruction_set.md index f96ee5b5..fcec717a 100644 --- a/src/vm/instruction_set.md +++ b/src/vm/instruction_set.md @@ -1796,30 +1796,32 @@ Get [fields from the transaction](../protocol/tx_format/transaction.md). | `GTF_INPUT_COIN_AMOUNT` | `0x105` | `tx.inputs[$rB].amount` | | `GTF_INPUT_COIN_ASSET_ID` | `0x106` | Memory address of `tx.inputs[$rB].asset_id` | | `GTF_INPUT_COIN_TX_POINTER` | `0x107` | Memory address of `tx.inputs[$rB].txPointer` | -| `GTF_INPUT_COIN_WITNESS_INDEX` | `0x108` | `tx.inputs[$rB].witnessIndex` | -| `GTF_INPUT_COIN_MATURITY` | `0x109` | `tx.inputs[$rB].maturity` | -| `GTF_INPUT_COIN_PREDICATE_LENGTH` | `0x10A` | `tx.inputs[$rB].predicateLength` | -| `GTF_INPUT_COIN_PREDICATE_DATA_LENGTH` | `0x10B` | `tx.inputs[$rB].predicateDataLength` | -| `GTF_INPUT_COIN_PREDICATE` | `0x10C` | Memory address of `tx.inputs[$rB].predicate` | -| `GTF_INPUT_COIN_PREDICATE_DATA` | `0x10D` | Memory address of `tx.inputs[$rB].predicateData` | -| `GTF_INPUT_CONTRACT_TX_ID` | `0x10E` | Memory address of `tx.inputs[$rB].txID` | -| `GTF_INPUT_CONTRACT_OUTPUT_INDEX` | `0x10F` | `tx.inputs[$rB].outputIndex` | -| `GTF_INPUT_CONTRACT_BALANCE_ROOT` | `0x110` | Memory address of `tx.inputs[$rB].balanceRoot` | -| `GTF_INPUT_CONTRACT_STATE_ROOT` | `0x111` | Memory address of `tx.inputs[$rB].stateRoot` | -| `GTF_INPUT_CONTRACT_TX_POINTER` | `0x112` | Memory address of `tx.inputs[$rB].txPointer` | -| `GTF_INPUT_CONTRACT_CONTRACT_ID` | `0x113` | Memory address of `tx.inputs[$rB].contractID` | -| `GTF_INPUT_MESSAGE_MESSAGE_ID` | `0x114` | Memory address of `tx.inputs[$rB].messageID` | -| `GTF_INPUT_MESSAGE_SENDER` | `0x115` | Memory address of `tx.inputs[$rB].sender` | -| `GTF_INPUT_MESSAGE_RECIPIENT` | `0x116` | Memory address of `tx.inputs[$rB].recipient` | -| `GTF_INPUT_MESSAGE_AMOUNT` | `0x117` | `tx.inputs[$rB].amount` | -| `GTF_INPUT_MESSAGE_NONCE` | `0x118` | `tx.inputs[$rB].nonce` | -| `GTF_INPUT_MESSAGE_WITNESS_INDEX` | `0x119` | `tx.inputs[$rB].witnessIndex` | -| `GTF_INPUT_MESSAGE_DATA_LENGTH` | `0x11A` | `tx.inputs[$rB].dataLength` | -| `GTF_INPUT_MESSAGE_PREDICATE_LENGTH` | `0x11B` | `tx.inputs[$rB].predicateLength` | -| `GTF_INPUT_MESSAGE_PREDICATE_DATA_LENGTH` | `0x11C` | `tx.inputs[$rB].predicateDataLength` | -| `GTF_INPUT_MESSAGE_DATA` | `0x11D` | Memory address of `tx.inputs[$rB].data` | -| `GTF_INPUT_MESSAGE_PREDICATE` | `0x11E` | Memory address of `tx.inputs[$rB].predicate` | -| `GTF_INPUT_MESSAGE_PREDICATE_DATA` | `0x11F` | Memory address of `tx.inputs[$rB].predicateData` | +| `GTF_INPUT_COIN_MESSAGE_POINTER` | `0x108` | Memory address of `tx.inputs[$rB].messagePointer`| +| `GTF_INPUT_COIN_WITNESS_INDEX` | `0x109` | `tx.inputs[$rB].witnessIndex` | +| `GTF_INPUT_COIN_MATURITY` | `0x10A` | `tx.inputs[$rB].maturity` | +| `GTF_INPUT_COIN_PREDICATE_LENGTH` | `0x10B` | `tx.inputs[$rB].predicateLength` | +| `GTF_INPUT_COIN_PREDICATE_DATA_LENGTH` | `0x10C` | `tx.inputs[$rB].predicateDataLength` | +| `GTF_INPUT_COIN_PREDICATE` | `0x10D` | Memory address of `tx.inputs[$rB].predicate` | +| `GTF_INPUT_COIN_PREDICATE_DATA` | `0x10E` | Memory address of `tx.inputs[$rB].predicateData` | +| `GTF_INPUT_CONTRACT_TX_ID` | `0x10F` | Memory address of `tx.inputs[$rB].txID` | +| `GTF_INPUT_CONTRACT_OUTPUT_INDEX` | `0x110` | `tx.inputs[$rB].outputIndex` | +| `GTF_INPUT_CONTRACT_BALANCE_ROOT` | `0x111` | Memory address of `tx.inputs[$rB].balanceRoot` | +| `GTF_INPUT_CONTRACT_STATE_ROOT` | `0x112` | Memory address of `tx.inputs[$rB].stateRoot` | +| `GTF_INPUT_CONTRACT_TX_POINTER` | `0x113` | Memory address of `tx.inputs[$rB].txPointer` | +| `GTF_INPUT_CONTRACT_CONTRACT_ID` | `0x114` | Memory address of `tx.inputs[$rB].contractID` | +| `GTF_INPUT_MESSAGE_MESSAGE_ID` | `0x115` | Memory address of `tx.inputs[$rB].messageID` | +| `GTF_INPUT_MESSAGE_SENDER` | `0x116` | Memory address of `tx.inputs[$rB].sender` | +| `GTF_INPUT_MESSAGE_RECIPIENT` | `0x117` | Memory address of `tx.inputs[$rB].recipient` | +| `GTF_INPUT_MESSAGE_AMOUNT` | `0x118` | `tx.inputs[$rB].amount` | +| `GTF_INPUT_MESSAGE_NONCE` | `0x119` | `tx.inputs[$rB].nonce` | +| `GTF_INPUT_MESSAGE_MESSAGE_POINTER` | `0x11A` | Memory address of `tx.inputs[$rB].messagePointer`| +| `GTF_INPUT_MESSAGE_WITNESS_INDEX` | `0x11B` | `tx.inputs[$rB].witnessIndex` | +| `GTF_INPUT_MESSAGE_DATA_LENGTH` | `0x11C` | `tx.inputs[$rB].dataLength` | +| `GTF_INPUT_MESSAGE_PREDICATE_LENGTH` | `0x11D` | `tx.inputs[$rB].predicateLength` | +| `GTF_INPUT_MESSAGE_PREDICATE_DATA_LENGTH` | `0x11E` | `tx.inputs[$rB].predicateDataLength` | +| `GTF_INPUT_MESSAGE_DATA` | `0x11F` | Memory address of `tx.inputs[$rB].data` | +| `GTF_INPUT_MESSAGE_PREDICATE` | `0x120` | Memory address of `tx.inputs[$rB].predicate` | +| `GTF_INPUT_MESSAGE_PREDICATE_DATA` | `0x121` | Memory address of `tx.inputs[$rB].predicateData` | | `GTF_OUTPUT_TYPE` | `0x201` | `tx.outputs[$rB].type` | | `GTF_OUTPUT_COIN_TO` | `0x202` | Memory address of `tx.outputs[$rB].to` | | `GTF_OUTPUT_COIN_AMOUNT` | `0x203` | `tx.outputs[$rB].amount` | From f542416a7bb12d3e1037724c12dc3a2121e151c7 Mon Sep 17 00:00:00 2001 From: PixelCircuits Date: Sat, 10 Dec 2022 00:55:44 -0500 Subject: [PATCH 03/15] removed message balance from change outputs --- src/protocol/tx_validity.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/protocol/tx_validity.md b/src/protocol/tx_validity.md index b9179462..6b44bf0b 100644 --- a/src/protocol/tx_validity.md +++ b/src/protocol/tx_validity.md @@ -109,6 +109,10 @@ def sum_outputs(tx, asset_id) -> int: total += output.amount return total +def message_balance(tx, asset_id) -> int: + messageBalance = sum_messages(tx, asset_id) + return messageBalance + def available_balance(tx, asset_id) -> int: availableBalance = sum_inputs(tx, asset_id) + sum_messages(tx, asset_id) return availableBalance @@ -165,10 +169,11 @@ Given transaction `tx`, the following checks must pass: If `tx.scriptLength == 0`, there is no script and the transaction defines a simple balance transfer, so no further checks are required. -If `tx.scriptLength > 0`, the script must be executed. For each asset ID `asset_id` in the input set, the free balance available to be moved around by the script and called contracts is `freeBalance[asset_id]`: +If `tx.scriptLength > 0`, the script must be executed. For each asset ID `asset_id` in the input set, the free balance available to be moved around by the script and called contracts is `freeBalance[asset_id]`. The initial message balance available to be moved around by the script and called contracts is `messageBalance`: ```py freeBalance[asset_id] = available_balance(tx, asset_id) - unavailable_balance(tx, asset_id) +messageBalance = message_balance(tx, 0) ``` Once the free balances are computed, the [script is executed](../vm/index.md#script-execution). After execution, the following is extracted: @@ -191,8 +196,12 @@ Given transaction `tx`, state `state`, and contract set `contracts`, the followi If change outputs are present, they must have: -1. if the transaction does not revert; an `amount` of `unspentBalance + floor((unspentGas * tx.gasPrice) / GAS_PRICE_FACTOR)` if their asset ID is `0`, or an `amount` of the unspent free balance for that asset ID after VM execution is complete, or -1. if the transaction reverts; an `amount` of the initial free balance plus `unspentGas * tx.gasPrice` if their asset ID is `0`, or an `amount` of the initial free balance for that asset ID. +- if the transaction does not revert; + - if the asset ID is `0`; an `amount` of `unspentBalance + floor((unspentGas * tx.gasPrice) / GAS_PRICE_FACTOR)` + - otherwise; an `amount` of the unspent free balance for that asset ID after VM execution is complete +- if the transaction reverts; + - if the asset ID is `0`; an `amount` of the initial free balance plus `(unspentGas * tx.gasPrice) - messageBalance` + - otherwise; an `amount` of the initial free balance for that asset ID. ### State Changes From 5deab73f06c4172f9a9bb89227addcc14f22af95 Mon Sep 17 00:00:00 2001 From: PixelCircuits Date: Sat, 10 Dec 2022 01:06:13 -0500 Subject: [PATCH 04/15] formatting --- src/protocol/tx_validity.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocol/tx_validity.md b/src/protocol/tx_validity.md index 6b44bf0b..fdf5dfaa 100644 --- a/src/protocol/tx_validity.md +++ b/src/protocol/tx_validity.md @@ -196,10 +196,10 @@ Given transaction `tx`, state `state`, and contract set `contracts`, the followi If change outputs are present, they must have: -- if the transaction does not revert; +- if the transaction does not revert; - if the asset ID is `0`; an `amount` of `unspentBalance + floor((unspentGas * tx.gasPrice) / GAS_PRICE_FACTOR)` - otherwise; an `amount` of the unspent free balance for that asset ID after VM execution is complete -- if the transaction reverts; +- if the transaction reverts; - if the asset ID is `0`; an `amount` of the initial free balance plus `(unspentGas * tx.gasPrice) - messageBalance` - otherwise; an `amount` of the initial free balance for that asset ID. From 8481ee081453afbf5efd6e544e4750239fd9d2fd Mon Sep 17 00:00:00 2001 From: Brandon Kite Date: Tue, 14 Feb 2023 10:44:02 -0800 Subject: [PATCH 05/15] Refactor of retryable messages (#453) --- src/protocol/tx_format/input.md | 44 ++++++++++++--------------- src/protocol/tx_format/transaction.md | 2 +- src/protocol/tx_validity.md | 29 ++++++++++-------- src/vm/index.md | 2 +- 4 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/protocol/tx_format/input.md b/src/protocol/tx_format/input.md index df50cfab..fa6815ac 100644 --- a/src/protocol/tx_format/input.md +++ b/src/protocol/tx_format/input.md @@ -19,21 +19,20 @@ Transaction is invalid if: ## InputCoin -| name | type | description | -|-----------------------|----------------------------------------|------------------------------------------------------------------------| -| `txID` | `byte[32]` | Hash of transaction or ID of originating message ID. | -| `outputIndex` | `uint8` | Index of transaction output. | -| `owner` | `byte[32]` | Owning address or predicate root. | -| `amount` | `uint64` | Amount of coins. | -| `asset_id` | `byte[32]` | Asset ID of the coins. | -| `txPointer` | [TXPointer](./tx_pointer.md) | Points to the TX whose output is being spent. | -| `messagePointer` | [MessagePointer](./message_pointer.md) | Points to the message being spent. | -| `witnessIndex` | `uint8` | Index of witness that authorizes spending the coin. | -| `maturity` | `uint32` | UTXO being spent must have been created at least this many blocks ago. | -| `predicateLength` | `uint16` | Length of predicate, in instructions. | -| `predicateDataLength` | `uint16` | Length of predicate input data, in bytes. | -| `predicate` | `byte[]` | Predicate bytecode. | -| `predicateData` | `byte[]` | Predicate input data (parameters). | +| name | type | description | +|-----------------------|------------------------------|------------------------------------------------------------------------| +| `txID` | `byte[32]` | Hash of transaction. | +| `outputIndex` | `uint8` | Index of transaction output. | +| `owner` | `byte[32]` | Owning address or predicate root. | +| `amount` | `uint64` | Amount of coins. | +| `asset_id` | `byte[32]` | Asset ID of the coins. | +| `txPointer` | [TXPointer](./tx_pointer.md) | Points to the TX whose output is being spent. | +| `witnessIndex` | `uint8` | Index of witness that authorizes spending the coin. | +| `maturity` | `uint32` | UTXO being spent must have been created at least this many blocks ago. | +| `predicateLength` | `uint16` | Length of predicate, in instructions. | +| `predicateDataLength` | `uint16` | Length of predicate input data, in bytes. | +| `predicate` | `byte[]` | Predicate bytecode. | +| `predicateData` | `byte[]` | Predicate input data (parameters). | Given helper `len()` that returns the number of bytes of a field. @@ -48,13 +47,11 @@ Transaction is invalid if: If `h` is the block height the UTXO being spent was created, transaction is invalid if `blockheight() < h + maturity`. -> **Note:** when signing a transaction, `txPointer` and `messagePointer` are set to zero. +> **Note:** when signing a transaction, `txPointer` is set to zero. > -> **Note:** when verifying a predicate, `txPointer` and `messagePointer` are initialized to zero. +> **Note:** when verifying a predicate, `txPointer` is initialized to zero. > -> **Note:** when executing a script, `txPointer` and `messagePointer` are initialized to zero. -> -> **Note:** a message from the base chain with data length of zero is spent as a coin input using the message ID as the `txID` and `outputIndex` set to zero. +> **Note:** when executing a script, `txPointer` is initialized to zero. The predicate root is computed identically to the contract root, used to compute the contract ID, [here](../id/contract.md). @@ -102,11 +99,10 @@ Given helper `len()` that returns the number of bytes of a field. Transaction is invalid if: - `witnessIndex >= tx.witnessesCount` -- `dataLength == 0` - `dataLength > MAX_MESSAGE_DATA_LENGTH` - `predicateLength > MAX_PREDICATE_LENGTH` - `predicateDataLength > MAX_PREDICATE_DATA_LENGTH` -- If `predicateLength > 0`; the computed predicate root (see below) is not equal `owner` +- If `predicateLength > 0`; the computed predicate root (see below) is not equal `recipient` - `dataLength != len(data)` - `predicateLength * 4 != len(predicate)` - `predicateDataLength != len(predicateData)` @@ -119,6 +115,6 @@ The predicate root is computed identically to the contract root, used to compute > > **Note:** when executing a script, `messagePointer` is initialized to zero. > -> **Note:** a message from the base chain with data length of zero is spent as a coin input using the message ID as the `txID` and `outputIndex` set to zero. +> **Note:** a message from the base chain with data length of zero is spendable in a similar manner to `InputType.Coin`. > -> **Note:** `InputMessages` are not considered spent until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit +> **Note:** `InputMessages` with data length greater than zero are not considered spent until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit diff --git a/src/protocol/tx_format/transaction.md b/src/protocol/tx_format/transaction.md index a7472647..657029c5 100644 --- a/src/protocol/tx_format/transaction.md +++ b/src/protocol/tx_format/transaction.md @@ -21,7 +21,7 @@ Transaction is invalid if: - `inputsCount > MAX_INPUTS` - `outputsCount > MAX_OUTPUTS` - `witnessesCount > MAX_WITNESSES` -- No inputs are of type `InputType.Coin` or `InputType.Message` +- No inputs are of type `InputType.Coin` or `InputType.Message` with `input.dataLength` == 0 - More than one output is of type `OutputType.Change` for any asset ID in the input set - Any output is of type `OutputType.Change` for any asset ID not in the input set - More than one input of type `InputType.Coin` for any [Coin ID](../id/utxo.md#coin-id) in the input set diff --git a/src/protocol/tx_validity.md b/src/protocol/tx_validity.md index fdf5dfaa..2bc4e5a8 100644 --- a/src/protocol/tx_validity.md +++ b/src/protocol/tx_validity.md @@ -87,11 +87,14 @@ If this check passes, the UTXO ID `(txID, outputIndex)` fields of each contract For each asset ID `asset_id` in the input and output set: ```py -def sum_messages(tx, asset_id) -> int: +def sum_data_messages(tx, asset_id) -> int: + """ + Returns the total balance available from messages containing data + """ total: int = 0 if asset_id == 0: for input in tx.inputs: - if input.type == InputType.Message: + if input.type == InputType.Message and input.dataLength > 0: total += input.amount return total @@ -100,6 +103,8 @@ def sum_inputs(tx, asset_id) -> int: for input in tx.inputs: if input.type == InputType.Coin and input.asset_id == asset_id: total += input.amount + elif input.type == InputType.Message and asset_id == 0 and input.dataLength == 0: + total += input.amount return total def sum_outputs(tx, asset_id) -> int: @@ -109,12 +114,11 @@ def sum_outputs(tx, asset_id) -> int: total += output.amount return total -def message_balance(tx, asset_id) -> int: - messageBalance = sum_messages(tx, asset_id) - return messageBalance - def available_balance(tx, asset_id) -> int: - availableBalance = sum_inputs(tx, asset_id) + sum_messages(tx, asset_id) + """ + Make the data message balance available to the script + """ + availableBalance = sum_inputs(tx, asset_id) + sum_data_messages(tx, asset_id) return availableBalance def unavailable_balance(tx, asset_id) -> int: @@ -128,14 +132,15 @@ def unavailable_balance(tx, asset_id) -> int: bytesBalance = size(tx) * GAS_PER_BYTE * gasPrice / GAS_PRICE_FACTOR # Total fee balance feeBalance = ceiling(gasBalance + bytesBalance) - # Total message balance - messageBalance = sum_messages(tx, asset_id) # Only base asset can be used to pay for gas if asset_id == 0: - return sentBalance + feeBalance + messageBalance + return sentBalance + feeBalance return sentBalance -return available_balance(tx, asset_id) >= unavailable_balance(tx, asset_id) +# The sum_data_messages total is not included in the unavailable_balance since it is spendable as long as there +# is enough base asset amount to cover gas costs without using data messages. Messages containing data can't +# cover gas costs since they are retryable. +return available_balance(tx, asset_id) >= (unavailable_balance(tx, asset_id) + sum_data_messages(tx, asset_id)) ``` ### Valid Signatures @@ -173,7 +178,7 @@ If `tx.scriptLength > 0`, the script must be executed. For each asset ID `asset_ ```py freeBalance[asset_id] = available_balance(tx, asset_id) - unavailable_balance(tx, asset_id) -messageBalance = message_balance(tx, 0) +messageBalance = sum_data_messages(tx, 0) ``` Once the free balances are computed, the [script is executed](../vm/index.md#script-execution). After execution, the following is extracted: diff --git a/src/vm/index.md b/src/vm/index.md index 77d6cc6b..1665d85d 100644 --- a/src/vm/index.md +++ b/src/vm/index.md @@ -101,7 +101,7 @@ There are 3 _contexts_ in the FuelVM: [predicates](#predicate-verification), [sc ## Predicate Verification -For any input of type [`InputType.Coin`](../protocol/tx_format/index.md), a non-zero `predicateLength` field means the UTXO being spent is a [P2SH](https://en.bitcoinwiki.org/wiki/P2SH) rather than a [P2PKH](https://en.bitcoinwiki.org/wiki/Pay-to-Pubkey_Hash) output. +For any input of type [`InputType.Coin`](../protocol/tx_format/input.md#inputcoin) or [`InputType.Message`](../protocol/tx_format/input.md#inputmessage), a non-zero `predicateLength` field means the UTXO being spent is a [P2SH](https://en.bitcoinwiki.org/wiki/P2SH) rather than a [P2PKH](https://en.bitcoinwiki.org/wiki/Pay-to-Pubkey_Hash) output. For each such input in the transaction, the VM is [initialized](#vm-initialization), then: From ba305a4e9519d69117dab5c8aad33d0ea69c95fc Mon Sep 17 00:00:00 2001 From: Voxelot Date: Mon, 27 Feb 2023 08:17:08 -0800 Subject: [PATCH 06/15] remove output message, change casing of block header fields --- src/protocol/block_header.md | 4 ++-- src/protocol/tx_format/output.md | 13 ------------- src/vm/instruction_set.md | 2 -- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/protocol/block_header.md b/src/protocol/block_header.md index bf7ecb39..6ef6b22d 100644 --- a/src/protocol/block_header.md +++ b/src/protocol/block_header.md @@ -8,6 +8,6 @@ name | type | description ----------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------- `da_height` | `uint64` | Height of the data availability layer up to which (inclusive) input messages are processed. `txCount` | `uint64` | Number of [transaction](./tx_format/transaction.md)s in this block. -`outputMessagesCount` | `uint64` | Number of [output message](./tx_format/output.md#outputmessage)s in this block. +`message_receipt_count` | `uint64` | Number of [output message](../protocol/abi/receipts.md#messageout_receipt)s in this block. `txRoot` | `byte[32]` | [Merkle root](./cryptographic_primitives.md#binary-merkle-tree) of [transaction](./tx_format/transaction.md)s in this block. -`outputMessagesRoot` | `byte[32]` | [Merkle root](./cryptographic_primitives.md#binary-merkle-tree) of [output message](./tx_format/output.md#outputmessage)s in this block. +`message_receipt_root` | `byte[32]` | [Merkle root](./cryptographic_primitives.md#binary-merkle-tree) of [output message](./tx_format/output.md#outputmessage)s in this block. diff --git a/src/protocol/tx_format/output.md b/src/protocol/tx_format/output.md index c9d3c731..ae084b25 100644 --- a/src/protocol/tx_format/output.md +++ b/src/protocol/tx_format/output.md @@ -51,19 +51,6 @@ The balance root `balanceRoot` is the root of the [SMT](../cryptographic_primiti The state root `stateRoot` is the root of the [SMT](../cryptographic_primitives.md#sparse-merkle-tree) of storage slots. Each storage slot is a `byte[32]`, keyed by a `byte[32]`. -## OutputMessage - -| name | type | description | -|-------------|------------|-----------------------------------------------| -| `recipient` | `byte[32]` | The address of the message recipient. | -| `amount` | `uint64` | Amount of base asset coins sent with message. | - -> **Note:** when signing a transaction `recipient` and `amount` are set to zero. -> -> **Note:** when verifying a predicate or executing a script, `recipient` and `amount` are initialized to zero. -> -> **Note:** this output type is unspendable and can be pruned from the UTXO set. - ## OutputChange | name | type | description | diff --git a/src/vm/instruction_set.md b/src/vm/instruction_set.md index 6377624d..bd6c8f16 100644 --- a/src/vm/instruction_set.md +++ b/src/vm/instruction_set.md @@ -1851,8 +1851,6 @@ Get [fields from the transaction](../protocol/tx_format/transaction.md). | `GTF_OUTPUT_CONTRACT_INPUT_INDEX` | `0x205` | `tx.outputs[$rB].inputIndex` | | `GTF_OUTPUT_CONTRACT_BALANCE_ROOT` | `0x206` | Memory address of `tx.outputs[$rB].balanceRoot` | | `GTF_OUTPUT_CONTRACT_STATE_ROOT` | `0x207` | Memory address of `tx.outputs[$rB].stateRoot` | -| `GTF_OUTPUT_MESSAGE_RECIPIENT` | `0x208` | Memory address of `tx.outputs[$rB].recipient` | -| `GTF_OUTPUT_MESSAGE_AMOUNT` | `0x209` | `tx.outputs[$rB].amount` | | `GTF_OUTPUT_CONTRACT_CREATED_CONTRACT_ID` | `0x20A` | Memory address of `tx.outputs[$rB].contractID` | | `GTF_OUTPUT_CONTRACT_CREATED_STATE_ROOT` | `0x20B` | Memory address of `tx.outputs[$rB].stateRoot` | | `GTF_WITNESS_DATA_LENGTH` | `0x301` | `tx.witnesses[$rB].dataLength` | From 0520171f072e56a4c86330259a79971683b58b61 Mon Sep 17 00:00:00 2001 From: John Adler Date: Mon, 27 Feb 2023 11:18:05 -0500 Subject: [PATCH 07/15] fmt --- src/protocol/block_header.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/protocol/block_header.md b/src/protocol/block_header.md index 6ef6b22d..a0a25852 100644 --- a/src/protocol/block_header.md +++ b/src/protocol/block_header.md @@ -4,10 +4,10 @@ The application header is a network-agnostic block header. Different [networks](../network/index.md) may wrap the application header in a consensus header, depending on their consensus protocol. -name | type | description -----------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------- -`da_height` | `uint64` | Height of the data availability layer up to which (inclusive) input messages are processed. -`txCount` | `uint64` | Number of [transaction](./tx_format/transaction.md)s in this block. +name | type | description +------------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------- +`da_height` | `uint64` | Height of the data availability layer up to which (inclusive) input messages are processed. +`txCount` | `uint64` | Number of [transaction](./tx_format/transaction.md)s in this block. `message_receipt_count` | `uint64` | Number of [output message](../protocol/abi/receipts.md#messageout_receipt)s in this block. -`txRoot` | `byte[32]` | [Merkle root](./cryptographic_primitives.md#binary-merkle-tree) of [transaction](./tx_format/transaction.md)s in this block. +`txRoot` | `byte[32]` | [Merkle root](./cryptographic_primitives.md#binary-merkle-tree) of [transaction](./tx_format/transaction.md)s in this block. `message_receipt_root` | `byte[32]` | [Merkle root](./cryptographic_primitives.md#binary-merkle-tree) of [output message](./tx_format/output.md#outputmessage)s in this block. From 5d3854af2fa05360b58723fbd522516174bbda10 Mon Sep 17 00:00:00 2001 From: Voxelot Date: Mon, 27 Feb 2023 08:38:35 -0800 Subject: [PATCH 08/15] updating smo to not use tx outputs --- src/protocol/block_header.md | 2 +- src/protocol/tx_format/index.md | 1 - src/protocol/tx_format/output.md | 15 +++++------ src/protocol/tx_validity.md | 2 -- src/vm/instruction_set.md | 46 +++++++++++++------------------- 5 files changed, 27 insertions(+), 39 deletions(-) diff --git a/src/protocol/block_header.md b/src/protocol/block_header.md index a0a25852..de35c218 100644 --- a/src/protocol/block_header.md +++ b/src/protocol/block_header.md @@ -10,4 +10,4 @@ name | type | description `txCount` | `uint64` | Number of [transaction](./tx_format/transaction.md)s in this block. `message_receipt_count` | `uint64` | Number of [output message](../protocol/abi/receipts.md#messageout_receipt)s in this block. `txRoot` | `byte[32]` | [Merkle root](./cryptographic_primitives.md#binary-merkle-tree) of [transaction](./tx_format/transaction.md)s in this block. -`message_receipt_root` | `byte[32]` | [Merkle root](./cryptographic_primitives.md#binary-merkle-tree) of [output message](./tx_format/output.md#outputmessage)s in this block. +`message_receipt_root` | `byte[32]` | [Merkle root](./cryptographic_primitives.md#binary-merkle-tree) of [output message](../protocol/abi/receipts.md#messageout_receipt)s in this block. diff --git a/src/protocol/tx_format/index.md b/src/protocol/tx_format/index.md index b23d8ac3..26cb3e12 100644 --- a/src/protocol/tx_format/index.md +++ b/src/protocol/tx_format/index.md @@ -14,7 +14,6 @@ The Fuel Transaction Format. - [Output](./output.md) - [OutputCoin](./output.md#outputcoin) - [OutputContract](./output.md#outputcontract) - - [OutputMessage](./output.md#outputmessage) - [OutputChange](./output.md#outputchange) - [OutputVariable](./output.md#outputvariable) - [OutputContractCreated](./output.md#outputcontractcreated) diff --git a/src/protocol/tx_format/output.md b/src/protocol/tx_format/output.md index ae084b25..c974d826 100644 --- a/src/protocol/tx_format/output.md +++ b/src/protocol/tx_format/output.md @@ -4,17 +4,16 @@ enum OutputType : uint8 { Coin = 0, Contract = 1, - Message = 2, - Change = 3, - Variable = 4, - ContractCreated = 5, + Change = 2, + Variable = 3, + ContractCreated = 4, } ``` -| name | type | description | -|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------| -| `type` | [OutputType](#output) | Type of output. | -| `data` | One of [OutputCoin](#outputcoin), [OutputContract](#outputcontract), [OutputMessage](#outputmessage) [OutputChange](#outputchange), [OutputVariable](#outputvariable), or [OutputContractCreated](#outputcontractcreated). | Output data. | +| name | type | description | +|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------| +| `type` | [OutputType](#output) | Type of output. | +| `data` | One of [OutputCoin](#outputcoin), [OutputContract](#outputcontract), [OutputChange](#outputchange), [OutputVariable](#outputvariable), or [OutputContractCreated](#outputcontractcreated). | Output data. | Transaction is invalid if: diff --git a/src/protocol/tx_validity.md b/src/protocol/tx_validity.md index 2bc4e5a8..da9633ec 100644 --- a/src/protocol/tx_validity.md +++ b/src/protocol/tx_validity.md @@ -48,8 +48,6 @@ Write-create access list: Note that block proposers use the contract ID `contractID` for inputs and outputs of type [`InputType.Contract`](./tx_format/input.md#inputcontract) and [`OutputType.Contract`](./tx_format/output.md#outputcontract) rather than the pair of `txID` and `outputIndex`. -Note that [`OutputType.Message` outputs](./tx_format/output.md#outputmessage) do not have a [UTXO ID](./id/utxo.md), and are unspendable. - ## VM Precondition Validity Rules This section defines _VM precondition validity rules_ for transactions: the bare minimum required to accept an unconfirmed transaction into a mempool, and preconditions that the VM assumes to hold prior to execution. Chains of unconfirmed transactions are omitted. diff --git a/src/vm/instruction_set.md b/src/vm/instruction_set.md index bd6c8f16..d45d96b8 100644 --- a/src/vm/instruction_set.md +++ b/src/vm/instruction_set.md @@ -1387,31 +1387,29 @@ Cease VM execution and revert script effects. After a revert: 1. All [OutputContract](../protocol/tx_format/output.md#outputcontract) outputs will have the same `balanceRoot` and `stateRoot` as on initialization. 1. All [OutputVariable](../protocol/tx_format/output.md#outputvariable) outputs will have `to`, `amount`, and `asset_id` of zero. -### SMO: Send message to output +### SMO: Send message out -| | | -|-------------|---------------------------------------------------------------------------------------------------------------------------| -| Description | Send a message to recipient address `MEM[$rA, 32]` with call abi `MEM[$rA + 32, $rB]` and `$rD` coins, with output `$rC`. | -| Operation | ```outputmessage(MEM[$fp, 32], MEM[$rA, 32], MEM[$rA + 32, $rB], $rD, $rC);``` | -| Syntax | `smo $rA, $rB, $rC, $rD` | -| Encoding | `0x00 rA rB rC rD` | -| Effects | Output message | -| Notes | | +| | | +|-------------|------------------------------------------------------------------------------------------------------------------| +| Description | Send a message to recipient address `MEM[$rA, 32]` with message data `MEM[$rB, $rC]` and `$rD` base asset coins. | +| Operation | ```outputmessage(MEM[$fp, 32], MEM[$rA, 32], MEM[$rB, $rC], $rD);``` | +| Syntax | `smo $rA, $rB, $rC, $rD` | +| Encoding | `0x00 rA rB rC rD` | +| Effects | Output message | +| Notes | | Given helper `balanceOfStart(asset_id: byte[32]) -> uint32` which returns the memory address of the remaining free balance of `asset_id`, or panics if `asset_id` has no free balance remaining. Panic if: -- `$rA + $rB + 32` overflows -- `$rA + $rB + 32 > VM_MAX_RAM` -- `$rB > MEM_MAX_ACCESS_SIZE` -- `$rB > MESSAGE_MAX_DATA_SIZE` -- `$rC > tx.outputsCount` +- `$rA + 32` overflows +- `$rB + $rC` overflows +- `$rA + 32 > VM_MAX_RAM` +- `$rB + $rC > VM_MAX_RAM` +- `$rC > MEM_MAX_ACCESS_SIZE` +- `$rC > MESSAGE_MAX_DATA_SIZE` - In an external context, if `$rD > MEM[balanceOfStart(0), 8]` - In an internal context, if `$rD` is greater than the balance of asset ID 0 of output with contract ID `MEM[$fp, 32]` -- `tx.outputs[$rC].type != OutputType.Message` -- `tx.outputs[$rC].recipient != 0` -- `MEM[$rA, 32] == 0` Append a receipt to the list of receipts, modifying `tx.receiptsRoot`: @@ -1423,17 +1421,11 @@ Append a receipt to the list of receipts, modifying `tx.receiptsRoot`: | `recipient` | `byte[32]` | The address of the message recipient: `MEM[$rA, 32]`. | | `amount` | `uint64` | Amount of base asset coins sent with message: `$rD`. | | `nonce` | `byte[32]` | The message nonce as described [here](../protocol/id/utxo.md#message-nonce). | -| `len` | `uint16` | Length of message data, in bytes: `$rB`. | -| `digest` | `byte[32]` | [Hash](#s256-sha-2-256) of `MEM[$rA + 32, $rB]`. | - -In an external context, decrease `MEM[balanceOfStart(0), 8]` by `$rD`. In an internal context, decrease asset ID 0 balance of output with contract ID `MEM[$fp, 32]` by `$rD`. Then set: +| `len` | `uint16` | Length of message data, in bytes: `$rC`. | +| `digest` | `byte[32]` | [Hash](#s256-sha-2-256) of `MEM[$rB, $rC]`. | -- `tx.outputs[$rC].recipient = MEM[$rA, 32]` -- `tx.outputs[$rC].amount = $rD` - -This modifies the `balanceRoot` field of the appropriate output. -`messageID` is added to the `OutputMessage` Merkle tree as part of block header. -TODO: document output messages Merkle tree construction and maintenance and link here +In an external context, decrease `MEM[balanceOfStart(0), 8]` by `$rD`. In an internal context, decrease asset ID 0 balance of output with contract ID `MEM[$fp, 32]` by `$rD`. This modifies the `balanceRoot` field of the appropriate contract that had its' funds deducted. +`messageID` is added to the MessageReceipts Merkle tree as part of block header. ### SCWQ: State clear sequential 32 byte slots From 5778a1b35544dca44283e9bda450d492a7981add Mon Sep 17 00:00:00 2001 From: Voxelot Date: Mon, 27 Feb 2023 08:40:40 -0800 Subject: [PATCH 09/15] update smo receipt --- src/protocol/abi/receipts.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocol/abi/receipts.md b/src/protocol/abi/receipts.md index 5da343bf..f6d813d8 100644 --- a/src/protocol/abi/receipts.md +++ b/src/protocol/abi/receipts.md @@ -260,9 +260,9 @@ _Important note:_ For the JSON representation of receipts, we represent 64-bit u - `recipient`: Hexadecimal string representation of the 256-bit (32-byte) address of the message recipient: `MEM[$rA, 32]`. - `amount`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$rD`. - `nonce`: Hexadecimal string representation of the 256-bit (32-byte) message nonce as described [here](../id/utxo.md#message-nonce). -- `len`: Decimal string representation of a 16-bit unsigned integer; value of register `$rB`. -- `digest`: Hexadecimal string representation of 256-bit (32-byte), hash of `MEM[$rA + 32, $rB]`. -- `data`: Hexadecimal string representation of the value of the memory range `MEM[$rA + 32, $rB]`. +- `len`: Decimal string representation of a 16-bit unsigned integer; value of register `$rC`. +- `digest`: Hexadecimal string representation of 256-bit (32-byte), hash of `MEM[$rB, $rC]`. +- `data`: Hexadecimal string representation of the value of the memory range `MEM[$rB, $rC]`. ```json { From 95bed90b3f67fdaf34ef0081f856e246b0404121 Mon Sep 17 00:00:00 2001 From: Voxelot Date: Mon, 27 Feb 2023 08:47:08 -0800 Subject: [PATCH 10/15] update message nonce definition --- src/protocol/id/utxo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/id/utxo.md b/src/protocol/id/utxo.md index 41b1b8e7..039518fc 100644 --- a/src/protocol/id/utxo.md +++ b/src/protocol/id/utxo.md @@ -18,7 +18,7 @@ The ID of a message is computed as the [hash](../cryptographic_primitives.md#has ### Message Nonce -The nonce value for `InputMessage` is determined by the sending system and is published at the time the message is sent. The nonce value for `OutputMessage` is computed as the [hash](../cryptographic_primitives.md#hashing) of the [Transaction ID](./transaction.md) that the message is an output for and the index of the output as a `uint8`: `hash(byte[32] ++ uint8)`. +The nonce value for `InputMessage` is determined by the sending system and is published at the time the message is sent. The nonce value for `OutputMessage` is computed as the [hash](../cryptographic_primitives.md#hashing) of the [Transaction ID](./transaction.md) that emitted the message and the index of the message receipt `uint8`: `hash(byte[32] ++ uint8)`. ## Fee ID From f3b47c76efefe876c4bc427a14ec0c25863e474f Mon Sep 17 00:00:00 2001 From: Voxelot Date: Mon, 27 Feb 2023 08:58:34 -0800 Subject: [PATCH 11/15] remove input.messageid --- src/protocol/tx_format/input.md | 1 - src/protocol/tx_validity.md | 6 ++---- src/vm/instruction_set.md | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/protocol/tx_format/input.md b/src/protocol/tx_format/input.md index fa6815ac..356caf5e 100644 --- a/src/protocol/tx_format/input.md +++ b/src/protocol/tx_format/input.md @@ -80,7 +80,6 @@ Transaction is invalid if: | name | type | description | |-----------------------|----------------------------------------|--------------------------------------------------------------| -| `messageID` | `byte[32]` | The messageID as described [here](../id/utxo.md#message-id). | | `sender` | `byte[32]` | The address of the message sender. | | `recipient` | `byte[32]` | The address or predicate root of the message recipient. | | `amount` | `uint64` | Amount of base asset coins sent with message. | diff --git a/src/protocol/tx_validity.md b/src/protocol/tx_validity.md index da9633ec..888f1ab4 100644 --- a/src/protocol/tx_validity.md +++ b/src/protocol/tx_validity.md @@ -54,9 +54,7 @@ This section defines _VM precondition validity rules_ for transactions: the bare For a transaction `tx`, UTXO set `state`, contract set `contracts`, and message set `messages`, the following checks must pass. -> **Note:** [InputMessages](./tx_format/input.md#inputmessage) don't exit the `messages` message set until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit. -> -> **Note:** Messages with no data are included as part of the UTXO set `state` using the message ID as `txID` and `outputIndex` set to zero. Messages with no data are not included in the `messages` message set. +> **Note:** [InputMessages](./tx_format/input.md#inputmessage) where `input.dataLength > 0` are not dropped from the `messages` message set until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit. ### Base Sanity Checks @@ -70,7 +68,7 @@ for input in tx.inputs: if not input.contractID in contracts: return False elif input.type == InputType.Message: - if not input.messageID in messages: + if not input.nonce in messages: return False else: if not (input.txID, input.outputIndex) in state: diff --git a/src/vm/instruction_set.md b/src/vm/instruction_set.md index d45d96b8..d85ca1c9 100644 --- a/src/vm/instruction_set.md +++ b/src/vm/instruction_set.md @@ -1823,7 +1823,6 @@ Get [fields from the transaction](../protocol/tx_format/transaction.md). | `GTF_INPUT_CONTRACT_STATE_ROOT` | `0x112` | Memory address of `tx.inputs[$rB].stateRoot` | | `GTF_INPUT_CONTRACT_TX_POINTER` | `0x113` | Memory address of `tx.inputs[$rB].txPointer` | | `GTF_INPUT_CONTRACT_CONTRACT_ID` | `0x114` | Memory address of `tx.inputs[$rB].contractID` | -| `GTF_INPUT_MESSAGE_MESSAGE_ID` | `0x115` | Memory address of `tx.inputs[$rB].messageID` | | `GTF_INPUT_MESSAGE_SENDER` | `0x116` | Memory address of `tx.inputs[$rB].sender` | | `GTF_INPUT_MESSAGE_RECIPIENT` | `0x117` | Memory address of `tx.inputs[$rB].recipient` | | `GTF_INPUT_MESSAGE_AMOUNT` | `0x118` | `tx.inputs[$rB].amount` | From 20fe6d347bf27e8620374a25aaba88d04483bcf0 Mon Sep 17 00:00:00 2001 From: Voxelot Date: Mon, 27 Feb 2023 09:01:16 -0800 Subject: [PATCH 12/15] remove message pointer --- src/SUMMARY.md | 1 - src/protocol/tx_format/index.md | 1 - src/protocol/tx_format/input.md | 9 --------- src/protocol/tx_format/message_pointer.md | 9 --------- src/protocol/tx_validity.md | 2 +- src/vm/instruction_set.md | 2 -- 6 files changed, 1 insertion(+), 23 deletions(-) delete mode 100644 src/protocol/tx_format/message_pointer.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 170336e9..7d098df5 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -10,7 +10,6 @@ - [Output](./protocol/tx_format/output.md) - [Witness](./protocol/tx_format/witness.md) - [TXPointer](./protocol/tx_format/tx_pointer.md) - - [MessagePointer](./protocol/tx_format/message_pointer.md) - [Computing Identifiers](./protocol/id/index.md) - [Transaction ID](./protocol/id/transaction.md) - [Contract ID](./protocol/id/contract.md) diff --git a/src/protocol/tx_format/index.md b/src/protocol/tx_format/index.md index 26cb3e12..b79d4bae 100644 --- a/src/protocol/tx_format/index.md +++ b/src/protocol/tx_format/index.md @@ -19,4 +19,3 @@ The Fuel Transaction Format. - [OutputContractCreated](./output.md#outputcontractcreated) - [Witness](./witness.md) - [TXPointer](./tx_pointer.md) -- [MessagePointer](./message_pointer.md) diff --git a/src/protocol/tx_format/input.md b/src/protocol/tx_format/input.md index 356caf5e..99d6e2ec 100644 --- a/src/protocol/tx_format/input.md +++ b/src/protocol/tx_format/input.md @@ -84,7 +84,6 @@ Transaction is invalid if: | `recipient` | `byte[32]` | The address or predicate root of the message recipient. | | `amount` | `uint64` | Amount of base asset coins sent with message. | | `nonce` | `uint64` | The message nonce. | -| `messagePointer` | [MessagePointer](./message_pointer.md) | Points to the message being spent. | | `witnessIndex` | `uint8` | Index of witness that authorizes spending the coin. | | `dataLength` | `uint16` | Length of message data, in bytes. | | `predicateLength` | `uint16` | Length of predicate, in instructions. | @@ -108,12 +107,4 @@ Transaction is invalid if: The predicate root is computed identically to the contract root, used to compute the contract ID, [here](../id/contract.md). -> **Note:** when signing a transaction, `messagePointer` is set to zero. -> -> **Note:** when verifying a predicate, `messagePointer` is initialized to zero. -> -> **Note:** when executing a script, `messagePointer` is initialized to zero. -> -> **Note:** a message from the base chain with data length of zero is spendable in a similar manner to `InputType.Coin`. -> > **Note:** `InputMessages` with data length greater than zero are not considered spent until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit diff --git a/src/protocol/tx_format/message_pointer.md b/src/protocol/tx_format/message_pointer.md deleted file mode 100644 index 1691180c..00000000 --- a/src/protocol/tx_format/message_pointer.md +++ /dev/null @@ -1,9 +0,0 @@ -# MessagePointer - -The location of the message on the base chain. It can be used by UTXOs as a reference to the message or by the transaction itself to make it unique. - -| name | type | description | -|---------------|----------|--------------------| -| `blockHeight` | `uint32` | Block height. | -| `txIndex` | `uint16` | Transaction index. | -| `logIndex` | `uint16` | Log index. | diff --git a/src/protocol/tx_validity.md b/src/protocol/tx_validity.md index 888f1ab4..6f1f70d8 100644 --- a/src/protocol/tx_validity.md +++ b/src/protocol/tx_validity.md @@ -76,7 +76,7 @@ for input in tx.inputs: return True ``` -If this check passes, the UTXO ID `(txID, outputIndex)` fields of each contract input is set to the UTXO ID of the respective contract. The `txPointer` or `messagePointer` of each input is also set to the TX pointer of the UTXO with ID `utxoID` or the message pointer of the base chain message. +If this check passes, the UTXO ID `(txID, outputIndex)` fields of each contract input is set to the UTXO ID of the respective contract. The `txPointer` of each input is also set to the TX pointer of the UTXO with ID `utxoID`. ### Sufficient Balance diff --git a/src/vm/instruction_set.md b/src/vm/instruction_set.md index d85ca1c9..07fbfd31 100644 --- a/src/vm/instruction_set.md +++ b/src/vm/instruction_set.md @@ -1810,7 +1810,6 @@ Get [fields from the transaction](../protocol/tx_format/transaction.md). | `GTF_INPUT_COIN_AMOUNT` | `0x105` | `tx.inputs[$rB].amount` | | `GTF_INPUT_COIN_ASSET_ID` | `0x106` | Memory address of `tx.inputs[$rB].asset_id` | | `GTF_INPUT_COIN_TX_POINTER` | `0x107` | Memory address of `tx.inputs[$rB].txPointer` | -| `GTF_INPUT_COIN_MESSAGE_POINTER` | `0x108` | Memory address of `tx.inputs[$rB].messagePointer`| | `GTF_INPUT_COIN_WITNESS_INDEX` | `0x109` | `tx.inputs[$rB].witnessIndex` | | `GTF_INPUT_COIN_MATURITY` | `0x10A` | `tx.inputs[$rB].maturity` | | `GTF_INPUT_COIN_PREDICATE_LENGTH` | `0x10B` | `tx.inputs[$rB].predicateLength` | @@ -1827,7 +1826,6 @@ Get [fields from the transaction](../protocol/tx_format/transaction.md). | `GTF_INPUT_MESSAGE_RECIPIENT` | `0x117` | Memory address of `tx.inputs[$rB].recipient` | | `GTF_INPUT_MESSAGE_AMOUNT` | `0x118` | `tx.inputs[$rB].amount` | | `GTF_INPUT_MESSAGE_NONCE` | `0x119` | `tx.inputs[$rB].nonce` | -| `GTF_INPUT_MESSAGE_MESSAGE_POINTER` | `0x11A` | Memory address of `tx.inputs[$rB].messagePointer`| | `GTF_INPUT_MESSAGE_WITNESS_INDEX` | `0x11B` | `tx.inputs[$rB].witnessIndex` | | `GTF_INPUT_MESSAGE_DATA_LENGTH` | `0x11C` | `tx.inputs[$rB].dataLength` | | `GTF_INPUT_MESSAGE_PREDICATE_LENGTH` | `0x11D` | `tx.inputs[$rB].predicateLength` | From 9c60e266fa5f74328402272d1a0cfd88cc968caf Mon Sep 17 00:00:00 2001 From: Voxelot Date: Mon, 27 Feb 2023 09:06:55 -0800 Subject: [PATCH 13/15] remove message id from input --- src/vm/instruction_set.md | 50 +++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/vm/instruction_set.md b/src/vm/instruction_set.md index 07fbfd31..0b81c8a5 100644 --- a/src/vm/instruction_set.md +++ b/src/vm/instruction_set.md @@ -1810,29 +1810,29 @@ Get [fields from the transaction](../protocol/tx_format/transaction.md). | `GTF_INPUT_COIN_AMOUNT` | `0x105` | `tx.inputs[$rB].amount` | | `GTF_INPUT_COIN_ASSET_ID` | `0x106` | Memory address of `tx.inputs[$rB].asset_id` | | `GTF_INPUT_COIN_TX_POINTER` | `0x107` | Memory address of `tx.inputs[$rB].txPointer` | -| `GTF_INPUT_COIN_WITNESS_INDEX` | `0x109` | `tx.inputs[$rB].witnessIndex` | -| `GTF_INPUT_COIN_MATURITY` | `0x10A` | `tx.inputs[$rB].maturity` | -| `GTF_INPUT_COIN_PREDICATE_LENGTH` | `0x10B` | `tx.inputs[$rB].predicateLength` | -| `GTF_INPUT_COIN_PREDICATE_DATA_LENGTH` | `0x10C` | `tx.inputs[$rB].predicateDataLength` | -| `GTF_INPUT_COIN_PREDICATE` | `0x10D` | Memory address of `tx.inputs[$rB].predicate` | -| `GTF_INPUT_COIN_PREDICATE_DATA` | `0x10E` | Memory address of `tx.inputs[$rB].predicateData` | -| `GTF_INPUT_CONTRACT_TX_ID` | `0x10F` | Memory address of `tx.inputs[$rB].txID` | -| `GTF_INPUT_CONTRACT_OUTPUT_INDEX` | `0x110` | `tx.inputs[$rB].outputIndex` | -| `GTF_INPUT_CONTRACT_BALANCE_ROOT` | `0x111` | Memory address of `tx.inputs[$rB].balanceRoot` | -| `GTF_INPUT_CONTRACT_STATE_ROOT` | `0x112` | Memory address of `tx.inputs[$rB].stateRoot` | -| `GTF_INPUT_CONTRACT_TX_POINTER` | `0x113` | Memory address of `tx.inputs[$rB].txPointer` | -| `GTF_INPUT_CONTRACT_CONTRACT_ID` | `0x114` | Memory address of `tx.inputs[$rB].contractID` | -| `GTF_INPUT_MESSAGE_SENDER` | `0x116` | Memory address of `tx.inputs[$rB].sender` | -| `GTF_INPUT_MESSAGE_RECIPIENT` | `0x117` | Memory address of `tx.inputs[$rB].recipient` | -| `GTF_INPUT_MESSAGE_AMOUNT` | `0x118` | `tx.inputs[$rB].amount` | -| `GTF_INPUT_MESSAGE_NONCE` | `0x119` | `tx.inputs[$rB].nonce` | -| `GTF_INPUT_MESSAGE_WITNESS_INDEX` | `0x11B` | `tx.inputs[$rB].witnessIndex` | -| `GTF_INPUT_MESSAGE_DATA_LENGTH` | `0x11C` | `tx.inputs[$rB].dataLength` | -| `GTF_INPUT_MESSAGE_PREDICATE_LENGTH` | `0x11D` | `tx.inputs[$rB].predicateLength` | -| `GTF_INPUT_MESSAGE_PREDICATE_DATA_LENGTH` | `0x11E` | `tx.inputs[$rB].predicateDataLength` | -| `GTF_INPUT_MESSAGE_DATA` | `0x11F` | Memory address of `tx.inputs[$rB].data` | -| `GTF_INPUT_MESSAGE_PREDICATE` | `0x120` | Memory address of `tx.inputs[$rB].predicate` | -| `GTF_INPUT_MESSAGE_PREDICATE_DATA` | `0x121` | Memory address of `tx.inputs[$rB].predicateData` | +| `GTF_INPUT_COIN_WITNESS_INDEX` | `0x108` | `tx.inputs[$rB].witnessIndex` | +| `GTF_INPUT_COIN_MATURITY` | `0x109` | `tx.inputs[$rB].maturity` | +| `GTF_INPUT_COIN_PREDICATE_LENGTH` | `0x10A` | `tx.inputs[$rB].predicateLength` | +| `GTF_INPUT_COIN_PREDICATE_DATA_LENGTH` | `0x10B` | `tx.inputs[$rB].predicateDataLength` | +| `GTF_INPUT_COIN_PREDICATE` | `0x10C` | Memory address of `tx.inputs[$rB].predicate` | +| `GTF_INPUT_COIN_PREDICATE_DATA` | `0x10D` | Memory address of `tx.inputs[$rB].predicateData` | +| `GTF_INPUT_CONTRACT_TX_ID` | `0x10E` | Memory address of `tx.inputs[$rB].txID` | +| `GTF_INPUT_CONTRACT_OUTPUT_INDEX` | `0x10F` | `tx.inputs[$rB].outputIndex` | +| `GTF_INPUT_CONTRACT_BALANCE_ROOT` | `0x110` | Memory address of `tx.inputs[$rB].balanceRoot` | +| `GTF_INPUT_CONTRACT_STATE_ROOT` | `0x111` | Memory address of `tx.inputs[$rB].stateRoot` | +| `GTF_INPUT_CONTRACT_TX_POINTER` | `0x112` | Memory address of `tx.inputs[$rB].txPointer` | +| `GTF_INPUT_CONTRACT_CONTRACT_ID` | `0x113` | Memory address of `tx.inputs[$rB].contractID` | +| `GTF_INPUT_MESSAGE_SENDER` | `0x114` | Memory address of `tx.inputs[$rB].sender` | +| `GTF_INPUT_MESSAGE_RECIPIENT` | `0x115` | Memory address of `tx.inputs[$rB].recipient` | +| `GTF_INPUT_MESSAGE_AMOUNT` | `0x116` | `tx.inputs[$rB].amount` | +| `GTF_INPUT_MESSAGE_NONCE` | `0x117` | `tx.inputs[$rB].nonce` | +| `GTF_INPUT_MESSAGE_WITNESS_INDEX` | `0x118` | `tx.inputs[$rB].witnessIndex` | +| `GTF_INPUT_MESSAGE_DATA_LENGTH` | `0x119` | `tx.inputs[$rB].dataLength` | +| `GTF_INPUT_MESSAGE_PREDICATE_LENGTH` | `0x11A` | `tx.inputs[$rB].predicateLength` | +| `GTF_INPUT_MESSAGE_PREDICATE_DATA_LENGTH` | `0x11B` | `tx.inputs[$rB].predicateDataLength` | +| `GTF_INPUT_MESSAGE_DATA` | `0x11C` | Memory address of `tx.inputs[$rB].data` | +| `GTF_INPUT_MESSAGE_PREDICATE` | `0x11D` | Memory address of `tx.inputs[$rB].predicate` | +| `GTF_INPUT_MESSAGE_PREDICATE_DATA` | `0x11E` | Memory address of `tx.inputs[$rB].predicateData` | | `GTF_OUTPUT_TYPE` | `0x201` | `tx.outputs[$rB].type` | | `GTF_OUTPUT_COIN_TO` | `0x202` | Memory address of `tx.outputs[$rB].to` | | `GTF_OUTPUT_COIN_AMOUNT` | `0x203` | `tx.outputs[$rB].amount` | @@ -1840,8 +1840,8 @@ Get [fields from the transaction](../protocol/tx_format/transaction.md). | `GTF_OUTPUT_CONTRACT_INPUT_INDEX` | `0x205` | `tx.outputs[$rB].inputIndex` | | `GTF_OUTPUT_CONTRACT_BALANCE_ROOT` | `0x206` | Memory address of `tx.outputs[$rB].balanceRoot` | | `GTF_OUTPUT_CONTRACT_STATE_ROOT` | `0x207` | Memory address of `tx.outputs[$rB].stateRoot` | -| `GTF_OUTPUT_CONTRACT_CREATED_CONTRACT_ID` | `0x20A` | Memory address of `tx.outputs[$rB].contractID` | -| `GTF_OUTPUT_CONTRACT_CREATED_STATE_ROOT` | `0x20B` | Memory address of `tx.outputs[$rB].stateRoot` | +| `GTF_OUTPUT_CONTRACT_CREATED_CONTRACT_ID` | `0x208` | Memory address of `tx.outputs[$rB].contractID` | +| `GTF_OUTPUT_CONTRACT_CREATED_STATE_ROOT` | `0x209` | Memory address of `tx.outputs[$rB].stateRoot` | | `GTF_WITNESS_DATA_LENGTH` | `0x301` | `tx.witnesses[$rB].dataLength` | | `GTF_WITNESS_DATA` | `0x302` | Memory address of `tx.witnesses[$rB].data` | From d7b83060cca53b85fda2d1cd7a29397669736ca4 Mon Sep 17 00:00:00 2001 From: Voxelot Date: Mon, 27 Feb 2023 09:14:03 -0800 Subject: [PATCH 14/15] update transaction create validity rules --- src/protocol/tx_format/transaction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/tx_format/transaction.md b/src/protocol/tx_format/transaction.md index 657029c5..a242f064 100644 --- a/src/protocol/tx_format/transaction.md +++ b/src/protocol/tx_format/transaction.md @@ -110,7 +110,7 @@ The receipts root `receiptsRoot` is the root of the [binary Merkle tree](../cryp Transaction is invalid if: -- Any input is of type `InputType.Contract` or `InputType.Message` +- Any input is of type `InputType.Contract` or `InputType.Message` where `input.dataLength > 0` - Any output is of type `OutputType.Contract` or `OutputType.Variable` or `OutputType.Message` - More than one output is of type `OutputType.Change` with `asset_id` of zero - Any output is of type `OutputType.Change` with non-zero `asset_id` From 29e2079353c003942d1ebe8649642509b2bcb305 Mon Sep 17 00:00:00 2001 From: Voxelot Date: Mon, 27 Feb 2023 09:26:49 -0800 Subject: [PATCH 15/15] smo link --- src/vm/instruction_set.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/instruction_set.md b/src/vm/instruction_set.md index 0b81c8a5..bb73b45d 100644 --- a/src/vm/instruction_set.md +++ b/src/vm/instruction_set.md @@ -69,7 +69,7 @@ - [MINT: Mint new coins](#mint-mint-new-coins) - [RETD: Return from context with data](#retd-return-from-context-with-data) - [RVRT: Revert](#rvrt-revert) - - [SMO: Send message to output](#smo-send-message-to-output) + - [SMO: Send message to output](#smo-send-message-out) - [SCWQ: State clear sequential 32 byte slots](#scwq-state-clear-sequential-32-byte-slots) - [SRW: State read word](#srw-state-read-word) - [SRWQ: State read sequential 32 byte slots](#srwq-state-read-sequential-32-byte-slots)