Skip to content

Commit

Permalink
fix: false decryption fix (#7066)
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan authored Jun 26, 2024
1 parent 014ba3b commit 48d9df4
Show file tree
Hide file tree
Showing 44 changed files with 310 additions and 133 deletions.
2 changes: 1 addition & 1 deletion barretenberg/ts/src/types/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class Fr {
const valueBigInt = typeof value === 'bigint' ? value : toBigIntBE(value);

if (valueBigInt > Fr.MAX_VALUE) {
throw new Error(`Fr out of range: ${valueBigInt}`);
throw new Error(`Value 0x${valueBigInt.toString(16)} is greater or equal to field modulus.`);
}

this.value = typeof value === 'bigint' ? toBufferBE(value) : value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ mod test {
impl NoteInterface<ADDRESS_NOTE_LEN, ADDRESS_NOTE_BYTES_LEN> for AddressNote {
fn compute_note_content_hash(self) -> Field {1}

fn get_note_type_id() -> Field {1}
fn get_note_type_id() -> Field {
1
}

fn get_header(self) -> NoteHeader { self.header}

Expand Down
1 change: 1 addition & 0 deletions noir/noir-repo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion noir/noir-repo/aztec_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ noirc_errors.workspace = true
iter-extended.workspace = true
convert_case = "0.6.0"
regex = "1.10"

tiny-keccak = { version = "2.0.0", features = ["keccak"] }
86 changes: 56 additions & 30 deletions noir/noir-repo/aztec_macros/src/transforms/note_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use noirc_frontend::{
Type,
};

use acvm::AcirField;
use regex::Regex;
// TODO(#7165): nuke the following dependency from here and Cargo.toml
use tiny_keccak::{Hasher, Keccak};

use crate::{
chained_dep,
Expand Down Expand Up @@ -97,7 +100,6 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt
.collect::<Result<Vec<_>, _>>()?;
let [note_serialized_len, note_bytes_len]: [_; 2] =
note_interface_generics.try_into().unwrap();
let note_type_id = note_type_id(&note_type);

// Automatically inject the header field if it's not present
let (header_field_name, _) = if let Some(existing_header) =
Expand Down Expand Up @@ -184,8 +186,9 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt
}

if !check_trait_method_implemented(trait_impl, "get_note_type_id") {
let note_type_id = compute_note_type_id(&note_type);
let get_note_type_id_fn =
generate_note_get_type_id(&note_type_id, note_interface_impl_span)?;
generate_get_note_type_id(note_type_id, note_interface_impl_span)?;
trait_impl.items.push(TraitImplItem::Function(get_note_type_id_fn));
}

Expand Down Expand Up @@ -324,16 +327,17 @@ fn generate_note_set_header(

// Automatically generate the note type id getter method. The id itself its calculated as the concatenation
// of the conversion of the characters in the note's struct name to unsigned integers.
fn generate_note_get_type_id(
note_type_id: &str,
fn generate_get_note_type_id(
note_type_id: u32,
impl_span: Option<Span>,
) -> Result<NoirFunction, AztecMacroError> {
// TODO(#7165): replace {} with dep::aztec::protocol_types::abis::note_selector::compute_note_selector(\"{}\") in the function source below
let function_source = format!(
"
fn get_note_type_id() -> Field {{
{}
}}
",
fn get_note_type_id() -> Field {{
{}
}}
",
note_type_id
)
.to_string();
Expand Down Expand Up @@ -387,7 +391,7 @@ fn generate_note_properties_struct(

// Generate the deserialize_content method as
//
// fn deserialize_content(serialized_note: [Field; NOTE_SERILIZED_LEN]) -> Self {
// fn deserialize_content(serialized_note: [Field; NOTE_SERIALIZED_LEN]) -> Self {
// NoteType {
// note_field1: serialized_note[0] as Field,
// note_field2: NoteFieldType2::from_field(serialized_note[1])...
Expand Down Expand Up @@ -525,10 +529,10 @@ fn generate_note_exports_global(
let struct_source = format!(
"
#[abi(notes)]
global {0}_EXPORTS: (Field, str<{1}>) = ({2},\"{0}\");
global {0}_EXPORTS: (Field, str<{1}>) = (0x{2},\"{0}\");
",
note_type,
note_type_id.len(),
note_type.len(),
note_type_id
)
.to_string();
Expand Down Expand Up @@ -685,10 +689,18 @@ fn generate_note_deserialize_content_source(
.to_string()
}

// TODO(#7165): nuke this function
// Utility function to generate the note type id as a Field
fn note_type_id(note_type: &str) -> String {
fn compute_note_type_id(note_type: &str) -> u32 {
// TODO(#4519) Improve automatic note id generation and assignment
note_type.chars().map(|c| (c as u32).to_string()).collect::<Vec<String>>().join("")
let mut keccak = Keccak::v256();
let mut result = [0u8; 32];
keccak.update(note_type.as_bytes());
keccak.finalize(&mut result);
// Take the first 4 bytes of the hash and convert them to an integer
// If you change the following value you have to change NUM_BYTES_PER_NOTE_TYPE_ID in l1_note_payload.ts as well
let num_bytes_per_note_type_id = 4;
u32::from_be_bytes(result[0..num_bytes_per_note_type_id].try_into().unwrap())
}

pub fn inject_note_exports(
Expand Down Expand Up @@ -717,47 +729,61 @@ pub fn inject_note_exports(
},
file_id,
))?;
let init_function =
let get_note_type_id_function =
context.def_interner.function(&func_id).block(&context.def_interner);
let init_function_statement_id = init_function.statements().first().ok_or((
AztecMacroError::CouldNotExportStorageLayout {
span: None,
secondary_message: Some(format!(
"Could not retrieve note id statement from function for note {}",
note.borrow().name.0.contents
)),
},
file_id,
))?;
let note_id_statement = context.def_interner.statement(init_function_statement_id);
let get_note_type_id_statement_id =
get_note_type_id_function.statements().first().ok_or((
AztecMacroError::CouldNotExportStorageLayout {
span: None,
secondary_message: Some(format!(
"Could not retrieve note id statement from function for note {}",
note.borrow().name.0.contents
)),
},
file_id,
))?;
let note_type_id_statement =
context.def_interner.statement(get_note_type_id_statement_id);

let note_id_value = match note_id_statement {
let note_type_id = match note_type_id_statement {
HirStatement::Expression(expression_id) => {
match context.def_interner.expression(&expression_id) {
HirExpression::Literal(HirLiteral::Integer(value, _)) => Ok(value),
HirExpression::Literal(_) => Err((
AztecMacroError::CouldNotExportStorageLayout {
span: None,
secondary_message: Some(
"note_type_id statement must be a literal integer expression"
.to_string(),
),
},
file_id,
)),
_ => Err((
AztecMacroError::CouldNotExportStorageLayout {
span: None,
secondary_message: Some(
"note_id statement must be a literal expression".to_string(),
"note_type_id statement must be a literal expression"
.to_string(),
),
},
file_id,
)),
}
}
_ => Err((
AztecMacroError::CouldNotAssignStorageSlots {
AztecMacroError::CouldNotExportStorageLayout {
span: None,
secondary_message: Some(
"note_id statement must be an expression".to_string(),
"note_type_id statement must be an expression".to_string(),
),
},
file_id,
)),
}?;
let global = generate_note_exports_global(
&note.borrow().name.0.contents,
&note_id_value.to_string(),
&note_type_id.to_hex(),
)
.map_err(|err| (err, file_id))?;

Expand Down
5 changes: 2 additions & 3 deletions noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::BTreeMap;

use acvm::acir::circuit::ErrorSelector;
use acvm::AcirField;
use iter_extended::vecmap;
use noirc_abi::{Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue};
use noirc_frontend::ast::Visibility;
Expand Down Expand Up @@ -107,9 +108,7 @@ pub(super) fn value_from_hir_expression(context: &Context, expression: HirExpres
},
HirLiteral::Bool(value) => AbiValue::Boolean { value },
HirLiteral::Str(value) => AbiValue::String { value },
HirLiteral::Integer(field, sign) => {
AbiValue::Integer { value: field.to_string(), sign }
}
HirLiteral::Integer(field, sign) => AbiValue::Integer { value: field.to_hex(), sign },
_ => unreachable!("Literal cannot be used in the abi"),
},
_ => unreachable!("Type cannot be used in the abi {:?}", expression),
Expand Down
1 change: 1 addition & 0 deletions yarn-project/aztec.js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export {
waitForAccountSynch,
waitForPXE,
} from './utils/index.js';
export { NoteSelector } from '@aztec/foundation/abi';

export { createPXEClient } from './rpc_clients/index.js';

Expand Down
2 changes: 2 additions & 0 deletions yarn-project/aztec.js/src/rpc_clients/pxe_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
GrumpkinScalar,
Point,
} from '@aztec/circuits.js';
import { NoteSelector } from '@aztec/foundation/abi';
import { createJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client';

/**
Expand Down Expand Up @@ -53,6 +54,7 @@ export const createPXEClient = (url: string, fetch = makeFetch([1, 2, 3], false)
Point,
TxExecutionRequest,
TxHash,
NoteSelector,
},
{ Tx, SimulatedTx, TxReceipt, EncryptedNoteL2BlockL2Logs, UnencryptedL2BlockL2Logs, NullifierMembershipWitness },
false,
Expand Down
12 changes: 4 additions & 8 deletions yarn-project/builder/src/contract-interface-gen/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ function generateNotesGetter(input: ContractArtifact) {
.map(
([name, { id }]) =>
`${name}: {
id: new Fr(${id.toBigInt()}n),
id: new NoteSelector(${id.value}),
}`,
)
.join(',\n');
Expand Down Expand Up @@ -281,11 +281,7 @@ function generateEvents(events: any[] | undefined) {
if (payload === undefined) {
return undefined;
}
if (
!eventSelector.equals(
EventSelector.fromField(payload.eventTypeId),
)
) {
if (!eventSelector.equals(payload.eventTypeId)) {
return undefined;
}
if (payload.event.items.length !== fieldsLength) {
Expand Down Expand Up @@ -349,14 +345,14 @@ import {
DeployMethod,
EthAddress,
EthAddressLike,
EventSelector,
FieldLike,
Fr,
EventSelector,
FunctionSelector,
FunctionSelectorLike,
L1EventPayload,
loadContractArtifact,
NoirCompiledContract,
NoteSelector,
Point,
PublicKey,
Wallet,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Fr, GrumpkinScalar } from '@aztec/circuits.js';
import { Grumpkin } from '@aztec/circuits.js/barretenberg';
import { NoteSelector } from '@aztec/foundation/abi';
import { updateInlineTestData } from '@aztec/foundation/testing';

import { Note } from '../payload.js';
Expand All @@ -20,10 +21,10 @@ describe('encrypt log incoming body', () => {
const viewingPubKey = grumpkin.mul(Grumpkin.generator, viewingSecretKey);

const note = Note.random();
const noteTypeId = Fr.random();
const storageSlot = Fr.random();
const noteTypeId = NoteSelector.random();

const body = new EncryptedNoteLogIncomingBody(noteTypeId, storageSlot, note);
const body = new EncryptedNoteLogIncomingBody(storageSlot, noteTypeId, note);

const encrypted = body.computeCiphertext(ephSecretKey, viewingPubKey);

Expand All @@ -44,7 +45,7 @@ describe('encrypt log incoming body', () => {
const viewingPubKey = grumpkin.mul(Grumpkin.generator, viewingSecretKey);

const note = new Note([new Fr(1), new Fr(2), new Fr(3)]);
const noteTypeId = new Fr(1);
const noteTypeId = new NoteSelector(1);
const storageSlot = new Fr(2);

const body = new EncryptedNoteLogIncomingBody(storageSlot, noteTypeId, note);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Fr, type GrumpkinPrivateKey, type PublicKey } from '@aztec/circuits.js';
import { NoteSelector } from '@aztec/foundation/abi';
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';

import { Note } from '../payload.js';
import { EncryptedLogIncomingBody } from './encrypted_log_incoming_body.js';

export class EncryptedNoteLogIncomingBody extends EncryptedLogIncomingBody {
constructor(public storageSlot: Fr, public noteTypeId: Fr, public note: Note) {
constructor(public storageSlot: Fr, public noteTypeId: NoteSelector, public note: Note) {
super();
}

Expand All @@ -16,7 +17,8 @@ export class EncryptedNoteLogIncomingBody extends EncryptedLogIncomingBody {
*/
public toBuffer(): Buffer {
const noteBufferWithoutLength = this.note.toBuffer().subarray(4);
return serializeToBuffer(this.storageSlot, this.noteTypeId, noteBufferWithoutLength);
// Note: We serialize note type to field first because that's how it's done in Noir
return serializeToBuffer(this.storageSlot, this.noteTypeId.toField(), noteBufferWithoutLength);
}

/**
Expand All @@ -28,7 +30,7 @@ export class EncryptedNoteLogIncomingBody extends EncryptedLogIncomingBody {
public static fromBuffer(buf: Buffer): EncryptedNoteLogIncomingBody {
const reader = BufferReader.asReader(buf);
const storageSlot = Fr.fromBuffer(reader);
const noteTypeId = Fr.fromBuffer(reader);
const noteTypeId = NoteSelector.fromField(Fr.fromBuffer(reader));

// 2 Fields (storage slot and note type id) are not included in the note buffer
const fieldsInNote = reader.getLength() / 32 - 2;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AztecAddress, KeyValidationRequest, computeOvskApp, derivePublicKeyFromSecretKey } from '@aztec/circuits.js';
import { EventSelector } from '@aztec/foundation/abi';
import { pedersenHash } from '@aztec/foundation/crypto';
import { Fr, GrumpkinScalar } from '@aztec/foundation/fields';

Expand Down Expand Up @@ -29,7 +30,7 @@ describe('L1 Event Payload', () => {
randomness = Fr.random();
maskedContractAddress = pedersenHash([contractAddress, randomness], 0);

payload = new L1EventPayload(Event.random(), contractAddress, randomness, Fr.random());
payload = new L1EventPayload(Event.random(), contractAddress, randomness, EventSelector.random());

ovskM = GrumpkinScalar.random();
ivskM = GrumpkinScalar.random();
Expand Down
Loading

0 comments on commit 48d9df4

Please sign in to comment.