diff --git a/barretenberg/cpp/pil/vm2/bitwise.pil b/barretenberg/cpp/pil/vm2/bitwise.pil index 8c9367eab2cc..53e4aed638d3 100644 --- a/barretenberg/cpp/pil/vm2/bitwise.pil +++ b/barretenberg/cpp/pil/vm2/bitwise.pil @@ -57,6 +57,7 @@ start * (1 - start) = 0; pol commit start_keccak; pol commit start_sha256; start_keccak * (1 - start_keccak) = 0; +start_sha256 * (1 - start_sha256) = 0; // If any of the above selectors is 1, then start must be 1. (start_keccak + start_sha256) * (1 - start) = 0; diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/bitwise.test.cpp index 6b3c882fc08a..fe8fa3aff30f 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/bitwise.test.cpp @@ -579,5 +579,91 @@ TEST(BitwiseConstrainingTest, ExecBitwiseDispatchOnErrorFF) check_interaction(trace); } +// ========================================================================= +// Audit-generated edge case tests +// ========================================================================= + +// Tests that start_sha256 must be boolean (0 or 1). +// This test verifies that the constraint `start_sha256 * (1 - start_sha256) = 0` is enforced. +TEST(BitwiseConstrainingTest, NegativeStartSha256NonBoolean) +{ + // Test with start_sha256 = 2 (non-boolean value) + TestTraceContainer trace({ + { + { C::bitwise_start_sha256, 2 }, // Non-boolean value should fail + }, + }); + + // Subrelation 3 is: start_sha256 * (1 - start_sha256) = 0 + EXPECT_THROW_WITH_MESSAGE(check_relation(trace, 3UL), ""); +} + +// Tests that start_keccak must be boolean +TEST(BitwiseConstrainingTest, NegativeStartKeccakNonBoolean) +{ + TestTraceContainer trace({ + { + { C::bitwise_start_keccak, 2 }, // Non-boolean value should fail + }, + }); + + // Subrelation 2 is: start_keccak * (1 - start_keccak) = 0 + EXPECT_THROW_WITH_MESSAGE(check_relation(trace, 2UL), ""); +} + +// Edge case: XOR of identical values should yield 0 +TEST(BitwiseConstrainingTest, XorIdenticalValuesYieldsZero) +{ + TestTraceContainer trace; + BitwiseTraceBuilder builder; + + std::vector events = { + { .operation = BitwiseOperation::XOR, + .a = MemoryValue::from(0xDEADBEEF), + .b = MemoryValue::from(0xDEADBEEF), + .res = 0 }, // x XOR x = 0 + }; + + builder.process(events, trace); + + check_relation(trace); +} + +// Edge case: OR with all 1s should yield all 1s +TEST(BitwiseConstrainingTest, OrWithMaxValue) +{ + TestTraceContainer trace; + BitwiseTraceBuilder builder; + + std::vector events = { + { .operation = BitwiseOperation::OR, + .a = MemoryValue::from(0xFFFFFFFF), + .b = MemoryValue::from(0x12345678), + .res = 0xFFFFFFFF }, + }; + + builder.process(events, trace); + + check_relation(trace); +} + +// Edge case: AND with 0 should yield 0 +TEST(BitwiseConstrainingTest, AndWithZero) +{ + TestTraceContainer trace; + BitwiseTraceBuilder builder; + + std::vector events = { + { .operation = BitwiseOperation::AND, + .a = MemoryValue::from(0xDEADBEEF), + .b = MemoryValue::from(0x00000000), + .res = 0 }, + }; + + builder.process(events, trace); + + check_relation(trace); +} + } // namespace } // namespace bb::avm2::constraining diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/bitwise.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/bitwise.hpp index ba59a4aeacea..8f656d41617c 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/bitwise.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/bitwise.hpp @@ -14,8 +14,8 @@ template class bitwiseImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 5, - 3, 4, 4, 5, 3, 3, 3, 3, 3, 3, 3 }; + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, + 5, 3, 4, 4, 5, 3, 3, 3, 3, 3, 3, 3 }; template inline static bool skip(const AllEntities& in) { @@ -36,20 +36,20 @@ template class bitwise : public Relation> { static constexpr const std::string_view NAME = "bitwise"; // Subrelation indices constants, to be used in tests. - static constexpr size_t SR_LAST_ON_ERROR = 8; - static constexpr size_t SR_RES_TAG_SHOULD_MATCH_INPUT = 9; - static constexpr size_t SR_INPUT_TAG_CANNOT_BE_FF = 10; - static constexpr size_t SR_INPUT_TAGS_SHOULD_MATCH = 11; - static constexpr size_t SR_BITW_OP_ID_REL = 12; - static constexpr size_t SR_BITW_CTR_DECREMENT = 13; - static constexpr size_t SR_BITW_SEL_CTR_NON_ZERO = 14; - static constexpr size_t SR_BITW_LAST_FOR_CTR_ONE = 15; - static constexpr size_t SR_BITW_INIT_A = 16; - static constexpr size_t SR_BITW_INIT_B = 17; - static constexpr size_t SR_BITW_INIT_C = 18; - static constexpr size_t SR_BITW_ACC_REL_A = 19; - static constexpr size_t SR_BITW_ACC_REL_B = 20; - static constexpr size_t SR_BITW_ACC_REL_C = 21; + static constexpr size_t SR_LAST_ON_ERROR = 9; + static constexpr size_t SR_RES_TAG_SHOULD_MATCH_INPUT = 10; + static constexpr size_t SR_INPUT_TAG_CANNOT_BE_FF = 11; + static constexpr size_t SR_INPUT_TAGS_SHOULD_MATCH = 12; + static constexpr size_t SR_BITW_OP_ID_REL = 13; + static constexpr size_t SR_BITW_CTR_DECREMENT = 14; + static constexpr size_t SR_BITW_SEL_CTR_NON_ZERO = 15; + static constexpr size_t SR_BITW_LAST_FOR_CTR_ONE = 16; + static constexpr size_t SR_BITW_INIT_A = 17; + static constexpr size_t SR_BITW_INIT_B = 18; + static constexpr size_t SR_BITW_INIT_C = 19; + static constexpr size_t SR_BITW_ACC_REL_A = 20; + static constexpr size_t SR_BITW_ACC_REL_B = 21; + static constexpr size_t SR_BITW_ACC_REL_C = 22; static std::string get_subrelation_label(size_t index) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/bitwise_impl.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/bitwise_impl.hpp index cd9d3d43c011..7946b1abb786 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/bitwise_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/bitwise_impl.hpp @@ -37,90 +37,96 @@ void bitwiseImpl::accumulate(ContainerOverSubrelations& evals, } { using View = typename std::tuple_element_t<3, ContainerOverSubrelations>::View; + auto tmp = static_cast(in.get(C::bitwise_start_sha256)) * + (FF(1) - static_cast(in.get(C::bitwise_start_sha256))); + std::get<3>(evals) += (tmp * scaling_factor); + } + { + using View = typename std::tuple_element_t<4, ContainerOverSubrelations>::View; auto tmp = (static_cast(in.get(C::bitwise_start_keccak)) + static_cast(in.get(C::bitwise_start_sha256))) * (FF(1) - static_cast(in.get(C::bitwise_start))); - std::get<3>(evals) += (tmp * scaling_factor); + std::get<4>(evals) += (tmp * scaling_factor); } { - using View = typename std::tuple_element_t<4, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<5, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_sel_tag_ff_err)) * (FF(1) - static_cast(in.get(C::bitwise_sel_tag_ff_err))); - std::get<4>(evals) += (tmp * scaling_factor); + std::get<5>(evals) += (tmp * scaling_factor); } { - using View = typename std::tuple_element_t<5, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<6, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_sel_tag_mismatch_err)) * (FF(1) - static_cast(in.get(C::bitwise_sel_tag_mismatch_err))); - std::get<5>(evals) += (tmp * scaling_factor); + std::get<6>(evals) += (tmp * scaling_factor); } { - using View = typename std::tuple_element_t<6, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<7, ContainerOverSubrelations>::View; auto tmp = (static_cast(in.get(C::bitwise_err)) - (FF(1) - (FF(1) - static_cast(in.get(C::bitwise_sel_tag_mismatch_err))) * (FF(1) - static_cast(in.get(C::bitwise_sel_tag_ff_err))))); - std::get<6>(evals) += (tmp * scaling_factor); + std::get<7>(evals) += (tmp * scaling_factor); } { - using View = typename std::tuple_element_t<7, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<8, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_last)) * (FF(1) - static_cast(in.get(C::bitwise_last))); - std::get<7>(evals) += (tmp * scaling_factor); + std::get<8>(evals) += (tmp * scaling_factor); } { // LAST_ON_ERROR - using View = typename std::tuple_element_t<8, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<9, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_err)) * (static_cast(in.get(C::bitwise_last)) - FF(1)); - std::get<8>(evals) += (tmp * scaling_factor); + std::get<9>(evals) += (tmp * scaling_factor); } { // RES_TAG_SHOULD_MATCH_INPUT - using View = typename std::tuple_element_t<9, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<10, ContainerOverSubrelations>::View; auto tmp = (FF(1) - static_cast(in.get(C::bitwise_err))) * static_cast(in.get(C::bitwise_start)) * (static_cast(in.get(C::bitwise_tag_c)) - static_cast(in.get(C::bitwise_tag_a))); - std::get<9>(evals) += (tmp * scaling_factor); + std::get<10>(evals) += (tmp * scaling_factor); } { // INPUT_TAG_CANNOT_BE_FF - using View = typename std::tuple_element_t<10, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<11, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_start)) * ((CView(bitwise_TAG_A_DIFF) * (static_cast(in.get(C::bitwise_sel_tag_ff_err)) * (FF(1) - static_cast(in.get(C::bitwise_tag_a_inv))) + static_cast(in.get(C::bitwise_tag_a_inv))) - FF(1)) + static_cast(in.get(C::bitwise_sel_tag_ff_err))); - std::get<10>(evals) += (tmp * scaling_factor); + std::get<11>(evals) += (tmp * scaling_factor); } { // INPUT_TAGS_SHOULD_MATCH - using View = typename std::tuple_element_t<11, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<12, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_start)) * (CView(bitwise_TAG_AB_DIFF) * ((FF(1) - static_cast(in.get(C::bitwise_sel_tag_mismatch_err))) * (FF(1) - static_cast(in.get(C::bitwise_tag_ab_diff_inv))) + static_cast(in.get(C::bitwise_tag_ab_diff_inv))) - static_cast(in.get(C::bitwise_sel_tag_mismatch_err))); - std::get<11>(evals) += (tmp * scaling_factor); + std::get<12>(evals) += (tmp * scaling_factor); } { // BITW_OP_ID_REL - using View = typename std::tuple_element_t<12, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<13, ContainerOverSubrelations>::View; auto tmp = (static_cast(in.get(C::bitwise_op_id_shift)) - static_cast(in.get(C::bitwise_op_id))) * (FF(1) - static_cast(in.get(C::bitwise_last))); - std::get<12>(evals) += (tmp * scaling_factor); + std::get<13>(evals) += (tmp * scaling_factor); } { // BITW_CTR_DECREMENT - using View = typename std::tuple_element_t<13, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<14, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_sel)) * ((static_cast(in.get(C::bitwise_ctr_shift)) - static_cast(in.get(C::bitwise_ctr))) + FF(1)) * (FF(1) - static_cast(in.get(C::bitwise_last))); - std::get<13>(evals) += (tmp * scaling_factor); + std::get<14>(evals) += (tmp * scaling_factor); } { // BITW_SEL_CTR_NON_ZERO - using View = typename std::tuple_element_t<14, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<15, ContainerOverSubrelations>::View; auto tmp = (static_cast(in.get(C::bitwise_ctr)) * ((FF(1) - static_cast(in.get(C::bitwise_sel))) * (FF(1) - static_cast(in.get(C::bitwise_ctr_inv))) + static_cast(in.get(C::bitwise_ctr_inv))) - static_cast(in.get(C::bitwise_sel))); - std::get<14>(evals) += (tmp * scaling_factor); + std::get<15>(evals) += (tmp * scaling_factor); } { // BITW_LAST_FOR_CTR_ONE - using View = typename std::tuple_element_t<15, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<16, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_sel)) * (((static_cast(in.get(C::bitwise_ctr)) - FF(1)) * (static_cast(in.get(C::bitwise_last)) * @@ -128,52 +134,52 @@ void bitwiseImpl::accumulate(ContainerOverSubrelations& evals, static_cast(in.get(C::bitwise_ctr_min_one_inv))) + static_cast(in.get(C::bitwise_last))) - FF(1)); - std::get<15>(evals) += (tmp * scaling_factor); + std::get<16>(evals) += (tmp * scaling_factor); } { // BITW_INIT_A - using View = typename std::tuple_element_t<16, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<17, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_last)) * (static_cast(in.get(C::bitwise_acc_ia)) - static_cast(in.get(C::bitwise_ia_byte))); - std::get<16>(evals) += (tmp * scaling_factor); + std::get<17>(evals) += (tmp * scaling_factor); } { // BITW_INIT_B - using View = typename std::tuple_element_t<17, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<18, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_last)) * (static_cast(in.get(C::bitwise_acc_ib)) - static_cast(in.get(C::bitwise_ib_byte))); - std::get<17>(evals) += (tmp * scaling_factor); + std::get<18>(evals) += (tmp * scaling_factor); } { // BITW_INIT_C - using View = typename std::tuple_element_t<18, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<19, ContainerOverSubrelations>::View; auto tmp = static_cast(in.get(C::bitwise_last)) * (static_cast(in.get(C::bitwise_acc_ic)) - static_cast(in.get(C::bitwise_ic_byte))); - std::get<18>(evals) += (tmp * scaling_factor); + std::get<19>(evals) += (tmp * scaling_factor); } { // BITW_ACC_REL_A - using View = typename std::tuple_element_t<19, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<20, ContainerOverSubrelations>::View; auto tmp = ((static_cast(in.get(C::bitwise_acc_ia)) - static_cast(in.get(C::bitwise_ia_byte))) - FF(256) * static_cast(in.get(C::bitwise_acc_ia_shift))) * (FF(1) - static_cast(in.get(C::bitwise_last))); - std::get<19>(evals) += (tmp * scaling_factor); + std::get<20>(evals) += (tmp * scaling_factor); } { // BITW_ACC_REL_B - using View = typename std::tuple_element_t<20, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<21, ContainerOverSubrelations>::View; auto tmp = ((static_cast(in.get(C::bitwise_acc_ib)) - static_cast(in.get(C::bitwise_ib_byte))) - FF(256) * static_cast(in.get(C::bitwise_acc_ib_shift))) * (FF(1) - static_cast(in.get(C::bitwise_last))); - std::get<20>(evals) += (tmp * scaling_factor); + std::get<21>(evals) += (tmp * scaling_factor); } { // BITW_ACC_REL_C - using View = typename std::tuple_element_t<21, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<22, ContainerOverSubrelations>::View; auto tmp = ((static_cast(in.get(C::bitwise_acc_ic)) - static_cast(in.get(C::bitwise_ic_byte))) - FF(256) * static_cast(in.get(C::bitwise_acc_ic_shift))) * (FF(1) - static_cast(in.get(C::bitwise_last))); - std::get<21>(evals) += (tmp * scaling_factor); + std::get<22>(evals) += (tmp * scaling_factor); } { - using View = typename std::tuple_element_t<22, ContainerOverSubrelations>::View; + using View = typename std::tuple_element_t<23, ContainerOverSubrelations>::View; auto tmp = (static_cast(in.get(C::bitwise_sel_get_ctr)) - static_cast(in.get(C::bitwise_start)) * (FF(1) - static_cast(in.get(C::bitwise_err)))); - std::get<22>(evals) += (tmp * scaling_factor); + std::get<23>(evals) += (tmp * scaling_factor); } }