Skip to content
Closed
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
33 changes: 13 additions & 20 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,38 +890,35 @@ fn handle_black_box_function(avm_instrs: &mut Vec<AvmInstruction>, operation: &B
),
}
}

/// Emit a storage write opcode
/// The current implementation writes an array of values into storage ( contiguous slots in memory )
fn handle_storage_write(
avm_instrs: &mut Vec<AvmInstruction>,
destinations: &Vec<ValueOrArray>,
inputs: &Vec<ValueOrArray>,
) {
assert!(inputs.len() == 2);
assert!(destinations.len() == 1);
assert!(destinations.is_empty());

let slot_offset_maybe = inputs[0];
let slot_offset = match slot_offset_maybe {
ValueOrArray::MemoryAddress(slot_offset) => slot_offset.0,
_ => panic!("ForeignCall address destination should be a single value"),
_ => panic!("Storage write address destination should be a single value"),
};

let src_offset_maybe = inputs[1];
let (src_offset, src_size) = match src_offset_maybe {
ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer.0, size),
_ => panic!("Storage write address inputs should be an array of values"),
let src_offset = match src_offset_maybe {
ValueOrArray::MemoryAddress(offset) => offset.0,
_ => panic!("Storage write address inputs should be a single value"),
};

avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::SSTORE,
indirect: Some(ZEROTH_OPERAND_INDIRECT),
indirect: Some(ALL_DIRECT),
operands: vec![
AvmOperand::U32 {
value: src_offset as u32,
},
AvmOperand::U32 {
value: src_size as u32,
},
AvmOperand::U32 {
value: slot_offset as u32,
},
Expand All @@ -937,32 +934,28 @@ fn handle_storage_read(
destinations: &Vec<ValueOrArray>,
inputs: &Vec<ValueOrArray>,
) {
// For the foreign calls we want to handle, we do not want inputs, as they are getters
assert!(inputs.len() == 2); // output, len - but we dont use this len - its for the oracle
assert!(inputs.len() == 1);
assert!(destinations.len() == 1);

let slot_offset_maybe = inputs[0];
let slot_offset = match slot_offset_maybe {
ValueOrArray::MemoryAddress(slot_offset) => slot_offset.0,
_ => panic!("ForeignCall address destination should be a single value"),
_ => panic!("Storage read address destination should be a single value"),
};

let dest_offset_maybe = destinations[0];
let (dest_offset, src_size) = match dest_offset_maybe {
ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer.0, size),
_ => panic!("Storage write address inputs should be an array of values"),
let dest_offset = match dest_offset_maybe {
ValueOrArray::MemoryAddress(slot_offset) => slot_offset.0,
_ => panic!("Storage read address inputs should be a single value"),
};

avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::SLOAD,
indirect: Some(SECOND_OPERAND_INDIRECT),
indirect: Some(ALL_DIRECT),
operands: vec![
AvmOperand::U32 {
value: slot_offset as u32,
},
AvmOperand::U32 {
value: src_size as u32,
},
AvmOperand::U32 {
value: dest_offset as u32,
},
Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ library Constants {
uint256 internal constant ARGS_HASH_CHUNK_COUNT = 32;
uint256 internal constant INITIAL_L2_BLOCK_NUM = 1;
uint256 internal constant BLOB_SIZE_IN_BYTES = 126976;
uint256 internal constant MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 9000;
uint256 internal constant MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 15000;
uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 500;
uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS = 500;
uint256 internal constant REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE =
Expand Down
24 changes: 17 additions & 7 deletions noir-projects/aztec-nr/aztec/src/oracle/storage.nr
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
use dep::protocol_types::traits::{Deserialize, Serialize};

#[oracle(storageRead)]
fn storage_read_oracle<N>(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}
fn storage_read_oracle(_storage_slot: Field) -> Field {}

unconstrained fn storage_read_oracle_wrapper<N>(_storage_slot: Field) -> [Field; N] {
storage_read_oracle(_storage_slot, N)
unconstrained fn storage_read_oracle_wrapper(storage_slot: Field) -> Field {
storage_read_oracle(storage_slot)
}

pub fn storage_read<N>(storage_slot: Field) -> [Field; N] {
storage_read_oracle_wrapper(storage_slot)
let mut ret: [Field; N] = [0; N];
for i in 0..N {
ret[i] = storage_read_oracle_wrapper(storage_slot + (i as Field));
}
ret
}

#[oracle(storageWrite)]
fn storage_write_oracle<N>(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}
fn storage_write_oracle(_storage_slot: Field, _value: Field) {}

unconstrained pub fn storage_write<N>(storage_slot: Field, fields: [Field; N]) {
let _hash = storage_write_oracle(storage_slot, fields);
unconstrained fn storage_write_oracle_wrapper(storage_slot: Field, value: Field) {
storage_write_oracle(storage_slot, value);
}

pub fn storage_write<N>(storage_slot: Field, fields: [Field; N]) {
for i in 0..N {
storage_write_oracle_wrapper(storage_slot + (i as Field), fields[i]);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
use dep::aztec::protocol_types::traits::{Serialize, Deserialize};

struct Note {
a: Field,
b: Field,
}

impl Serialize<2> for Note {
fn serialize(self) -> [Field; 2] {
[self.a, self.b]
}
}

impl Deserialize<2> for Note {
fn deserialize(wire: [Field; 2]) -> Note {
Note {a: wire[0], b: wire[1]}
}
}

contract AvmTest {
use crate::Note;

// Libs
use dep::aztec::state_vars::PublicMutable;
use dep::aztec::protocol_types::{address::{AztecAddress, EthAddress}, constants::L1_TO_L2_MESSAGE_LENGTH};
Expand All @@ -12,18 +33,35 @@ contract AvmTest {
fn constructor() {}

struct Storage {
owner: PublicMutable<AztecAddress>
single: PublicMutable<Field>,
list: PublicMutable<Note>,
}

#[aztec(public-vm)]
fn setStorageSingle(a: Field) {
storage.single.write(a);
}

#[aztec(public-vm)]
fn readStorageSingle() -> pub Field {
storage.single.read()
}

#[aztec(public-vm)]
fn setReadStorageSingle(a: Field) -> pub Field {
storage.single.write(a);
storage.single.read()
}

#[aztec(public-vm)]
fn setAdmin() {
storage.owner.write(context.sender());
fn setStorageList(a: Field, b: Field) {
storage.list.write(Note { a, b });
}

#[aztec(public-vm)]
fn setAndRead() -> pub AztecAddress {
storage.owner.write(context.sender());
storage.owner.read()
fn readStorageList() -> pub [Field; 2] {
let note: Note = storage.list.read();
note.serialize()
}

#[aztec(public-vm)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ global INITIAL_L2_BLOCK_NUM: Field = 1;
global BLOB_SIZE_IN_BYTES: Field = 126976;

// CONTRACT CLASS CONSTANTS
global MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u64 = 9000;
global MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u64 = 15000;
// Bytecode size for private functions is per function, not for the entire contract.
// Note that private functions bytecode includes a mix of acir and brillig.
global MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS: u64 = 500;
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/circuits.js/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const ARGS_HASH_CHUNK_LENGTH = 32;
export const ARGS_HASH_CHUNK_COUNT = 32;
export const INITIAL_L2_BLOCK_NUM = 1;
export const BLOB_SIZE_IN_BYTES = 126976;
export const MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 9000;
export const MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 15000;
export const MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 500;
export const MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS = 500;
export const REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE =
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

exports[`GasToken returns canonical protocol contract 1`] = `
{
"address": AztecAddress<0x01ffec73ac535628f98088b70f766f47989801a0dfc754cf4996f505cfd8f082>,
"address": AztecAddress<0x0b990cd3da37d6d83cd1dc2cca06ee3cae22877ec9040b817c9ce3ae47634683>,
"instance": {
"address": AztecAddress<0x01ffec73ac535628f98088b70f766f47989801a0dfc754cf4996f505cfd8f082>,
"contractClassId": Fr<0x2c32fd0ebccda2e20057f37fa2e6085c07d9a1236a72a54f58c724418f7b4438>,
"address": AztecAddress<0x0b990cd3da37d6d83cd1dc2cca06ee3cae22877ec9040b817c9ce3ae47634683>,
"contractClassId": Fr<0x136acc115d2b9c3acc18236bb2b72077c0cd855963de8c24f27c3c69120385c9>,
"initializationHash": Fr<0x0bf6e812f14bb029f7cb9c8da8367dd97c068e788d4f21007fd97014eba8cf9f>,
"portalContractAddress": EthAddress<0x0000000000000000000000000000000000000000>,
"publicKeysHash": Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>,
Expand All @@ -18,7 +18,7 @@ exports[`GasToken returns canonical protocol contract 1`] = `
exports[`GasToken returns canonical protocol contract 2`] = `
{
"artifactHash": Fr<0x076fb6d7493b075a880eeed90fec7c4c01e0a24d442522449e4d56c26357205f>,
"id": Fr<0x2c32fd0ebccda2e20057f37fa2e6085c07d9a1236a72a54f58c724418f7b4438>,
"id": Fr<0x136acc115d2b9c3acc18236bb2b72077c0cd855963de8c24f27c3c69120385c9>,
"privateFunctions": [
{
"isInternal": false,
Expand All @@ -27,7 +27,7 @@ exports[`GasToken returns canonical protocol contract 2`] = `
},
],
"privateFunctionsRoot": Fr<0x13b29c3f4a96eb14d5d3539a6308ff9736ad5d67e3f61ffbb7da908e14980828>,
"publicBytecodeCommitment": Fr<0x1c5e1c199e3affad8f3d3ec7db3e3b40639b3c0ef82351506ceb25cde3b04924>,
"publicBytecodeCommitment": Fr<0x1db9d13c128a3c6f7d736161ca3cfeb78b19e5018c3765e90c760aedc7959e26>,
"version": 1,
}
`;
Expand Down
5 changes: 3 additions & 2 deletions yarn-project/simulator/src/acvm/acvm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { ORACLE_NAMES } from './oracle/index.js';
*/
type ACIRCallback = Record<
ORACLE_NAMES,
(...args: ForeignCallInput[]) => ForeignCallOutput | Promise<ForeignCallOutput>
(...args: ForeignCallInput[]) => ForeignCallOutput | Promise<ForeignCallOutput> | Promise<void>
>;

/**
Expand Down Expand Up @@ -102,7 +102,8 @@ export async function acvm(
}

const result = await oracleFunction.call(callback, ...args);
return [result];
// void functions return undefined, which is mapped to an empty array.
return result === undefined ? [] : [result];
} catch (err) {
let typedError: Error;
if (err instanceof Error) {
Expand Down
11 changes: 5 additions & 6 deletions yarn-project/simulator/src/acvm/oracle/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,13 @@ export class Oracle {
return toACVMField(portalContactAddress);
}

async storageRead([startStorageSlot]: ACVMField[], [numberOfElements]: ACVMField[]): Promise<ACVMField[]> {
const values = await this.typedOracle.storageRead(fromACVMField(startStorageSlot), +numberOfElements);
return values.map(toACVMField);
async storageRead([storageSlot]: ACVMField[]): Promise<ACVMField> {
const value = await this.typedOracle.storageRead(fromACVMField(storageSlot));
return toACVMField(value);
}

async storageWrite([startStorageSlot]: ACVMField[], values: ACVMField[]): Promise<ACVMField[]> {
const newValues = await this.typedOracle.storageWrite(fromACVMField(startStorageSlot), values.map(fromACVMField));
return newValues.map(toACVMField);
async storageWrite([storageSlot]: ACVMField[], [value]: ACVMField[]): Promise<void> {
await this.typedOracle.storageWrite(fromACVMField(storageSlot), fromACVMField(value));
}

emitEncryptedLog(
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/simulator/src/acvm/oracle/typed_oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ export abstract class TypedOracle {
throw new Error('Not available.');
}

storageRead(_startStorageSlot: Fr, _numberOfElements: number): Promise<Fr[]> {
storageRead(_storageSlot: Fr): Promise<Fr> {
throw new Error('Not available.');
}

storageWrite(_startStorageSlot: Fr, _values: Fr[]): Promise<Fr[]> {
storageWrite(_storageSlot: Fr, _value: Fr): Promise<void> {
throw new Error('Not available.');
}

Expand Down
Loading