diff --git a/.gitignore b/.gitignore index 7585238e..d47934e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ book +.idea/ diff --git a/spell-check-custom-words.txt b/spell-check-custom-words.txt index 19e880ac..2e1abac7 100644 --- a/spell-check-custom-words.txt +++ b/spell-check-custom-words.txt @@ -268,4 +268,5 @@ intra OOB unspendable priori -padding \ No newline at end of file +padding +incentivize \ No newline at end of file diff --git a/src/fuel-vm/instruction-set.md b/src/fuel-vm/instruction-set.md index 1db1a03a..80afeecc 100644 --- a/src/fuel-vm/instruction-set.md +++ b/src/fuel-vm/instruction-set.md @@ -2523,7 +2523,7 @@ Get [fields from the transaction](../tx-format/transaction.md). | `GTF_WITNESS_DATA_LENGTH` | `0x400` | `tx.witnesses[$rB].dataLength` | | `GTF_WITNESS_DATA` | `0x401` | Memory address of `tx.witnesses[$rB].data` | | `GTF_POLICY_TYPES` | `0x500` | `tx.policies.policyTypes` | -| `GTF_POLICY_GAS_PRICE` | `0x501` | `tx.policies[0x00].gasPrice` | +| `GTF_POLICY_TIP` | `0x501` | `tx.policies[0x00].tip` | | `GTF_POLICY_WITNESS_LIMIT` | `0x502` | `tx.policies[count_ones(0b11 & tx.policyTypes) - 1].witnessLimit` | | `GTF_POLICY_MATURITY` | `0x503` | `tx.policies[count_ones(0b111 & tx.policyTypes) - 1].maturity` | | `GTF_POLICY_MAX_FEE` | `0x504` | `tx.policies[count_ones(0b1111 & tx.policyTypes) - 1].maxFee` | diff --git a/src/protocol/tx-validity.md b/src/protocol/tx-validity.md index 24ce8bb5..a4460a19 100644 --- a/src/protocol/tx-validity.md +++ b/src/protocol/tx-validity.md @@ -212,14 +212,14 @@ def max_gas(tx) -> int: if tx.type == TransactionType.Script: gas = gas + tx.gasLimit return gas - - -def reserved_feeBalance(tx, assetId) -> int: + + +def maxFee(tx, assetId, gasPrice) -> int: """ Computes the maximum potential amount of fees that may need to be charged to process a transaction. """ maxGas = max_gas(tx) - feeBalance = gas_to_fee(maxGas, tx.gasPrice) + feeBalance = gas_to_fee(maxGas, gasPrice) # Only base asset can be used to pay for gas if assetId == 0: return feeBalance @@ -238,7 +238,7 @@ def available_balance(tx, assetId) -> int: def unavailable_balance(tx, assetId) -> int: sentBalance = sum_outputs(tx, assetId) # Total fee balance - feeBalance = reserved_fee_balance(tx, assetId) + feeBalance = tx.policies.max_fee # Only base asset can be used to pay for gas if assetId == 0: return sentBalance + feeBalance @@ -305,7 +305,8 @@ If the transaction as included in a block does not match this final transaction, The cost of a transaction can be described by: ```py -cost(tx) = gas_to_fee(min_gas(tx) + tx.gasLimit - unspentGas, tx.gasPrice) +def cost(tx, gasPrice) -> int: + return gas_to_fee(min_gas(tx) + tx.gasLimit - unspentGas, gasPrice) ``` where: @@ -325,8 +326,8 @@ A naturally occurring result of a variable gas limit is the concept of minimum a ```py min_gas = min_gas(tx) max_gas = min_gas + (tx.witnessBytesLimit - tx.witnessBytes) * GAS_PER_BYTE + tx.gasLimit -min_fee = gas_to_fee(min_gas, tx.gasPrice) -max_fee = gas_to_fee(max_gas, tx.gasPrice) +min_fee = gas_to_fee(min_gas, gasPrice) +max_fee = gas_to_fee(max_gas, gasPrice) ``` The cost of the transaction `cost(tx)` must lie within the range defined by [`min_fee`, `max_fee`]. `min_gas` is defined as the sum of all intrinsic costs of the transaction known prior to execution. The definition of `max_gas` illustrates that the delta between minimum gas and maximum gas is the sum of: @@ -349,10 +350,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 asset ID is `0`; an `amount` of `unspentBalance + floor((unspentGas * tx.gasPrice) / GAS_PRICE_FACTOR)` + - if the asset ID is `0`; an `amount` of `unspentBalance + floor((unspentGas * 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` + - if the asset ID is `0`; an `amount` of the initial free balance plus `(unspentGas * gasPrice) - messageBalance` - otherwise; an `amount` of the initial free balance for that asset ID. ### State Changes diff --git a/src/tx-format/index.md b/src/tx-format/index.md index b53e214d..bfc91a1f 100644 --- a/src/tx-format/index.md +++ b/src/tx-format/index.md @@ -18,4 +18,5 @@ The Fuel Transaction Format. - [`OutputVariable`](./output.md#outputvariable) - [`OutputContractCreated`](./output.md#outputcontractcreated) - [`Witness`](./witness.md) +- [`Policy`](./policy.md) - [`TXPointer`](./tx-pointer.md) diff --git a/src/tx-format/policy.md b/src/tx-format/policy.md index ca2c572e..fb4a1a5a 100644 --- a/src/tx-format/policy.md +++ b/src/tx-format/policy.md @@ -3,22 +3,22 @@ ```c++ // index using powers of 2 for efficient bitmasking enum PolicyType : uint32 { - GasPrice = 1, + Tip = 1, WitnessLimit = 2, Maturity = 4, MaxFee = 8, } ``` -| name | type | description | -|--------|---------------------------------------------------------------------------------------|--------------| -| `data` | One of [`GasPrice`](#gasprice), [`WitnessLimit`](#witnesslimit), or [`Maturity`](#maturity) | Policy data. | +| name | type | description | +|--------|-----------------------------------------------------------------------------------|--------------| +| `data` | One of [`Tip`](#tip), [`WitnessLimit`](#witnesslimit), or [`Maturity`](#maturity) | Policy data. | -## `GasPrice` +## `Tip` -| name | type | description | -|------------|----------|---------------------------| -| `gasPrice` | `uint64` | Gas price for transaction | +| name | type | description | +|------------|----------|-----------------------------------------------------------------------------------------------| +| `tip` | `uint64` | Additional, optional fee in `BASE_ASSET` to incentivize block producer to include transaction | ## `WitnessLimit` @@ -44,11 +44,11 @@ Transaction is invalid if: ## `MaxFee` -| name | type | description | -|-----------|----------|-----------------------------------------------------------------| -| `max_fee` | `uint64` | The maximum fee payable by this transaction using `BASE_ASSET`. | +| name | type | description | +|-----------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `max_fee` | `uint64` | Required policy to specify the maximum fee payable by this transaction using `BASE_ASSET`. This is used to check transactions before the actual `gas_price` is known. | Transaction is invalid if: - `max_fee > sum_inputs(tx, BASE_ASSET_ID) - sum_outputs(tx, BASE_ASSET_ID)` -- `max_fee < reserved_fee_balance(tx, BASE_ASSET_ID)` +- `max_fee < max_fee(tx, BASE_ASSET_ID, gas_price)` diff --git a/src/tx-format/transaction.md b/src/tx-format/transaction.md index 30c54c67..776b9a82 100644 --- a/src/tx-format/transaction.md +++ b/src/tx-format/transaction.md @@ -87,7 +87,7 @@ Transaction is invalid if: - `scriptLength * 4 != len(script)` - `scriptDataLength != len(scriptData)` - `max_gas(tx) > MAX_GAS_PER_TX` -- No policy of type `PolicyType.GasPrice` +- No policy of type `PolicyType.MaxFee` is set - `count_ones(policyTypes) > count_variants(PolicyType)` - `policyTypes > sum_variants(PolicyType)` - `len(policies) > count_ones(policyTypes)` @@ -136,7 +136,7 @@ Transaction is invalid if: - `storageSlotsCount > MAX_STORAGE_SLOTS` - `max_gas(tx) > MAX_GAS_PER_TX` - The [Sparse Merkle tree](../protocol/cryptographic-primitives.md#sparse-merkle-tree) root of `storageSlots` is not equal to the `stateRoot` of the one `OutputType.ContractCreated` output -- No policy of type `PolicyType.GasPrice` +- No policy of type `PolicyType.MaxFee` is set - `count_ones(policyTypes) > count_variants(PolicyType)` - `policyTypes > sum_variants(PolicyType)` - `len(policies) > count_ones(policyTypes)` @@ -148,13 +148,14 @@ Creates a contract with contract ID as computed [here](../identifiers/contract-i The transaction is created by the block producer and is not signed. Since it is not usable outside of block creation or execution, all fields must be fully set upon creation without any zeroing. This means that the transaction ID must also include the correct `txPointer` value, not zeroed out. -| name | type | description | -|------------------|-------------------------------|------------------------------------------------------| -| `txPointer` | [`TXPointer`](./tx-pointer.md) | The location of the `Mint` transaction in the block. | -| `inputContract` | [`InputContract`](./input.md) | The contract UTXO that assets are minted to. | -| `outputContract` | [`OutputContract`](./output.md) | The contract UTXO that assets are being minted to. | -| `mintAmount` | `uint64` | The amount of funds minted. | -| `mintAssetId` | `byte[32]` | The asset IDs corresponding to the minted amount. | +| name | type | description | +|------------------|---------------------------------|----------------------------------------------------------------------------| +| `txPointer` | [`TXPointer`](./tx-pointer.md) | The location of the `Mint` transaction in the block. | +| `inputContract` | [`InputContract`](./input.md) | The contract UTXO that assets are minted to. | +| `outputContract` | [`OutputContract`](./output.md) | The contract UTXO that assets are being minted to. | +| `mintAmount` | `uint64` | The amount of funds minted. | +| `mintAssetId` | `byte[32]` | The asset IDs corresponding to the minted amount. | +| `gasPrice` | `uint64` | The gas price to be used in calculating all fees for transactions on block | Transaction is invalid if: