Skip to content

Commit

Permalink
feat!: implement keccakf1600 in brillig (AztecProtocol#3914)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Jan 11, 2024
1 parent de31b47 commit a182381
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 8 deletions.
62 changes: 62 additions & 0 deletions barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,15 @@ struct BlackBoxOp {
static Keccak256 bincodeDeserialize(std::vector<uint8_t>);
};

struct Keccakf1600 {
Circuit::HeapVector message;
Circuit::HeapArray output;

friend bool operator==(const Keccakf1600&, const Keccakf1600&);
std::vector<uint8_t> bincodeSerialize() const;
static Keccakf1600 bincodeDeserialize(std::vector<uint8_t>);
};

struct EcdsaSecp256k1 {
Circuit::HeapVector hashed_msg;
Circuit::HeapArray public_key_x;
Expand Down Expand Up @@ -558,6 +567,7 @@ struct BlackBoxOp {
Blake2s,
Blake3,
Keccak256,
Keccakf1600,
EcdsaSecp256k1,
EcdsaSecp256r1,
SchnorrVerify,
Expand Down Expand Up @@ -3148,6 +3158,58 @@ Circuit::BlackBoxOp::Keccak256 serde::Deserializable<Circuit::BlackBoxOp::Keccak

namespace Circuit {

inline bool operator==(const BlackBoxOp::Keccakf1600& lhs, const BlackBoxOp::Keccakf1600& rhs)
{
if (!(lhs.message == rhs.message)) {
return false;
}
if (!(lhs.output == rhs.output)) {
return false;
}
return true;
}

inline std::vector<uint8_t> BlackBoxOp::Keccakf1600::bincodeSerialize() const
{
auto serializer = serde::BincodeSerializer();
serde::Serializable<BlackBoxOp::Keccakf1600>::serialize(*this, serializer);
return std::move(serializer).bytes();
}

inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std::vector<uint8_t> input)
{
auto deserializer = serde::BincodeDeserializer(input);
auto value = serde::Deserializable<BlackBoxOp::Keccakf1600>::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 <typename Serializer>
void serde::Serializable<Circuit::BlackBoxOp::Keccakf1600>::serialize(const Circuit::BlackBoxOp::Keccakf1600& obj,
Serializer& serializer)
{
serde::Serializable<decltype(obj.message)>::serialize(obj.message, serializer);
serde::Serializable<decltype(obj.output)>::serialize(obj.output, serializer);
}

template <>
template <typename Deserializer>
Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable<Circuit::BlackBoxOp::Keccakf1600>::deserialize(
Deserializer& deserializer)
{
Circuit::BlackBoxOp::Keccakf1600 obj;
obj.message = serde::Deserializable<decltype(obj.message)>::deserialize(deserializer);
obj.output = serde::Deserializable<decltype(obj.output)>::deserialize(deserializer);
return obj;
}

namespace Circuit {

inline bool operator==(const BlackBoxOp::EcdsaSecp256k1& lhs, const BlackBoxOp::EcdsaSecp256k1& rhs)
{
if (!(lhs.hashed_msg == rhs.hashed_msg)) {
Expand Down
52 changes: 51 additions & 1 deletion noir/acvm-repo/acir/codegen/acir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,15 @@ namespace Circuit {
static Keccak256 bincodeDeserialize(std::vector<uint8_t>);
};

struct Keccakf1600 {
Circuit::HeapVector message;
Circuit::HeapArray output;

friend bool operator==(const Keccakf1600&, const Keccakf1600&);
std::vector<uint8_t> bincodeSerialize() const;
static Keccakf1600 bincodeDeserialize(std::vector<uint8_t>);
};

struct EcdsaSecp256k1 {
Circuit::HeapVector hashed_msg;
Circuit::HeapArray public_key_x;
Expand Down Expand Up @@ -534,7 +543,7 @@ namespace Circuit {
static EmbeddedCurveDouble bincodeDeserialize(std::vector<uint8_t>);
};

std::variant<Sha256, Blake2s, Blake3, Keccak256, EcdsaSecp256k1, EcdsaSecp256r1, SchnorrVerify, PedersenCommitment, PedersenHash, FixedBaseScalarMul, EmbeddedCurveAdd, EmbeddedCurveDouble> value;
std::variant<Sha256, Blake2s, Blake3, Keccak256, Keccakf1600, EcdsaSecp256k1, EcdsaSecp256r1, SchnorrVerify, PedersenCommitment, PedersenHash, FixedBaseScalarMul, EmbeddedCurveAdd, EmbeddedCurveDouble> value;

friend bool operator==(const BlackBoxOp&, const BlackBoxOp&);
std::vector<uint8_t> bincodeSerialize() const;
Expand Down Expand Up @@ -2686,6 +2695,47 @@ Circuit::BlackBoxOp::Keccak256 serde::Deserializable<Circuit::BlackBoxOp::Keccak
return obj;
}

namespace Circuit {

inline bool operator==(const BlackBoxOp::Keccakf1600 &lhs, const BlackBoxOp::Keccakf1600 &rhs) {
if (!(lhs.message == rhs.message)) { return false; }
if (!(lhs.output == rhs.output)) { return false; }
return true;
}

inline std::vector<uint8_t> BlackBoxOp::Keccakf1600::bincodeSerialize() const {
auto serializer = serde::BincodeSerializer();
serde::Serializable<BlackBoxOp::Keccakf1600>::serialize(*this, serializer);
return std::move(serializer).bytes();
}

inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std::vector<uint8_t> input) {
auto deserializer = serde::BincodeDeserializer(input);
auto value = serde::Deserializable<BlackBoxOp::Keccakf1600>::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 <typename Serializer>
void serde::Serializable<Circuit::BlackBoxOp::Keccakf1600>::serialize(const Circuit::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) {
serde::Serializable<decltype(obj.message)>::serialize(obj.message, serializer);
serde::Serializable<decltype(obj.output)>::serialize(obj.output, serializer);
}

template <>
template <typename Deserializer>
Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable<Circuit::BlackBoxOp::Keccakf1600>::deserialize(Deserializer &deserializer) {
Circuit::BlackBoxOp::Keccakf1600 obj;
obj.message = serde::Deserializable<decltype(obj.message)>::deserialize(deserializer);
obj.output = serde::Deserializable<decltype(obj.output)>::deserialize(deserializer);
return obj;
}

namespace Circuit {

inline bool operator==(const BlackBoxOp::EcdsaSecp256k1 &lhs, const BlackBoxOp::EcdsaSecp256k1 &rhs) {
Expand Down
4 changes: 2 additions & 2 deletions noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ pub(crate) fn solve(
let lane = witness_assignment.try_to_u64();
state[i] = lane.unwrap();
}
let state = keccakf1600(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(())
Expand Down
2 changes: 2 additions & 0 deletions noir/acvm-repo/brillig/src/black_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub enum BlackBoxOp {
Blake3 { 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,
Expand Down
19 changes: 17 additions & 2 deletions noir/acvm-repo/brillig_vm/src/black_box.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use acir::brillig::{BlackBoxOp, HeapArray, HeapVector, Value};
use acir::{BlackBoxFunc, FieldElement};
use acvm_blackbox_solver::{
blake2s, blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, sha256,
BlackBoxFunctionSolver, BlackBoxResolutionError,
blake2s, blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, keccakf1600,
sha256, BlackBoxFunctionSolver, BlackBoxResolutionError,
};

use crate::{Memory, Registers};
Expand Down Expand Up @@ -70,6 +70,20 @@ pub(crate) fn evaluate_black_box<Solver: BlackBoxFunctionSolver>(
memory.write_slice(registers.get(output.pointer).to_usize(), &to_value_vec(&bytes));
Ok(())
}
BlackBoxOp::Keccakf1600 { message, output } => {
let state_vec: Vec<u64> = 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<Value> =
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,
Expand Down Expand Up @@ -195,6 +209,7 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc {
BlackBoxOp::Blake2s { .. } => BlackBoxFunc::Blake2s,
BlackBoxOp::Blake3 { .. } => BlackBoxFunc::Blake3,
BlackBoxOp::Keccak256 { .. } => BlackBoxFunc::Keccak256,
BlackBoxOp::Keccakf1600 { .. } => BlackBoxFunc::Keccakf1600,
BlackBoxOp::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1,
BlackBoxOp::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1,
BlackBoxOp::SchnorrVerify { .. } => BlackBoxFunc::SchnorrVerify,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,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],
Expand Down Expand Up @@ -230,9 +244,6 @@ pub(crate) fn convert_black_box_call(
BlackBoxFunc::RecursiveAggregation => unimplemented!(
"ICE: `BlackBoxFunc::RecursiveAggregation` is not implemented by the Brillig VM"
),
BlackBoxFunc::Keccakf1600 => {
unimplemented!("ICE: `BlackBoxFunc::Keccakf1600` is not implemented by the Brillig VM")
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit a182381

Please sign in to comment.