Skip to content

Commit

Permalink
feat: publish transaction_fee
Browse files Browse the repository at this point in the history
  • Loading branch information
just-mitch committed May 1, 2024
1 parent f60dfcd commit 605ee13
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 56 deletions.
1 change: 1 addition & 0 deletions foundry/foundry-repo
Submodule foundry-repo added at de33b6
38 changes: 24 additions & 14 deletions l1-contracts/src/core/libraries/decoders/TxsDecoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,19 @@ import {Hash} from "../Hash.sol";
* | 0x0 | 0x4 | len(numTxs) (denoted t)
* | | | TxEffect 0 {
* | 0x4 | 0x1 | revertCode
* | 0x5 | 0x1 | len(newNoteHashes) (denoted b)
* | 0x5 + 0x1 | b * 0x20 | newNoteHashes
* | 0x5 + 0x1 + b * 0x20 | 0x1 | len(newNullifiers) (denoted c)
* | 0x5 + 0x1 + b * 0x20 + 0x1 | c * 0x20 | newNullifiers
* | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 | 0x1 | len(newL2ToL1Msgs) (denoted d)
* | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 | d * 0x20 | newL2ToL1Msgs
* | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 | 0x1 | len(newPublicDataWrites) (denoted e)
* | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 | e * 0x40 | newPublicDataWrites
* | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x04 | byteLen(newEncryptedLogs) (denoted f)
* | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 | f | newEncryptedLogs
* | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f | 0x04 | byteLen(newUnencryptedLogs) (denoted g)
* | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 | g | newUnencryptedLogs
* | 0x5 | 0x20 | transactionFee
* | 0x37 | 0x1 | len(newNoteHashes) (denoted b)
* | 0x37 + 0x1 | b * 0x20 | newNoteHashes
* | 0x37 + 0x1 + b * 0x20 | 0x1 | len(newNullifiers) (denoted c)
* | 0x37 + 0x1 + b * 0x20 + 0x1 | c * 0x20 | newNullifiers
* | 0x37 + 0x1 + b * 0x20 + 0x1 + c * 0x20 | 0x1 | len(newL2ToL1Msgs) (denoted d)
* | 0x37 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 | d * 0x20 | newL2ToL1Msgs
* | 0x37 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 | 0x1 | len(newPublicDataWrites) (denoted e)
* | 0x37 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 | e * 0x40 | newPublicDataWrites
* | 0x37 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x04 | byteLen(newEncryptedLogs) (denoted f)
* | 0x37 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 | f | newEncryptedLogs
* | 0x37 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f | 0x04 | byteLen(newUnencryptedLogs) (denoted g)
* | 0x37 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 | g | newUnencryptedLogs
* | | | },
* | | | TxEffect 1 {
* | | | ...
Expand All @@ -45,6 +46,7 @@ import {Hash} from "../Hash.sol";
library TxsDecoder {
struct ArrayOffsets {
uint256 revertCode;
uint256 transactionFee;
uint256 noteHash;
uint256 nullifier;
uint256 l2ToL1Msgs;
Expand Down Expand Up @@ -90,6 +92,7 @@ library TxsDecoder {
* Compute the leaf to insert.
* Leaf_i = (
* revertCode,
* transactionFee,
* newNoteHashesKernel,
* newNullifiersKernel,
* newL2ToL1MsgsKernel,
Expand All @@ -105,6 +108,10 @@ library TxsDecoder {
offsets.revertCode = offset;
offset += 0x1;

// Transaction Fee
offsets.transactionFee = offset;
offset += 0x20;

// Note hashes
uint256 count = read1(_body, offset);
offset += 0x1;
Expand Down Expand Up @@ -143,7 +150,10 @@ library TxsDecoder {
// Insertions are split into multiple `bytes.concat` to work around stack too deep.
vars.baseLeaf = bytes.concat(
// pad the revert code to 32 bytes to match the hash preimage
sliceAndPadLeft(_body, offsets.revertCode, 0x1, 0x20),
bytes.concat(
sliceAndPadLeft(_body, offsets.revertCode, 0x1, 0x20),
slice(_body, offsets.transactionFee, 0x20)
),
bytes.concat(
sliceAndPadRight(
_body,
Expand Down Expand Up @@ -179,7 +189,7 @@ library TxsDecoder {
// We pad base leaves with hashes of empty tx effect.
for (uint256 i = numTxEffects; i < vars.baseLeaves.length; i++) {
// Value taken from tx_effect.test.ts "hash of empty tx effect matches snapshot" test case
vars.baseLeaves[i] = hex"0071f7630d28ce02cc1ca8b15c44953f84a39e1478445395247ae04dfa213c0e";
vars.baseLeaves[i] = hex"00822c2cdfbc7a6e5f4dd355251f4dfc9af1b1a64152464b9b83c5007eeed0f3";
}
}

Expand Down
14 changes: 7 additions & 7 deletions l1-contracts/test/fixtures/empty_block_0.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@
"l2ToL1Messages": []
},
"block": {
"archive": "0x080ba94e0599e43b20d1d5dd297f12eee1ab3b74fc07c4b6e505d0d54dc4c878",
"archive": "0x092e7b5812f430a11de252abb67ba28c237b78aa717cf67a0a7d13ac229cb476",
"body": "0x00000000",
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896",
"txsEffectsHash": "0x0041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c",
"decodedHeader": {
"contentCommitment": {
"inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c",
"outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3",
"txTreeHeight": 1,
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896"
"txsEffectsHash": "0x0041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c"
},
"globalVariables": {
"blockNumber": 1,
"chainId": 31337,
"timestamp": 0,
"version": 1,
"coinbase": "0xc1e85ff1bdb95e08537b887b0f371638903460e3",
"feeRecipient": "0x0cb7735e3f0a0df7ec2303f5817cec5ad40812a970544fc1fc2c310eeb3988cc",
"coinbase": "0xb35cee29ec094ab8b8be05b158e0bf50d2432952",
"feeRecipient": "0x2e318034e3a2c52d895e8af8e14f8b95c5e49c461d12b4657ab8c85539013b02",
"gasFees": {
"feePerDaGas": 0,
"feePerL2Gas": 0
Expand Down Expand Up @@ -55,8 +55,8 @@
}
}
},
"header": "0x067a48e3140b6f15d71751ededfa0cccde3d436bb71aa7fec226b0bfe51dc5cf00000001000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000c1e85ff1bdb95e08537b887b0f371638903460e30cb7735e3f0a0df7ec2303f5817cec5ad40812a970544fc1fc2c310eeb3988cc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"publicInputsHash": "0x000cae072f9ae6a94c6c642594e0985c0df681cfa951939a901291b8e569bc2c",
"header": "0x067a48e3140b6f15d71751ededfa0cccde3d436bb71aa7fec226b0bfe51dc5cf0000000100000000000000000000000000000000000000000000000000000000000000010041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000b35cee29ec094ab8b8be05b158e0bf50d24329522e318034e3a2c52d895e8af8e14f8b95c5e49c461d12b4657ab8c85539013b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"publicInputsHash": "0x00ae98c27e880d898c1dd0cdb9b2da88de6719f7b3bf0707a4f13381ac22dce8",
"numTxs": 0
}
}
18 changes: 9 additions & 9 deletions l1-contracts/test/fixtures/empty_block_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,31 @@
"l2ToL1Messages": []
},
"block": {
"archive": "0x12b17b38f46254c7143bd35e6348dc09cc8833d6b34e192cd00e243a3bbe562f",
"archive": "0x0a195ab304da7c6cf916ff7a40cb570f728481aac14b2d5df776c5306d0671f5",
"body": "0x00000000",
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896",
"txsEffectsHash": "0x0041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c",
"decodedHeader": {
"contentCommitment": {
"inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c",
"outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3",
"txTreeHeight": 1,
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896"
"txsEffectsHash": "0x0041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c"
},
"globalVariables": {
"blockNumber": 2,
"chainId": 31337,
"timestamp": 1714163483,
"timestamp": 1714575319,
"version": 1,
"coinbase": "0xc1e85ff1bdb95e08537b887b0f371638903460e3",
"feeRecipient": "0x0cb7735e3f0a0df7ec2303f5817cec5ad40812a970544fc1fc2c310eeb3988cc",
"coinbase": "0xb35cee29ec094ab8b8be05b158e0bf50d2432952",
"feeRecipient": "0x2e318034e3a2c52d895e8af8e14f8b95c5e49c461d12b4657ab8c85539013b02",
"gasFees": {
"feePerDaGas": 0,
"feePerL2Gas": 0
}
},
"lastArchive": {
"nextAvailableLeafIndex": 2,
"root": "0x080ba94e0599e43b20d1d5dd297f12eee1ab3b74fc07c4b6e505d0d54dc4c878"
"root": "0x092e7b5812f430a11de252abb67ba28c237b78aa717cf67a0a7d13ac229cb476"
},
"stateReference": {
"l1ToL2MessageTree": {
Expand All @@ -55,8 +55,8 @@
}
}
},
"header": "0x080ba94e0599e43b20d1d5dd297f12eee1ab3b74fc07c4b6e505d0d54dc4c87800000002000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000662c0f1bc1e85ff1bdb95e08537b887b0f371638903460e30cb7735e3f0a0df7ec2303f5817cec5ad40812a970544fc1fc2c310eeb3988cc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"publicInputsHash": "0x00f4dc87aadb7c9e401412f285d770460dcd43d2baba6b7cceecde9b86361663",
"header": "0x092e7b5812f430a11de252abb67ba28c237b78aa717cf67a0a7d13ac229cb4760000000200000000000000000000000000000000000000000000000000000000000000010041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000663257d7b35cee29ec094ab8b8be05b158e0bf50d24329522e318034e3a2c52d895e8af8e14f8b95c5e49c461d12b4657ab8c85539013b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"publicInputsHash": "0x00dde76c303e0e4d99151f2178e0b6cca10687f5a956084cae2fe6d320e3b9ec",
"numTxs": 0
}
}
16 changes: 8 additions & 8 deletions l1-contracts/test/fixtures/mixed_block_0.json

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions l1-contracts/test/fixtures/mixed_block_1.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ impl BaseRollupInputs {
// Calculate the tx effects hash of the transaction
let tx_effects_hash = compute_tx_effects_hash(
self.kernel_data.public_inputs.end,
self.kernel_data.public_inputs.revert_code
self.kernel_data.public_inputs.revert_code,
self.kernel_data.public_inputs.compute_transaction_fee()
);
let out_hash = compute_kernel_out_hash(self.kernel_data.public_inputs.end);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,19 @@ pub fn compute_txs_effects_hash(previous_rollup_data: [PreviousRollupData; 2]) -
)
}

global TX_EFFECTS_HASH_INPUT_FIELDS = 197;
global TX_EFFECTS_HASH_INPUT_FIELDS = 198;

// Computes the tx effects hash for a base rollup (a single transaction)
// TODO(Alvaro): This is too slow for brillig without the array optimization
pub fn compute_tx_effects_hash(combined: CombinedAccumulatedData, revert_code: u8) -> Field {
pub fn compute_tx_effects_hash(
combined: CombinedAccumulatedData,
revert_code: u8,
transaction_fee: Field
) -> Field {
// Compute tx effect hash
// Consist of
// 1 field for revert code
// 1 field for transaction fee
// MAX_NEW_NOTE_HASHES_PER_TX fields for note hashes
// MAX_NEW_NULLIFIERS_PER_TX fields for nullifiers
// 2 l2 -> l1 messages -> 2 fields
Expand All @@ -153,6 +159,9 @@ pub fn compute_tx_effects_hash(combined: CombinedAccumulatedData, revert_code: u
txs_effects_hash_input[offset] = revert_code as Field;
offset += 1;

txs_effects_hash_input[offset] = transaction_fee;
offset += 1;

for j in 0..MAX_NEW_NOTE_HASHES_PER_TX {
txs_effects_hash_input[offset + j] = new_note_hashes[j];
}
Expand Down Expand Up @@ -200,7 +209,9 @@ pub fn compute_tx_effects_hash(combined: CombinedAccumulatedData, revert_code: u
#[test]
fn consistent_TX_EFFECTS_HASH_INPUT_FIELDS() {
// 1 for revert_code
// 1 for transaction_fee
let expected_size = 1
+ 1
+ MAX_NEW_NOTE_HASHES_PER_TX
+ MAX_NEW_NULLIFIERS_PER_TX
+ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
abis::{
accumulated_data::CombinedAccumulatedData, combined_constant_data::CombinedConstantData,
validation_requests::RollupValidationRequests
validation_requests::RollupValidationRequests, gas::Gas
},
partial_state_reference::PartialStateReference
partial_state_reference::PartialStateReference, traits::Empty
};
use crate::mocked::AggregationObject;

Expand All @@ -15,3 +15,80 @@ struct KernelCircuitPublicInputs {
start_state: PartialStateReference,
revert_code: u8,
}

impl KernelCircuitPublicInputs {
pub fn compute_gas_used(self) -> Gas {
self.constants.tx_context.gas_settings.teardown_gas_limits + self.end.gas_used
}

pub fn compute_transaction_fee(self) -> Field {
let gas_used = self.compute_gas_used();
let gas_fees = self.constants.global_variables.gas_fees;
let inclusion_fee = self.constants.tx_context.gas_settings.inclusion_fee;
inclusion_fee + gas_used.compute_fee(gas_fees)
}
}

impl Empty for KernelCircuitPublicInputs {
fn empty() -> Self {
KernelCircuitPublicInputs {
aggregation_object: AggregationObject::empty(),
rollup_validation_requests: RollupValidationRequests::empty(),
end: CombinedAccumulatedData::empty(),
constants: CombinedConstantData::empty(),
start_state: PartialStateReference::empty(),
revert_code: 0,
}
}
}

mod tests {
use crate::abis::{
kernel_circuit_public_inputs::kernel_circuit_public_inputs::KernelCircuitPublicInputs,
accumulated_data::CombinedAccumulatedData, combined_constant_data::CombinedConstantData,
validation_requests::RollupValidationRequests, gas::Gas, gas_fees::GasFees
};
use crate::partial_state_reference::PartialStateReference;
use crate::mocked::AggregationObject;

#[test]
unconstrained fn empty_has_zero_gas_and_fee() {
let empty = KernelCircuitPublicInputs::empty();
assert_eq(empty.compute_gas_used(), Gas::empty());
assert_eq(empty.compute_transaction_fee(), 0);
}

#[test]
unconstrained fn non_empty_gas_and_fee() {
let mut inputs = KernelCircuitPublicInputs {
aggregation_object: AggregationObject::empty(),
rollup_validation_requests: RollupValidationRequests::empty(),
end: CombinedAccumulatedData::empty(),
constants: CombinedConstantData::empty(),
start_state: PartialStateReference::empty(),
revert_code: 0
};

inputs.end.gas_used = Gas {
da_gas: 10,
l2_gas: 20
};

inputs.constants.tx_context.gas_settings.teardown_gas_limits = Gas {
da_gas: 100,
l2_gas: 200
};

inputs.constants.tx_context.gas_settings.inclusion_fee = 42;

inputs.constants.global_variables.gas_fees = GasFees {
fee_per_da_gas: 2,
fee_per_l2_gas: 3
};

let gas_used = inputs.compute_gas_used();
assert_eq(gas_used, Gas { da_gas: 110, l2_gas: 220 });
let transaction_fee = inputs.compute_transaction_fee();
assert_eq(transaction_fee, 42 + 2 * 110 + 3 * 220);
}
}
Loading

0 comments on commit 605ee13

Please sign in to comment.