Skip to content

Commit

Permalink
feat: Wire AVM gas used to public kernel (#5740)
Browse files Browse the repository at this point in the history
Starts wiring gas settings and usage across application and kernel
circuits, tracking L2 gas used in the AVM first. This required the
following changes to structs:
- `PublicCircuitPublicInputs` now includes a `gas_left` to report how
much was left at the end of their execution, as a means to report how
much was used.
- `CallContext` now includes a `gas_left` to inform the app circuit
(private or public) how much gas it has available for execution.
- `TxRequest` and `TxExecutionRequest` include a `GasSettings` so the
user can specify their gas limits and max fees when creating a new tx.

Other changes:
- Renamed `GasUsed` struct to just `Gas` since it's used for tracking
gas used and for tracking gas left depending on the context.
- `FeePaymentMethod.getFunctionCalls` now accepts a `GasSettings`
instead of a flat MaxFee, though the max fee can be calculated from the
gas settings.
  • Loading branch information
spalladino authored Apr 16, 2024
1 parent d37cbb9 commit 4f55d10
Show file tree
Hide file tree
Showing 95 changed files with 851 additions and 440 deletions.
5 changes: 4 additions & 1 deletion docs/docs/protocol-specs/circuits/private-function.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ After generating a proof for a private function circuit, that proof (and associa
| `portal_contract_address` | `AztecAddress` | Address of the portal contract to the storage contract. |
| `is_delegate_call` | `bool` | A flag indicating whether the call is a [delegate call](../calls/delegate-calls.md). |
| `is_static_call` | `bool` | A flag indicating whether the call is a [static call](../calls/static-calls.md). |
| `gas_settings` | [`GasSettings`](#gassettings) | Limits and max fees per each gas dimension. |
| `gas_settings` | [`GasSettings`](#gassettings) | User-defined limits and max fees per each gas dimension for the transaction. |
| `gas_left.da_gas` | `u32` | How much DA gas is available for this call. |
| `gas_left.l1_gas` | `u32` | How much L1 gas is available for this call. |
| `gas_left.l2_gas` | `u32` | How much L2 gas is available for this call. |
| `transaction_fee` | `field` | Accumulated transaction fee, only set during teardown phase. |

### `GasSettings`
Expand Down
19 changes: 19 additions & 0 deletions docs/docs/protocol-specs/circuits/private-kernel-initial.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,11 @@ class TransactionRequest {
function_data: FunctionData
args_hash: field
tx_context: TransactionContext
gas_settings: GasSettings
}
TransactionRequest *-- FunctionData: function_data
TransactionRequest *-- TransactionContext: tx_context
TransactionRequest *-- GasSettings: gas_settings
TransactionRequest ..> ConstantData: tx_context
Expand Down Expand Up @@ -428,6 +430,19 @@ class FunctionData {
function_type: private|public
}
class GasSettings {
da.gas_limit: u32
da.teardown_gas_limit: u32
da.max_fee_per_gas: Fr
l1.gas_limit: u32
l1.teardown_gas_limit: u32
l1.max_fee_per_gas: Fr
l2.gas_limit: u32
l2.teardown_gas_limit: u32
l2.max_fee_per_gas: Fr
inclusion_fee: Fr
}
class PrivateFunctionPublicInputs {
call_context: CallContext
args_hash: field
Expand Down Expand Up @@ -478,6 +493,9 @@ class CallContext {
portal_contract_address: AztecAddress
is_delegate_call: bool
is_static_call: bool
gas_left: Gas
gas_settings: GasSettings
transaction_fee: field
}
CallContext ..> CallerContext : call_context
Expand Down Expand Up @@ -702,6 +720,7 @@ Data that represents the caller's intent.
| `function_data` | [`FunctionData`](#functiondata) | Data of the function being called. |
| `args_hash` | `field` | Hash of the function arguments. |
| `tx_context` | [`TransactionContext`](#transactioncontext) | Information about the transaction. |
| `gas_settings` | [`GasSettings`](#gassettings) | User-defined gas limits and max fees. |

### `PrivateCall`

Expand Down
18 changes: 18 additions & 0 deletions docs/docs/protocol-specs/circuits/private-kernel-inner.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,11 @@ class TransactionRequest {
function_data: FunctionData
args_hash: field
tx_context: TransactionContext
gas_settings: GasSettings
}
TransactionRequest *-- FunctionData: function_data
TransactionRequest *-- TransactionContext: tx_context
TransactionRequest *-- GasSettings: gas_settings

TransactionRequest ..> ConstantData: tx_context

Expand Down Expand Up @@ -224,6 +226,19 @@ class FunctionData {
function_type: private|public
}

class GasSettings {
da.gas_limit: u32
da.teardown_gas_limit: u32
da.max_fee_per_gas: Fr
l1.gas_limit: u32
l1.teardown_gas_limit: u32
l1.max_fee_per_gas: Fr
l2.gas_limit: u32
l2.teardown_gas_limit: u32
l2.max_fee_per_gas: Fr
inclusion_fee: Fr
}

class PrivateFunctionPublicInputs {
call_context: CallContext
args_hash: field
Expand Down Expand Up @@ -276,6 +291,9 @@ class CallContext {
portal_contract_address: AztecAddress
is_delegate_call: bool
is_static_call: bool
gas_left: Gas
gas_settings: GasSettings
transaction_fee: field
}
CallContext ..> CallerContext : call_context

Expand Down
16 changes: 8 additions & 8 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,18 @@ library Constants {
uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE =
0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631;
uint256 internal constant DEPLOYER_CONTRACT_ADDRESS =
0x1b02447505c1781a416a5f44bc5be922f0d2f709e0996877f673a86bd49f79f4;
0x2d8e7aedc70b65d49e6aa0794d8d12721896c177e87126701f6e60d184358e74;
uint256 internal constant L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 17;
uint256 internal constant MAX_NOTE_FIELDS_LENGTH = 20;
uint256 internal constant GET_NOTE_ORACLE_RETURN_LENGTH = 23;
uint256 internal constant MAX_NOTES_PER_PAGE = 10;
uint256 internal constant VIEW_NOTE_ORACLE_RETURN_LENGTH = 212;
uint256 internal constant AZTEC_ADDRESS_LENGTH = 1;
uint256 internal constant CALL_CONTEXT_LENGTH = 18;
uint256 internal constant CALL_CONTEXT_LENGTH = 21;
uint256 internal constant GAS_SETTINGS_LENGTH = 10;
uint256 internal constant DIMENSION_GAS_SETTINGS_LENGTH = 3;
uint256 internal constant GAS_FEES_LENGTH = 3;
uint256 internal constant GAS_USED_LENGTH = 3;
uint256 internal constant GAS_LENGTH = 3;
uint256 internal constant CONTENT_COMMITMENT_LENGTH = 4;
uint256 internal constant CONTRACT_INSTANCE_LENGTH = 6;
uint256 internal constant CONTRACT_STORAGE_READ_LENGTH = 2;
Expand All @@ -110,13 +110,13 @@ library Constants {
uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4;
uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5;
uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6;
uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 221;
uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 218;
uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 209;
uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 224;
uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 221;
uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 215;
uint256 internal constant STATE_REFERENCE_LENGTH = 8;
uint256 internal constant TX_CONTEXT_DATA_LENGTH = 4;
uint256 internal constant TX_REQUEST_LENGTH = 8;
uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 22;
uint256 internal constant TX_REQUEST_LENGTH = 18;
uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 25;
uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674;
uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048;
uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::context::globals::public_global_variables::PublicGlobalVariables;

use dep::protocol_types::{abis::call_context::CallContext, header::Header, traits::Empty};
use dep::protocol_types::{abis::call_context::CallContext, abis::gas::Gas, header::Header, traits::Empty};

// PublicContextInputs are expected to be provided to each public function
// docs:start:public-context-inputs
Expand All @@ -23,4 +23,4 @@ impl Empty for PublicContextInputs {
start_side_effect_counter: 0 as u32,
}
}
}
}
8 changes: 5 additions & 3 deletions noir-projects/aztec-nr/aztec/src/context/private_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ use crate::{
};
use dep::protocol_types::{
abis::{
call_context::CallContext, function_data::FunctionData, function_selector::FunctionSelector,
max_block_number::MaxBlockNumber, nullifier_key_validation_request::NullifierKeyValidationRequest,
gas::Gas, call_context::CallContext, function_data::FunctionData,
function_selector::FunctionSelector, max_block_number::MaxBlockNumber,
nullifier_key_validation_request::NullifierKeyValidationRequest,
private_call_stack_item::PrivateCallStackItem,
private_circuit_public_inputs::PrivateCircuitPublicInputs,
public_call_stack_item::PublicCallStackItem,
Expand Down Expand Up @@ -494,7 +495,8 @@ impl PrivateContext {
unencrypted_log_preimages_length: 0,
historical_header: Header::empty(),
prover_address: AztecAddress::zero(),
revert_code: 0
revert_code: 0,
gas_left: Gas::empty()
},
is_execution_request: true
};
Expand Down
3 changes: 2 additions & 1 deletion noir-projects/aztec-nr/aztec/src/context/public_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ impl PublicContext {
unencrypted_log_preimages_length,
historical_header: self.inputs.historical_header,
prover_address: self.prover_address,
revert_code: 0
revert_code: 0,
gas_left: self.inputs.call_context.gas_left
};
pub_circuit_pub_inputs
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use dep::aztec::context::PublicContext;
use dep::aztec::protocol_types::hash::sha256_to_field;

pub fn calculate_fee(_context: PublicContext) -> U128 {
// TODO(palla/gas-in-circuits): Use the transaction_fee injected into the context
U128::from_integer(1)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl PrivateKernelInitCircuitPrivateInputs {
public_inputs.constants = CombinedConstantData {
historical_header: self.private_call.call_stack_item.public_inputs.historical_header,
tx_context: self.tx_request.tx_context,
gas_settings: GasSettings::empty(), // TODO(palla/gas-in-circuits)
gas_settings: self.tx_request.gas_settings,
};
public_inputs.min_revertible_side_effect_counter = self.private_call.call_stack_item.public_inputs.min_revertible_side_effect_counter;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ pub fn initialize_end_values(
) {
initialize_emitted_end_values(previous_kernel, circuit_outputs);

// Copy gas-used as-is. Gas used in this iteration will be deducted later in update_(non)_revertible_gas_used.
circuit_outputs.end.gas_used = previous_kernel.public_inputs.end.gas_used;
circuit_outputs.end_non_revertible.gas_used = previous_kernel.public_inputs.end_non_revertible.gas_used;

if circuit_outputs.revert_code == 0 {
let start = previous_kernel.public_inputs.end;
circuit_outputs.end.public_call_stack = array_to_bounded_vec(start.public_call_stack);
Expand Down Expand Up @@ -169,6 +173,60 @@ pub fn update_validation_requests(public_call: PublicCallData, circuit_outputs:
propagate_valid_public_data_reads(public_call, circuit_outputs);
}

pub fn update_revertible_gas_used(public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder) {
let tx_gas_limits = circuit_outputs.constants.gas_settings.get_gas_limits();
let call_gas_left = public_call.call_stack_item.public_inputs.gas_left;
let accum_end_non_revertible_gas_used = circuit_outputs.end_non_revertible.gas_used;

// dep::types::debug_log::debug_log_format(
// "Updating revertible gas: limit.da={0} limit.l1={1} limit.l2={2} left.da={3} left.l1={4} left.l2={5} used.da={6} used.l1={7} used.l2={8}",
// [
// tx_gas_limits.da_gas as Field,
// tx_gas_limits.l1_gas as Field,
// tx_gas_limits.l2_gas as Field,
// call_gas_left.da_gas as Field,
// call_gas_left.l1_gas as Field,
// call_gas_left.l2_gas as Field,
// accum_end_non_revertible_gas_used.da_gas as Field,
// accum_end_non_revertible_gas_used.l1_gas as Field,
// accum_end_non_revertible_gas_used.l2_gas as Field
// ]
// );

circuit_outputs.end.gas_used = tx_gas_limits
.sub(call_gas_left)
.sub(accum_end_non_revertible_gas_used);
}

pub fn update_non_revertible_gas_used(public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder) {
let tx_gas_limits = circuit_outputs.constants.gas_settings.get_gas_limits();
let call_gas_left = public_call.call_stack_item.public_inputs.gas_left;
let accum_end_gas_used = circuit_outputs.end.gas_used;

// dep::types::debug_log::debug_log_format(
// "Updating non-revertible gas: limit.da={0} limit.l1={1} limit.l2={2} left.da={3} left.l1={4} left.l2={5} used.da={6} used.l1={7} used.l2={8}",
// [
// tx_gas_limits.da_gas as Field,
// tx_gas_limits.l1_gas as Field,
// tx_gas_limits.l2_gas as Field,
// call_gas_left.da_gas as Field,
// call_gas_left.l1_gas as Field,
// call_gas_left.l2_gas as Field,
// accum_end_gas_used.da_gas as Field,
// accum_end_gas_used.l1_gas as Field,
// accum_end_gas_used.l2_gas as Field
// ]
// );

// println(
// f"Updating non-revertible gas: tx_gas_limits={tx_gas_limits} call_gas_left={call_gas_left} accum_end_gas_used={accum_end_gas_used}"
// );

circuit_outputs.end_non_revertible.gas_used = tx_gas_limits
.sub(call_gas_left)
.sub(accum_end_gas_used);
}

pub fn update_public_end_non_revertible_values(
public_call: PublicCallData,
circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ impl PublicKernelAppLogicCircuitPrivateInputs {

common::update_validation_requests(self.public_call, &mut public_inputs);

common::update_revertible_gas_used(self.public_call, &mut public_inputs);

if public_inputs.revert_code == 0 {
// Pops the item from the call stack and validates it against the current execution.
let call_request = public_inputs.end.public_call_stack.pop();
Expand Down Expand Up @@ -75,9 +77,9 @@ mod tests {
};
use dep::types::{
abis::{
kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, public_data_read::PublicDataRead,
public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequest,
side_effect::{SideEffect, SideEffectLinkedToNoteHash}
gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs,
public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest,
read_request::ReadRequest, side_effect::{SideEffect, SideEffectLinkedToNoteHash}
},
address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId,
hash::{compute_l2_to_l1_hash, compute_logs_hash, silo_note_hash, silo_nullifier},
Expand Down Expand Up @@ -448,4 +450,28 @@ mod tests {
assert_eq(request_context.counter, request_1.counter);
assert_eq(request_context.contract_address, storage_contract_address);
}

#[test]
fn updates_revertible_gas_used() {
let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new();

// Transaction gas limit is 1k
builder.previous_kernel.gas_settings.da.gas_limit = 1000;
builder.previous_kernel.gas_settings.l1.gas_limit = 1000;
builder.previous_kernel.gas_settings.l2.gas_limit = 1000;

// Revertible has already used 300
builder.previous_kernel.gas_used = Gas::new(300, 300, 300);

// This call starts with 700 gas left
builder.public_call.public_inputs.call_context.gas_left = Gas::new(700, 700, 700);

// And uses 200, ending with 500 left
builder.public_call.public_inputs.gas_left = Gas::new(500, 500, 500);

// So the updated gas used by revertible must go up by 200, and non-revertible must stay the same
let output = builder.execute();
assert_eq(output.end.gas_used, Gas::new(500, 500, 500));
assert_eq(output.end_non_revertible.gas_used, Gas::new(0, 0, 0));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ impl PublicKernelSetupCircuitPrivateInputs {
// validate the inputs unique to having a previous private kernel
self.validate_inputs();

common::update_non_revertible_gas_used(self.public_call, &mut public_inputs);

// Pops the item from the call stack and validates it against the current execution.
let call_request = public_inputs.end_non_revertible.public_call_stack.pop();
common::validate_call_against_request(self.public_call, call_request);
Expand Down Expand Up @@ -68,7 +70,7 @@ mod tests {
};
use dep::types::{
abis::{
call_request::CallRequest, function_selector::FunctionSelector,
call_request::CallRequest, function_selector::FunctionSelector, gas::Gas,
kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, max_block_number::MaxBlockNumber,
public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest,
public_call_data::PublicCallData, read_request::ReadRequest
Expand Down Expand Up @@ -496,4 +498,31 @@ mod tests {

builder.failed();
}

#[test]
fn updates_non_revertible_gas_used() {
let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new();

// Transaction gas limit is 1k
builder.previous_kernel.gas_settings.da.gas_limit = 1000;
builder.previous_kernel.gas_settings.l1.gas_limit = 1000;
builder.previous_kernel.gas_settings.l2.gas_limit = 1000;

// Revertible has already used 100
builder.previous_revertible.gas_used = Gas::new(100, 100, 100);

// And non-revertible has used another 200
builder.previous_kernel.gas_used = Gas::new(200, 200, 200);

// So this call starts with 700 gas left
builder.public_call.public_inputs.call_context.gas_left = Gas::new(700, 700, 700);

// And uses 300, ending with 400 left
builder.public_call.public_inputs.gas_left = Gas::new(400, 400, 400);

// So the updated gas used by non-revertible must go up by 300, and revertible must stay the same
let output = builder.execute();
assert_eq(output.end_non_revertible.gas_used, Gas::new(500, 500, 500));
assert_eq(output.end.gas_used, Gas::new(100, 100, 100));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ mod private_circuit_public_inputs;

mod gas_fees;
mod gas_settings;
mod gas_used;
mod gas;
Loading

0 comments on commit 4f55d10

Please sign in to comment.