Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro committed Mar 12, 2024
1 parent d79cfb6 commit a13d83e
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 175 deletions.
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
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 @@ -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

0 comments on commit a13d83e

Please sign in to comment.