Skip to content

Commit

Permalink
feat: contract storage reads serialize with side effect counter (#6961)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanks12 authored Jun 7, 2024
1 parent 662187d commit db49ed5
Show file tree
Hide file tree
Showing 14 changed files with 39 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector<FF> const& public_in
// slot, value, side effect
ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset];
ko_values[dest_offset] = public_inputs_vec[pcpi_offset + 1];
// TODO(md): serialize side effect in ts
// ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2];
ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2];
}
// For EMITNOTEHASH
for (size_t i = 0; i < MAX_NEW_NOTE_HASHES_PER_CALL; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#define GAS_LENGTH 2
#define CALL_CONTEXT_LENGTH 6
#define CONTENT_COMMITMENT_LENGTH 4
#define CONTRACT_STORAGE_READ_LENGTH 2
#define CONTRACT_STORAGE_READ_LENGTH 3
#define CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH 3
#define GLOBAL_VARIABLES_LENGTH 8
#define APPEND_ONLY_TREE_SNAPSHOT_LENGTH 2
Expand All @@ -30,5 +30,5 @@
#define STATE_REFERENCE_LENGTH 8
#define TOTAL_FEES_LENGTH 1
#define HEADER_LENGTH 23
#define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 514
#define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 530
#define PUBLIC_CONTEXT_INPUTS_LENGTH 41
4 changes: 2 additions & 2 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ library Constants {
uint256 internal constant CALL_CONTEXT_LENGTH = 6;
uint256 internal constant CONTENT_COMMITMENT_LENGTH = 4;
uint256 internal constant CONTRACT_INSTANCE_LENGTH = 5;
uint256 internal constant CONTRACT_STORAGE_READ_LENGTH = 2;
uint256 internal constant CONTRACT_STORAGE_READ_LENGTH = 3;
uint256 internal constant CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 3;
uint256 internal constant ETH_ADDRESS_LENGTH = 1;
uint256 internal constant FUNCTION_DATA_LENGTH = 2;
Expand Down Expand Up @@ -148,7 +148,7 @@ library Constants {
uint256 internal constant TOTAL_FEES_LENGTH = 1;
uint256 internal constant HEADER_LENGTH = 23;
uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 457;
uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 514;
uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 530;
uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 460;
uint256 internal constant PUBLIC_CONTEXT_INPUTS_LENGTH = 41;
uint256 internal constant AGGREGATION_OBJECT_LENGTH = 16;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,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 = 0x1f0e71146c5d4a5bdcf517f0063cda7767e51fcb9cebc877feb348a77a7a6b4a;
let test_data_call_stack_item_request_hash = 0x124a62189073cc551fea148d735d1e8b452e38537e075895b02ccfd9c9901819;
assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);
}

Expand All @@ -87,7 +87,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 = 0x079a2b28b4853de9169d7dc40ac41c6d80b465d82c60195ede91504013f8b11b;
let test_data_call_stack_item_hash = 0x2cbb07062730bfc4933f5e8d533d5b62ac6e1b7922b831993377cd85d7445399;
assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,6 @@ fn empty_hash() {
let hash = inputs.hash();

// Value from public_circuit_public_inputs.test.ts "computes empty item hash" test
let test_data_empty_hash = 0x0933cf2bb384c9733d5a8311bfdc089489c2557df2265026579f9ac2b21d2ef9;
let test_data_empty_hash = 0x03ab5026ab5b3e6b81be5c3ec31c7937f293180c25a240eb75693cda81bb2a05;
assert_eq(hash, test_data_empty_hash);
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ global GAS_SETTINGS_LENGTH: u32 = GAS_LENGTH * 2 + GAS_FEES_LENGTH + /* inclusio
global CALL_CONTEXT_LENGTH: u32 = 6;
global CONTENT_COMMITMENT_LENGTH: u32 = 4;
global CONTRACT_INSTANCE_LENGTH: u32 = 5;
global CONTRACT_STORAGE_READ_LENGTH: u32 = 2;
global CONTRACT_STORAGE_READ_LENGTH: u32 = 3;
global CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: u32 = 3;
global ETH_ADDRESS_LENGTH = 1;
global FUNCTION_DATA_LENGTH: u32 = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ use crate::{
struct StorageRead {
storage_slot: Field,
current_value: Field,
// TODO(dbanks12): use side effects properly in kernel checks
counter: u32,
}

impl Eq for StorageRead {
fn eq(self, other: Self) -> bool {
(self.storage_slot == other.storage_slot) & (self.current_value == other.current_value)
(self.storage_slot == other.storage_slot) & (self.current_value == other.current_value) & (self.current_value == other.current_value)
}
}

Expand All @@ -19,6 +21,7 @@ impl Empty for StorageRead {
Self {
storage_slot: 0,
current_value: 0,
counter: 0,
}
}
}
Expand All @@ -31,7 +34,7 @@ impl Hash for StorageRead {

impl Serialize<CONTRACT_STORAGE_READ_LENGTH> for StorageRead {
fn serialize(self) -> [Field; CONTRACT_STORAGE_READ_LENGTH] {
[self.storage_slot, self.current_value]
[self.storage_slot, self.current_value, self.counter as Field]
}
}

Expand All @@ -40,13 +43,14 @@ impl Deserialize<CONTRACT_STORAGE_READ_LENGTH> for StorageRead {
Self {
storage_slot: serialized[0],
current_value: serialized[1],
counter: serialized[2] as u32,
}
}
}

impl StorageRead {
pub fn is_empty(self) -> bool {
self.storage_slot == 0
(self.storage_slot == 0) & (self.current_value == 0) & (self.counter == 0)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ impl PublicCallDataBuilder {
// The default storage slot is its index + 1.
storage_slot: (value_offset + i + 1) as Field,
// The default value is its index + 999.
current_value: (value_offset + i + 999) as Field
current_value: (value_offset + i + 999) as Field,
counter: i as u32
};
self.public_inputs.contract_storage_reads.push(read_request);
}
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/circuits.js/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const GAS_SETTINGS_LENGTH = 7;
export const CALL_CONTEXT_LENGTH = 6;
export const CONTENT_COMMITMENT_LENGTH = 4;
export const CONTRACT_INSTANCE_LENGTH = 5;
export const CONTRACT_STORAGE_READ_LENGTH = 2;
export const CONTRACT_STORAGE_READ_LENGTH = 3;
export const CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 3;
export const ETH_ADDRESS_LENGTH = 1;
export const FUNCTION_DATA_LENGTH = 2;
Expand Down Expand Up @@ -132,7 +132,7 @@ export const TX_REQUEST_LENGTH = 13;
export const TOTAL_FEES_LENGTH = 1;
export const HEADER_LENGTH = 23;
export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 457;
export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 514;
export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 530;
export const PRIVATE_CALL_STACK_ITEM_LENGTH = 460;
export const PUBLIC_CONTEXT_INPUTS_LENGTH = 41;
export const AGGREGATION_OBJECT_LENGTH = 16;
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`] = `"0x079a2b28b4853de9169d7dc40ac41c6d80b465d82c60195ede91504013f8b11b"`;
exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x2cbb07062730bfc4933f5e8d533d5b62ac6e1b7922b831993377cd85d7445399"`;

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

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

exports[`PublicCallStackItem computes hash 1`] = `Fr<0x1f73cf733bf4e60f76427159b1973ed07f9893912a45bbd9b97e497742df4aa5>`;
exports[`PublicCallStackItem computes hash 1`] = `Fr<0x1943f02bfc111012aa1f28688425817d45653586f0c4665feb6723c9b539e147>`;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x0933cf2bb384c9733d5a8311bfdc089489c2557df2265026579f9ac2b21d2ef9>`;
exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x03ab5026ab5b3e6b81be5c3ec31c7937f293180c25a240eb75693cda81bb2a05>`;

exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x07eedf68666e5f27b2a22040daeb9049e3e5181a50183dcdccc5eb23e3d1fe54>`;
exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x17c2cd1141dbec7dd8598fee17e90627d0e843e7991533d4378191cea7c2abad>`;
23 changes: 11 additions & 12 deletions yarn-project/circuits.js/src/structs/contract_storage_read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@ export class ContractStorageRead {
*/
public readonly currentValue: Fr,
/**
* TODO: WILL NEED THIS for vm? why are these not serialised?
* Optional side effect counter tracking position of this event in tx execution.
* Note: Not serialized
* Side effect counter tracking position of this event in tx execution.
*/
public readonly sideEffectCounter?: number,
public readonly sideEffectCounter: number,
public contractAddress?: AztecAddress, // TODO: Should not be optional. This is a temporary hack to silo the storage slot with the correct address for nested executions.
) {}

Expand All @@ -39,37 +37,37 @@ export class ContractStorageRead {
*/
currentValue: Fr;
/**
* Optional side effect counter tracking position of this event in tx execution.
* Side effect counter tracking position of this event in tx execution.
*/
sideEffectCounter?: number;
sideEffectCounter: number;
contractAddress?: AztecAddress;
}) {
return new ContractStorageRead(args.storageSlot, args.currentValue, args.sideEffectCounter, args.contractAddress);
}

