Skip to content

Commit

Permalink
feat: enforce gas limits from private kernels (#6105)
Browse files Browse the repository at this point in the history
Now we assert that we stayed within user limits during private execution.
  • Loading branch information
just-mitch authored May 1, 2024
1 parent 72321f9 commit 4395855
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 12 deletions.
1 change: 1 addition & 0 deletions docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,10 @@ struct PrivateAccumulatedDataBuilder {
private_call_stack: BoundedVec<CallRequest, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX>,
public_call_stack: BoundedVec<CallRequest, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX>,

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,
Expand Down Expand Up @@ -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(),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down

0 comments on commit 4395855

Please sign in to comment.