diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index 3aaedf41c5e..52df3243076 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -36,6 +36,7 @@ #define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 866 #define PUBLIC_CONTEXT_INPUTS_LENGTH 41 #define AVM_ACCUMULATED_DATA_LENGTH 318 +#define AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH 1006 #define AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS 86 #define AVM_PROOF_LENGTH_IN_FIELDS 4291 #define AVM_PUBLIC_COLUMN_MAX_SIZE 1024 diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr index 0f31631c0c3..89c7410bfd6 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr @@ -13,7 +13,6 @@ use dep::types::{ abis::{ accumulated_data::CombinedAccumulatedData, combined_constant_data::CombinedConstantData, - gas::Gas, log_hash::{LogHash, ScopedLogHash}, }, constants::{ @@ -105,7 +104,7 @@ impl PublicBaseRollupInputs { end, start_state, revert_code, - gas_used: Gas::empty(), // gas_used is not used in rollup circuits. + gas_used: from_public.end_gas_used, fee_payer: from_private.fee_payer, } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr index 6f13d86177c..1ce06e8f53a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr @@ -35,6 +35,7 @@ pub struct AvmCircuitPublicInputs { /////////////////////////////////// // Outputs. end_tree_snapshots: TreeSnapshots, + end_gas_used: Gas, accumulated_data: AvmAccumulatedData, transaction_fee: Field, reverted: bool, @@ -55,6 +56,7 @@ impl Empty for AvmCircuitPublicInputs { previous_non_revertible_accumulated_data: PrivateToAvmAccumulatedData::empty(), previous_revertible_accumulated_data: PrivateToAvmAccumulatedData::empty(), end_tree_snapshots: TreeSnapshots::empty(), + end_gas_used: Gas::empty(), accumulated_data: AvmAccumulatedData::empty(), transaction_fee: 0, reverted: false, @@ -88,6 +90,7 @@ impl Eq for AvmCircuitPublicInputs { == other.previous_revertible_accumulated_data ) & (self.end_tree_snapshots == other.end_tree_snapshots) + & (self.end_gas_used == other.end_gas_used) & (self.accumulated_data == other.accumulated_data) & (self.transaction_fee == other.transaction_fee) & (self.reverted == other.reverted) @@ -116,6 +119,7 @@ impl Serialize for AvmCircuitPublicInputs { fields.extend_from_array(self.previous_non_revertible_accumulated_data.serialize()); fields.extend_from_array(self.previous_revertible_accumulated_data.serialize()); fields.extend_from_array(self.end_tree_snapshots.serialize()); + fields.extend_from_array(self.end_gas_used.serialize()); fields.extend_from_array(self.accumulated_data.serialize()); fields.push(self.transaction_fee); fields.push(self.reverted as Field); @@ -156,6 +160,7 @@ impl Deserialize for AvmCircuitPublicInputs { PrivateToAvmAccumulatedData::deserialize, ), end_tree_snapshots: reader.read_struct(TreeSnapshots::deserialize), + end_gas_used: reader.read_struct(Gas::deserialize), accumulated_data: reader.read_struct(AvmAccumulatedData::deserialize), transaction_fee: reader.read(), reverted: reader.read() as bool, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 6f77b744519..64e92007b45 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -476,10 +476,10 @@ pub global AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = GLOBAL_VARIABLES_LENGTH + PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH /* previous_non_revertible_accumulated_data */ + PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH /* previous_revertible_accumulated_data */ + TREE_SNAPSHOTS_LENGTH /* end_tree_snapshots */ + + GAS_LENGTH /* end_gas_used */ + AVM_ACCUMULATED_DATA_LENGTH + 1 /* transaction_fee */ - + 1 /* reverted */ -; + + 1 /* reverted */; pub global CONSTANT_ROLLUP_DATA_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 1 /* vk_tree_root */ diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 364e1cfca4d..5a0017dc7a7 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -207,6 +207,7 @@ export const PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1196; export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2931; export const VM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2340; export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 600; +export const AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1006; export const CONSTANT_ROLLUP_DATA_LENGTH = 13; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 30; export const BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 90; diff --git a/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts index 6c68ce02a23..0ff41750b69 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts @@ -30,6 +30,7 @@ export class AvmCircuitPublicInputs { public previousNonRevertibleAccumulatedData: PrivateToAvmAccumulatedData, public previousRevertibleAccumulatedData: PrivateToAvmAccumulatedData, public endTreeSnapshots: TreeSnapshots, + public endGasUsed: Gas, public accumulatedData: AvmAccumulatedData, public transactionFee: Fr, public reverted: boolean, @@ -50,6 +51,7 @@ export class AvmCircuitPublicInputs { reader.readObject(PrivateToAvmAccumulatedData), reader.readObject(PrivateToAvmAccumulatedData), reader.readObject(TreeSnapshots), + reader.readObject(Gas), reader.readObject(AvmAccumulatedData), reader.readObject(Fr), reader.readBoolean(), @@ -70,6 +72,7 @@ export class AvmCircuitPublicInputs { this.previousNonRevertibleAccumulatedData, this.previousRevertibleAccumulatedData, this.endTreeSnapshots, + this.endGasUsed, this.accumulatedData, this.transactionFee, this.reverted, @@ -99,6 +102,7 @@ export class AvmCircuitPublicInputs { PrivateToAvmAccumulatedData.fromFields(reader), PrivateToAvmAccumulatedData.fromFields(reader), TreeSnapshots.fromFields(reader), + Gas.fromFields(reader), AvmAccumulatedData.fromFields(reader), reader.readField(), reader.readBoolean(), @@ -119,6 +123,7 @@ export class AvmCircuitPublicInputs { PrivateToAvmAccumulatedData.empty(), PrivateToAvmAccumulatedData.empty(), TreeSnapshots.empty(), + Gas.empty(), AvmAccumulatedData.empty(), Fr.zero(), false, @@ -147,6 +152,7 @@ export class AvmCircuitPublicInputs { previousNonRevertibleAccumulatedData: ${inspect(this.previousNonRevertibleAccumulatedData)}, previousRevertibleAccumulatedData: ${inspect(this.previousRevertibleAccumulatedData)}, endTreeSnapshots: ${inspect(this.endTreeSnapshots)}, + endGasUsed: ${inspect(this.endGasUsed)}, accumulatedData: ${inspect(this.accumulatedData)}, transactionFee: ${inspect(this.transactionFee)}, reverted: ${this.reverted}, diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 3054dc575e1..8c60ede4f03 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -649,7 +649,7 @@ function makeAvmCircuitPublicInputs(seed = 1) { return new AvmCircuitPublicInputs( makeGlobalVariables(seed), makeTreeSnapshots(seed + 0x10), - makeGas(), + makeGas(seed + 0x20), makeGasSettings(), makeTuple(MAX_ENQUEUED_CALLS_PER_TX, makePublicCallRequest, seed + 0x100), makeTuple(MAX_ENQUEUED_CALLS_PER_TX, makePublicCallRequest, seed + 0x200), @@ -659,8 +659,9 @@ function makeAvmCircuitPublicInputs(seed = 1) { makePrivateToAvmAccumulatedData(seed + 0x500), makePrivateToAvmAccumulatedData(seed + 0x600), makeTreeSnapshots(seed + 0x700), + makeGas(seed + 0x750), makeAvmAccumulatedData(seed + 0x800), - fr(seed + 0x700), + fr(seed + 0x900), false, ); } diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 4f0147f12ae..2ed19ccaf27 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -2126,6 +2126,7 @@ function mapAvmCircuitPublicInputsToNoir(inputs: AvmCircuitPublicInputs): AvmCir inputs.previousRevertibleAccumulatedData, ), end_tree_snapshots: mapTreeSnapshotsToNoir(inputs.endTreeSnapshots), + end_gas_used: mapGasToNoir(inputs.endGasUsed), accumulated_data: mapAvmAccumulatedDataToNoir(inputs.accumulatedData), transaction_fee: mapFieldToNoir(inputs.transactionFee), reverted: inputs.reverted, diff --git a/yarn-project/simulator/src/public/enqueued_calls_processor.test.ts b/yarn-project/simulator/src/public/enqueued_calls_processor.test.ts index 6b66e8fd877..f3502980876 100644 --- a/yarn-project/simulator/src/public/enqueued_calls_processor.test.ts +++ b/yarn-project/simulator/src/public/enqueued_calls_processor.test.ts @@ -202,7 +202,9 @@ describe('enqueued_calls_processor', () => { const output = txResult.avmProvingRequest!.inputs.output; + const expectedGasUsedForFee = expectedTotalGas; const expectedTxFee = expectedTotalGas.computeFee(gasFees); + expect(output.endGasUsed).toEqual(expectedGasUsedForFee); expect(output.transactionFee).toEqual(expectedTxFee); // We keep all data. @@ -235,7 +237,9 @@ describe('enqueued_calls_processor', () => { const output = txResult.avmProvingRequest!.inputs.output; + const expectedGasUsedForFee = expectedTotalGas; const expectedTxFee = expectedTotalGas.computeFee(gasFees); + expect(output.endGasUsed).toEqual(expectedGasUsedForFee); expect(output.transactionFee).toEqual(expectedTxFee); // We keep all data. @@ -266,8 +270,9 @@ describe('enqueued_calls_processor', () => { const output = txResult.avmProvingRequest!.inputs.output; - const expectedTotalGasForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); - const expectedTxFee = expectedTotalGasForFee.computeFee(gasFees); + const expectedGasUsedForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); + const expectedTxFee = expectedGasUsedForFee.computeFee(gasFees); + expect(output.endGasUsed).toEqual(expectedGasUsedForFee); expect(output.transactionFee).toEqual(expectedTxFee); // We keep all data. @@ -313,8 +318,9 @@ describe('enqueued_calls_processor', () => { const output = txResult.avmProvingRequest!.inputs.output; - const expectedTotalGasForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); - const expectedTxFee = expectedTotalGasForFee.computeFee(gasFees); + const expectedGasUsedForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); + const expectedTxFee = expectedGasUsedForFee.computeFee(gasFees); + expect(output.endGasUsed).toEqual(expectedGasUsedForFee); expect(output.transactionFee).toEqual(expectedTxFee); // We keep all data. @@ -459,8 +465,9 @@ describe('enqueued_calls_processor', () => { const output = txResult.avmProvingRequest!.inputs.output; - const expectedTotalGasForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); - const expectedTxFee = expectedTotalGasForFee.computeFee(gasFees); + const expectedGasUsedForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); + const expectedTxFee = expectedGasUsedForFee.computeFee(gasFees); + expect(output.endGasUsed).toEqual(expectedGasUsedForFee); expect(output.transactionFee).toEqual(expectedTxFee); // we keep the non-revertible data. @@ -535,8 +542,9 @@ describe('enqueued_calls_processor', () => { const output = txResult.avmProvingRequest!.inputs.output; // Should still charge the full teardownGasLimits for fee even though teardown reverted. - const expectedTotalGasForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); - const expectedTxFee = expectedTotalGasForFee.computeFee(gasFees); + const expectedGasUsedForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); + const expectedTxFee = expectedGasUsedForFee.computeFee(gasFees); + expect(output.endGasUsed).toEqual(expectedGasUsedForFee); expect(output.transactionFee).toEqual(expectedTxFee); // We keep the non-revertible data. @@ -618,8 +626,9 @@ describe('enqueued_calls_processor', () => { const output = txResult.avmProvingRequest!.inputs.output; // Should still charge the full teardownGasLimits for fee even though teardown reverted. - const expectedTotalGasForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); - const expectedTxFee = expectedTotalGasForFee.computeFee(gasFees); + const expectedGasUsedForFee = expectedTotalGas.sub(expectedTeardownGasUsed).add(teardownGasLimits); + const expectedTxFee = expectedGasUsedForFee.computeFee(gasFees); + expect(output.endGasUsed).toEqual(expectedGasUsedForFee); expect(output.transactionFee).toEqual(expectedTxFee); // we keep the non-revertible data diff --git a/yarn-project/simulator/src/public/enqueued_calls_processor.ts b/yarn-project/simulator/src/public/enqueued_calls_processor.ts index 1aaeef23cac..f1610d2ae04 100644 --- a/yarn-project/simulator/src/public/enqueued_calls_processor.ts +++ b/yarn-project/simulator/src/public/enqueued_calls_processor.ts @@ -286,8 +286,14 @@ export class EnqueuedCallsProcessor { }, ); + const gasUsedForFee = this.getGasUsedForFee(tx, phaseGasUsed); const transactionFee = this.getTransactionFee(tx, phaseGasUsed); - avmProvingRequest!.inputs.output = this.generateAvmCircuitPublicInputs(tx, tailKernelOutput, transactionFee); + avmProvingRequest!.inputs.output = this.generateAvmCircuitPublicInputs( + tx, + tailKernelOutput, + gasUsedForFee, + transactionFee, + ); const gasUsed = { totalGas: this.getActualGasUsed(tx, phaseGasUsed), @@ -412,16 +418,19 @@ export class EnqueuedCallsProcessor { private getTransactionFee(tx: Tx, phaseGasUsed: PhaseGasUsed): Fr { const gasFees = this.globalVariables.gasFees; - const txFee = tx.data.gasUsed // This should've included teardown gas limits. - .add(phaseGasUsed[TxExecutionPhase.SETUP]) - .add(phaseGasUsed[TxExecutionPhase.APP_LOGIC]) - .computeFee(gasFees); + const txFee = this.getGasUsedForFee(tx, phaseGasUsed).computeFee(gasFees); this.log.debug(`Computed tx fee`, { txFee, gasUsed: inspect(phaseGasUsed), gasFees: inspect(gasFees) }); return txFee; } + private getGasUsedForFee(tx: Tx, phaseGasUsed: PhaseGasUsed) { + return tx.data.gasUsed // This should've included teardown gas limits. + .add(phaseGasUsed[TxExecutionPhase.SETUP]) + .add(phaseGasUsed[TxExecutionPhase.APP_LOGIC]); + } + private getActualGasUsed(tx: Tx, phaseGasUsed: PhaseGasUsed) { const requireTeardown = tx.data.hasTeardownPublicCallRequest(); const teardownGasLimits = tx.data.constants.txContext.gasSettings.teardownGasLimits; @@ -488,7 +497,12 @@ export class EnqueuedCallsProcessor { } // Temporary hack to create the AvmCircuitPublicInputs from public tail's public inputs. - private generateAvmCircuitPublicInputs(tx: Tx, tailOutput: KernelCircuitPublicInputs, transactionFee: Fr) { + private generateAvmCircuitPublicInputs( + tx: Tx, + tailOutput: KernelCircuitPublicInputs, + gasUsedForFee: Gas, + transactionFee: Fr, + ) { const startTreeSnapshots = new TreeSnapshots( tailOutput.constants.historicalHeader.state.l1ToL2MessageTree, tailOutput.startState.noteHashTree, @@ -532,6 +546,7 @@ export class EnqueuedCallsProcessor { convertAccumulatedData(tx.data.forPublic!.nonRevertibleAccumulatedData), convertAccumulatedData(tx.data.forPublic!.revertibleAccumulatedData), endTreeSnapshots, + gasUsedForFee, convertAvmAccumulatedData(tailOutput.end), transactionFee, !tailOutput.revertCode.equals(RevertCode.OK),