From 160c9a590070f885a3d467b9e2eabd5114b2a125 Mon Sep 17 00:00:00 2001 From: guipublic Date: Thu, 8 Feb 2024 09:50:29 +0000 Subject: [PATCH] create constraints for sha256 compression opcode --- .../dsl/acir_format/acir_format.cpp | 3 + .../dsl/acir_format/acir_format.hpp | 2 + .../dsl/acir_format/acir_format.test.cpp | 6 + .../acir_format/acir_to_constraint_buf.hpp | 18 +++ .../acir_format/bigint_constraint.test.cpp | 4 + .../dsl/acir_format/block_constraint.test.cpp | 1 + .../dsl/acir_format/ec_operations.test.cpp | 1 + .../dsl/acir_format/ecdsa_secp256k1.test.cpp | 3 + .../dsl/acir_format/ecdsa_secp256r1.test.cpp | 4 + .../acir_format/recursion_constraint.test.cpp | 2 + .../dsl/acir_format/sha256_constraint.cpp | 50 +++++++++ .../dsl/acir_format/sha256_constraint.hpp | 14 +++ .../acir_format/sha256_constraint.test.cpp | 104 ++++++++++++++++++ 13 files changed, 212 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 6831103c3c3..79f39889e56 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -32,6 +32,9 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo for (const auto& constraint : constraint_system.sha256_constraints) { create_sha256_constraints(builder, constraint); } + for (const auto& constraint : constraint_system.sha256_compression) { + create_sha256_compression_constraints(builder, constraint); + } // Add schnorr constraints for (const auto& constraint : constraint_system.schnorr_constraints) { diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 6ccf0371774..c74607e7412 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -34,6 +34,7 @@ struct AcirFormat { std::vector logic_constraints; std::vector range_constraints; std::vector sha256_constraints; + std::vector sha256_compression; std::vector schnorr_constraints; std::vector ecdsa_k1_constraints; std::vector ecdsa_r1_constraints; @@ -65,6 +66,7 @@ struct AcirFormat { logic_constraints, range_constraints, sha256_constraints, + sha256_compression, schnorr_constraints, ecdsa_k1_constraints, ecdsa_r1_constraints, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp index fe34de33aca..7107c95970a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -34,6 +34,7 @@ TEST_F(AcirFormatTests, TestASingleConstraintNoPubInputs) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, @@ -148,6 +149,7 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit) .logic_constraints = { logic_constraint }, .range_constraints = { range_a, range_b }, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, @@ -214,6 +216,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass) .logic_constraints = {}, .range_constraints = range_constraints, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = { schnorr_constraint }, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, @@ -308,6 +311,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifySmallRange) .logic_constraints = {}, .range_constraints = range_constraints, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = { schnorr_constraint }, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, @@ -421,6 +425,7 @@ TEST_F(AcirFormatTests, TestVarKeccak) .logic_constraints = {}, .range_constraints = { range_a, range_b, range_c, range_d }, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, @@ -466,6 +471,7 @@ TEST_F(AcirFormatTests, TestKeccakPermutation) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp index 7d48827ef27..44cfc8a1091 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp @@ -139,6 +139,24 @@ 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) { + af.sha256_compression.push_back(Sha256Compression{ + .inputs = map(arg.inputs, + [](auto& e) { + return Sha256Input{ + .witness = e.witness.value, + .num_bits = e.num_bits, + }; + }), + .hash_values = map(arg.hash_values, + [](auto& e) { + return Sha256Input{ + .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) { af.blake2s_constraints.push_back(Blake2sConstraint{ .inputs = map(arg.inputs, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp index 161c6076692..ab1035b0112 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp @@ -172,6 +172,7 @@ TEST_F(BigIntTests, TestBigIntConstraintMultiple) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, @@ -238,6 +239,7 @@ TEST_F(BigIntTests, TestBigIntConstraintSimple) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, @@ -289,6 +291,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, @@ -344,6 +347,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse2) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp index 90daa030f6e..37a4dd6dd53 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp @@ -115,6 +115,7 @@ TEST_F(UltraPlonkRAM, TestBlockConstraint) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp index 67af3597c9a..92dc537bfbd 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp @@ -54,6 +54,7 @@ TEST_F(EcOperations, TestECOperations) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp index e0ea17fb13b..9e546398c07 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp @@ -94,6 +94,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintSucceed) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = { ecdsa_k1_constraint }, .ecdsa_r1_constraints = {}, @@ -141,6 +142,7 @@ TEST_F(ECDSASecp256k1, TestECDSACompilesForVerifier) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = { ecdsa_k1_constraint }, .ecdsa_r1_constraints = {}, @@ -183,6 +185,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintFail) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = { ecdsa_k1_constraint }, .ecdsa_r1_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp index 86ed2428d67..8269593eefb 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp @@ -129,6 +129,7 @@ TEST(ECDSASecp256r1, test_hardcoded) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = { ecdsa_r1_constraint }, @@ -177,6 +178,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintSucceed) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = { ecdsa_r1_constraint }, @@ -223,6 +225,7 @@ TEST(ECDSASecp256r1, TestECDSACompilesForVerifier) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = { ecdsa_r1_constraint }, @@ -264,6 +267,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintFail) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = { ecdsa_r1_constraint }, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index 0a22466ce88..1c530678e87 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -87,6 +87,7 @@ Builder create_inner_circuit() .logic_constraints = { logic_constraint }, .range_constraints = { range_a, range_b }, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, @@ -242,6 +243,7 @@ Builder create_outer_circuit(std::vector& inner_circuits) .logic_constraints = {}, .range_constraints = {}, .sha256_constraints = {}, + .sha256_compression = {}, .schnorr_constraints = {}, .ecdsa_k1_constraints = {}, .ecdsa_r1_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp index 14d52e14117..f7a0a421362 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp @@ -1,6 +1,7 @@ #include "sha256_constraint.hpp" #include "barretenberg/dsl/types.hpp" #include "barretenberg/stdlib/hash/sha256/sha256.hpp" +#include "barretenberg/stdlib/hash/sha256/sha256_plookup.hpp" #include "round.hpp" namespace acir_format { @@ -41,9 +42,58 @@ template void create_sha256_constraints(Builder& builder, con } } +template +void create_sha256_compression_constraints(Builder& builder, const Sha256Compression& constraint) +{ + using field_ct = bb::stdlib::field_t; + + std::array inputs; + std::array hash_inputs; + + // Get the witness assignment for each witness index + // Note that we do not range-check the inputs, which should be 32 bits, + // because of the lookup-tables. + size_t i = 0; + for (const auto& witness_index_num_bits : constraint.inputs) { + auto witness_index = witness_index_num_bits.witness; + field_ct element = field_ct::from_witness_index(&builder, witness_index); + inputs[i] = element; + ++i; + } + i = 0; + for (const auto& witness_index_num_bits : constraint.hash_values) { + auto witness_index = witness_index_num_bits.witness; + field_ct element = field_ct::from_witness_index(&builder, witness_index); + hash_inputs[i] = element; + ++i; + } + + // Compute sha256 compression + auto output_bytes = bb::stdlib::sha256_plookup::sha256_block(hash_inputs, inputs); + + for (size_t i = 0; i < 8; ++i) { + poly_triple assert_equal{ + .a = output_bytes[i].normalize().witness_index, + .b = constraint.result[i], + .c = 0, + .q_m = 0, + .q_l = 1, + .q_r = -1, + .q_o = 0, + .q_c = 0, + }; + builder.create_poly_gate(assert_equal); + } +} + template void create_sha256_constraints(UltraCircuitBuilder& builder, const Sha256Constraint& constraint); template void create_sha256_constraints(GoblinUltraCircuitBuilder& builder, const Sha256Constraint& constraint); +template void create_sha256_compression_constraints(UltraCircuitBuilder& builder, + const Sha256Compression& constraint); +template void create_sha256_compression_constraints(GoblinUltraCircuitBuilder& builder, + const Sha256Compression& constraint); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp index d1e26a8aeb1..0c36058393a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp @@ -24,7 +24,21 @@ struct Sha256Constraint { MSGPACK_FIELDS(inputs, result); }; +struct Sha256Compression { + std::vector inputs; + std::vector hash_values; + std::vector result; + + friend bool operator==(Sha256Compression const& lhs, Sha256Compression const& rhs) = default; + // for serialization, update with any new fields + MSGPACK_FIELDS(inputs, hash_values, result); +}; + // This function does not work (properly) because the stdlib:sha256 function is not working correctly for 512 bits // pair template void create_sha256_constraints(Builder& builder, const Sha256Constraint& constraint); + +template +void create_sha256_compression_constraints(Builder& builder, const Sha256Compression& constraint); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp new file mode 100644 index 00000000000..fbce9f6e246 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp @@ -0,0 +1,104 @@ +#include "sha256_constraint.hpp" +#include "acir_format.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" + +#include +#include + +namespace acir_format::tests { +using curve_ct = bb::stdlib::secp256k1; + +class Sha256Tests : public ::testing::Test { + protected: + static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } +}; + +TEST_F(Sha256Tests, TestSha256Compression) +{ + + std::vector inputs; + for (uint32_t i = 1; i < 17; ++i) { + inputs.push_back({ .witness = i, .num_bits = 32 }); + } + std::vector hash_values; + for (uint32_t i = 17; i < 25; ++i) { + hash_values.push_back({ .witness = i, .num_bits = 32 }); + } + Sha256Compression sha256_compression{ + .inputs = inputs, + .hash_values = hash_values, + .result = { 25, 26, 27, 28, 29, 30, 31, 32 }, + }; + + AcirFormat constraint_system{ .varnum = 34, + .recursive = false, + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .sha256_compression = { sha256_compression }, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, + .bigint_operations = {}, + .constraints = {}, + .block_constraints = {} }; + + WitnessVector witness{ 0, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + static_cast(3349900789), + 1645852969, + static_cast(3630270619), + 1004429770, + 739824817, + static_cast(3544323979), + 557795688, + static_cast(3481642555) }; + + auto builder = create_circuit(constraint_system, /*size_hint=*/0, witness); + + auto composer = Composer(); + auto prover = composer.create_ultra_with_keccak_prover(builder); + auto proof = prover.construct_proof(); + + auto verifier = composer.create_ultra_with_keccak_verifier(builder); + + EXPECT_EQ(verifier.verify_proof(proof), true); +} +} // namespace acir_format::tests \ No newline at end of file