Skip to content

Commit

Permalink
fix(public-kernel): only validate start-gas for execution requests
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanks12 committed May 1, 2024
1 parent 248761e commit 03fa539
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,19 @@ pub fn update_non_revertible_gas_used(public_call: PublicCallData, circuit_outpu

// Validates that the start gas injected into the app circuit matches the remaining gas
pub fn validate_start_gas(public_call: PublicCallData, previous_kernel: PublicKernelData) {
let public_call_start_gas = public_call.call_stack_item.public_inputs.start_gas_left;
let tx_gas_limits = previous_kernel.public_inputs.constants.tx_context.gas_settings.gas_limits;
let computed_start_gas = tx_gas_limits.sub(previous_kernel.public_inputs.end.gas_used).sub(previous_kernel.public_inputs.end_non_revertible.gas_used);
assert(
public_call_start_gas == computed_start_gas, "Start gas for public phase does not match transaction gas left"
);
// If this is a nested call (not an execution request), the start gas is correct as long as the
// call being processed by this kernel iteration matches the call at the top of the callstack
// as per the previous kernel's outputs.
// An execution request's start gas is the remaining gas left in the transaction after the previous kernel.
// A nested call's start gas is the gas allocated to it by its caller and placed in the callstack.
if (public_call.call_stack_item.is_execution_request) {
let public_call_start_gas = public_call.call_stack_item.public_inputs.start_gas_left;
let tx_gas_limits = previous_kernel.public_inputs.constants.tx_context.gas_settings.gas_limits;
let computed_start_gas = tx_gas_limits.sub(previous_kernel.public_inputs.end.gas_used).sub(previous_kernel.public_inputs.end_non_revertible.gas_used);
assert(
public_call_start_gas == computed_start_gas, "Start gas for public phase does not match transaction gas left"
);
}
}

// Validates the transaction fee injected into the app circuit is zero for non-teardown phases
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ mod tests {
fn validates_start_gas() {
let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new();

builder.public_call.is_execution_request = true; // don't need to check start gas for nested calls
builder.public_call.public_inputs.start_gas_left = Gas::new(100, 100);

builder.failed();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ mod tests {
fn validates_start_gas() {
let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new();

builder.public_call.is_execution_request = true; // don't need to check start gas for nested calls
builder.public_call.public_inputs.start_gas_left = Gas::new(100, 100);

builder.failed();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,18 @@ impl PublicKernelTeardownCircuitPrivateInputs {

// Validates that the start gas injected into the app circuit matches the teardown gas limits set by the user
fn validate_start_gas(self) {
let public_call_start_gas = self.public_call.call_stack_item.public_inputs.start_gas_left;
let teardown_gas_limit = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.teardown_gas_limits;
assert(
public_call_start_gas == teardown_gas_limit, "Start gas for teardown phase does not match teardown gas allocation"
);
// If this is a nested call (not an execution request), the start gas is correct as long as the
// call being processed by this kernel iteration matches the call at the top of the callstack
// as per the previous kernel's outputs.
// An execution request's start gas is the remaining gas left in the transaction after the previous kernel.
// A nested call's start gas is the gas allocated to it by its caller and placed in the callstack.
if (self.public_call.call_stack_item.is_execution_request) {
let public_call_start_gas = self.public_call.call_stack_item.public_inputs.start_gas_left;
let teardown_gas_limit = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.teardown_gas_limits;
assert(
public_call_start_gas == teardown_gas_limit, "Start gas for teardown phase does not match teardown gas allocation"
);
}
}

// Validates the transaction fee injected into the app circuit is properly computed from gas_used and block gas_fees
Expand Down Expand Up @@ -413,6 +420,8 @@ mod tests {
#[test(should_fail_with="Start gas for teardown phase does not match teardown gas allocation")]
fn validates_start_gas() {
let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new();

builder.public_call.is_execution_request = true; // don't need to check start gas for nested calls
builder.public_call.public_inputs.start_gas_left = Gas::new(10, 30);

builder.failed();
Expand Down

0 comments on commit 03fa539

Please sign in to comment.