From 784d7b2cfb35f1c923f363f33b3fedadaabba48a Mon Sep 17 00:00:00 2001 From: Tom French Date: Wed, 10 Jan 2024 10:20:45 +0000 Subject: [PATCH 1/3] feat!: implement keccakf1600 in brillig --- noir/acvm-repo/acvm/src/pwg/blackbox/hash.rs | 79 ----------------- noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs | 8 +- noir/acvm-repo/blackbox_solver/src/lib.rs | 86 +++++++++++++++++++ .../bn254_blackbox_solver/src/lib.rs | 12 +-- noir/acvm-repo/brillig/src/black_box.rs | 10 ++- noir/acvm-repo/brillig_vm/src/black_box.rs | 17 +++- .../brillig/brillig_gen/brillig_black_box.rs | 22 +++-- .../src/brillig/brillig_ir/debug_show.rs | 3 + 8 files changed, 140 insertions(+), 97 deletions(-) diff --git a/noir/acvm-repo/acvm/src/pwg/blackbox/hash.rs b/noir/acvm-repo/acvm/src/pwg/blackbox/hash.rs index bbf7dd43bd95..1ada397fc598 100644 --- a/noir/acvm-repo/acvm/src/pwg/blackbox/hash.rs +++ b/noir/acvm-repo/acvm/src/pwg/blackbox/hash.rs @@ -86,82 +86,3 @@ fn write_digest_to_outputs( Ok(()) } - -const ROUNDS: usize = 24; - -const RC: [u64; ROUNDS] = [ - 1u64, - 0x8082u64, - 0x800000000000808au64, - 0x8000000080008000u64, - 0x808bu64, - 0x80000001u64, - 0x8000000080008081u64, - 0x8000000000008009u64, - 0x8au64, - 0x88u64, - 0x80008009u64, - 0x8000000au64, - 0x8000808bu64, - 0x800000000000008bu64, - 0x8000000000008089u64, - 0x8000000000008003u64, - 0x8000000000008002u64, - 0x8000000000000080u64, - 0x800au64, - 0x800000008000000au64, - 0x8000000080008081u64, - 0x8000000000008080u64, - 0x80000001u64, - 0x8000000080008008u64, -]; - -const RHO: [u32; 24] = - [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44]; - -const PI: [usize; 24] = - [10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1]; - -const KECCAK_LANES: usize = 25; - -pub(crate) fn keccakf1600(state: &mut [u64; KECCAK_LANES]) { - for rc in RC { - let mut array: [u64; 5] = [0; 5]; - - // Theta - for x in 0..5 { - for y_count in 0..5 { - let y = y_count * 5; - array[x] ^= state[x + y]; - } - } - - for x in 0..5 { - for y_count in 0..5 { - let y = y_count * 5; - state[y + x] ^= array[(x + 4) % 5] ^ array[(x + 1) % 5].rotate_left(1); - } - } - - // Rho and pi - let mut last = state[1]; - for x in 0..24 { - array[0] = state[PI[x]]; - state[PI[x]] = last.rotate_left(RHO[x]); - last = array[0]; - } - - // Chi - for y_step in 0..5 { - let y = y_step * 5; - array[..5].copy_from_slice(&state[y..(5 + y)]); - - for x in 0..5 { - state[y + x] = array[x] ^ ((!array[(x + 1) % 5]) & (array[(x + 2) % 5])); - } - } - - // Iota - state[0] ^= rc; - } -} diff --git a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs index eb16c984b00a..5eea234885c5 100644 --- a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -3,9 +3,9 @@ use acir::{ native_types::{Witness, WitnessMap}, FieldElement, }; -use acvm_blackbox_solver::{blake2s, blake3, keccak256, sha256}; +use acvm_blackbox_solver::{blake2s, blake3, keccak256, keccakf1600, sha256}; -use self::{hash::keccakf1600, pedersen::pedersen_hash}; +use self::pedersen::pedersen_hash; use super::{insert_value, OpcodeNotSolvable, OpcodeResolutionError}; use crate::{pwg::witness_to_value, BlackBoxFunctionSolver}; @@ -119,8 +119,8 @@ pub(crate) fn solve( let lane = witness_assignment.try_to_u64(); state[i] = lane.unwrap(); } - keccakf1600(&mut state); - for (output_witness, value) in outputs.iter().zip(state.into_iter()) { + let output_state = keccakf1600(state)?; + for (output_witness, value) in outputs.iter().zip(output_state.into_iter()) { insert_value(output_witness, FieldElement::from(value as u128), initial_witness)?; } Ok(()) diff --git a/noir/acvm-repo/blackbox_solver/src/lib.rs b/noir/acvm-repo/blackbox_solver/src/lib.rs index 6458f4e6f645..43d687b50a5c 100644 --- a/noir/acvm-repo/blackbox_solver/src/lib.rs +++ b/noir/acvm-repo/blackbox_solver/src/lib.rs @@ -106,6 +106,92 @@ fn generic_hash_256(message: &[u8]) -> Result<[u8; 32], String> { Ok(output_bytes) } +pub fn keccakf1600( + mut state: [u64; KECCAK_LANES], +) -> Result<[u64; KECCAK_LANES], BlackBoxResolutionError> { + keccakf1600_internal(&mut state); + Ok(state) +} + +const ROUNDS: usize = 24; + +const RC: [u64; ROUNDS] = [ + 1u64, + 0x8082u64, + 0x800000000000808au64, + 0x8000000080008000u64, + 0x808bu64, + 0x80000001u64, + 0x8000000080008081u64, + 0x8000000000008009u64, + 0x8au64, + 0x88u64, + 0x80008009u64, + 0x8000000au64, + 0x8000808bu64, + 0x800000000000008bu64, + 0x8000000000008089u64, + 0x8000000000008003u64, + 0x8000000000008002u64, + 0x8000000000000080u64, + 0x800au64, + 0x800000008000000au64, + 0x8000000080008081u64, + 0x8000000000008080u64, + 0x80000001u64, + 0x8000000080008008u64, +]; + +const RHO: [u32; 24] = + [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44]; + +const PI: [usize; 24] = + [10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1]; + +const KECCAK_LANES: usize = 25; + +fn keccakf1600_internal(state: &mut [u64; KECCAK_LANES]) { + for rc in RC { + let mut array: [u64; 5] = [0; 5]; + + // Theta + for x in 0..5 { + for y_count in 0..5 { + let y = y_count * 5; + array[x] ^= state[x + y]; + } + } + + for x in 0..5 { + for y_count in 0..5 { + let y = y_count * 5; + state[y + x] ^= array[(x + 4) % 5] ^ array[(x + 1) % 5].rotate_left(1); + } + } + + // Rho and pi + let mut last = state[1]; + for x in 0..24 { + array[0] = state[PI[x]]; + state[PI[x]] = last.rotate_left(RHO[x]); + last = array[0]; + } + + // Chi + for y_step in 0..5 { + let y = y_step * 5; + array[..5].copy_from_slice(&state[y..(5 + y)]); + + for x in 0..5 { + state[y + x] = array[x] ^ ((!array[(x + 1) % 5]) & (array[(x + 2) % 5])); + } + } + + // Iota + state[0] ^= rc; + } +} + fn verify_secp256k1_ecdsa_signature( hashed_msg: &[u8], public_key_x_bytes: &[u8; 32], diff --git a/noir/acvm-repo/bn254_blackbox_solver/src/lib.rs b/noir/acvm-repo/bn254_blackbox_solver/src/lib.rs index 80de89490ddd..92c45e93dea3 100644 --- a/noir/acvm-repo/bn254_blackbox_solver/src/lib.rs +++ b/noir/acvm-repo/bn254_blackbox_solver/src/lib.rs @@ -90,18 +90,18 @@ impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { fn ec_add( &self, - input1_x: &FieldElement, - input1_y: &FieldElement, - input2_x: &FieldElement, - input2_y: &FieldElement, + _input1_x: &FieldElement, + _input1_y: &FieldElement, + _input2_x: &FieldElement, + _input2_y: &FieldElement, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { todo!(); } fn ec_double( &self, - input_x: &FieldElement, - input_y: &FieldElement, + _input_x: &FieldElement, + _input_y: &FieldElement, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { todo!(); } diff --git a/noir/acvm-repo/brillig/src/black_box.rs b/noir/acvm-repo/brillig/src/black_box.rs index 4c755f8eae2a..f04cbb83de38 100644 --- a/noir/acvm-repo/brillig/src/black_box.rs +++ b/noir/acvm-repo/brillig/src/black_box.rs @@ -11,6 +11,8 @@ pub enum BlackBoxOp { Blake2s { message: HeapVector, output: HeapArray }, /// Calculates the Keccak256 hash of the inputs. Keccak256 { message: HeapVector, output: HeapArray }, + /// Keccak Permutation function of 1600 width + Keccakf1600 { message: HeapVector, output: HeapArray }, /// Verifies a ECDSA signature over the secp256k1 curve. EcdsaSecp256k1 { hashed_msg: HeapVector, @@ -42,7 +44,13 @@ pub enum BlackBoxOp { /// Performs scalar multiplication over the embedded curve. FixedBaseScalarMul { low: RegisterIndex, high: RegisterIndex, result: HeapArray }, /// Performs addtion over the embedded curve. - EmbeddedCurveAdd { input1_x: RegisterIndex, input1_y: RegisterIndex, input2_x: RegisterIndex, input2_y: RegisterIndex, result: HeapArray }, + EmbeddedCurveAdd { + input1_x: RegisterIndex, + input1_y: RegisterIndex, + input2_x: RegisterIndex, + input2_y: RegisterIndex, + result: HeapArray, + }, /// Performs point doubling over the embedded curve. EmbeddedCurveDouble { input1_x: RegisterIndex, input1_y: RegisterIndex, result: HeapArray }, } diff --git a/noir/acvm-repo/brillig_vm/src/black_box.rs b/noir/acvm-repo/brillig_vm/src/black_box.rs index 012d527e44ed..3452e246a3bd 100644 --- a/noir/acvm-repo/brillig_vm/src/black_box.rs +++ b/noir/acvm-repo/brillig_vm/src/black_box.rs @@ -1,7 +1,7 @@ use acir::brillig::{BlackBoxOp, HeapArray, HeapVector, Value}; use acir::{BlackBoxFunc, FieldElement}; use acvm_blackbox_solver::{ - blake2s, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, sha256, + blake2s, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, keccakf1600, sha256, BlackBoxFunctionSolver, BlackBoxResolutionError, }; @@ -64,6 +64,20 @@ pub(crate) fn evaluate_black_box( memory.write_slice(registers.get(output.pointer).to_usize(), &to_value_vec(&bytes)); Ok(()) } + BlackBoxOp::Keccakf1600 { message, output } => { + let state_vec: Vec = read_heap_vector(memory, registers, message) + .iter() + .map(|value| value.to_field().try_to_u64().unwrap()) + .collect(); + let state: [u64; 25] = state_vec.try_into().unwrap(); + + let new_state = keccakf1600(state)?; + + let new_state: Vec = + new_state.into_iter().map(|x| Value::from(x as usize)).collect(); + memory.write_slice(registers.get(output.pointer).to_usize(), &new_state); + Ok(()) + } BlackBoxOp::EcdsaSecp256k1 { hashed_msg, public_key_x, @@ -188,6 +202,7 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { BlackBoxOp::Sha256 { .. } => BlackBoxFunc::SHA256, BlackBoxOp::Blake2s { .. } => BlackBoxFunc::Blake2s, BlackBoxOp::Keccak256 { .. } => BlackBoxFunc::Keccak256, + BlackBoxOp::Keccakf1600 { .. } => BlackBoxFunc::Keccakf1600, BlackBoxOp::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1, BlackBoxOp::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1, BlackBoxOp::SchnorrVerify { .. } => BlackBoxFunc::SchnorrVerify, diff --git a/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index 8235cbf63401..d59fa473129c 100644 --- a/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -58,6 +58,20 @@ pub(crate) fn convert_black_box_call( unreachable!("ICE: Keccak256 expects message, message size and result array") } } + BlackBoxFunc::Keccakf1600 => { + if let ([message], [BrilligVariable::BrilligArray(result_array)]) = + (function_arguments, function_results) + { + let state_vector = convert_array_or_vector(brillig_context, message, bb_func); + + brillig_context.black_box_op_instruction(BlackBoxOp::Keccakf1600 { + message: state_vector.to_heap_vector(), + output: result_array.to_heap_array(), + }); + } else { + unreachable!("ICE: Keccakf1600 expects one array argument and one array result") + } + } BlackBoxFunc::EcdsaSecp256k1 => { if let ( [BrilligVariable::BrilligArray(public_key_x), BrilligVariable::BrilligArray(public_key_y), BrilligVariable::BrilligArray(signature), message], @@ -171,8 +185,7 @@ pub(crate) fn convert_black_box_call( } BlackBoxFunc::EmbeddedCurveAdd => { if let ( - [BrilligVariable::Simple(input1_x), BrilligVariable::Simple(input1_y), - BrilligVariable::Simple(input2_x), BrilligVariable::Simple(input2_y)], + [BrilligVariable::Simple(input1_x), BrilligVariable::Simple(input1_y), BrilligVariable::Simple(input2_x), BrilligVariable::Simple(input2_y)], [BrilligVariable::BrilligArray(result_array)], ) = (function_arguments, function_results) { @@ -188,7 +201,7 @@ pub(crate) fn convert_black_box_call( "ICE: EmbeddedCurveAdd expects four register arguments and one array result" ) } - } + } BlackBoxFunc::EmbeddedCurveDouble => { if let ( [BrilligVariable::Simple(input1_x), BrilligVariable::Simple(input1_y)], @@ -221,9 +234,6 @@ pub(crate) fn convert_black_box_call( BlackBoxFunc::Blake3 => { unimplemented!("ICE: `BlackBoxFunc::Blake3` is not implemented by the Brillig VM") } - BlackBoxFunc::Keccakf1600 => { - unimplemented!("ICE: `BlackBoxFunc::Keccakf1600` is not implemented by the Brillig VM") - } } } diff --git a/noir/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/noir/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index 0d35d948694b..e38bc6801286 100644 --- a/noir/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/noir/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -350,6 +350,9 @@ impl DebugShow { BlackBoxOp::Keccak256 { message, output } => { debug_println!(self.enable_debug_trace, " KECCAK256 {} -> {}", message, output); } + BlackBoxOp::Keccakf1600 { message, output } => { + debug_println!(self.enable_debug_trace, " KECCAKF1600 {} -> {}", message, output); + } BlackBoxOp::Blake2s { message, output } => { debug_println!(self.enable_debug_trace, " BLAKE2S {} -> {}", message, output); } From 6ca4b0273457eb22746921a520583422602e3acb Mon Sep 17 00:00:00 2001 From: Tom French Date: Wed, 10 Jan 2024 13:29:17 +0000 Subject: [PATCH 2/3] chore: update c++ serialiser logic --- .../dsl/acir_format/serde/acir.hpp | 62 +++++++++++++++++++ noir/acvm-repo/acir/codegen/acir.cpp | 52 +++++++++++++++- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp index b3c2106a4fec..06142dcb956f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -455,6 +455,15 @@ struct BlackBoxOp { static Keccak256 bincodeDeserialize(std::vector); }; + struct Keccakf1600 { + Circuit::HeapVector message; + Circuit::HeapArray output; + + friend bool operator==(const Keccakf1600&, const Keccakf1600&); + std::vector bincodeSerialize() const; + static Keccakf1600 bincodeDeserialize(std::vector); + }; + struct EcdsaSecp256k1 { Circuit::HeapVector hashed_msg; Circuit::HeapArray public_key_x; @@ -546,6 +555,7 @@ struct BlackBoxOp { std::variant BlackBoxOp::Keccakf1600::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std::vector input) +{ + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; +} + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccakf1600& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::Keccakf1600 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + inline bool operator==(const BlackBoxOp::EcdsaSecp256k1& lhs, const BlackBoxOp::EcdsaSecp256k1& rhs) { if (!(lhs.hashed_msg == rhs.hashed_msg)) { diff --git a/noir/acvm-repo/acir/codegen/acir.cpp b/noir/acvm-repo/acir/codegen/acir.cpp index d0b920e057c4..25cc85a43d44 100644 --- a/noir/acvm-repo/acir/codegen/acir.cpp +++ b/noir/acvm-repo/acir/codegen/acir.cpp @@ -437,6 +437,15 @@ namespace Circuit { static Keccak256 bincodeDeserialize(std::vector); }; + struct Keccakf1600 { + Circuit::HeapVector message; + Circuit::HeapArray output; + + friend bool operator==(const Keccakf1600&, const Keccakf1600&); + std::vector bincodeSerialize() const; + static Keccakf1600 bincodeDeserialize(std::vector); + }; + struct EcdsaSecp256k1 { Circuit::HeapVector hashed_msg; Circuit::HeapArray public_key_x; @@ -525,7 +534,7 @@ namespace Circuit { static EmbeddedCurveDouble bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const BlackBoxOp&, const BlackBoxOp&); std::vector bincodeSerialize() const; @@ -2636,6 +2645,47 @@ Circuit::BlackBoxOp::Keccak256 serde::Deserializable BlackBoxOp::Keccakf1600::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::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::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::Keccakf1600 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + namespace Circuit { inline bool operator==(const BlackBoxOp::EcdsaSecp256k1 &lhs, const BlackBoxOp::EcdsaSecp256k1 &rhs) { From e369b3bc8d566e0606c749043cb6b96051b0fb1b Mon Sep 17 00:00:00 2001 From: Tom French Date: Thu, 11 Jan 2024 22:24:31 +0000 Subject: [PATCH 3/3] chore: delete old keccak impl --- noir/acvm-repo/blackbox_solver/src/lib.rs | 86 ----------------------- 1 file changed, 86 deletions(-) diff --git a/noir/acvm-repo/blackbox_solver/src/lib.rs b/noir/acvm-repo/blackbox_solver/src/lib.rs index ba62e3e7501e..e11b9316fdd1 100644 --- a/noir/acvm-repo/blackbox_solver/src/lib.rs +++ b/noir/acvm-repo/blackbox_solver/src/lib.rs @@ -115,92 +115,6 @@ fn generic_hash_256(message: &[u8]) -> Result<[u8; 32], String> { Ok(output_bytes) } -pub fn keccakf1600( - mut state: [u64; KECCAK_LANES], -) -> Result<[u64; KECCAK_LANES], BlackBoxResolutionError> { - keccakf1600_internal(&mut state); - Ok(state) -} - -const ROUNDS: usize = 24; - -const RC: [u64; ROUNDS] = [ - 1u64, - 0x8082u64, - 0x800000000000808au64, - 0x8000000080008000u64, - 0x808bu64, - 0x80000001u64, - 0x8000000080008081u64, - 0x8000000000008009u64, - 0x8au64, - 0x88u64, - 0x80008009u64, - 0x8000000au64, - 0x8000808bu64, - 0x800000000000008bu64, - 0x8000000000008089u64, - 0x8000000000008003u64, - 0x8000000000008002u64, - 0x8000000000000080u64, - 0x800au64, - 0x800000008000000au64, - 0x8000000080008081u64, - 0x8000000000008080u64, - 0x80000001u64, - 0x8000000080008008u64, -]; - -const RHO: [u32; 24] = - [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44]; - -const PI: [usize; 24] = - [10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1]; - -const KECCAK_LANES: usize = 25; - -fn keccakf1600_internal(state: &mut [u64; KECCAK_LANES]) { - for rc in RC { - let mut array: [u64; 5] = [0; 5]; - - // Theta - for x in 0..5 { - for y_count in 0..5 { - let y = y_count * 5; - array[x] ^= state[x + y]; - } - } - - for x in 0..5 { - for y_count in 0..5 { - let y = y_count * 5; - state[y + x] ^= array[(x + 4) % 5] ^ array[(x + 1) % 5].rotate_left(1); - } - } - - // Rho and pi - let mut last = state[1]; - for x in 0..24 { - array[0] = state[PI[x]]; - state[PI[x]] = last.rotate_left(RHO[x]); - last = array[0]; - } - - // Chi - for y_step in 0..5 { - let y = y_step * 5; - array[..5].copy_from_slice(&state[y..(5 + y)]); - - for x in 0..5 { - state[y + x] = array[x] ^ ((!array[(x + 1) % 5]) & (array[(x + 2) % 5])); - } - } - - // Iota - state[0] ^= rc; - } -} - fn verify_secp256k1_ecdsa_signature( hashed_msg: &[u8], public_key_x_bytes: &[u8; 32],