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: Sync from aztec-packages #6104

Closed
wants to merge 3 commits into from
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
2 changes: 1 addition & 1 deletion .aztec-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bcec12dbf79b658406dc21083f8fdeef8962085e
7fb2a454531db8cef757b5ec2028d97e823bef5f
19 changes: 3 additions & 16 deletions 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 acvm-repo/acir/codegen/acir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ namespace Program {

struct ToRadix {
Program::MemoryAddress input;
uint32_t radix;
Program::MemoryAddress radix;
Program::HeapArray output;
bool output_bits;

Expand Down
5 changes: 4 additions & 1 deletion acvm-repo/bn254_blackbox_solver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ mod schnorr;
use ark_ec::AffineRepr;
pub use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul};
pub use generator::generators::derive_generators;
pub use poseidon2::{field_from_hex, poseidon2_permutation, Poseidon2Config, POSEIDON2_CONFIG};
pub use poseidon2::{
field_from_hex, poseidon2_permutation, poseidon_hash, Poseidon2Config, Poseidon2Sponge,
POSEIDON2_CONFIG,
};

// Temporary hack, this ensure that we always use a bn254 field here
// without polluting the feature flags of the `acir_field` crate.
Expand Down
84 changes: 84 additions & 0 deletions acvm-repo/bn254_blackbox_solver/src/poseidon2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,75 @@ impl<'a> Poseidon2<'a> {
}
}

/// Performs a poseidon hash with a sponge construction equivalent to the one in poseidon2.nr
pub fn poseidon_hash(inputs: &[FieldElement]) -> Result<FieldElement, BlackBoxResolutionError> {
let two_pow_64 = 18446744073709551616_u128.into();
let iv = FieldElement::from(inputs.len()) * two_pow_64;
let mut sponge = Poseidon2Sponge::new(iv, 3);
for input in inputs.iter() {
sponge.absorb(*input)?;
}
sponge.squeeze()
}

pub struct Poseidon2Sponge<'a> {
rate: usize,
poseidon: Poseidon2<'a>,
squeezed: bool,
cache: Vec<FieldElement>,
state: Vec<FieldElement>,
}

impl<'a> Poseidon2Sponge<'a> {
pub fn new(iv: FieldElement, rate: usize) -> Poseidon2Sponge<'a> {
let mut result = Poseidon2Sponge {
cache: Vec::with_capacity(rate),
state: vec![FieldElement::zero(); rate + 1],
squeezed: false,
rate,
poseidon: Poseidon2::new(),
};
result.state[rate] = iv;
result
}

fn perform_duplex(&mut self) -> Result<(), BlackBoxResolutionError> {
// zero-pad the cache
for _ in self.cache.len()..self.rate {
self.cache.push(FieldElement::zero());
}
// add the cache into sponge state
for i in 0..self.rate {
self.state[i] += self.cache[i];
}
self.state = self.poseidon.permutation(&self.state, 4)?;
Ok(())
}

pub fn absorb(&mut self, input: FieldElement) -> Result<(), BlackBoxResolutionError> {
assert!(!self.squeezed);
if self.cache.len() == self.rate {
// If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache
self.perform_duplex()?;
self.cache = vec![input];
} else {
// If we're absorbing, and the cache is not full, add the input into the cache
self.cache.push(input);
}
Ok(())
}

pub fn squeeze(&mut self) -> Result<FieldElement, BlackBoxResolutionError> {
assert!(!self.squeezed);
// If we're in absorb mode, apply sponge permutation to compress the cache.
self.perform_duplex()?;
self.squeezed = true;

// Pop one item off the top of the permutation and return it.
Ok(self.state[0])
}
}

#[cfg(test)]
mod test {
use acir::AcirField;
Expand All @@ -562,4 +631,19 @@ mod test {
];
assert_eq!(result, expected_result);
}

#[test]
fn hash_smoke_test() {
let fields = [
FieldElement::from(1u128),
FieldElement::from(2u128),
FieldElement::from(3u128),
FieldElement::from(4u128),
];
let result = super::poseidon_hash(&fields).expect("should hash successfully");
assert_eq!(
result,
field_from_hex("130bf204a32cac1f0ace56c78b731aa3809f06df2731ebcf6b3464a15788b1b9"),
);
}
}
2 changes: 1 addition & 1 deletion acvm-repo/brillig/src/black_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ pub enum BlackBoxOp {
},
ToRadix {
input: MemoryAddress,
radix: u32,
radix: MemoryAddress,
output: HeapArray,
output_bits: bool,
},
Expand Down
6 changes: 5 additions & 1 deletion acvm-repo/brillig_vm/src/black_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@
to_u8_vec(read_heap_array(memory, key)).try_into().map_err(|_| {
BlackBoxResolutionError::Failed(bb_func, "Invalid ley length".to_string())
})?;
let ciphertext = aes128_encrypt(&inputs, iv, key)?;

