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!: add blake3 blackbox function to acir format #3856

Merged
merged 2 commits into from
Jan 5, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ void build_constraints(Builder& builder, acir_format const& constraint_system, b
create_blake2s_constraints(builder, constraint);
}

// Add blake3 constraints
for (const auto& constraint : constraint_system.blake3_constraints) {
create_blake3_constraints(builder, constraint);
}

// Add keccak constraints
for (const auto& constraint : constraint_system.keccak_constraints) {
create_keccak_constraints(builder, constraint);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "barretenberg/dsl/types.hpp"
#include "barretenberg/serialize/msgpack.hpp"
#include "blake2s_constraint.hpp"
#include "blake3_constraint.hpp"
#include "block_constraint.hpp"
#include "ecdsa_secp256k1.hpp"
#include "ecdsa_secp256r1.hpp"
Expand Down Expand Up @@ -30,6 +31,7 @@ struct acir_format {
std::vector<EcdsaSecp256k1Constraint> ecdsa_k1_constraints;
std::vector<EcdsaSecp256r1Constraint> ecdsa_r1_constraints;
std::vector<Blake2sConstraint> blake2s_constraints;
std::vector<Blake3Constraint> blake3_constraints;
std::vector<KeccakConstraint> keccak_constraints;
std::vector<KeccakVarConstraint> keccak_var_constraints;
std::vector<Keccakf1600> keccak_permutations;
Expand All @@ -56,6 +58,7 @@ struct acir_format {
ecdsa_k1_constraints,
ecdsa_r1_constraints,
blake2s_constraints,
blake3_constraints,
keccak_constraints,
keccak_var_constraints,
keccak_permutations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ TEST_F(AcirFormatTests, TestASingleConstraintNoPubInputs)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -144,6 +145,7 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -209,6 +211,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -297,6 +300,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifySmallRange)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -404,6 +408,7 @@ TEST_F(AcirFormatTests, TestVarKeccak)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = { keccak },
.keccak_permutations = {},
Expand Down Expand Up @@ -442,6 +447,7 @@ TEST_F(AcirFormatTests, TestKeccakPermutation)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = { keccak_permutation },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "barretenberg/common/container.hpp"
#include "barretenberg/common/throw_or_abort.hpp"
#include "barretenberg/dsl/acir_format/blake2s_constraint.hpp"
#include "barretenberg/dsl/acir_format/blake3_constraint.hpp"
#include "barretenberg/dsl/acir_format/block_constraint.hpp"
#include "barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp"
#include "barretenberg/dsl/acir_format/keccak_constraint.hpp"
Expand Down Expand Up @@ -113,6 +114,17 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, aci
}),
.result = map(arg.outputs, [](auto& e) { return e.value; }),
});
} else if constexpr (std::is_same_v<T, Circuit::BlackBoxFuncCall::Blake3>) {
af.blake3_constraints.push_back(Blake3Constraint{
.inputs = map(arg.inputs,
[](auto& e) {
return Blake3Input{
.witness = e.witness.value,
.num_bits = e.num_bits,
};
}),
.result = map(arg.outputs, [](auto& e) { return e.value; }),
});
} else if constexpr (std::is_same_v<T, Circuit::BlackBoxFuncCall::SchnorrVerify>) {
af.schnorr_constraints.push_back(SchnorrConstraint{
.message = map(arg.message, [](auto& e) { return e.witness.value; }),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "blake3_constraint.hpp"
#include "round.hpp"

namespace acir_format {

template <typename Builder> void create_blake3_constraints(Builder& builder, const Blake3Constraint& constraint)
{
using byte_array_ct = proof_system::plonk::stdlib::byte_array<Builder>;
using field_ct = proof_system::plonk::stdlib::field_t<Builder>;

// Create byte array struct
byte_array_ct arr(&builder);

// Get the witness assignment for each witness index
// Write the witness assignment to the byte_array
for (const auto& witness_index_num_bits : constraint.inputs) {
auto witness_index = witness_index_num_bits.witness;
auto num_bits = witness_index_num_bits.num_bits;

// XXX: The implementation requires us to truncate the element to the nearest byte and not bit
auto num_bytes = round_to_nearest_byte(num_bits);

field_ct element = field_ct::from_witness_index(&builder, witness_index);
byte_array_ct element_bytes(element, num_bytes);

arr.write(element_bytes);
}

byte_array_ct output_bytes = proof_system::plonk::stdlib::blake3s<Builder>(arr);

// Convert byte array to vector of field_t
auto bytes = output_bytes.bytes();

for (size_t i = 0; i < bytes.size(); ++i) {
builder.assert_equal(bytes[i].normalize().witness_index, constraint.result[i]);
}
}

template void create_blake3_constraints<UltraCircuitBuilder>(UltraCircuitBuilder& builder,
const Blake3Constraint& constraint);
template void create_blake3_constraints<GoblinUltraCircuitBuilder>(GoblinUltraCircuitBuilder& builder,
const Blake3Constraint& constraint);

} // namespace acir_format
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once
#include "barretenberg/dsl/types.hpp"
#include "barretenberg/serialize/msgpack.hpp"
#include <cstdint>
#include <vector>

namespace acir_format {

struct Blake3Input {
uint32_t witness;
uint32_t num_bits;

// For serialization, update with any new fields
MSGPACK_FIELDS(witness, num_bits);
friend bool operator==(Blake3Input const& lhs, Blake3Input const& rhs) = default;
};

struct Blake3Constraint {
std::vector<Blake3Input> inputs;
std::vector<uint32_t> result;

// For serialization, update with any new fields
MSGPACK_FIELDS(inputs, result);
friend bool operator==(Blake3Constraint const& lhs, Blake3Constraint const& rhs) = default;
};

template <typename Builder> void create_blake3_constraints(Builder& builder, const Blake3Constraint& constraint);

} // namespace acir_format
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ TEST_F(UltraPlonkRAM, TestBlockConstraint)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintSucceed)
.ecdsa_k1_constraints = { ecdsa_k1_constraint },
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -138,6 +139,7 @@ TEST_F(ECDSASecp256k1, TestECDSACompilesForVerifier)
.ecdsa_k1_constraints = { ecdsa_k1_constraint },
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -174,6 +176,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintFail)
.ecdsa_k1_constraints = { ecdsa_k1_constraint },
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ TEST(ECDSASecp256r1, test_hardcoded)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = { ecdsa_r1_constraint },
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -173,6 +174,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintSucceed)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = { ecdsa_r1_constraint },
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -213,6 +215,7 @@ TEST(ECDSASecp256r1, TestECDSACompilesForVerifier)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = { ecdsa_r1_constraint },
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -248,6 +251,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintFail)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = { ecdsa_r1_constraint },
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ Builder create_inner_circuit()
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down Expand Up @@ -248,6 +249,7 @@ Builder create_outer_circuit(std::vector<Builder>& inner_circuits)
.ecdsa_k1_constraints = {},
.ecdsa_r1_constraints = {},
.blake2s_constraints = {},
.blake3_constraints = {},
.keccak_constraints = {},
.keccak_var_constraints = {},
.keccak_permutations = {},
Expand Down
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 @@ -70,6 +70,15 @@ struct BlackBoxFuncCall {
static Blake2s bincodeDeserialize(std::vector<uint8_t>);
};

