Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(public-kernel): only validate start-gas for execution requests #6100

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,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 @@ -416,6 +423,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
Loading