toBuffer() {
return serializeToBuffer(this.storageSlot, this.currentValue);
return serializeToBuffer(this.storageSlot, this.currentValue, new Fr(this.sideEffectCounter));
}

static fromBuffer(buffer: Buffer | BufferReader) {
const reader = BufferReader.asReader(buffer);
return new ContractStorageRead(Fr.fromBuffer(reader), Fr.fromBuffer(reader));
return new ContractStorageRead(Fr.fromBuffer(reader), Fr.fromBuffer(reader), Fr.fromBuffer(reader).toNumber());
}

static empty() {
return new ContractStorageRead(Fr.ZERO, Fr.ZERO);
return new ContractStorageRead(Fr.ZERO, Fr.ZERO, 0);
}

isEmpty() {
return this.storageSlot.isZero() && this.currentValue.isZero();
return this.storageSlot.isZero() && this.currentValue.isZero() && this.sideEffectCounter == 0;
}

toFriendlyJSON() {
return `Slot=${this.storageSlot.toFriendlyJSON()}: ${this.currentValue.toFriendlyJSON()}`;
}

toFields(): Fr[] {
const fields = [this.storageSlot, this.currentValue];
const fields = [this.storageSlot, this.currentValue, new Fr(this.sideEffectCounter)];
if (fields.length !== CONTRACT_STORAGE_READ_LENGTH) {
throw new Error(
`Invalid number of fields for ContractStorageRead. Expected ${CONTRACT_STORAGE_READ_LENGTH}, got ${fields.length}`,
Expand All @@ -83,7 +81,8 @@ export class ContractStorageRead {

const storageSlot = reader.readField();
const currentValue = reader.readField();
const sideEffectCounter = reader.readField().toNumber();

return new ContractStorageRead(storageSlot, currentValue);
return new ContractStorageRead(storageSlot, currentValue, sideEffectCounter);
}
}
2 changes: 1 addition & 1 deletion yarn-project/circuits.js/src/tests/factories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ export function makeContractStorageUpdateRequest(seed = 1): ContractStorageUpdat
* @returns A contract storage read.
*/
export function makeContractStorageRead(seed = 1): ContractStorageRead {
return new ContractStorageRead(fr(seed), fr(seed + 1));
return new ContractStorageRead(fr(seed), fr(seed + 1), seed + 2);
}

export function makeValidationRequests(seed = 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1855,6 +1855,7 @@ export function mapStorageReadToNoir(storageRead: ContractStorageRead): StorageR
return {
storage_slot: mapFieldToNoir(storageRead.storageSlot),
current_value: mapFieldToNoir(storageRead.currentValue),
counter: mapNumberToNoir(storageRead.sideEffectCounter),
};
}
/**
Expand Down

0 comments on commit db49ed5

Please sign in to comment.