diff --git a/barretenberg/cpp/scripts/test_chonk_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_chonk_standalone_vks_havent_changed.sh index 554805e35eea..29a2d87a43dd 100755 --- a/barretenberg/cpp/scripts/test_chonk_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_chonk_standalone_vks_havent_changed.sh @@ -13,7 +13,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-chonk-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-chonk-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-chonk-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_short_hash="f185b2ed" +pinned_short_hash="e3757861" pinned_chonk_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-chonk-inputs-${pinned_short_hash}.tar.gz" script_path="$(cd "$(dirname "${BASH_SOURCE[0]}")/scripts" && pwd)/$(basename "${BASH_SOURCE[0]}")" diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/gate_count_constants.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/gate_count_constants.hpp index 2ccfa0789bd2..3ce67a24edc7 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/gate_count_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/gate_count_constants.hpp @@ -27,7 +27,7 @@ template inline constexpr size_t BIG_QUAD = 2 + ZERO_GATE + M template inline constexpr size_t LOGIC_XOR_32 = 6 + ZERO_GATE + MEGA_OFFSET; template inline constexpr size_t LOGIC_AND_32 = 6 + ZERO_GATE + MEGA_OFFSET; template inline constexpr size_t RANGE_32 = 2744 + ZERO_GATE + MEGA_OFFSET; -template inline constexpr size_t SHA256_COMPRESSION = 6695 + ZERO_GATE + MEGA_OFFSET; +template inline constexpr size_t SHA256_COMPRESSION = 6702 + ZERO_GATE + MEGA_OFFSET; template inline constexpr size_t AES128_ENCRYPTION = 1432 + ZERO_GATE + MEGA_OFFSET; // The mega offset works differently for ECDSA opcodes because of the use of ROM tables, which use indices that diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256.cpp index 0f7f194357a5..33c275d1aa6b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256.cpp @@ -67,30 +67,6 @@ SHA256::sparse_witness_limbs SHA256::convert_witness(const fie return result; } -/** - * @brief Apply an implicit 32-bit range constraint by performing a lookup on the input. - * - * @details This is more efficient in the context of SHA-256 operations than explicit 32-bit range constraints since the - * lookup table is already in use. We use the SHA256_MAJ_INPUT MultiTable since it results in only 3 lookup gates per - * lookup. - * - * @note The result of the lookup is not used, but the accumulator outputs are marked as intentionally unused to - * avoid false positives in the boomerang value detection analysis. - * - * @param input The field element to constrain to 32 bits. - */ -template -void SHA256::apply_32_bit_range_constraint_via_lookup(const field_t& input) -{ - auto lookup_data = plookup_read::get_lookup_accumulators(MultiTableId::SHA256_MAJ_INPUT, input); - // Mark all accumulator outputs as intentionally unused (they exist only for the range constraint side-effect) - for (auto& col : lookup_data.columns) { - for (auto& elem : col) { - mark_witness_as_used(elem); - } - } -} - /** * @brief Extend the 16-word message block to 64 words per SHA-256 specification. * @@ -191,6 +167,15 @@ std::array, 64> SHA256::extend_witness(const std::arra w_sparse[i] = sparse_witness_limbs(w_out); } + /** + * Explicitly constrain w[62] and w[63] to 32 bits. All other computed w_out values + * (w[16..61]) are implicitly constrained via lookups in convert_witness(). + * + * While not strictly necessary for soundness, this simplifies security analysis at minimal cost. + */ + w_sparse[62].normal.create_range_constraint(32); + w_sparse[63].normal.create_range_constraint(32); + std::array w_extended; for (size_t i = 0; i < 64; ++i) { w_extended[i] = w_sparse[i].normal; @@ -335,8 +320,9 @@ field_t SHA256::majority_with_sigma0(sparse_value& a, const sp * This is the only public entry point for the stdlib SHA-256 implementation. We implement only the compression function * (rather than a full hash) because this is all that is required in DSL. * - * @note It is assumed that all 24 inputs (8 hash state + 16 message words) are 32-bit constrained externally so that - * the input has a unique representation. + * @note All 24 inputs (8 hash state + 16 message words) are 32-bit range constrained to ensure unique representation. + * Most are implicitly constrained via lookup tables; only h_init[3], h_init[7], and input[0] require explicit + * constraints as they are used purely in arithmetic operations. * * @param h_init The 8-word (256-bit) initial hash state. For the first block of a message, * this should be the standard SHA-256 IV. For subsequent blocks, this is the @@ -350,6 +336,12 @@ std::array, 8> SHA256::sha256_block(const std::array; + // Constrain inputs not implicitly constrained via lookups (h_init[3], h_init[7], input[0]). + // Other inputs are lookup-constrained in sparse form conversions or message extension. + h_init[3].create_range_constraint(32); + h_init[7].create_range_constraint(32); + input[0].create_range_constraint(32); + /** * Initialize round variables with previous block output. * Note: We delay converting `a` and `e` into their respective sparse forms because it's done as part of the @@ -400,8 +392,8 @@ std::array, 8> SHA256::sha256_block(const std::array class SHA256 { static sparse_witness_limbs convert_witness(const field_ct& input); - static void apply_32_bit_range_constraint_via_lookup(const field_ct& input); - static field_ct choose_with_sigma1(sparse_value& e, const sparse_value& f, const sparse_value& g); static field_ct majority_with_sigma0(sparse_value& a, const sparse_value& b, const sparse_value& c); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256.test.cpp index 56f05a12802c..64ec9e1706ef 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256.test.cpp @@ -87,7 +87,7 @@ TYPED_TEST(Sha256Test, BlockNistVectorOne) EXPECT_EQ(circuit_val, EXPECTED[i]) << "Circuit mismatch at index " << i; } - check_circuit_and_gate_count(builder, 6695); + check_circuit_and_gate_count(builder, 6702); EXPECT_EQ(builder.get_tables_size(), 35992); } @@ -165,7 +165,7 @@ TYPED_TEST(Sha256Test, BlockNistVectorTwo) EXPECT_EQ(circuit_val, EXPECTED[i]) << "Circuit mismatch at index " << i; } - check_circuit_and_gate_count(builder, 10633); + check_circuit_and_gate_count(builder, 10646); EXPECT_EQ(builder.get_tables_size(), 35992); }