Skip to content

Commit

Permalink
fix: include return, revert and gas in compressed call stack item
Browse files Browse the repository at this point in the history
  • Loading branch information
LHerskind committed Jul 5, 2024
1 parent 1834b8b commit a77b618
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 46 deletions.
8 changes: 4 additions & 4 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ library Constants {
uint256 internal constant SCOPED_ENCRYPTED_LOG_HASH_LENGTH = 5;
uint256 internal constant NOTE_LOG_HASH_LENGTH = 4;
uint256 internal constant NOTE_HASH_LENGTH = 2;
uint256 internal constant SCOPED_NOTE_HASH_LENGTH = 4;
uint256 internal constant SCOPED_NOTE_HASH_LENGTH = 3;
uint256 internal constant NULLIFIER_LENGTH = 3;
uint256 internal constant SCOPED_NULLIFIER_LENGTH = 4;
uint256 internal constant CALLER_CONTEXT_LENGTH = 3;
Expand All @@ -165,10 +165,10 @@ library Constants {
uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3;
uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 333;
uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = 40;
uint256 internal constant PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 10;
uint256 internal constant PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 16;
uint256 internal constant CALL_REQUEST_LENGTH = 7;
uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1232;
uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2307;
uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1168;
uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2243;
uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 983;
uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3258;
uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 383;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct PublicCallStackItem {

impl PublicCallStackItem {
fn as_execution_request(self) -> Self {
// WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`
// WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.getCompressed()`
let public_inputs = self.public_inputs;
let mut request_public_inputs = PublicCircuitPublicInputs::empty();
request_public_inputs.call_context = public_inputs.call_context;
Expand All @@ -33,11 +33,21 @@ impl PublicCallStackItem {
}

fn get_compressed(self) -> PublicCallStackItemCompressed {
let item = if self.is_execution_request {
self.as_execution_request()
} else {
self
};

PublicCallStackItemCompressed {
contract_address: self.contract_address,
call_context: self.public_inputs.call_context,
function_data: self.function_data,
args_hash: self.public_inputs.args_hash
contract_address: item.contract_address,
call_context: item.public_inputs.call_context,
function_data: item.function_data,
args_hash: item.public_inputs.args_hash,
returns_hash: item.public_inputs.returns_hash,
revert_code: item.public_inputs.revert_code,
start_gas_left: item.public_inputs.start_gas_left,
end_gas_left: item.public_inputs.end_gas_left
}
}
}
Expand Down Expand Up @@ -66,7 +76,7 @@ mod tests {
let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };

// Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test
let test_data_call_stack_item_request_hash = 0x00ae3637b279ce8be67fd283808915bce72cb2943cb9bdbcb19d35cf8ca8fe9e;
let test_data_call_stack_item_request_hash = 0x1331fdec4ec7bd6bb23447c47753659b68e3a285d812ab6eaf9258a902d16e8e;
assert_eq(call_stack_item.get_compressed().hash(), test_data_call_stack_item_request_hash);
}

Expand All @@ -84,7 +94,7 @@ mod tests {
let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };

// Value from public_call_stack_item.test.ts "Computes a callstack item hash" test
let test_data_call_stack_item_hash = 0x00ae3637b279ce8be67fd283808915bce72cb2943cb9bdbcb19d35cf8ca8fe9e;
let test_data_call_stack_item_hash = 0x1331fdec4ec7bd6bb23447c47753659b68e3a285d812ab6eaf9258a902d16e8e;
assert_eq(call_stack_item.get_compressed().hash(), test_data_call_stack_item_hash);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::abis::{call_context::CallContext, function_data::FunctionData};
use crate::abis::{call_context::CallContext, function_data::FunctionData, gas::Gas};
use crate::address::AztecAddress;
use crate::constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH};
use crate::traits::{Hash, Empty, Serialize, Deserialize};
Expand All @@ -23,6 +23,10 @@ struct PublicCallStackItemCompressed {
call_context: CallContext,
function_data: FunctionData,
args_hash: Field,
returns_hash: Field,
revert_code: u8,
start_gas_left: Gas,
end_gas_left: Gas,
}

impl Eq for PublicCallStackItemCompressed {
Expand All @@ -31,29 +35,30 @@ impl Eq for PublicCallStackItemCompressed {
& (self.call_context == other.call_context)
& (self.function_data == other.function_data)
& (self.args_hash == other.args_hash)
& (self.returns_hash == other.returns_hash)
& (self.revert_code == other.revert_code)
& (self.start_gas_left == other.start_gas_left)
& (self.end_gas_left == other.end_gas_left)
}
}

impl Hash for PublicCallStackItemCompressed {
fn hash(self) -> Field {
let item = self;
std::hash::pedersen_hash_with_separator([
item.contract_address.to_field(),
item.call_context.hash(),
item.function_data.hash(),
item.args_hash,
], GENERATOR_INDEX__CALL_STACK_ITEM)
std::hash::pedersen_hash_with_separator(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)
}
}

impl Empty for PublicCallStackItemCompressed {

fn empty() -> Self {
PublicCallStackItemCompressed {
contract_address: AztecAddress::empty(),
call_context: CallContext::empty(),
function_data: FunctionData::empty(),
args_hash: 0,
returns_hash: 0,
revert_code: 0,
start_gas_left: Gas::empty(),
end_gas_left: Gas::empty(),
}
}
}
Expand All @@ -66,6 +71,10 @@ impl Serialize<PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH> for PublicCallStackItem
fields.extend_from_array(self.call_context.serialize());
fields.extend_from_array(self.function_data.serialize());
fields.push(self.args_hash);
fields.push(self.returns_hash);
fields.push(self.revert_code as Field);
fields.extend_from_array(self.start_gas_left.serialize());
fields.extend_from_array(self.end_gas_left.serialize());

assert_eq(fields.len(), PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH);

Expand All @@ -82,6 +91,10 @@ impl Deserialize<PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH> for PublicCallStackIt
call_context: reader.read_struct(CallContext::deserialize),
function_data: reader.read_struct(FunctionData::deserialize),
args_hash: reader.read(),
returns_hash: reader.read(),
revert_code: reader.read() as u8,
start_gas_left: reader.read_struct(Gas::deserialize),
end_gas_left: reader.read_struct(Gas::deserialize),
};
reader.finish();
item
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ global PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3;
global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + MAX_L2_TO_L1_MSGS_PER_TX + 6 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH;
global COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH;

global PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = AZTEC_ADDRESS_LENGTH + CALL_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH + 1;
global PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = AZTEC_ADDRESS_LENGTH + CALL_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH + 3 + 2 * GAS_LENGTH;
global CALL_REQUEST_LENGTH = 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + 2;
global PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_TX) + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (SCOPED_ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (SCOPED_LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + (SCOPED_PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX);
global PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH;
Expand Down
8 changes: 4 additions & 4 deletions yarn-project/circuits.js/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export const ENCRYPTED_LOG_HASH_LENGTH = 4;
export const SCOPED_ENCRYPTED_LOG_HASH_LENGTH = 5;
export const NOTE_LOG_HASH_LENGTH = 4;
export const NOTE_HASH_LENGTH = 2;
export const SCOPED_NOTE_HASH_LENGTH = 4;
export const SCOPED_NOTE_HASH_LENGTH = 3;
export const NULLIFIER_LENGTH = 3;
export const SCOPED_NULLIFIER_LENGTH = 4;
export const CALLER_CONTEXT_LENGTH = 3;
Expand All @@ -149,10 +149,10 @@ export const VALIDATION_REQUESTS_LENGTH = 1026;
export const PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3;
export const COMBINED_ACCUMULATED_DATA_LENGTH = 333;
export const COMBINED_CONSTANT_DATA_LENGTH = 40;
export const PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 10;
export const PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 16;
export const CALL_REQUEST_LENGTH = 7;
export const PRIVATE_ACCUMULATED_DATA_LENGTH = 1232;
export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2307;
export const PRIVATE_ACCUMULATED_DATA_LENGTH = 1168;
export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2243;
export const PUBLIC_ACCUMULATED_DATA_LENGTH = 983;
export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3258;
export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 383;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x00ae3637b279ce8be67fd283808915bce72cb2943cb9bdbcb19d35cf8ca8fe9e"`;
exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x1331fdec4ec7bd6bb23447c47753659b68e3a285d812ab6eaf9258a902d16e8e"`;

exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x00ae3637b279ce8be67fd283808915bce72cb2943cb9bdbcb19d35cf8ca8fe9e"`;
exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x1331fdec4ec7bd6bb23447c47753659b68e3a285d812ab6eaf9258a902d16e8e"`;

exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x00ccf05f0449b7f9f0e4b20585334b860596780a70e41b939f67731e6276fba1>`;
exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x077ecad5709816865f4c65422d74c646739f4177691a5d87c716219e72da0705>`;

exports[`PublicCallStackItem computes hash 1`] = `Fr<0x153cad9cc1e6d97618fd6f920ebe80a1e1cfc8a1f336aab769397e66729b1b33>`;
exports[`PublicCallStackItem computes hash 1`] = `Fr<0x2799d225e955c0d1db6fa7adb9be5cbd2ca760a48996443a629e01ce28a3919d>`;
24 changes: 22 additions & 2 deletions yarn-project/circuits.js/src/structs/public_call_stack_item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,31 @@ export class PublicCallStackItem {
}

getCompressed(): PublicCallStackItemCompressed {
let publicInputsToHash = this.publicInputs;
if (this.isExecutionRequest) {
// An execution request (such as an enqueued call from private) is hashed with
// only the publicInput members present in a PublicCallRequest.
// This allows us to check that the request (which is created/hashed before
// side-effects and output info are unknown for public calls) matches the call
// being processed by a kernel iteration.
// WARNING: This subset of publicInputs that is set here must align with
// `parse_public_call_stack_item_from_oracle` in enqueue_public_function_call.nr
// and `PublicCallStackItem::as_execution_request()` in public_call_stack_item.ts
const { callContext, argsHash } = this.publicInputs;
publicInputsToHash = PublicCircuitPublicInputs.empty();
publicInputsToHash.callContext = callContext;
publicInputsToHash.argsHash = argsHash;
}

return new PublicCallStackItemCompressed(
this.contractAddress,
this.publicInputs.callContext,
publicInputsToHash.callContext,
this.functionData,
this.publicInputs.argsHash,
publicInputsToHash.argsHash,
publicInputsToHash.returnsHash,
publicInputsToHash.revertCode,
publicInputsToHash.startGasLeft,
publicInputsToHash.endGasLeft,
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,53 @@
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { pedersenHash } from '@aztec/foundation/crypto';
import { Fr } from '@aztec/foundation/fields';
import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize';
import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize';
import { type FieldsOf } from '@aztec/foundation/types';

import { GeneratorIndex } from '../constants.gen.js';
import { GeneratorIndex, PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH } from '../constants.gen.js';
import { CallContext } from './call_context.js';
import { FunctionData } from './function_data.js';
import { Gas } from './gas.js';
import { RevertCode } from './revert_code.js';

/**
* Call stack item on a public call.
* Compressed call stack item on a public call.
*/
export class PublicCallStackItemCompressed {
constructor(
public contractAddress: AztecAddress,
public callContext: CallContext,
public functionData: FunctionData,
public argsHash: Fr,
public returnsHash: Fr,
public revertCode: RevertCode,
/** How much gas was available for execution. */
public startGasLeft: Gas,
/** How much gas was left after execution. */
public endGasLeft: Gas,
) {}

static getFields(fields: FieldsOf<PublicCallStackItemCompressed>) {
return [fields.contractAddress, fields.callContext, fields.functionData, fields.argsHash] as const;
return [
fields.contractAddress,
fields.callContext,
fields.functionData,
fields.argsHash,
fields.returnsHash,
fields.revertCode,
fields.startGasLeft,
fields.endGasLeft,
] as const;
}

toFields(): Fr[] {
const fields = serializeToFields(...PublicCallStackItemCompressed.getFields(this));
if (fields.length !== PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH) {
throw new Error(
`Invalid number of fields for PublicCallStackItemCompressed. Expected ${PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH}, got ${fields.length}`,
);
}
return fields;
}

toBuffer() {
Expand All @@ -39,18 +66,26 @@ export class PublicCallStackItemCompressed {
reader.readObject(CallContext),
reader.readObject(FunctionData),
reader.readObject(Fr),
reader.readObject(Fr),
reader.readObject(RevertCode),
reader.readObject(Gas),
reader.readObject(Gas),
);
}

static fromFields(fields: Fr[] | FieldReader): PublicCallStackItemCompressed {
const reader = FieldReader.asReader(fields);

const contractAddress = AztecAddress.fromFields(reader);
const callContext = CallContext.fromFields(reader);
const functionData = FunctionData.fromFields(reader);
const argsHash = reader.readField();

return new PublicCallStackItemCompressed(contractAddress, callContext, functionData, argsHash);
return new PublicCallStackItemCompressed(
AztecAddress.fromFields(reader),
CallContext.fromFields(reader),
FunctionData.fromFields(reader),
reader.readField(),
reader.readField(),
RevertCode.fromFields(reader),
Gas.fromFields(reader),
Gas.fromFields(reader),
);
}

/**
Expand All @@ -63,6 +98,10 @@ export class PublicCallStackItemCompressed {
CallContext.empty(),
FunctionData.empty({ isPrivate: false }),
Fr.ZERO,
Fr.ZERO,
RevertCode.OK,
Gas.empty(),
Gas.empty(),
);
}

Expand All @@ -71,7 +110,11 @@ export class PublicCallStackItemCompressed {
this.contractAddress.isZero() &&
this.callContext.isEmpty() &&
this.functionData.isEmpty() &&
this.argsHash.isEmpty()
this.argsHash.isEmpty() &&
this.returnsHash.isEmpty() &&
this.revertCode === RevertCode.OK &&
this.startGasLeft.isEmpty() &&
this.endGasLeft.isEmpty()
);
}

Expand All @@ -80,9 +123,6 @@ export class PublicCallStackItemCompressed {
* @returns Hash.
*/
public hash() {
return pedersenHash(
[this.contractAddress, this.callContext.hash(), this.functionData.hash(), this.argsHash],
GeneratorIndex.CALL_STACK_ITEM,
);
return pedersenHash(this.toFields(), GeneratorIndex.CALL_STACK_ITEM);
}
}

0 comments on commit a77b618

Please sign in to comment.