Skip to content

Commit

Permalink
feat: sum transaction fees and pay on l1 (AztecProtocol#6522)
Browse files Browse the repository at this point in the history
Add `totalFees` to block header. Update the spec.

Note: we could have had the L1 rollup contract iterate over all the
tx_effects and pay out that way. Doing it ourselves in the circuit feels
cheaper though, and maybe safer for a world where:
1. tx_effects are spread over multiple l1 blocks
2. tx_effects are published as blobs so we wouldn't have direct access
to math over them on l1.
  • Loading branch information
just-mitch authored May 20, 2024
1 parent 07dc072 commit bf441da
Show file tree
Hide file tree
Showing 45 changed files with 210 additions and 109 deletions.
22 changes: 11 additions & 11 deletions barretenberg/cpp/pil/avm/constants.pil
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ namespace constants(256);
pol PORTAL_SELECTOR = 2;

// NOTE: constant expression evaluation does not seem to be supported yet in pil
// pol START_GLOBAL_VARIABLES = CALL_CONTEXT_LENGTH + HEADER_LENGTH = 6 + 22 = 28
// pol START_GLOBAL_VARIABLES = CALL_CONTEXT_LENGTH + HEADER_LENGTH = 6 + 23 = 29

// Global Variables
pol CHAIN_ID_SELECTOR = 28;
pol VERSION_SELECTOR = 29;
pol BLOCK_NUMBER_SELECTOR = 30;
pol TIMESTAMP_SELECTOR = 31;
pol COINBASE_SELECTOR = 32;
pol CHAIN_ID_SELECTOR = 29;
pol VERSION_SELECTOR = 30;
pol BLOCK_NUMBER_SELECTOR = 31;
pol TIMESTAMP_SELECTOR = 32;
pol COINBASE_SELECTOR = 33;

pol END_GLOBAL_VARIABLES = 28 + 8; // We only use the first 5 of 8 global variables for now
pol END_GLOBAL_VARIABLES = 29 + 8; // We only use the first 5 of 8 global variables for now

pol START_SIDE_EFFECT_COUNTER = 36;
pol START_SIDE_EFFECT_COUNTER = 37;

// Gas
pol FEE_PER_DA_GAS_SELECTOR = 37;
pol FEE_PER_L2_GAS_SELECTOR = 38;
pol FEE_PER_DA_GAS_SELECTOR = 38;
pol FEE_PER_L2_GAS_SELECTOR = 39;

pol TRANSACTION_FEE_SELECTOR = 39;
pol TRANSACTION_FEE_SELECTOR = 40;

Original file line number Diff line number Diff line change
Expand Up @@ -915,63 +915,63 @@ template <typename FF_> class avm_mainImpl {
{
Avm_DECLARE_VIEWS(83);

auto tmp = (avm_main_sel_op_fee_per_da_gas * (avm_kernel_kernel_sel - FF(37)));
auto tmp = (avm_main_sel_op_fee_per_da_gas * (avm_kernel_kernel_sel - FF(38)));
tmp *= scaling_factor;
std::get<83>(evals) += tmp;
}
// Contribution 84
{
Avm_DECLARE_VIEWS(84);

auto tmp = (avm_main_sel_op_fee_per_l2_gas * (avm_kernel_kernel_sel - FF(38)));
auto tmp = (avm_main_sel_op_fee_per_l2_gas * (avm_kernel_kernel_sel - FF(39)));
tmp *= scaling_factor;
std::get<84>(evals) += tmp;
}
// Contribution 85
{
Avm_DECLARE_VIEWS(85);

auto tmp = (avm_main_sel_op_transaction_fee * (avm_kernel_kernel_sel - FF(39)));
auto tmp = (avm_main_sel_op_transaction_fee * (avm_kernel_kernel_sel - FF(40)));
tmp *= scaling_factor;
std::get<85>(evals) += tmp;
}
// Contribution 86
{
Avm_DECLARE_VIEWS(86);

auto tmp = (avm_main_sel_op_chain_id * (avm_kernel_kernel_sel - FF(28)));
auto tmp = (avm_main_sel_op_chain_id * (avm_kernel_kernel_sel - FF(29)));
tmp *= scaling_factor;
std::get<86>(evals) += tmp;
}
// Contribution 87
{
Avm_DECLARE_VIEWS(87);

auto tmp = (avm_main_sel_op_version * (avm_kernel_kernel_sel - FF(29)));
auto tmp = (avm_main_sel_op_version * (avm_kernel_kernel_sel - FF(30)));
tmp *= scaling_factor;
std::get<87>(evals) += tmp;
}
// Contribution 88
{
Avm_DECLARE_VIEWS(88);

auto tmp = (avm_main_sel_op_block_number * (avm_kernel_kernel_sel - FF(30)));
auto tmp = (avm_main_sel_op_block_number * (avm_kernel_kernel_sel - FF(31)));
tmp *= scaling_factor;
std::get<88>(evals) += tmp;
}
// Contribution 89
{
Avm_DECLARE_VIEWS(89);

auto tmp = (avm_main_sel_op_coinbase * (avm_kernel_kernel_sel - FF(32)));
auto tmp = (avm_main_sel_op_coinbase * (avm_kernel_kernel_sel - FF(33)));
tmp *= scaling_factor;
std::get<89>(evals) += tmp;
}
// Contribution 90
{
Avm_DECLARE_VIEWS(90);

auto tmp = (avm_main_sel_op_timestamp * (avm_kernel_kernel_sel - FF(31)));
auto tmp = (avm_main_sel_op_timestamp * (avm_kernel_kernel_sel - FF(32)));
tmp *= scaling_factor;
std::get<90>(evals) += tmp;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ const size_t ROLLUP_VALIDATION_REQUESTS_LENGTH = MAX_BLOCK_NUMBER_LENGTH;
const size_t STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH;
const size_t TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH;
const size_t TX_REQUEST_LENGTH = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH;
const size_t HEADER_LENGTH =
APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH;
const size_t TOTAL_FEES_LENGTH = 1;
const size_t HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH +
GLOBAL_VARIABLES_LENGTH + TOTAL_FEES_LENGTH;
const size_t PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH =
CALL_CONTEXT_LENGTH + 4 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) +
(READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) +
Expand Down Expand Up @@ -172,7 +173,7 @@ const size_t KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LE
PARTIAL_STATE_REFERENCE_LENGTH + 1 + AZTEC_ADDRESS_LENGTH;
const size_t CONSTANT_ROLLUP_DATA_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 4 + GLOBAL_VARIABLES_LENGTH;
const size_t BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH =
CONSTANT_ROLLUP_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 4;
CONSTANT_ROLLUP_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 5;
const size_t ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH;
const size_t GET_NOTES_ORACLE_RETURN_LENGTH = 674;
const size_t NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048;
Expand Down
5 changes: 4 additions & 1 deletion docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ CombinedConstantData --> TxContext
class Header {
+GlobalVariables global_variables
+Fr total_fees
}
Header --> GlobalVariables
Expand Down Expand Up @@ -538,10 +539,12 @@ The interplay between these two `revert_code`s is as follows:
| 1 | 1 | 3 |
| 2 or 3 | (any) | (unchanged) |

## Base Rollup Kernel Circuit
## Rollup Kernel Circuits

The base rollup kernel circuit takes in a `KernelData`, which contains a `KernelCircuitPublicInputs`, which it uses to compute the `transaction_fee`.

Additionally, it verifies that the max fees per gas specified by the user are greater than the current block's fees per gas. It also verifies the `constant_data.global_variables.gas_fees` are correct.

After the public data writes specific to this transaction have been processed, and a new tree root is produced, the kernel circuit injects an additional public data write based upon that root which deducts the transaction fee from the `fee_payer`'s balance.

The calculated trasaction fee is set as output on the base rollup as `accumulated_fees`. Each subsequent merge rollup circuit sums this value from both of its inputs. The root rollup circuit then uses this value to set the `total_fees` in the `Header`.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ The block header contains a `GlobalVariables`, which contains a `GasFees` object
- `feePerDaGas`: The fee in [FPA](./fee-payment-asset.md) per unit of DA gas consumed for transactions in the block.
- `feePerL2Gas`: The fee in FPA per unit of L2 gas consumed for transactions in the block.

`GlobalVariables` also includes a `coinbase` field, which is the L1 address that receives the fees.

The block header also contains a `totalFees` field, which is the total fees collected in the block in FPA.

## Updating the `GasFees` Object

Presently, the `feePerDaGas` and `feePerL2Gas` are fixed at `1` FPA per unit of DA gas and L2 gas consumed, respectively.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ These are held in the L2 blocks `Header`
classDiagram
class Header {
+GlobalVariables globalVariables
+Fr totalFees
}
class GlobalVariables {
+GasFees gasFees
+EthAddress coinbase
}
class GasFees {
Expand All @@ -97,6 +99,10 @@ A transaction cannot be executed if the `maxFeesPerGas` is less than the `feePer

The `feePerGas` is presently held constant at `1` for both dimensions, but may be updated in future protocol versions.

`totalFees` is the total fees collected in the block in FPA.

`coinbase` is the L1 address that receives the fees.

## Transaction Fee

The transaction fee is calculated as:
Expand Down
1 change: 1 addition & 0 deletions docs/docs/protocol-specs/rollup-circuits/base-rollup.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class Header {
content_commitment: ContentCommitment
state: StateReference
global_variables: GlobalVariables
total_fees: Fr
}
Header *.. Body : txs_hash
Header *-- ContentCommitment: content_commitment
Expand Down
1 change: 1 addition & 0 deletions docs/docs/protocol-specs/rollup-circuits/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ class Header {
content_commitment: ContentCommitment
state: StateReference
global_variables: GlobalVariables
total_fees: Fr
}
Header *.. Body : txs_hash
Header *-- ContentCommitment: content_commitment
Expand Down
1 change: 1 addition & 0 deletions docs/docs/protocol-specs/rollup-circuits/root-rollup.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class Header {
content_commitment: ContentCommitment
state: StateReference
global_variables: GlobalVariables
total_fees: Fr
}
Header *.. Body : txs_hash
Header *-- ContentCommitment: content_commitment
Expand Down
1 change: 1 addition & 0 deletions docs/docs/protocol-specs/state/archive.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Header {
body_hash: Fr[2]
state: StateReference
global_variables: GlobalVariables
total_fees: Fr
}
Header *.. Body : body_hash
Header *-- StateReference : state
Expand Down
1 change: 1 addition & 0 deletions docs/docs/protocol-specs/state/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class Header {
content_commitment: ContentCommitment
state: StateReference
global_variables: GlobalVariables
total_fees: Fr
}
Header *.. Body : txs_hash
Header *-- ContentCommitment: content_commitment
Expand Down
6 changes: 3 additions & 3 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ contract Rollup is IRollup {
header.globalVariables.blockNumber, header.contentCommitment.outHash, l2ToL1TreeHeight
);

// pay the coinbase 1 gas token if it is not empty
if (header.globalVariables.coinbase != address(0)) {
GAS_TOKEN.transfer(address(header.globalVariables.coinbase), 1);
// pay the coinbase 1 gas token if it is not empty and header.totalFees is not zero
if (header.globalVariables.coinbase != address(0) && header.totalFees > 0) {
GAS_TOKEN.transfer(address(header.globalVariables.coinbase), header.totalFees);
}

emit L2BlockProcessed(header.globalVariables.blockNumber);
Expand Down
5 changes: 3 additions & 2 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,9 @@ library Constants {
APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH;
uint256 internal constant TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH;
uint256 internal constant TX_REQUEST_LENGTH = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH;
uint256 internal constant TOTAL_FEES_LENGTH = 1;
uint256 internal constant HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH
+ CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH;
+ CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH + TOTAL_FEES_LENGTH;
uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 4
+ MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL)
+ (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL)
Expand Down Expand Up @@ -211,7 +212,7 @@ library Constants {
uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH =
APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 4 + GLOBAL_VARIABLES_LENGTH;
uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = CONSTANT_ROLLUP_DATA_LENGTH
+ PARTIAL_STATE_REFERENCE_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 4;
+ PARTIAL_STATE_REFERENCE_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 5;
uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH =
2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH;
uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674;
Expand Down
7 changes: 6 additions & 1 deletion l1-contracts/src/core/libraries/HeaderLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import {Hash} from "./Hash.sol";
* | 0x0208 | 0x20 | gasFees.feePerL2Gas
* | | | }
* | | | }
* | 0x0228 | 0x20 | total_fees
* | --- | --- | ---
*/
library HeaderLib {
Expand Down Expand Up @@ -100,9 +101,10 @@ library HeaderLib {
ContentCommitment contentCommitment;
StateReference stateReference;
GlobalVariables globalVariables;
uint256 totalFees;
}

uint256 private constant HEADER_LENGTH = 0x228; // Header byte length
uint256 private constant HEADER_LENGTH = 0x248; // Header byte length

/**
* @notice Validates the header
Expand Down Expand Up @@ -190,6 +192,9 @@ library HeaderLib {
header.globalVariables.gasFees.feePerDaGas = uint256(bytes32(_header[0x01e8:0x0208]));
header.globalVariables.gasFees.feePerL2Gas = uint256(bytes32(_header[0x0208:0x0228]));

// Reading totalFees
header.totalFees = uint256(bytes32(_header[0x0228:0x0248]));

return header;
}
}
12 changes: 6 additions & 6 deletions l1-contracts/test/fixtures/empty_block_0.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"l2ToL1Messages": []
},
"block": {
"archive": "0x0ed815d35918f1aabf391fa174a1d95476da157e40b7fc581b2c8f4cfd23e6b3",
"archive": "0x1457164d01299b0097706a5b0e8735720280e2937d369b2bee07ba987fd6846e",
"body": "0x00000000",
"txsEffectsHash": "0x002676dbd818b1ba16e11597cb5c07b06aa7771127b02a77d0c3a6039bb9fef1",
"decodedHeader": {
Expand All @@ -23,16 +23,16 @@
"chainId": 31337,
"timestamp": 0,
"version": 1,
"coinbase": "0xbe70f89d75a00bd140342ebc63beb517cf9735bc",
"feeRecipient": "0x08eb6120958820f4b4fd61a9bcaa32c33349663034e1db315ba57c67d155b172",
"coinbase": "0x13def1c0178621c029040272730bb660031f3d51",
"feeRecipient": "0x2193c536a292e81634f7f77e7c9f3fdc7a197d396bfda81fdc0112e0b2bc9bb6",
"gasFees": {
"feePerDaGas": 0,
"feePerL2Gas": 0
}
},
"lastArchive": {
"nextAvailableLeafIndex": 1,
"root": "0x067a48e3140b6f15d71751ededfa0cccde3d436bb71aa7fec226b0bfe51dc5cf"
"root": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db8"
},
"stateReference": {
"l1ToL2MessageTree": {
Expand All @@ -55,8 +55,8 @@
}
}
},
"header": "0x067a48e3140b6f15d71751ededfa0cccde3d436bb71aa7fec226b0bfe51dc5cf000000010000000000000000000000000000000000000000000000000000000000000001002676dbd818b1ba16e11597cb5c07b06aa7771127b02a77d0c3a6039bb9fef100089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000be70f89d75a00bd140342ebc63beb517cf9735bc08eb6120958820f4b4fd61a9bcaa32c33349663034e1db315ba57c67d155b17200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"publicInputsHash": "0x00e9c95b88dbc49351e6a0a9b660918147d3c69410df4fba105c047a4f253a47",
"header": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db8000000010000000000000000000000000000000000000000000000000000000000000001002676dbd818b1ba16e11597cb5c07b06aa7771127b02a77d0c3a6039bb9fef100089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000013def1c0178621c029040272730bb660031f3d512193c536a292e81634f7f77e7c9f3fdc7a197d396bfda81fdc0112e0b2bc9bb6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"publicInputsHash": "0x004fa9f8a995305c2569a378b91e45d14f9a6b7d9ba0ca19e0ac0e4ea79123fb",
"numTxs": 0
}
}
Loading

0 comments on commit bf441da

Please sign in to comment.