Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: FieldNote #3037

Merged
merged 9 commits into from
Oct 31, 2023
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,10 @@ describe('Private Execution test suite', () => {

beforeAll(async () => {
// These args should match the ones hardcoded in importer contract
const dummyNote = { amount: 1, secretHash: 2 };
const deepStruct = { aField: 1, aBool: true, aNote: dummyNote, manyNotes: [dummyNote, dummyNote, dummyNote] };
// eslint-disable-next-line camelcase
const dummyNote = { amount: 1, secret_hash: 2 };
// eslint-disable-next-line camelcase
const deepStruct = { a_field: 1, a_bool: true, a_note: dummyNote, many_notes: [dummyNote, dummyNote, dummyNote] };
args = [1, true, 1, [1, 2], dummyNote, deepStruct];
testCodeGenArtifact = getFunctionArtifact(TestContractArtifact, 'test_code_gen');
const serializedArgs = encodeArguments(testCodeGenArtifact, args);
Expand Down
8 changes: 8 additions & 0 deletions yarn-project/aztec-nr/field-note/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "field_note"
authors = ["aztec-labs"]
compiler_version = "0.7.1"
type = "lib"

[dependencies]
aztec = { path = "../aztec" }
90 changes: 90 additions & 0 deletions yarn-project/aztec-nr/field-note/src/field_note.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use dep::aztec::{
note::{
note_header::NoteHeader,
note_interface::NoteInterface,
},
hash::pedersen_hash,
context::PrivateContext,
};

global FIELD_NOTE_LEN: Field = 1;

// A note which stores a field and is expected to be passed around using the `addNote` function.
// WARNING: This Note is not private as it does not contain randomness and hence it can be easy to perform preimage
// attack on it.
struct FieldNote {
value: Field,
header: NoteHeader,
}

impl FieldNote {
pub fn new(value: Field) -> Self {
FieldNote {
value,
header: NoteHeader::empty(),
}
}

pub fn serialize(self) -> [Field; FIELD_NOTE_LEN]{
[self.value]
}

pub fn deserialize(preimage: [Field; FIELD_NOTE_LEN]) -> Self {
FieldNote {
value: preimage[0],
header: NoteHeader::empty(),
}
}

pub fn compute_note_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(self.serialize(), 0)
}

pub fn compute_nullifier(self) -> Field {
// This note is expected to be shared between users and for this reason can't be nullified using a secret.
0
}

pub fn set_header(&mut self, header: NoteHeader) {
self.header = header;
}
}

fn deserialize(preimage: [Field; FIELD_NOTE_LEN]) -> FieldNote {
FieldNote::deserialize(preimage)
}

fn serialize(note: FieldNote) -> [Field; FIELD_NOTE_LEN]{
note.serialize()
}

fn compute_note_hash(note: FieldNote) -> Field {
note.compute_note_hash()
}

fn compute_nullifier(note: FieldNote) -> Field {
note.compute_nullifier()
}

fn get_header(note: FieldNote) -> NoteHeader {
note.header
}

fn set_header(note: &mut FieldNote, header: NoteHeader) {
note.set_header(header);
}

fn broadcast(context: &mut PrivateContext, slot: Field, note: FieldNote) {
assert(false, "FieldNote does not support broadcast. Add it to PXE directly using the `.addNote` function.");
}

global FieldNoteMethods = NoteInterface {
deserialize,
serialize,
compute_note_hash,
compute_nullifier,
get_header,
set_header,
broadcast,
};
1 change: 1 addition & 0 deletions yarn-project/aztec-nr/field-note/src/lib.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod field_note;
24 changes: 22 additions & 2 deletions yarn-project/end-to-end/src/e2e_non_contract_account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { siloNullifier } from '@aztec/circuits.js/abis';
import { DebugLogger } from '@aztec/foundation/log';
import { toBigInt } from '@aztec/foundation/serialize';
import { TestContract } from '@aztec/noir-contracts/types';
import { AztecNode, PXE, TxStatus } from '@aztec/types';
import { AztecNode, NotePreimage, PXE, TxStatus } from '@aztec/types';

import { setup } from './fixtures/utils.js';

Expand All @@ -17,9 +17,9 @@ describe('e2e_non_contract_account', () => {
let logger: DebugLogger;

let contract: TestContract;
let wallet: Wallet;

beforeEach(async () => {
let wallet: Wallet;
({ teardown, aztecNode, pxe, wallet, logger } = await setup(1));
nonContractAccountWallet = new SignerlessWallet(pxe);

Expand Down Expand Up @@ -59,4 +59,24 @@ describe('e2e_non_contract_account', () => {
const msgSender = toBigInt(logs[0].log.data);
expect(msgSender).toBe(0n);
}, 120_000);

// Note: This test doesn't really belong here as it doesn't have anything to do with non-contract accounts. I needed
// to test the FieldNote functionality and it doesn't really fit anywhere else. Creating a separate e2e test for this
// seems wasteful. Move this test if a better place is found.
Comment on lines +63 to +65
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we need to way to unit test aztec.nr stuff

it('can set and get a constant', async () => {
const value = 123n;

const receipt = await contract.methods.set_constant(value).send().wait({ interval: 0.1 });

// check that 1 commitment was created
const tx = await pxe.getTx(receipt.txHash);
const nonZeroCommitments = tx?.newCommitments.filter(c => c.value > 0);
expect(nonZeroCommitments?.length).toBe(1);

// Add the note
const preimage = new NotePreimage([new Fr(value)]);
await wallet.addNote(wallet.getCompleteAddress().address, contract.address, new Fr(1), preimage, receipt.txHash);

expect(await contract.methods.get_constant().view()).toEqual(value);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ contract ImportTest {
true,
1 as u32,
[1, 2],
AStructTestCodeGenStruct { amount: 1, secretHash: 2 },
AStructTestCodeGenStruct { amount: 1, secret_hash: 2 },
ADeepStructTestCodeGenStruct {
aField: 1,
aBool: true,
aNote: ANoteADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 },
manyNotes: [
ManyNotesADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 },
ManyNotesADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 },
ManyNotesADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 },
a_field: 1,
a_bool: true,
a_note: ANoteADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 },
many_notes: [
ManyNotesADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 },
ManyNotesADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 },
ManyNotesADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 },
]
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ type = "contract"

[dependencies]
aztec = { path = "../../../../aztec-nr/aztec" }
field_note = { path = "../../../../aztec-nr/field-note" }
token_portal_content_hash_lib = { path = "../token_portal_content_hash_lib" }
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@ use dep::aztec::constants_gen::RETURN_VALUES_LENGTH;

struct AStructTestCodeGenStruct {
amount: Field,
secretHash: Field,
secret_hash: Field,
}

struct ADeepStructTestCodeGenStruct {
aField: Field,
aBool: bool,
aNote: ANoteADeepStructTestCodeGenStruct,
manyNotes: [ManyNotesADeepStructTestCodeGenStruct;3],
a_field: Field,
a_bool: bool,
a_note: ANoteADeepStructTestCodeGenStruct,
many_notes: [ManyNotesADeepStructTestCodeGenStruct;3],
}

struct ANoteADeepStructTestCodeGenStruct {
amount: Field,
secretHash: Field,
secret_hash: Field,
}

struct ManyNotesADeepStructTestCodeGenStruct {
amount: Field,
secretHash: Field,
secret_hash: Field,
}


Expand Down Expand Up @@ -83,11 +83,11 @@ impl TestPrivateContextInterface {
self,
context: &mut PrivateContext,
amount: Field,
secretHash: Field
secret_hash: Field
) {
let mut serialized_args = [0; 2];
serialized_args[0] = amount;
serialized_args[1] = secretHash;
serialized_args[1] = secret_hash;

context.call_public_function(self.address, 0x9749ca06, serialized_args)
}
Expand All @@ -97,11 +97,11 @@ impl TestPrivateContextInterface {
self,
context: &mut PrivateContext,
amount: Field,
secretHash: Field
secret_hash: Field
) {
let mut serialized_args = [0; 2];
serialized_args[0] = amount;
serialized_args[1] = secretHash;
serialized_args[1] = secret_hash;

context.call_public_function(self.address, 0xdf02db8d, serialized_args)
}
Expand Down Expand Up @@ -197,34 +197,46 @@ impl TestPrivateContextInterface {
}


pub fn set_constant(
self,
context: &mut PrivateContext,
value: Field
) -> [Field; RETURN_VALUES_LENGTH] {
let mut serialized_args = [0; 1];
serialized_args[0] = value;

context.call_private_function(self.address, 0x1b3b9e18, serialized_args)
}


pub fn test_code_gen(
self,
context: &mut PrivateContext,
aField: Field,
aBool: bool,
aNumber: u32,
anArray: [Field;2],
aStruct: AStructTestCodeGenStruct,
aDeepStruct: ADeepStructTestCodeGenStruct
a_field: Field,
a_bool: bool,
a_number: u32,
an_array: [Field;2],
a_struct: AStructTestCodeGenStruct,
a_deep_struct: ADeepStructTestCodeGenStruct
) -> [Field; RETURN_VALUES_LENGTH] {
let mut serialized_args = [0; 17];
serialized_args[0] = aField;
serialized_args[1] = aBool as Field;
serialized_args[2] = aNumber as Field;
serialized_args[3] = anArray[0];
serialized_args[4] = anArray[1];
serialized_args[5] = aStruct.amount;
serialized_args[6] = aStruct.secretHash;
serialized_args[7] = aDeepStruct.aField;
serialized_args[8] = aDeepStruct.aBool as Field;
serialized_args[9] = aDeepStruct.aNote.amount;
serialized_args[10] = aDeepStruct.aNote.secretHash;
serialized_args[11] = aDeepStruct.manyNotes[0].amount;
serialized_args[12] = aDeepStruct.manyNotes[0].secretHash;
serialized_args[13] = aDeepStruct.manyNotes[1].amount;
serialized_args[14] = aDeepStruct.manyNotes[1].secretHash;
serialized_args[15] = aDeepStruct.manyNotes[2].amount;
serialized_args[16] = aDeepStruct.manyNotes[2].secretHash;
serialized_args[0] = a_field;
serialized_args[1] = a_bool as Field;
serialized_args[2] = a_number as Field;
serialized_args[3] = an_array[0];
serialized_args[4] = an_array[1];
serialized_args[5] = a_struct.amount;
serialized_args[6] = a_struct.secret_hash;
serialized_args[7] = a_deep_struct.a_field;
serialized_args[8] = a_deep_struct.a_bool as Field;
serialized_args[9] = a_deep_struct.a_note.amount;
serialized_args[10] = a_deep_struct.a_note.secret_hash;
serialized_args[11] = a_deep_struct.many_notes[0].amount;
serialized_args[12] = a_deep_struct.many_notes[0].secret_hash;
serialized_args[13] = a_deep_struct.many_notes[1].amount;
serialized_args[14] = a_deep_struct.many_notes[1].secret_hash;
serialized_args[15] = a_deep_struct.many_notes[2].amount;
serialized_args[16] = a_deep_struct.many_notes[2].secret_hash;

context.call_private_function(self.address, 0x0f054f9b, serialized_args)
}
Expand Down Expand Up @@ -270,11 +282,11 @@ impl TestPublicContextInterface {
self,
context: PublicContext,
amount: Field,
secretHash: Field
secret_hash: Field
) -> [Field; RETURN_VALUES_LENGTH] {
let mut serialized_args = [0; 2];
serialized_args[0] = amount;
serialized_args[1] = secretHash;
serialized_args[1] = secret_hash;

context.call_public_function(self.address, 0x9749ca06, serialized_args)
}
Expand All @@ -284,11 +296,11 @@ impl TestPublicContextInterface {
self,
context: PublicContext,
amount: Field,
secretHash: Field
secret_hash: Field
) -> [Field; RETURN_VALUES_LENGTH] {
let mut serialized_args = [0; 2];
serialized_args[0] = amount;
serialized_args[1] = secretHash;
serialized_args[1] = secret_hash;

context.call_public_function(self.address, 0xdf02db8d, serialized_args)
}
Expand Down
Loading