diff --git a/acvm-repo/acir/codegen/acir.cpp b/acvm-repo/acir/codegen/acir.cpp index d51fe8de910..0fc84d47a0f 100644 --- a/acvm-repo/acir/codegen/acir.cpp +++ b/acvm-repo/acir/codegen/acir.cpp @@ -468,6 +468,16 @@ namespace Circuit { static BinaryIntOp bincodeDeserialize(std::vector); }; + struct Cast { + Circuit::MemoryAddress destination; + Circuit::MemoryAddress source; + uint32_t bit_size; + + friend bool operator==(const Cast&, const Cast&); + std::vector bincodeSerialize() const; + static Cast bincodeDeserialize(std::vector); + }; + struct JumpIfNot { Circuit::MemoryAddress condition; uint64_t location; @@ -590,7 +600,7 @@ namespace Circuit { static Stop bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const BrilligOpcode&, const BrilligOpcode&); std::vector bincodeSerialize() const; @@ -4300,6 +4310,50 @@ Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable BrilligOpcode::Cast::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BrilligOpcode::Cast BrilligOpcode::Cast::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Cast &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination, serializer); + serde::Serializable::serialize(obj.source, serializer); + serde::Serializable::serialize(obj.bit_size, serializer); +} + +template <> +template +Circuit::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Cast obj; + obj.destination = serde::Deserializable::deserialize(deserializer); + obj.source = serde::Deserializable::deserialize(deserializer); + obj.bit_size = serde::Deserializable::deserialize(deserializer); + return obj; +} + namespace Circuit { inline bool operator==(const BrilligOpcode::JumpIfNot &lhs, const BrilligOpcode::JumpIfNot &rhs) { diff --git a/acvm-repo/acir/tests/test_program_serialization.rs b/acvm-repo/acir/tests/test_program_serialization.rs index 6a73522c822..2c8ad2b9986 100644 --- a/acvm-repo/acir/tests/test_program_serialization.rs +++ b/acvm-repo/acir/tests/test_program_serialization.rs @@ -206,11 +206,11 @@ fn simple_brillig_foreign_call() { let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 65, 10, 192, 32, 12, 4, 215, 148, 150, 246, - 212, 175, 216, 31, 244, 51, 61, 244, 226, 65, 196, 247, 171, 24, 33, 136, 122, 209, 129, - 144, 176, 132, 101, 247, 4, 160, 144, 217, 196, 45, 41, 218, 203, 91, 207, 241, 168, 117, - 94, 90, 230, 37, 238, 144, 216, 27, 249, 11, 87, 156, 131, 239, 223, 248, 207, 186, 81, - 235, 150, 67, 173, 221, 189, 95, 18, 34, 97, 64, 0, 116, 135, 40, 214, 136, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, + 212, 79, 177, 127, 208, 159, 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, + 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, 50, 245, 26, 175, 218, 231, 165, + 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, 104, + 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -305,15 +305,15 @@ fn complex_brillig_foreign_call() { let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 73, 14, 131, 48, 12, 28, 147, 166, 165, 167, - 126, 161, 82, 251, 128, 180, 47, 224, 47, 85, 111, 32, 56, 242, 124, 130, 24, 68, 176, 2, - 23, 130, 4, 35, 89, 206, 50, 137, 71, 182, 147, 28, 128, 96, 128, 241, 150, 113, 44, 156, - 135, 24, 121, 5, 189, 219, 134, 143, 164, 187, 203, 237, 165, 49, 59, 129, 70, 179, 131, - 198, 177, 31, 14, 90, 239, 148, 117, 73, 154, 63, 19, 121, 63, 23, 111, 214, 219, 149, 243, - 27, 125, 206, 117, 208, 63, 85, 222, 161, 248, 32, 167, 72, 162, 245, 235, 44, 166, 94, 20, - 21, 251, 30, 196, 253, 213, 85, 83, 254, 91, 163, 168, 90, 234, 43, 24, 191, 213, 190, 172, - 156, 235, 17, 126, 59, 49, 142, 68, 120, 75, 220, 7, 166, 84, 90, 68, 72, 194, 139, 180, - 136, 25, 58, 46, 103, 45, 188, 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, + 154, 35, 8, 51, 7, 232, 204, 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, + 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, 204, 48, 206, 18, 158, 19, 175, + 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, 160, + 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, + 250, 201, 99, 206, 251, 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, + 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 136, 249, 87, 249, 105, + 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, 34, 14, 164, + 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/acvm-repo/acvm/src/pwg/blackbox/hash.rs b/acvm-repo/acvm/src/pwg/blackbox/hash.rs index 1ada397fc59..06489822c92 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/hash.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/hash.rs @@ -3,7 +3,7 @@ use acir::{ native_types::{Witness, WitnessMap}, BlackBoxFunc, FieldElement, }; -use acvm_blackbox_solver::BlackBoxResolutionError; +use acvm_blackbox_solver::{sha256compression, BlackBoxResolutionError}; use crate::pwg::{insert_value, witness_to_value}; use crate::OpcodeResolutionError; @@ -86,3 +86,48 @@ fn write_digest_to_outputs( Ok(()) } + +pub(crate) fn solve_sha_256_permutation_opcode( + initial_witness: &mut WitnessMap, + inputs: &[FunctionInput], + hash_values: &[FunctionInput], + outputs: &[Witness], + black_box_func: BlackBoxFunc, +) -> Result<(), OpcodeResolutionError> { + let mut message = [0; 16]; + if inputs.len() != 16 { + return Err(OpcodeResolutionError::BlackBoxFunctionFailed( + black_box_func, + format!("Expected 16 inputs but encountered {}", &message.len()), + )); + } + for (i, input) in inputs.iter().enumerate() { + let value = witness_to_value(initial_witness, input.witness)?; + message[i] = value.to_u128() as u32; + } + + if hash_values.len() != 8 { + return Err(OpcodeResolutionError::BlackBoxFunctionFailed( + black_box_func, + format!("Expected 8 values but encountered {}", hash_values.len()), + )); + } + let mut state = [0; 8]; + for (i, hash) in hash_values.iter().enumerate() { + let value = witness_to_value(initial_witness, hash.witness)?; + state[i] = value.to_u128() as u32; + } + + sha256compression(&mut state, &message); + let outputs: [Witness; 8] = outputs.try_into().map_err(|_| { + OpcodeResolutionError::BlackBoxFunctionFailed( + black_box_func, + format!("Expected 8 outputs but encountered {}", outputs.len()), + ) + })?; + for (output_witness, value) in outputs.iter().zip(state.into_iter()) { + insert_value(output_witness, FieldElement::from(value as u128), initial_witness)?; + } + + Ok(()) +} diff --git a/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/acvm-repo/acvm/src/pwg/blackbox/mod.rs index 7146dff87e0..7ae92fd84fc 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -20,7 +20,7 @@ mod signature; use fixed_base_scalar_mul::{embedded_curve_add, fixed_base_scalar_mul}; // Hash functions should eventually be exposed for external consumers. -use hash::solve_generic_256_hash_opcode; +use hash::{solve_generic_256_hash_opcode, solve_sha_256_permutation_opcode}; use logic::{and, xor}; use pedersen::pedersen; use range::solve_range_opcode; @@ -205,6 +205,14 @@ pub(crate) fn solve( bigint_solver.bigint_to_bytes(*input, outputs, initial_witness) } BlackBoxFuncCall::Poseidon2Permutation { .. } => todo!(), - BlackBoxFuncCall::Sha256Compression { .. } => todo!(), + BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => { + solve_sha_256_permutation_opcode( + initial_witness, + inputs, + hash_values, + outputs, + bb_func.get_black_box_func(), + ) + } } } diff --git a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index 07c343c5ba0..27abd72305f 100644 --- a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,13 +2,13 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 73, 14, 131, 48, 12, 28, 147, 166, 165, 167, 126, 161, 82, 251, 128, 180, - 47, 224, 47, 85, 111, 32, 56, 242, 124, 130, 24, 68, 176, 2, 23, 130, 4, 35, 89, 206, 50, 137, 71, 182, 147, 28, 128, - 96, 128, 241, 150, 113, 44, 156, 135, 24, 121, 5, 189, 219, 134, 143, 164, 187, 203, 237, 165, 49, 59, 129, 70, 179, - 131, 198, 177, 31, 14, 90, 239, 148, 117, 73, 154, 63, 19, 121, 63, 23, 111, 214, 219, 149, 243, 27, 125, 206, 117, - 208, 63, 85, 222, 161, 248, 32, 167, 72, 162, 245, 235, 44, 166, 94, 20, 21, 251, 30, 196, 253, 213, 85, 83, 254, 91, - 163, 168, 90, 234, 43, 24, 191, 213, 190, 172, 156, 235, 17, 126, 59, 49, 142, 68, 120, 75, 220, 7, 166, 84, 90, 68, - 72, 194, 139, 180, 136, 25, 58, 46, 103, 45, 188, 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, 154, 35, 8, 51, 7, 232, 204, + 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, + 204, 48, 206, 18, 158, 19, 175, 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, + 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, 250, 201, 99, 206, 251, + 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, + 20, 85, 75, 253, 136, 249, 87, 249, 105, 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, + 34, 14, 164, 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/acvm-repo/acvm_js/test/shared/foreign_call.ts b/acvm-repo/acvm_js/test/shared/foreign_call.ts index cfa7c679b18..0be8937b57d 100644 --- a/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,10 +2,10 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 65, 10, 192, 32, 12, 4, 215, 148, 150, 246, 212, 175, 216, 31, 244, 51, - 61, 244, 226, 65, 196, 247, 171, 24, 33, 136, 122, 209, 129, 144, 176, 132, 101, 247, 4, 160, 144, 217, 196, 45, 41, - 218, 203, 91, 207, 241, 168, 117, 94, 90, 230, 37, 238, 144, 216, 27, 249, 11, 87, 156, 131, 239, 223, 248, 207, 186, - 81, 235, 150, 67, 173, 221, 189, 95, 18, 34, 97, 64, 0, 116, 135, 40, 214, 136, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, 212, 79, 177, 127, 208, 159, + 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, + 50, 245, 26, 175, 218, 231, 165, 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, + 104, 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index 7359cf307e4..a13f496f34f 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -18,7 +18,7 @@ thiserror.workspace = true blake2 = "0.10.6" blake3 = "1.5.0" -sha2 = "0.10.6" +sha2 = { version="0.10.6", features = ["compress",] } sha3 = "0.10.6" keccak = "0.1.4" k256 = { version = "0.11.0", features = [ diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index afba4eff17c..e033344fefa 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -43,6 +43,16 @@ pub fn keccak256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Keccak256, err)) } +pub fn sha256compression(state: &mut [u32; 8], msg_blocks: &[u32; 16]) { + let mut blocks = [0_u8; 64]; + for (i, block) in msg_blocks.iter().enumerate() { + let bytes = block.to_be_bytes(); + blocks[i * 4..i * 4 + 4].copy_from_slice(&bytes); + } + let blocks: GenericArray = blocks.into(); + sha2::compress256(state, &[blocks]); +} + const KECCAK_LANES: usize = 25; pub fn keccakf1600( diff --git a/acvm-repo/brillig/src/opcodes.rs b/acvm-repo/brillig/src/opcodes.rs index 06c8fdc04eb..51df1f90941 100644 --- a/acvm-repo/brillig/src/opcodes.rs +++ b/acvm-repo/brillig/src/opcodes.rs @@ -98,6 +98,11 @@ pub enum BrilligOpcode { lhs: MemoryAddress, rhs: MemoryAddress, }, + Cast { + destination: MemoryAddress, + source: MemoryAddress, + bit_size: u32, + }, JumpIfNot { condition: MemoryAddress, location: Label, diff --git a/acvm-repo/brillig_vm/src/black_box.rs b/acvm-repo/brillig_vm/src/black_box.rs index 04aa2bcf9af..5b2680465ab 100644 --- a/acvm-repo/brillig_vm/src/black_box.rs +++ b/acvm-repo/brillig_vm/src/black_box.rs @@ -2,7 +2,7 @@ use acir::brillig::{BlackBoxOp, HeapArray, HeapVector, Value}; use acir::{BlackBoxFunc, FieldElement}; use acvm_blackbox_solver::{ blake2s, blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, keccakf1600, - sha256, BlackBoxFunctionSolver, BlackBoxResolutionError, + sha256, sha256compression, BlackBoxFunctionSolver, BlackBoxResolutionError, }; use crate::Memory; @@ -185,7 +185,36 @@ pub(crate) fn evaluate_black_box( BlackBoxOp::BigIntFromLeBytes { .. } => todo!(), BlackBoxOp::BigIntToLeBytes { .. } => todo!(), BlackBoxOp::Poseidon2Permutation { .. } => todo!(), - BlackBoxOp::Sha256Compression { .. } => todo!(), + BlackBoxOp::Sha256Compression { input, hash_values, output } => { + let mut message = [0; 16]; + let inputs = read_heap_vector(memory, input); + if inputs.len() != 16 { + return Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::Sha256Compression, + format!("Expected 16 inputs but encountered {}", &inputs.len()), + )); + } + for (i, input) in inputs.iter().enumerate() { + message[i] = input.to_u128() as u32; + } + let mut state = [0; 8]; + let values = read_heap_vector(memory, hash_values); + if values.len() != 8 { + return Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::Sha256Compression, + format!("Expected 8 values but encountered {}", &values.len()), + )); + } + for (i, value) in values.iter().enumerate() { + state[i] = value.to_u128() as u32; + } + + sha256compression(&mut state, &message); + let state = state.map(|x| Value::from(x as u128)); + + memory.write_slice(memory.read_ref(output.pointer), &state); + Ok(()) + } } } diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index 1dd197112d8..13accbeacb3 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -193,6 +193,12 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { self.increment_program_counter() } } + Opcode::Cast { destination: destination_address, source: source_address, bit_size } => { + let source_value = self.memory.read(*source_address); + let casted_value = self.cast(*bit_size, source_value); + self.memory.write(*destination_address, casted_value); + self.increment_program_counter() + } Opcode::Jump { location: destination } => self.set_program_counter(*destination), Opcode::JumpIf { condition, location: destination } => { // Check if condition is true @@ -511,6 +517,13 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { .write(result, FieldElement::from_be_bytes_reduce(&result_value.to_bytes_be()).into()); Ok(()) } + + /// Casts a value to a different bit size. + fn cast(&self, bit_size: u32, value: Value) -> Value { + let lhs_big = BigUint::from_bytes_be(&value.to_field().to_be_bytes()); + let mask = BigUint::from(2_u32).pow(bit_size) - 1_u32; + FieldElement::from_be_bytes_reduce(&(lhs_big & mask).to_bytes_be()).into() + } } pub(crate) struct DummyBlackBoxSolver; @@ -708,6 +721,40 @@ mod tests { assert_eq!(output_value, Value::from(false)); } + #[test] + fn cast_opcode() { + let calldata = vec![Value::from((2_u128.pow(32)) - 1)]; + + let opcodes = &[ + Opcode::CalldataCopy { + destination_address: MemoryAddress::from(0), + size: 1, + offset: 0, + }, + Opcode::Cast { + destination: MemoryAddress::from(1), + source: MemoryAddress::from(0), + bit_size: 8, + }, + Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + ]; + let mut vm = VM::new(calldata, opcodes, vec![], &DummyBlackBoxSolver); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::Finished { return_data_offset: 1, return_data_size: 1 }); + + let VM { memory, .. } = vm; + + let casted_value = memory.read(MemoryAddress::from(1)); + assert_eq!(casted_value, Value::from(2_u128.pow(8) - 1)); + } + #[test] fn mov_opcode() { let calldata = vec![Value::from(1u128), Value::from(2u128), Value::from(3u128)]; diff --git a/aztec_macros/src/lib.rs b/aztec_macros/src/lib.rs index 7ca4b79eed8..0f054c262bf 100644 --- a/aztec_macros/src/lib.rs +++ b/aztec_macros/src/lib.rs @@ -337,26 +337,27 @@ fn check_for_storage_implementation(module: &SortedModule) -> bool { }) } -// Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,[Field; N]) -> [Field; 4]" is defined +// Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,Field,[Field; N]) -> [Field; 4]" is defined fn check_for_compute_note_hash_and_nullifier_definition(module: &SortedModule) -> bool { module.functions.iter().any(|func| { func.def.name.0.contents == "compute_note_hash_and_nullifier" - && func.def.parameters.len() == 4 + && func.def.parameters.len() == 5 && match &func.def.parameters[0].typ.typ { UnresolvedTypeData::Named(path, _, _) => path.segments.last().unwrap().0.contents == "AztecAddress", _ => false, } && func.def.parameters[1].typ.typ == UnresolvedTypeData::FieldElement && func.def.parameters[2].typ.typ == UnresolvedTypeData::FieldElement - // checks if the 4th parameter is an array and the Box in + && func.def.parameters[3].typ.typ == UnresolvedTypeData::FieldElement + // checks if the 5th parameter is an array and the Box in // Array(Option, Box) contains only fields - && match &func.def.parameters[3].typ.typ { + && match &func.def.parameters[4].typ.typ { UnresolvedTypeData::Array(_, inner_type) => { matches!(inner_type.typ, UnresolvedTypeData::FieldElement) }, _ => false, } - // We check the return type the same way as we did the 4th parameter + // We check the return type the same way as we did the 5th parameter && match &func.def.return_type { FunctionReturnType::Default(_) => false, FunctionReturnType::Ty(unresolved_type) => { diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index d095e4efd5f..65b593b77f5 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -25,7 +25,7 @@ use num_bigint::BigUint; use super::brillig_black_box::convert_black_box_call; use super::brillig_block_variables::BlockVariables; -use super::brillig_fn::FunctionContext; +use super::brillig_fn::{get_bit_size_from_ssa_type, FunctionContext}; /// Generate the compilation artifacts for compiling a function into brillig bytecode. pub(crate) struct BrilligBlock<'block> { @@ -88,16 +88,6 @@ impl<'block> BrilligBlock<'block> { self.convert_ssa_terminator(terminator_instruction, dfg); } - fn get_bit_size_from_ssa_type(typ: &Type) -> u32 { - match typ { - Type::Numeric(num_type) => match num_type { - NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => *bit_size, - NumericType::NativeField => FieldElement::max_num_bits(), - }, - _ => unreachable!("ICE bitwise not on a non numeric type"), - } - } - /// Creates a unique global label for a block. /// /// This uses the current functions's function ID and the block ID @@ -348,7 +338,7 @@ impl<'block> BrilligBlock<'block> { dfg.instruction_results(instruction_id)[0], dfg, ); - let bit_size = Self::get_bit_size_from_ssa_type(&dfg.type_of_value(*value)); + let bit_size = get_bit_size_from_ssa_type(&dfg.type_of_value(*value)); self.brillig_context.not_instruction(condition_register, bit_size, result_register); } Instruction::Call { func, arguments } => match &dfg[*func] { @@ -572,7 +562,7 @@ impl<'block> BrilligBlock<'block> { *bit_size, ); } - Instruction::Cast(value, _) => { + Instruction::Cast(value, typ) => { let result_ids = dfg.instruction_results(instruction_id); let destination_register = self.variables.define_register_variable( self.function_context, @@ -581,7 +571,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); let source_register = self.convert_ssa_register_value(*value, dfg); - self.convert_cast(destination_register, source_register); + self.convert_cast(destination_register, source_register, typ); } Instruction::ArrayGet { array, index } => { let result_ids = dfg.instruction_results(instruction_id); @@ -1159,11 +1149,11 @@ impl<'block> BrilligBlock<'block> { /// Converts an SSA cast to a sequence of Brillig opcodes. /// Casting is only necessary when shrinking the bit size of a numeric value. - fn convert_cast(&mut self, destination: MemoryAddress, source: MemoryAddress) { + fn convert_cast(&mut self, destination: MemoryAddress, source: MemoryAddress, typ: &Type) { // We assume that `source` is a valid `target_type` as it's expected that a truncate instruction was emitted // to ensure this is the case. - self.brillig_context.mov_instruction(destination, source); + self.brillig_context.cast_instruction(destination, source, get_bit_size_from_ssa_type(typ)); } /// Converts the Binary instruction into a sequence of Brillig opcodes. @@ -1209,7 +1199,7 @@ impl<'block> BrilligBlock<'block> { self.brillig_context.const_instruction( register_index, (*constant).into(), - Self::get_bit_size_from_ssa_type(typ), + get_bit_size_from_ssa_type(typ), ); new_variable } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs index 026def4ef11..e96a756a9ee 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs @@ -1,16 +1,17 @@ +use acvm::FieldElement; use iter_extended::vecmap; use crate::{ brillig::brillig_ir::{ artifact::{BrilligParameter, Label}, brillig_variable::BrilligVariable, - BrilligContext, + BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }, ssa::ir::{ basic_block::BasicBlockId, function::{Function, FunctionId}, post_order::PostOrder, - types::Type, + types::{NumericType, Type}, value::ValueId, }, }; @@ -72,7 +73,9 @@ impl FunctionContext { fn ssa_type_to_parameter(typ: &Type) -> BrilligParameter { match typ { - Type::Numeric(_) | Type::Reference(_) => BrilligParameter::Simple, + Type::Numeric(_) | Type::Reference(_) => { + BrilligParameter::Simple(get_bit_size_from_ssa_type(typ)) + } Type::Array(item_type, size) => BrilligParameter::Array( vecmap(item_type.iter(), |item_typ| { FunctionContext::ssa_type_to_parameter(item_typ) @@ -110,3 +113,14 @@ impl FunctionContext { .collect() } } + +pub(crate) fn get_bit_size_from_ssa_type(typ: &Type) -> u32 { + match typ { + Type::Numeric(num_type) => match num_type { + NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => *bit_size, + NumericType::NativeField => FieldElement::max_num_bits(), + }, + Type::Reference(_) => BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + _ => unreachable!("ICE bitwise not on a non numeric type"), + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 3fed8ee91d9..933396be0cb 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -339,7 +339,7 @@ mod tests { use crate::brillig::brillig_ir::tests::{ create_and_run_vm, create_context, create_entry_point_bytecode, }; - use crate::brillig::brillig_ir::BrilligContext; + use crate::brillig::brillig_ir::{BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE}; use crate::ssa::function_builder::FunctionBuilder; use crate::ssa::ir::function::RuntimeType; use crate::ssa::ir::map::Id; @@ -378,11 +378,16 @@ mod tests { expected_return: Vec, ) { let arguments = vec![ - BrilligParameter::Array(vec![BrilligParameter::Simple], array.len()), - BrilligParameter::Simple, + BrilligParameter::Array( + vec![BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], + array.len(), + ), + BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; - let returns = - vec![BrilligParameter::Array(vec![BrilligParameter::Simple], array.len() + 1)]; + let returns = vec![BrilligParameter::Array( + vec![BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], + array.len() + 1, + )]; let (_, mut function_context, mut context) = create_test_environment(); @@ -466,11 +471,16 @@ mod tests { expected_return_array: Vec, expected_return_item: Value, ) { - let arguments = - vec![BrilligParameter::Array(vec![BrilligParameter::Simple], array.len())]; + let arguments = vec![BrilligParameter::Array( + vec![BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], + array.len(), + )]; let returns = vec![ - BrilligParameter::Array(vec![BrilligParameter::Simple], array.len() - 1), - BrilligParameter::Simple, + BrilligParameter::Array( + vec![BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], + array.len() - 1, + ), + BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; let (_, mut function_context, mut context) = create_test_environment(); @@ -548,12 +558,17 @@ mod tests { expected_return: Vec, ) { let arguments = vec![ - BrilligParameter::Array(vec![BrilligParameter::Simple], array.len()), - BrilligParameter::Simple, - BrilligParameter::Simple, + BrilligParameter::Array( + vec![BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], + array.len(), + ), + BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), + BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; - let returns = - vec![BrilligParameter::Array(vec![BrilligParameter::Simple], array.len() + 1)]; + let returns = vec![BrilligParameter::Array( + vec![BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], + array.len() + 1, + )]; let (_, mut function_context, mut context) = create_test_environment(); @@ -660,12 +675,18 @@ mod tests { expected_removed_item: Value, ) { let arguments = vec![ - BrilligParameter::Array(vec![BrilligParameter::Simple], array.len()), - BrilligParameter::Simple, + BrilligParameter::Array( + vec![BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], + array.len(), + ), + BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; let returns = vec![ - BrilligParameter::Array(vec![BrilligParameter::Simple], array.len() - 1), - BrilligParameter::Simple, + BrilligParameter::Array( + vec![BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], + array.len() - 1, + ), + BrilligParameter::Simple(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; let (_, mut function_context, mut context) = create_test_environment(); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 94656ed6f46..963b602e7bf 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -501,6 +501,17 @@ impl BrilligContext { self.push_opcode(BrilligOpcode::Mov { destination, source }); } + /// Cast truncates the value to the given bit size and converts the type of the value in memory to that bit size. + pub(crate) fn cast_instruction( + &mut self, + destination: MemoryAddress, + source: MemoryAddress, + bit_size: u32, + ) { + self.debug_show.cast_instruction(destination, source, bit_size); + self.push_opcode(BrilligOpcode::Cast { destination, source, bit_size }); + } + /// Processes a binary instruction according `operation`. /// /// This method will compute lhs rhs diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 437774da157..4ef8c9d1dfc 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -6,8 +6,11 @@ use crate::ssa::ir::dfg::CallStack; /// Represents a parameter or a return value of a function. #[derive(Debug, Clone)] pub(crate) enum BrilligParameter { - Simple, + /// A simple parameter or return value. Holds the bit size of the parameter. + Simple(u32), + /// An array parameter or return value. Holds the type of an array item and its size. Array(Vec, usize), + /// A slice parameter or return value. Holds the type of a slice item. Slice(Vec), } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index 616c5c5027a..dd57f0c4426 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -171,6 +171,22 @@ impl DebugShow { debug_println!(self.enable_debug_trace, " MOV {}, {}", destination, source); } + /// Emits a `cast` instruction. + pub(crate) fn cast_instruction( + &self, + destination: MemoryAddress, + source: MemoryAddress, + bit_size: u32, + ) { + debug_println!( + self.enable_debug_trace, + " CAST {}, {} as u{}", + destination, + source, + bit_size + ); + } + /// Processes a binary instruction according `operation`. pub(crate) fn binary_instruction( &self, diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index fc4ac36d7fd..0eb4c8c31bd 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -5,7 +5,10 @@ use super::{ registers::BrilligRegistersContext, BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }; -use acvm::acir::brillig::{MemoryAddress, Opcode as BrilligOpcode}; +use acvm::{ + acir::brillig::{MemoryAddress, Opcode as BrilligOpcode}, + FieldElement, +}; pub(crate) const MAX_STACK_SIZE: usize = 1024; @@ -52,11 +55,7 @@ impl BrilligContext { }); // Copy calldata - self.push_opcode(BrilligOpcode::CalldataCopy { - destination_address: MemoryAddress(MAX_STACK_SIZE), - size: calldata_size, - offset: 0, - }); + self.copy_and_cast_calldata(arguments); // Allocate the variables for every argument: let mut current_calldata_pointer = MAX_STACK_SIZE; @@ -64,7 +63,7 @@ impl BrilligContext { let mut argument_variables: Vec<_> = arguments .iter() .map(|argument| match argument { - BrilligParameter::Simple => { + BrilligParameter::Simple(_) => { let simple_address = self.allocate_register(); let var = BrilligVariable::Simple(simple_address); self.mov_instruction(simple_address, MemoryAddress(current_calldata_pointer)); @@ -107,10 +106,40 @@ impl BrilligContext { } } + fn copy_and_cast_calldata(&mut self, arguments: &[BrilligParameter]) { + let calldata_size = BrilligContext::flattened_tuple_size(arguments); + self.push_opcode(BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress(MAX_STACK_SIZE), + size: calldata_size, + offset: 0, + }); + + fn flat_bit_sizes(param: &BrilligParameter) -> Box + '_> { + match param { + BrilligParameter::Simple(bit_size) => Box::new(std::iter::once(*bit_size)), + BrilligParameter::Array(item_types, item_count) => Box::new( + (0..*item_count).flat_map(move |_| item_types.iter().flat_map(flat_bit_sizes)), + ), + BrilligParameter::Slice(..) => unimplemented!("Unsupported slices as parameter"), + } + } + + for (i, bit_size) in arguments.iter().flat_map(flat_bit_sizes).enumerate() { + // Calldatacopy tags everything with field type, so when downcast when necessary + if bit_size < FieldElement::max_num_bits() { + self.push_opcode(BrilligOpcode::Cast { + destination: MemoryAddress(MAX_STACK_SIZE + i), + source: MemoryAddress(MAX_STACK_SIZE + i), + bit_size, + }); + } + } + } + /// Computes the size of a parameter if it was flattened fn flattened_size(param: &BrilligParameter) -> usize { match param { - BrilligParameter::Simple => 1, + BrilligParameter::Simple(_) => 1, BrilligParameter::Array(item_types, item_count) => { let item_size: usize = item_types.iter().map(BrilligContext::flattened_size).sum(); item_count * item_size @@ -128,7 +157,7 @@ impl BrilligContext { /// Computes the size of a parameter if it was flattened fn has_nested_arrays(tuple: &[BrilligParameter]) -> bool { - tuple.iter().any(|param| !matches!(param, BrilligParameter::Simple)) + tuple.iter().any(|param| !matches!(param, BrilligParameter::Simple(_))) } /// Deflatten an array by recursively allocating nested arrays and copying the plain values. @@ -165,7 +194,7 @@ impl BrilligContext { self.make_usize_constant((target_item_base_index + subitem_index).into()); match subitem { - BrilligParameter::Simple => { + BrilligParameter::Simple(_) => { self.array_get( flattened_array_pointer, source_index, @@ -250,7 +279,7 @@ impl BrilligContext { let returned_variables: Vec<_> = return_parameters .iter() .map(|return_parameter| match return_parameter { - BrilligParameter::Simple => BrilligVariable::Simple(self.allocate_register()), + BrilligParameter::Simple(_) => BrilligVariable::Simple(self.allocate_register()), BrilligParameter::Array(item_types, item_count) => { BrilligVariable::BrilligArray(BrilligArray { pointer: self.allocate_register(), @@ -272,7 +301,7 @@ impl BrilligContext { for (return_param, returned_variable) in return_parameters.iter().zip(&returned_variables) { match return_param { - BrilligParameter::Simple => { + BrilligParameter::Simple(_) => { self.mov_instruction( MemoryAddress(return_data_index), returned_variable.extract_register(), @@ -330,7 +359,7 @@ impl BrilligContext { self.make_usize_constant((target_item_base_index + target_offset).into()); match subitem { - BrilligParameter::Simple => { + BrilligParameter::Simple(_) => { self.array_get( deflattened_array_pointer, source_index, @@ -439,12 +468,12 @@ mod tests { ]; let arguments = vec![BrilligParameter::Array( vec![ - BrilligParameter::Array(vec![BrilligParameter::Simple], 2), - BrilligParameter::Simple, + BrilligParameter::Array(vec![BrilligParameter::Simple(8)], 2), + BrilligParameter::Simple(8), ], 2, )]; - let returns = vec![BrilligParameter::Simple]; + let returns = vec![BrilligParameter::Simple(8)]; let mut context = create_context(); @@ -477,8 +506,8 @@ mod tests { ]; let array_param = BrilligParameter::Array( vec![ - BrilligParameter::Array(vec![BrilligParameter::Simple], 2), - BrilligParameter::Simple, + BrilligParameter::Array(vec![BrilligParameter::Simple(8)], 2), + BrilligParameter::Simple(8), ], 2, ); diff --git a/docs/docs/noir/modules_packages_crates/crates_and_packages.md b/docs/docs/noir/modules_packages_crates/crates_and_packages.md index 760a463094c..95ee9f52ab2 100644 --- a/docs/docs/noir/modules_packages_crates/crates_and_packages.md +++ b/docs/docs/noir/modules_packages_crates/crates_and_packages.md @@ -24,7 +24,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### Contracts -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts/contracts). +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). ### Crate Root diff --git a/docs/docs/noir/modules_packages_crates/dependencies.md b/docs/docs/noir/modules_packages_crates/dependencies.md index a37dc401b7d..04c1703d929 100644 --- a/docs/docs/noir/modules_packages_crates/dependencies.md +++ b/docs/docs/noir/modules_packages_crates/dependencies.md @@ -35,7 +35,7 @@ If the module is in a subdirectory, you can define a subdirectory in your git re # Nargo.toml [dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/contracts/easy_private_token_contract"} +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/contracts/easy_private_token_contract"} ``` ## Specifying a local dependency diff --git a/noir_stdlib/src/sha256.nr b/noir_stdlib/src/sha256.nr index 39e39b8cb6e..6bcc5ea74c6 100644 --- a/noir_stdlib/src/sha256.nr +++ b/noir_stdlib/src/sha256.nr @@ -1,91 +1,6 @@ // Implementation of SHA-256 mapping a byte array of variable length to // 32 bytes. -// Internal functions act on 32-bit unsigned integers for simplicity. -// Auxiliary mappings; names as in FIPS PUB 180-4 -fn rotr32(a: u32, b: u32) -> u32 // 32-bit right rotation -{ - // None of the bits overlap between `(a >> b)` and `(a << (32 - b))` - // Addition is then equivalent to OR, with fewer constraints. - (a >> b) + (a << (32 - b)) -} - -fn ch(x: u32, y: u32, z: u32) -> u32 { - (x & y) ^ ((!x) & z) -} - -fn maj(x: u32, y: u32, z: u32) -> u32 { - (x & y) ^ (x & z) ^ (y & z) -} - -fn bigma0(x: u32) -> u32 { - rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22) -} -fn bigma1(x: u32) -> u32 { - rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25) -} - -fn sigma0(x: u32) -> u32 { - rotr32(x, 7) ^ rotr32(x, 18) ^ (x >> 3) -} - -fn sigma1(x: u32) -> u32 { - rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10) -} - -fn sha_w(msg: [u32; 16]) -> [u32; 64] // Expanded message blocks -{ - let mut w: [u32;64] = [0; 64]; - - for j in 0..16 { - w[j] = msg[j]; - } - - for j in 16..64 { - w[j] = crate::wrapping_add( - crate::wrapping_add(sigma1(w[j-2]), w[j-7]), - crate::wrapping_add(sigma0(w[j-15]), w[j-16]), - ); - } - - w -} -// SHA-256 compression function -fn sha_c(msg: [u32; 16], hash: [u32; 8]) -> [u32; 8] { - let K: [u32; 64] = [ - 1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, - 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, - 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, - 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, - 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, - 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, - 3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, - 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, - 2361852424, 2428436474, 2756734187, 3204031479, 3329325298 - ]; // first 32 bits of fractional parts of cube roots of first 64 primes - let mut out_h: [u32; 8] = hash; - let w = sha_w(msg); - for j in 0..64 { - let t1 = crate::wrapping_add( - crate::wrapping_add( - crate::wrapping_add(out_h[7], bigma1(out_h[4])), - ch(out_h[4], out_h[5], out_h[6]) - ), - crate::wrapping_add(K[j], w[j]) - ); - let t2 = crate::wrapping_add(bigma0(out_h[0]), maj(out_h[0], out_h[1], out_h[2])); - out_h[7] = out_h[6]; - out_h[6] = out_h[5]; - out_h[5] = out_h[4]; - out_h[4] = crate::wrapping_add(out_h[3], t1); - out_h[3] = out_h[2]; - out_h[2] = out_h[1]; - out_h[1] = out_h[0]; - out_h[0] = crate::wrapping_add(t1, t2); - } - - out_h -} // Convert 64-byte array to array of 16 u32s fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] { let mut msg32: [u32; 16] = [0; 16]; @@ -102,19 +17,15 @@ fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] { pub fn digest(msg: [u8; N]) -> [u8; 32] { let mut msg_block: [u8; 64] = [0; 64]; let mut h: [u32; 8] = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; // Intermediate hash, starting with the canonical initial value - let mut c: [u32; 8] = [0; 8]; // Compression of current message block as sequence of u32 let mut out_h: [u8; 32] = [0; 32]; // Digest as sequence of bytes let mut i: u64 = 0; // Message byte pointer - for k in 0..msg.len() { + for k in 0..N { // Populate msg_block msg_block[i as Field] = msg[k]; i = i + 1; if i == 64 { // Enough to hash block - c = sha_c(msg_u8_to_u32(msg_block), h); - for j in 0..8 { - h[j] = crate::wrapping_add(c[j], h[j]); - } + h = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), h); i = 0; } @@ -135,11 +46,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { } } } - c = h; - c = sha_c(msg_u8_to_u32(msg_block), c); - for j in 0..8 { - h[j] = crate::wrapping_add(h[j], c[j]); - } + h = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), h); i = 0; } @@ -159,11 +66,8 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { } } // Hash final padded block - c = h; - c = sha_c(msg_u8_to_u32(msg_block), c); - for j in 0..8 { - h[j] = crate::wrapping_add(h[j], c[j]); - } + h = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), h); + // Return final hash as byte array for j in 0..8 { for k in 0..4 { diff --git a/tooling/bb_abstraction_leaks/build.rs b/tooling/bb_abstraction_leaks/build.rs index 24603186c87..f9effd5d991 100644 --- a/tooling/bb_abstraction_leaks/build.rs +++ b/tooling/bb_abstraction_leaks/build.rs @@ -10,7 +10,7 @@ use const_format::formatcp; const USERNAME: &str = "AztecProtocol"; const REPO: &str = "aztec-packages"; -const VERSION: &str = "0.23.0"; +const VERSION: &str = "0.24.0"; const TAG: &str = formatcp!("aztec-packages-v{}", VERSION); const API_URL: &str = diff --git a/tooling/nargo_fmt/tests/expected/contract.nr b/tooling/nargo_fmt/tests/expected/contract.nr index ed828289d22..b80efeeb692 100644 --- a/tooling/nargo_fmt/tests/expected/contract.nr +++ b/tooling/nargo_fmt/tests/expected/contract.nr @@ -79,6 +79,7 @@ contract Benchmarking { contract_address: AztecAddress, nonce: Field, storage_slot: Field, + note_type_id: Field, preimage: [Field; VALUE_NOTE_LEN] ) -> [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); diff --git a/tooling/nargo_fmt/tests/input/contract.nr b/tooling/nargo_fmt/tests/input/contract.nr index 2e3f4d7c8c4..d10bfb745b6 100644 --- a/tooling/nargo_fmt/tests/input/contract.nr +++ b/tooling/nargo_fmt/tests/input/contract.nr @@ -75,6 +75,7 @@ contract Benchmarking { contract_address: AztecAddress, nonce: Field, storage_slot: Field, + note_type_id: Field, preimage: [Field; VALUE_NOTE_LEN] ) -> [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); diff --git a/tooling/noir_js_backend_barretenberg/package.json b/tooling/noir_js_backend_barretenberg/package.json index b8ab24a73bd..8f04decc57f 100644 --- a/tooling/noir_js_backend_barretenberg/package.json +++ b/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.23.0", + "@aztec/bb.js": "0.24.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/yarn.lock b/yarn.lock index a83bc234e1d..b00ce635bdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -221,9 +221,9 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.23.0": - version: 0.23.0 - resolution: "@aztec/bb.js@npm:0.23.0" +"@aztec/bb.js@npm:0.24.0": + version: 0.24.0 + resolution: "@aztec/bb.js@npm:0.24.0" dependencies: comlink: ^4.4.1 commander: ^10.0.1 @@ -231,7 +231,7 @@ __metadata: tslib: ^2.4.0 bin: bb.js: dest/node/main.js - checksum: e7bd32a20575a2834fa8a0500becdfae88a8f4a031c0f1796713d64a8ec90e516e16360f19031efeec59d51ede78c50422982ee08911c062bfa3142819af01fc + checksum: a086dabf30084cfa526e512148b9c02f0a0770dcc19b7dca4af9a3e98612b716acc7eaac6b52c0f12d985932e866d1cb9e534ded6ac9d747f3dd021afe25de27 languageName: node linkType: hard @@ -4379,7 +4379,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.23.0 + "@aztec/bb.js": 0.24.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3