struct Blake3 {
std::vector<Circuit::FunctionInput> inputs;
std::vector<Circuit::Witness> outputs;

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

struct SchnorrVerify {
Circuit::FunctionInput public_key_x;
Circuit::FunctionInput public_key_y;
Expand Down Expand Up @@ -182,6 +191,7 @@ struct BlackBoxFuncCall {
RANGE,
SHA256,
Blake2s,
Blake3,
SchnorrVerify,
PedersenCommitment,
PedersenHash,
Expand Down Expand Up @@ -2045,6 +2055,58 @@ Circuit::BlackBoxFuncCall::Blake2s serde::Deserializable<Circuit::BlackBoxFuncCa

namespace Circuit {

inline bool operator==(const BlackBoxFuncCall::Blake3& lhs, const BlackBoxFuncCall::Blake3& rhs)
{
if (!(lhs.inputs == rhs.inputs)) {
return false;
}
if (!(lhs.outputs == rhs.outputs)) {
return false;
}
return true;
}

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

inline BlackBoxFuncCall::Blake3 BlackBoxFuncCall::Blake3::bincodeDeserialize(std::vector<uint8_t> input)
{
auto deserializer = serde::BincodeDeserializer(input);
auto value = serde::Deserializable<BlackBoxFuncCall::Blake3>::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::BlackBoxFuncCall::Blake3>::serialize(const Circuit::BlackBoxFuncCall::Blake3& obj,
Serializer& serializer)
{
serde::Serializable<decltype(obj.inputs)>::serialize(obj.inputs, serializer);
serde::Serializable<decltype(obj.outputs)>::serialize(obj.outputs, serializer);
}

template <>
template <typename Deserializer>
Circuit::BlackBoxFuncCall::Blake3 serde::Deserializable<Circuit::BlackBoxFuncCall::Blake3>::deserialize(
Deserializer& deserializer)
{
Circuit::BlackBoxFuncCall::Blake3 obj;
obj.inputs = serde::Deserializable<decltype(obj.inputs)>::deserialize(deserializer);
obj.outputs = serde::Deserializable<decltype(obj.outputs)>::deserialize(deserializer);
return obj;
}

namespace Circuit {

inline bool operator==(const BlackBoxFuncCall::SchnorrVerify& lhs, const BlackBoxFuncCall::SchnorrVerify& rhs)
{
if (!(lhs.public_key_x == rhs.public_key_x)) {
Expand Down
Loading
Loading