From c6e3923784da3bbdc43d47478965a0f414012272 Mon Sep 17 00:00:00 2001 From: just-mitch Date: Tue, 30 Apr 2024 21:00:58 +0000 Subject: [PATCH] feat: enforce gas limits from private kernels --- .../protocol-specs/gas-and-fees/kernel-tracking.md | 1 + .../src/kernel_circuit_public_inputs_composer.nr | 11 +++++++++-- .../private-kernel-lib/src/private_kernel_tail.nr | 10 ++++++++++ .../src/private_kernel_tail_to_public.nr | 9 +++++++++ .../private_accumulated_data_builder.nr | 7 ------- .../crates/types/src/abis/gas.nr | 4 ++++ .../crates/types/src/tests/fixture_builder.nr | 4 +--- 7 files changed, 34 insertions(+), 12 deletions(-) diff --git a/docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md b/docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md index bf678054ce5..6b1ed68287a 100644 --- a/docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md +++ b/docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md @@ -206,6 +206,7 @@ It must: - check that there are enqueued public functions or a public teardown function - partition the side effects produced during private execution into revertible and non-revertible sets of `PublicAccumulatedData` - compute gas used for the revertible and non-revertible. Both sets can have a DA component, but the revertible set will also include the teardown gas allocations the user specified (if any). This ensures that the user effectively pre-pays for the gas consumed in teardown. +- ensure the gas used (across revertible and non-revertible) is less than the gas limits - ensure that `fee_payer` is set, and set it in the `PublicKernelCircuitPublicInputs` - copy the constants from the `PrivateKernelData` to the `PublicKernelCircuitPublicInputs.constants` diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr index 2abc0ee11f4..f51146ad434 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr @@ -113,13 +113,20 @@ impl KernelCircuitPublicInputsComposer { pub fn finish(self) -> KernelCircuitPublicInputs { let teardown_gas = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.teardown_gas_limits; - self.public_inputs.finish_tail(teardown_gas) + let inputs = self.public_inputs.finish_tail(teardown_gas); + let limits = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.gas_limits; + assert(inputs.end.gas_used.within(limits), "The gas used exceeds the gas limits"); + inputs } pub fn finish_to_public(self) -> PublicKernelCircuitPublicInputs { let min_revertible_side_effect_counter = self.previous_kernel.public_inputs.min_revertible_side_effect_counter; let teardown_gas = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.teardown_gas_limits; - self.public_inputs.finish_to_public(teardown_gas, min_revertible_side_effect_counter) + let inputs = self.public_inputs.finish_to_public(teardown_gas, min_revertible_side_effect_counter); + let limits = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.gas_limits; + let total_gas_used = inputs.end.gas_used + inputs.end_non_revertible.gas_used; + assert(total_gas_used.within(limits), "The gas used exceeds the gas limits"); + inputs } fn silo_values(&mut self) { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index 568098daa59..27fc6b7c721 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -115,6 +115,8 @@ mod tests { impl PrivateKernelTailInputsBuilder { pub fn new() -> Self { let mut previous_kernel = FixtureBuilder::new(); + previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1_000_000, 1_000_000); + previous_kernel.append_new_nullifiers(1); PrivateKernelTailInputsBuilder { @@ -572,4 +574,12 @@ mod tests { + Gas::new(DA_GAS_PER_BYTE * DA_BYTES_PER_FIELD * 1, 0); // tx nullifier assert_eq(public_inputs.end.gas_used, expected_gas_consumed); } + + #[test(should_fail_with="The gas used exceeds the gas limits")] + unconstrained fn gas_limits_are_enforced() { + let mut builder = PrivateKernelTailInputsBuilder::new(); + builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = Gas::new(300, 300); + builder.previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1, 1); + builder.failed(); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr index 1454b919aa5..5bd7b7a568e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr @@ -118,6 +118,7 @@ mod tests { impl PrivateKernelTailToPublicInputsBuilder { pub fn new() -> Self { let mut previous_kernel = FixtureBuilder::new(); + previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1_000_000, 1_000_000); previous_kernel.append_new_nullifiers(1); previous_kernel.push_public_call_request(1, false); @@ -600,4 +601,12 @@ mod tests { let expected_gas_consumed = Gas::new(300, 300) + Gas::tx_overhead(); assert_eq(public_inputs.end.gas_used, expected_gas_consumed); } + + #[test(should_fail_with="The gas used exceeds the gas limits")] + unconstrained fn gas_limits_are_enforced() { + let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); + builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = Gas::new(300, 300); + builder.previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1, 1); + builder.failed(); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index 5e62c134874..14041908fb5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -39,15 +39,10 @@ struct PrivateAccumulatedDataBuilder { private_call_stack: BoundedVec, public_call_stack: BoundedVec, - gas_used: Gas, - non_revertible_gas_used: Gas, } impl PrivateAccumulatedDataBuilder { pub fn finish(self) -> PrivateAccumulatedData { - assert(self.gas_used.is_empty()); - assert(self.non_revertible_gas_used.is_empty()); - PrivateAccumulatedData { new_note_hashes: self.new_note_hashes.storage, new_nullifiers: self.new_nullifiers.storage, @@ -318,8 +313,6 @@ impl Empty for PrivateAccumulatedDataBuilder { unencrypted_log_preimages_length: 0, private_call_stack: BoundedVec::new(), public_call_stack: BoundedVec::new(), - gas_used: Gas::empty(), - non_revertible_gas_used: Gas::empty(), } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr index 07e9c6d5360..4354f316c3a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr @@ -27,6 +27,10 @@ impl Gas { pub fn is_empty(self) -> bool { (self.da_gas == 0) & (self.l2_gas == 0) } + + pub fn within(self, limits: Gas) -> bool { + (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas) + } } impl Add for Gas { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 4cf0e8f7596..ef8a379e749 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -133,9 +133,7 @@ impl FixtureBuilder { encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, private_call_stack: self.private_call_stack, - public_call_stack: self.public_call_stack, - gas_used: self.gas_used, - non_revertible_gas_used: self.non_revertible_gas_used + public_call_stack: self.public_call_stack }; public_inputs.finish() }