Check warning on line 61 in acvm-repo/brillig_vm/src/black_box.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (ciphertext)

memory.write(outputs.size, ciphertext.len().into());

Check warning on line 63 in acvm-repo/brillig_vm/src/black_box.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (ciphertext)
memory.write_slice(memory.read_ref(outputs.pointer), &to_value_vec(&ciphertext));

Check warning on line 64 in acvm-repo/brillig_vm/src/black_box.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (ciphertext)

Ok(())
}
Expand Down Expand Up @@ -369,9 +369,13 @@
}
BlackBoxOp::ToRadix { input, radix, output, output_bits } => {
let input: F = *memory.read(*input).extract_field().expect("ToRadix input not a field");
let radix = memory
.read(*radix)
.expect_integer_with_bit_size(IntegerBitSize::U32)
.expect("ToRadix opcode's radix bit size does not match expected bit size 32");

let mut input = BigUint::from_bytes_be(&input.to_be_bytes());
let radix = BigUint::from(*radix);
let radix = BigUint::from_bytes_be(&radix.to_be_bytes());

let mut limbs: Vec<MemoryValue<F>> = Vec::with_capacity(output.size);

Expand Down
4 changes: 3 additions & 1 deletion aztec_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ acvm.workspace = true
noirc_frontend.workspace = true
noirc_errors.workspace = true
iter-extended.workspace = true
bn254_blackbox_solver.workspace = true
convert_case = "0.6.0"
im.workspace = true
regex = "1.10"
tiny-keccak = { version = "2.0.0", features = ["keccak"] }
itertools = "^0.10"
hex.workspace = true
57 changes: 47 additions & 10 deletions aztec_macros/src/transforms/contract_interface.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use acvm::acir::AcirField;

use bn254_blackbox_solver::poseidon_hash;
use noirc_errors::Location;
use noirc_frontend::ast::{Documented, Ident, NoirFunction, UnresolvedTypeData};
use noirc_frontend::{
Expand All @@ -9,7 +10,7 @@ use noirc_frontend::{
Type,
};

use tiny_keccak::{Hasher, Keccak};
use itertools::Itertools;

use crate::utils::parse_utils::parse_program;
use crate::utils::{
Expand Down Expand Up @@ -251,7 +252,7 @@ pub fn generate_contract_interface(
module_name,
stubs.iter().map(|(src, _)| src.to_owned()).collect::<Vec<String>>().join("\n"),
if has_storage_layout { storage_layout_getter.clone() } else { "".to_string() },
if has_storage_layout { format!("#[contract_library_method]\n{}", storage_layout_getter) } else { "".to_string() }
if has_storage_layout { format!("#[contract_library_method]\n{}", storage_layout_getter) } else { "".to_string() }
);

let (contract_interface_ast, errors) = parse_program(&contract_interface, empty_spans);
Expand Down Expand Up @@ -296,14 +297,8 @@ fn compute_fn_signature_hash(fn_name: &str, parameters: &[Type]) -> u32 {
fn_name,
parameters.iter().map(signature_of_type).collect::<Vec<_>>().join(",")
);
let mut keccak = Keccak::v256();
let mut result = [0u8; 32];
keccak.update(signature.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())

hash_to_selector(&signature)
}

// Updates the function signatures in the contract interface with the actual ones, replacing the placeholder.
Expand Down Expand Up @@ -429,3 +424,45 @@ pub fn update_fn_signatures_in_contract_interface(
}
Ok(())
}

fn poseidon2_hash_bytes(inputs: Vec<u8>) -> FieldElement {
let fields: Vec<_> = inputs
.into_iter()
.chunks(31)
.into_iter()
.map(|bytes_chunk| {
let mut chunk_as_vec: Vec<u8> = bytes_chunk.collect();
chunk_as_vec.extend(std::iter::repeat(0).take(32 - chunk_as_vec.len()));
// Build a little endian field element
chunk_as_vec.reverse();
FieldElement::from_be_bytes_reduce(&chunk_as_vec)
})
.collect();

poseidon_hash(&fields).expect("Poseidon hash failed")
}

pub(crate) fn hash_to_selector(inputs: &str) -> u32 {
let hash = poseidon2_hash_bytes(inputs.as_bytes().to_vec()).to_be_bytes();
// Take the last 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(hash[(32 - num_bytes_per_note_type_id)..32].try_into().unwrap())
}

#[cfg(test)]
mod test {
use crate::transforms::contract_interface::hash_to_selector;

#[test]
fn test_selector_is_valid() {
let selector = hash_to_selector("IS_VALID()");
assert_eq!(hex::encode(&selector.to_be_bytes()), "73cdda47");
}

#[test]
fn test_long_selector() {
let selector = hash_to_selector("foo_and_bar_and_baz_and_foo_bar_baz_and_bar_foo");
assert_eq!(hex::encode(&selector.to_be_bytes()), "7590a997");
}
}
13 changes: 3 additions & 10 deletions aztec_macros/src/transforms/note_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ use noirc_frontend::{

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

use crate::utils::parse_utils::parse_program;
use crate::{
Expand All @@ -28,6 +26,8 @@ use crate::{
},
};

use super::contract_interface::hash_to_selector;

// Automatic implementation of most of the methods in the NoteInterface trait, guiding the user with meaningful error messages in case some
// methods must be implemented manually.
pub fn generate_note_interface_impl(
Expand Down Expand Up @@ -751,14 +751,7 @@ fn generate_note_deserialize_content_source(
// Utility function to generate the note type id as a Field
fn compute_note_type_id(note_type: &str) -> u32 {
// TODO(#4519) Improve automatic note id generation and assignment
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())
hash_to_selector(note_type)
}

pub fn inject_note_exports(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ impl<F: AcirField + DebugToString, Registers: RegisterAllocator> BrilligContext<

let heap_array = self.codegen_brillig_array_to_heap_array(target_array);

let radix_var = self.make_constant_instruction(F::from(radix as u128), 32);

self.black_box_op_instruction(BlackBoxOp::ToRadix {
input: source_field.address,
radix,
radix: radix_var.address,
output: heap_array,
output_bits,
});
Expand All @@ -91,5 +93,6 @@ impl<F: AcirField + DebugToString, Registers: RegisterAllocator> BrilligContext<
self.deallocate_single_addr(items_len);
}
self.deallocate_register(heap_array.pointer);
self.deallocate_register(radix_var.address);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::{
brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable},
debug_show::DebugToString,
registers::RegisterAllocator,
BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
};

impl<F: AcirField + DebugToString, Registers: RegisterAllocator> BrilligContext<F, Registers> {
Expand All @@ -20,9 +20,12 @@ impl<F: AcirField + DebugToString, Registers: RegisterAllocator> BrilligContext<
pointer_register: MemoryAddress,
size: usize,
) {
let size_register = self.make_usize_constant_instruction(size.into());
self.codegen_allocate_mem(pointer_register, size_register.address);
self.deallocate_single_addr(size_register);
self.load_free_memory_pointer_instruction(pointer_register);
self.codegen_usize_op_in_place(
ReservedRegisters::free_memory_pointer(),
BrilligBinaryOp::Add,
size,
);
}

/// Allocates an array of size contained in size_register and stores the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ fn to_le_radix(
};

// Decompose the integer into its radix digits in little endian form.
let decomposed_integer = compute_to_radix(value, radix);
let decomposed_integer = compute_to_radix_le(value, radix);
let decomposed_integer = vecmap(0..limb_count as usize, |i| match decomposed_integer.get(i) {
Some(digit) => Value::U8(*digit),
None => Value::U8(0),
Expand All @@ -797,7 +797,7 @@ fn to_le_radix(
))
}

fn compute_to_radix(field: FieldElement, radix: u32) -> Vec<u8> {
fn compute_to_radix_le(field: FieldElement, radix: u32) -> Vec<u8> {
let bit_size = u32::BITS - (radix - 1).leading_zeros();
let radix_big = BigUint::from(radix);
assert_eq!(BigUint::from(2u128).pow(bit_size), radix_big, "ICE: Radix must be a power of 2");
Expand Down
Loading
Loading